fix deadlock of cl processor
* deadlock caused by 3a stats buffer waiting and 3a results apply
* reduce latency on stats queue wait
diff --git a/xcore/buffer_pool.cpp b/xcore/buffer_pool.cpp
index a761af4..5ead0dd 100644
--- a/xcore/buffer_pool.cpp
+++ b/xcore/buffer_pool.cpp
@@ -174,7 +174,7 @@
SmartLock lock (_mutex);
_started = false;
}
- _buf_list.wakeup ();
+ _buf_list.pause_pop ();
}
void
diff --git a/xcore/image_processor.cpp b/xcore/image_processor.cpp
index 9cba733..fde24b0 100644
--- a/xcore/image_processor.cpp
+++ b/xcore/image_processor.cpp
@@ -87,13 +87,63 @@
return false;
}
+class X3aResultsProcessThread
+ : public Thread
+{
+ typedef SafeList<X3aResult> ResultQueue;
+public:
+ X3aResultsProcessThread (ImageProcessor *processor)
+ : Thread ("x3a_results_process_thread")
+ , _processor (processor)
+ {}
+ ~X3aResultsProcessThread () {}
+
+ XCamReturn push_result (SmartPtr<X3aResult> &result) {
+ _queue.push (result);
+ return XCAM_RETURN_NO_ERROR;
+ }
+
+ void triger_stop () {
+ _queue.pause_pop ();
+ }
+
+ virtual bool loop ();
+
+private:
+ ImageProcessor *_processor;
+ ResultQueue _queue;
+};
+
+bool X3aResultsProcessThread::loop ()
+{
+ X3aResultList result_list;
+ SmartPtr<X3aResult> result;
+
+ result = _queue.pop (-1);
+ if (!result.ptr ())
+ return false;
+
+ result_list.push_back (result);
+ while ((result = _queue.pop (0)).ptr ()) {
+ result_list.push_back (result);
+ }
+
+ XCamReturn ret = _processor->process_3a_results (result_list);
+ if (ret != XCAM_RETURN_NO_ERROR) {
+ XCAM_LOG_DEBUG ("processing 3a result failed");
+ }
+
+ return true;
+}
ImageProcessor::ImageProcessor (const char* name)
: _name (NULL)
, _callback (NULL)
{
- _processor_thread = new ImageProcessorThread (this);
if (name)
_name = strdup (name);
+
+ _processor_thread = new ImageProcessorThread (this);
+ _results_thread = new X3aResultsProcessThread (this);
}
ImageProcessor::~ImageProcessor ()
@@ -113,7 +163,10 @@
XCamReturn
ImageProcessor::start()
{
- if (!_processor_thread->start()) {
+ if (!_results_thread->start ()) {
+ return XCAM_RETURN_ERROR_THREAD;
+ }
+ if (!_processor_thread->start ()) {
return XCAM_RETURN_ERROR_THREAD;
}
XCAM_LOG_INFO ("ImageProcessor(%s) started", XCAM_STR (_name));
@@ -123,11 +176,13 @@
XCamReturn
ImageProcessor::stop()
{
- _video_buf_queue.wakeup ();
+ _video_buf_queue.pause_pop ();
+ _results_thread->triger_stop ();
emit_stop ();
_processor_thread->stop ();
+ _results_thread->stop ();
XCAM_LOG_DEBUG ("ImageProcessor(%s) stopped", XCAM_STR (_name));
return XCAM_RETURN_NO_ERROR;
}
@@ -145,6 +200,40 @@
XCamReturn
ImageProcessor::push_3a_results (X3aResultList &results)
{
+ XCAM_ASSERT (!results.empty ());
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ for (X3aResultList::iterator i_res = results.begin();
+ i_res != results.end(); ++i_res) {
+ SmartPtr<X3aResult> &res = *i_res;
+
+ ret = _results_thread->push_result (res);
+ if (ret != XCAM_RETURN_NO_ERROR)
+ break;
+ }
+
+ XCAM_FAIL_RETURN(
+ WARNING,
+ ret == XCAM_RETURN_NO_ERROR,
+ ret,
+ "processor(%s) push 3a results failed", XCAM_STR(get_name()));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result)
+{
+ XCamReturn ret = _results_thread->push_result (result);
+ XCAM_FAIL_RETURN(
+ WARNING,
+ ret == XCAM_RETURN_NO_ERROR,
+ ret,
+ "processor(%s) push 3a result failed", XCAM_STR(get_name()));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+ImageProcessor::process_3a_results (X3aResultList &results)
+{
X3aResultList valid_results;
XCamReturn ret = XCAM_RETURN_NO_ERROR;
@@ -171,7 +260,7 @@
}
XCamReturn
-ImageProcessor::push_3a_result (SmartPtr<X3aResult> &result)
+ImageProcessor::process_3a_result (SmartPtr<X3aResult> &result)
{
X3aResultList valid_results;
XCamReturn ret = XCAM_RETURN_NO_ERROR;
diff --git a/xcore/image_processor.h b/xcore/image_processor.h
index 38f5920..611f6bd 100644
--- a/xcore/image_processor.h
+++ b/xcore/image_processor.h
@@ -45,11 +45,13 @@
};
class ImageProcessorThread;
+class X3aResultsProcessThread;
/* base class, ImageProcessor */
class ImageProcessor
{
friend class ImageProcessorThread;
+ friend class X3aResultsProcessThread;
typedef SafeList<VideoBuffer> VideoBufQueue;
@@ -81,14 +83,18 @@
void filter_valid_results (X3aResultList &input, X3aResultList &valid_results);
XCamReturn buffer_process_loop ();
+ XCamReturn process_3a_results (X3aResultList &results);
+ XCamReturn process_3a_result (SmartPtr<X3aResult> &result);
+
private:
XCAM_DEAD_COPY (ImageProcessor);
protected:
- char *_name;
- ImageProcessCallback *_callback;
- SmartPtr<ImageProcessorThread> _processor_thread;
- VideoBufQueue _video_buf_queue;
+ char *_name;
+ ImageProcessCallback *_callback;
+ SmartPtr<ImageProcessorThread> _processor_thread;
+ VideoBufQueue _video_buf_queue;
+ SmartPtr<X3aResultsProcessThread> _results_thread;
};
};
diff --git a/xcore/safe_list.h b/xcore/safe_list.h
index 5c465c9..c321064 100644
--- a/xcore/safe_list.h
+++ b/xcore/safe_list.h
@@ -35,7 +35,9 @@
public:
typedef SmartPtr<OBj> ObjPtr;
- SafeList () {}
+ SafeList ()
+ : _pop_paused (false)
+ {}
~SafeList () {
}
@@ -56,12 +58,22 @@
void wakeup () {
_new_obj_cond.broadcast ();
}
+ void pause_pop () {
+ SmartLock lock(_mutex);
+ _pop_paused = true;
+ wakeup ();
+ }
+ void resume_pop () {
+ SmartLock lock(_mutex);
+ _pop_paused = false;
+ }
inline void clear ();
private:
std::list<ObjPtr> _obj_list;
Mutex _mutex;
XCam::Cond _new_obj_cond;
+ bool _pop_paused;
};
@@ -72,6 +84,9 @@
SmartLock lock (_mutex);
int code = 0;
+ if (_pop_paused)
+ return NULL;
+
if (_obj_list.empty()) {
if (timeout < 0)
code = _new_obj_cond.wait(_mutex);
diff --git a/xcore/x3a_analyzer.cpp b/xcore/x3a_analyzer.cpp
index c119d44..4e02f35 100644
--- a/xcore/x3a_analyzer.cpp
+++ b/xcore/x3a_analyzer.cpp
@@ -33,7 +33,7 @@
~AnalyzerThread ();
void triger_stop() {
- _3a_stats_queue.wakeup ();
+ _3a_stats_queue.pause_pop ();
}
bool push_stats (const SmartPtr<X3aStats> &stats);
@@ -46,7 +46,7 @@
private:
X3aAnalyzer *_analyzer;
- SafeList<X3aStats> _3a_stats_queue;
+ SafeList<X3aStats> _3a_stats_queue;
};
AnalyzerThread::AnalyzerThread (X3aAnalyzer *analyzer)
@@ -86,11 +86,17 @@
AnalyzerThread::loop ()
{
const static int32_t timeout = -1;
+ SmartPtr<X3aStats> latest_stats;
SmartPtr<X3aStats> stats = _3a_stats_queue.pop (timeout);
if (!stats.ptr()) {
XCAM_LOG_DEBUG ("analyzer thread got empty stats, stop thread");
return false;
}
+ //while ((latest_stats = _3a_stats_queue.pop (0)).ptr ()) {
+ // stats = latest_stats;
+ // XCAM_LOG_WARNING ("lost 3a stats since 3a analyzer too slow");
+ //}
+
XCamReturn ret = _analyzer->analyze_3a_statistics (stats);
if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS)
return true;