Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_image_processor.cpp - CL image processor
      3  *
      4  *  Copyright (c) 2015 Intel Corporation
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Wind Yuan <feng.yuan (at) intel.com>
     19  */
     20 #include "cl_image_processor.h"
     21 #include "cl_context.h"
     22 #include "cl_device.h"
     23 #include "cl_image_handler.h"
     24 #include "cl_demo_handler.h"
     25 #include "xcam_thread.h"
     26 
     27 namespace XCam {
     28 
     29 class CLHandlerThread
     30     : public Thread
     31 {
     32 public:
     33     CLHandlerThread (CLImageProcessor *processor)
     34         : Thread ("CLHandlerThread")
     35         , _processor (processor)
     36     {}
     37     ~CLHandlerThread () {}
     38 
     39     virtual bool loop ();
     40 
     41 private:
     42     CLImageProcessor *_processor;
     43 };
     44 
     45 bool CLHandlerThread::loop ()
     46 {
     47     XCAM_ASSERT (_processor);
     48     XCamReturn ret = _processor->process_cl_buffer_queue ();
     49     if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS)
     50         return false;
     51     return true;
     52 }
     53 
     54 class CLBufferNotifyThread
     55     : public Thread
     56 {
     57 public:
     58     CLBufferNotifyThread (CLImageProcessor *processor)
     59         : Thread ("CLBufNtfThrd")
     60         , _processor (processor)
     61     {}
     62     ~CLBufferNotifyThread () {}
     63 
     64     virtual bool loop ();
     65 
     66 private:
     67     CLImageProcessor *_processor;
     68 };
     69 
     70 bool CLBufferNotifyThread::loop ()
     71 {
     72     XCAM_ASSERT (_processor);
     73     XCamReturn ret = _processor->process_done_buffer ();
     74     if (ret < XCAM_RETURN_NO_ERROR)
     75         return false;
     76     return true;
     77 }
     78 CLImageProcessor::CLImageProcessor (const char* name)
     79     : ImageProcessor (name ? name : "CLImageProcessor")
     80     , _seq_num (0)
     81     , _keep_attached_buffer (false)
     82 {
     83     _context = CLDevice::instance ()->get_context ();
     84     XCAM_ASSERT (_context.ptr());
     85 
     86     _handler_thread = new CLHandlerThread (this);
     87     XCAM_ASSERT (_handler_thread.ptr ());
     88 
     89     _done_buf_thread = new CLBufferNotifyThread (this);
     90     XCAM_ASSERT (_done_buf_thread.ptr ());
     91 
     92     XCAM_LOG_DEBUG ("CLImageProcessor constructed");
     93     XCAM_OBJ_PROFILING_INIT;
     94 }
     95 
     96 CLImageProcessor::~CLImageProcessor ()
     97 {
     98     XCAM_LOG_DEBUG ("CLImageProcessor destructed");
     99 }
    100 
    101 void
    102 CLImageProcessor::keep_attached_buf(bool flag)
    103 {
    104     _keep_attached_buffer = flag;
    105 }
    106 
    107 bool
    108 CLImageProcessor::add_handler (SmartPtr<CLImageHandler> &handler)
    109 {
    110     XCAM_ASSERT (handler.ptr ());
    111     _handlers.push_back (handler);
    112     return true;
    113 }
    114 
    115 CLImageProcessor::ImageHandlerList::iterator
    116 CLImageProcessor::handlers_begin ()
    117 {
    118     return _handlers.begin ();
    119 }
    120 
    121 CLImageProcessor::ImageHandlerList::iterator
    122 CLImageProcessor::handlers_end ()
    123 {
    124     return _handlers.end ();
    125 }
    126 
    127 SmartPtr<CLContext>
    128 CLImageProcessor::get_cl_context ()
    129 {
    130     return _context;
    131 }
    132 
    133 bool
    134 CLImageProcessor::can_process_result (SmartPtr<X3aResult> &result)
    135 {
    136     XCAM_UNUSED (result);
    137     return false;
    138 }
    139 
    140 XCamReturn
    141 CLImageProcessor::apply_3a_results (X3aResultList &results)
    142 {
    143     XCAM_UNUSED (results);
    144     return XCAM_RETURN_NO_ERROR;
    145 }
    146 
    147 XCamReturn
    148 CLImageProcessor::apply_3a_result (SmartPtr<X3aResult> &result)
    149 {
    150     XCAM_UNUSED (result);
    151     return XCAM_RETURN_NO_ERROR;
    152 }
    153 
    154 XCamReturn
    155 CLImageProcessor::process_buffer (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    156 {
    157     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    158     XCAM_ASSERT (input.ptr ());
    159 
    160     // Always set to NULL,  output buf should be handled in CLBufferNotifyThread
    161     output = NULL;
    162 
    163     STREAM_LOCK;
    164 
    165     if (_handlers.empty()) {
    166         ret = create_handlers ();
    167     }
    168 
    169     XCAM_FAIL_RETURN (
    170         WARNING,
    171         !_handlers.empty () && ret == XCAM_RETURN_NO_ERROR,
    172         XCAM_RETURN_ERROR_CL,
    173         "CL image processor create handlers failed");
    174 
    175     SmartPtr<PriorityBuffer> p_buf = new PriorityBuffer;
    176     p_buf->set_seq_num (_seq_num++);
    177     p_buf->data = input;
    178     p_buf->handler = *(_handlers.begin ());
    179 
    180     XCAM_FAIL_RETURN (
    181         WARNING,
    182         _process_buffer_queue.push_priority_buf (p_buf),
    183         XCAM_RETURN_ERROR_UNKNOWN,
    184         "CLImageProcessor push priority buffer failed");
    185 
    186     return XCAM_RETURN_BYPASS;
    187 }
    188 
    189 XCamReturn
    190 CLImageProcessor::process_done_buffer ()
    191 {
    192     SmartPtr<VideoBuffer> done_buf = _done_buffer_queue.pop (-1);
    193     if (!done_buf.ptr ())
    194         return XCAM_RETURN_ERROR_THREAD;
    195 
    196     //notify buffer done, only in this thread
    197     notify_process_buffer_done (done_buf);
    198     return XCAM_RETURN_NO_ERROR;
    199 }
    200 
    201 uint32_t
    202 CLImageProcessor::check_ready_buffers ()
    203 {
    204     uint32_t ready_count = 0;
    205     bool is_ready_or_disabled = false;
    206     UnsafePriorityBufferList::iterator i = _not_ready_buffers.begin ();
    207 
    208     while (i != _not_ready_buffers.end()) {
    209         SmartPtr<PriorityBuffer> buf = *i;
    210         XCAM_ASSERT (buf.ptr () && buf->handler.ptr ());
    211         {
    212             is_ready_or_disabled = (!buf->handler->is_handler_enabled () || buf->handler->is_ready ());
    213         }
    214         if (is_ready_or_disabled) {
    215             ready_count ++;
    216             _process_buffer_queue.push_priority_buf (buf);
    217             _not_ready_buffers.erase (i++);
    218         } else
    219             ++i;
    220     }
    221     return ready_count;
    222 }
    223 
    224 XCamReturn
    225 CLImageProcessor::process_cl_buffer_queue ()
    226 {
    227     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    228     SmartPtr<PriorityBuffer> p_buf;
    229     const int32_t timeout = 5000; // 5ms
    230     uint32_t ready_count = 0;
    231 
    232     {
    233         STREAM_LOCK;  // make sure handler APIs are protected
    234         check_ready_buffers ();
    235     }
    236 
    237     p_buf = _process_buffer_queue.pop (timeout);
    238 
    239     if (!p_buf.ptr ()) {
    240         //XCAM_LOG_DEBUG ("cl buffer queue stopped");
    241         return XCAM_RETURN_BYPASS;
    242     }
    243 
    244     SmartPtr<VideoBuffer> data = p_buf->data;
    245     SmartPtr<CLImageHandler> handler = p_buf->handler;
    246     SmartPtr <VideoBuffer> out_data;
    247 
    248     XCAM_ASSERT (data.ptr () && handler.ptr ());
    249 
    250     XCAM_LOG_DEBUG ("buf:%d, rank:%d\n", p_buf->seq_num, p_buf->rank);
    251 
    252     {
    253         STREAM_LOCK;
    254         if (handler->is_handler_enabled () && !handler->is_ready ()) {
    255             _not_ready_buffers.push_back (p_buf);
    256             return XCAM_RETURN_NO_ERROR;
    257         }
    258 
    259         ready_count = check_ready_buffers ();
    260         if (ready_count) {
    261             _process_buffer_queue.push_priority_buf (p_buf);
    262             return XCAM_RETURN_BYPASS;
    263         }
    264 
    265         ret = handler->execute (data, out_data);
    266         XCAM_FAIL_RETURN (
    267             WARNING,
    268             (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS),
    269             ret,
    270             "CLImageProcessor execute image handler failed");
    271         XCAM_ASSERT (out_data.ptr ());
    272         if (ret == XCAM_RETURN_BYPASS)
    273             return ret;
    274 
    275         // for loop in handler, find next handler
    276         ImageHandlerList::iterator i_handler = _handlers.begin ();
    277         while (i_handler != _handlers.end ())
    278         {
    279             if (handler.ptr () == (*i_handler).ptr ()) {
    280                 ++i_handler;
    281                 break;
    282             }
    283             ++i_handler;
    284         }
    285 
    286         //skip all disabled handlers
    287         while (i_handler != _handlers.end () && !(*i_handler)->is_handler_enabled ())
    288             ++i_handler;
    289 
    290         if (i_handler != _handlers.end ())
    291             p_buf->handler = *i_handler;
    292         else
    293             p_buf->handler = NULL;
    294     }
    295 
    296     // buffer processed by all handlers, done
    297     if (!p_buf->handler.ptr ()) {
    298         if (!_keep_attached_buffer && out_data.ptr ())
    299             out_data->clear_attached_buffers ();
    300 
    301         XCAM_OBJ_PROFILING_START;
    302         CLDevice::instance()->get_context ()->finish ();
    303         XCAM_OBJ_PROFILING_END (get_name (), XCAM_OBJ_DUR_FRAME_NUM);
    304 
    305         // buffer done, push back
    306         _done_buffer_queue.push (out_data);
    307         return XCAM_RETURN_NO_ERROR;
    308     }
    309 
    310     p_buf->data = out_data;
    311     p_buf->down_rank ();
    312 
    313     XCAM_FAIL_RETURN (
    314         WARNING,
    315         _process_buffer_queue.push_priority_buf (p_buf),
    316         XCAM_RETURN_ERROR_UNKNOWN,
    317         "CLImageProcessor push priority buffer failed");
    318 
    319     return ret;
    320 }
    321 
    322 XCamReturn
    323 CLImageProcessor::emit_start ()
    324 {
    325     _done_buffer_queue.resume_pop ();
    326     _process_buffer_queue.resume_pop ();
    327 
    328     if (!_done_buf_thread->start ())
    329         return XCAM_RETURN_ERROR_THREAD;
    330 
    331     if (!_handler_thread->start ())
    332         return XCAM_RETURN_ERROR_THREAD;
    333 
    334     return XCAM_RETURN_NO_ERROR;
    335 }
    336 
    337 void
    338 CLImageProcessor::emit_stop ()
    339 {
    340     _process_buffer_queue.pause_pop();
    341     _done_buffer_queue.pause_pop ();
    342 
    343 
    344     for (ImageHandlerList::iterator i_handler = _handlers.begin ();
    345             i_handler != _handlers.end ();  ++i_handler) {
    346         (*i_handler)->emit_stop ();
    347     }
    348 
    349     _handler_thread->stop ();
    350     _done_buf_thread->stop ();
    351     _not_ready_buffers.clear ();
    352     _process_buffer_queue.clear ();
    353     _done_buffer_queue.clear ();
    354 }
    355 
    356 XCamReturn
    357 CLImageProcessor::create_handlers ()
    358 {
    359     SmartPtr<CLImageHandler> demo_handler;
    360     demo_handler = create_cl_demo_image_handler (_context);
    361     // demo_handler = create_cl_binary_demo_image_handler (_context);
    362     XCAM_FAIL_RETURN (
    363         WARNING,
    364         demo_handler.ptr (),
    365         XCAM_RETURN_ERROR_CL,
    366         "CLImageProcessor create demo handler failed");
    367     add_handler (demo_handler);
    368 
    369     return XCAM_RETURN_NO_ERROR;
    370 }
    371 
    372 };
    373