Home | History | Annotate | Download | only in sample
      1 /*
      2  * sample_smart_analysis.cpp - smart analysis sample code
      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: Zong Wei <wei.zong (at) intel.com>
     19  */
     20 
     21 #include <base/xcam_smart_description.h>
     22 #include <base/xcam_buffer.h>
     23 #include <xcam_std.h>
     24 #include "aiq3a_utils.h"
     25 #include "x3a_result_factory.h"
     26 #include "smart_analyzer.h"
     27 
     28 using namespace XCam;
     29 
     30 #define DEFAULT_SAVE_FRAME_NAME "frame_buffer"
     31 #define XSMART_ANALYSIS_CONTEXT_CAST(context)  ((XCamSmartAnalyerContext*)(context))
     32 
     33 class FrameSaver
     34 {
     35 public:
     36     explicit FrameSaver (bool save, uint32_t interval, uint32_t count);
     37     ~FrameSaver ();
     38 
     39     void save_frame (XCamVideoBuffer *buffer);
     40 
     41     void enable_save_file (bool enable) {
     42         _save_file = enable;
     43     }
     44     void set_interval (uint32_t inteval) {
     45         _interval = inteval;
     46     }
     47     void set_frame_save (uint32_t frame_save) {
     48         _frame_save = frame_save;
     49     }
     50 
     51 private:
     52     XCAM_DEAD_COPY (FrameSaver);
     53     void open_file ();
     54     void close_file ();
     55 
     56 private:
     57     FILE *_file;
     58     bool _save_file;
     59     uint32_t _interval;
     60     uint32_t _frame_save;
     61     uint32_t _frame_count;
     62     uint32_t _skip_frame_count;
     63 
     64 };
     65 
     66 FrameSaver::FrameSaver (bool save, uint32_t interval, uint32_t count)
     67     : _file (NULL)
     68     , _save_file (save)
     69     , _interval (interval)
     70     , _frame_save (count)
     71     , _frame_count (0)
     72     , _skip_frame_count (300)
     73 {
     74 }
     75 
     76 FrameSaver::~FrameSaver ()
     77 {
     78     close_file ();
     79 }
     80 
     81 void
     82 FrameSaver::save_frame (XCamVideoBuffer *buffer)
     83 {
     84     if (NULL == buffer) {
     85         return;
     86     }
     87     if (!_save_file)
     88         return ;
     89 
     90     if ((_frame_count++ % _interval) != 0)
     91         return;
     92 
     93     if (_frame_count < _skip_frame_count)
     94         return;
     95 
     96     if (_frame_count > (_frame_save * _interval + _skip_frame_count)) {
     97         return;
     98     }
     99 
    100     open_file ();
    101 
    102     if (!_file) {
    103         XCAM_LOG_ERROR ("open file failed");
    104         return;
    105     }
    106 
    107     uint8_t *memory = xcam_video_buffer_map (buffer);
    108     XCamVideoBufferPlanarInfo planar;
    109     for (uint32_t index = 0; index < buffer->info.components; index++) {
    110         xcam_video_buffer_get_planar_info (&buffer->info, &planar, index);
    111         uint32_t line_bytes = planar.width * planar.pixel_bytes;
    112 
    113         for (uint32_t i = 0; i < planar.height; i++) {
    114             if (fwrite (memory + buffer->info.offsets [index] + i * buffer->info.strides [index],
    115                         1, line_bytes, _file) != line_bytes) {
    116                 XCAM_LOG_ERROR ("write file failed, size doesn't match");
    117                 return;
    118             }
    119         }
    120     }
    121     xcam_video_buffer_unmap (buffer);
    122     close_file ();
    123 }
    124 
    125 void
    126 FrameSaver::open_file ()
    127 {
    128     if ((_file) && (_frame_save == 0))
    129         return;
    130 
    131     char file_name[512];
    132     if (_frame_save != 0) {
    133         snprintf (file_name, sizeof(file_name), "%s%d%s", DEFAULT_SAVE_FRAME_NAME, _frame_count, ".yuv");
    134     }
    135 
    136     _file = fopen(file_name, "wb");
    137 }
    138 
    139 void
    140 FrameSaver::close_file ()
    141 {
    142     if (_file)
    143         fclose (_file);
    144     _file = NULL;
    145 }
    146 
    147 class SampleHandler
    148 {
    149 public:
    150     explicit SampleHandler (const char *name = NULL);
    151     virtual ~SampleHandler ();
    152 
    153     XCamReturn init (uint32_t width, uint32_t height, double framerate);
    154     XCamReturn deinit ();
    155     bool set_results_callback (AnalyzerCallback *callback);
    156 
    157     XCamReturn update_params (const XCamSmartAnalysisParam *params);
    158     XCamReturn analyze (XCamVideoBuffer *buffer);
    159 
    160 private:
    161     XCAM_DEAD_COPY (SampleHandler);
    162 
    163 private:
    164     char                    *_name;
    165     uint32_t                 _width;
    166     uint32_t                 _height;
    167     double                   _framerate;
    168     AnalyzerCallback        *_callback;
    169     SmartPtr<FrameSaver>    _frameSaver;
    170 };
    171 
    172 SampleHandler::SampleHandler (const char *name)
    173     : _name (NULL)
    174     , _width (0)
    175     , _height (0)
    176     , _framerate (30.0)
    177     , _callback (NULL)
    178 {
    179     if (name)
    180         _name = strndup (name, XCAM_MAX_STR_SIZE);
    181 
    182     if (!_frameSaver.ptr ()) {
    183         _frameSaver = new FrameSaver (true, 2, 16);
    184     }
    185 }
    186 
    187 SampleHandler::~SampleHandler ()
    188 {
    189     if (_name)
    190         xcam_free (_name);
    191 }
    192 
    193 XCamReturn
    194 SampleHandler::init (uint32_t width, uint32_t height, double framerate)
    195 {
    196     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    197     _width = width;
    198     _height = height;
    199     _framerate = framerate;
    200 
    201     return ret;
    202 }
    203 
    204 XCamReturn
    205 SampleHandler::deinit ()
    206 {
    207     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    208     return ret;
    209 }
    210 
    211 bool
    212 SampleHandler::set_results_callback (AnalyzerCallback *callback)
    213 {
    214     XCAM_ASSERT (!_callback);
    215     _callback = callback;
    216     return true;
    217 }
    218 
    219 XCamReturn
    220 SampleHandler::update_params (const XCamSmartAnalysisParam *params)
    221 {
    222     XCAM_UNUSED (params);
    223 
    224     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    225     return ret;
    226 }
    227 
    228 XCamReturn
    229 SampleHandler::analyze (XCamVideoBuffer *buffer)
    230 {
    231     XCAM_LOG_DEBUG ("Smart SampleHandler::analyze on ts:" XCAM_TIMESTAMP_FORMAT, XCAM_TIMESTAMP_ARGS (buffer->timestamp));
    232     if (NULL == buffer) {
    233         return XCAM_RETURN_ERROR_PARAM;
    234     }
    235     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    236 
    237     XCAM_LOG_DEBUG ("format(0x%x), color_bits(%d)", buffer->info.format, buffer->info.color_bits);
    238     XCAM_LOG_DEBUG ("size(%d), components(%d)", buffer->info.size, buffer->info.components);
    239     XCAM_LOG_DEBUG ("width(%d), heitht(%d)", buffer->info.width, buffer->info.height);
    240     XCAM_LOG_DEBUG ("aligned_width(%d), aligned_height(%d)", buffer->info.aligned_width, buffer->info.aligned_height);
    241 
    242     _frameSaver->save_frame (buffer);
    243 
    244     X3aResultList results;
    245     XCam3aResultBrightness xcam3a_brightness_result;
    246     xcam_mem_clear (xcam3a_brightness_result);
    247     xcam3a_brightness_result.head.type =   XCAM_3A_RESULT_BRIGHTNESS;
    248     xcam3a_brightness_result.head.process_type = XCAM_IMAGE_PROCESS_ALWAYS;
    249     xcam3a_brightness_result.head.version = XCAM_VERSION;
    250     xcam3a_brightness_result.brightness_level = 9.9;
    251 
    252     SmartPtr<X3aResult> brightness_result =
    253         X3aResultFactory::instance ()->create_3a_result ((XCam3aResultHead*)&xcam3a_brightness_result);
    254     results.push_back(brightness_result);
    255 
    256     if (_callback) {
    257         if (XCAM_RETURN_NO_ERROR == ret) {
    258             _callback->x3a_calculation_done (NULL, results);
    259         } else {
    260             _callback->x3a_calculation_failed (NULL, buffer->timestamp, "pre 3a analyze failed");
    261         }
    262     }
    263 
    264     return ret;
    265 }
    266 
    267 class XCamSmartAnalyerContext
    268     : public AnalyzerCallback
    269 {
    270 public:
    271     XCamSmartAnalyerContext ();
    272     ~XCamSmartAnalyerContext ();
    273     bool setup_handler ();
    274     SmartPtr<SampleHandler> &get_handler () {
    275         return _handler;
    276     }
    277 
    278     uint32_t get_results (X3aResultList &results);
    279 
    280     // derive from AnalyzerCallback
    281     virtual void x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results);
    282 
    283 private:
    284     XCAM_DEAD_COPY (XCamSmartAnalyerContext);
    285 
    286 private:
    287 // members
    288     SmartPtr<SampleHandler> _handler;
    289     Mutex                   _result_mutex;
    290     X3aResultList           _results;
    291 };
    292 
    293 XCamSmartAnalyerContext::XCamSmartAnalyerContext ()
    294 {
    295     setup_handler ();
    296 }
    297 
    298 XCamSmartAnalyerContext::~XCamSmartAnalyerContext ()
    299 {
    300     _handler->deinit ();
    301 }
    302 
    303 bool
    304 XCamSmartAnalyerContext::setup_handler ()
    305 {
    306     XCAM_ASSERT (!_handler.ptr ());
    307     _handler = new SampleHandler ();
    308     XCAM_ASSERT (_handler.ptr ());
    309     _handler->set_results_callback (this);
    310     return true;
    311 }
    312 
    313 void
    314 XCamSmartAnalyerContext::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results)
    315 {
    316     XCAM_UNUSED (analyzer);
    317     SmartLock  locker (_result_mutex);
    318     _results.insert (_results.end (), results.begin (), results.end ());
    319 }
    320 
    321 uint32_t
    322 XCamSmartAnalyerContext::get_results (X3aResultList &results)
    323 {
    324     uint32_t size = 0;
    325     SmartLock  locker (_result_mutex);
    326 
    327     results.assign (_results.begin (), _results.end ());
    328     size = _results.size ();
    329     _results.clear ();
    330 
    331     return size;
    332 }
    333 
    334 static XCamReturn
    335 xcam_create_context (XCamSmartAnalysisContext **context, uint32_t *async_mode, XcamPostResultsFunc post_func)
    336 {
    337     XCAM_ASSERT (context);
    338     XCAM_UNUSED (post_func);
    339     XCamSmartAnalyerContext *analysis_context = new XCamSmartAnalyerContext ();
    340     *context = ((XCamSmartAnalysisContext*)(analysis_context));
    341     *async_mode = false;
    342 
    343     return XCAM_RETURN_NO_ERROR;
    344 }
    345 
    346 static XCamReturn
    347 xcam_destroy_context (XCamSmartAnalysisContext *context)
    348 {
    349     XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context);
    350     delete analysis_context;
    351     return XCAM_RETURN_NO_ERROR;
    352 }
    353 
    354 static XCamReturn
    355 xcam_update_params (XCamSmartAnalysisContext *context, const XCamSmartAnalysisParam *params)
    356 {
    357     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    358     XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context);
    359     XCAM_ASSERT (analysis_context);
    360 
    361     SmartPtr<SampleHandler> handler = analysis_context->get_handler ();
    362     XCAM_ASSERT (handler.ptr ());
    363     XCAM_ASSERT (params);
    364 
    365     ret = handler->update_params (params);
    366     if (ret != XCAM_RETURN_NO_ERROR) {
    367         XCAM_LOG_WARNING ("update params failed");
    368     }
    369 
    370     return ret;
    371 }
    372 
    373 static XCamReturn
    374 xcam_get_results (XCamSmartAnalysisContext *context, XCam3aResultHead *results[], uint32_t *res_count)
    375 {
    376     XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context);
    377     XCAM_ASSERT (analysis_context);
    378     X3aResultList analysis_results;
    379     uint32_t result_count = analysis_context->get_results (analysis_results);
    380 
    381     if (!result_count) {
    382         *res_count = 0;
    383         XCAM_LOG_DEBUG ("Smart Analysis return no result");
    384         return XCAM_RETURN_NO_ERROR;
    385     }
    386 
    387     // mark as static
    388     static XCam3aResultHead *res_array[XCAM_3A_MAX_RESULT_COUNT];
    389     XCAM_ASSERT (result_count < XCAM_3A_MAX_RESULT_COUNT);
    390     result_count = translate_3a_results_to_xcam (analysis_results, res_array, XCAM_3A_MAX_RESULT_COUNT);
    391 
    392     for (uint32_t i = 0; i < result_count; ++i) {
    393         results[i] = res_array[i];
    394     }
    395     *res_count = result_count;
    396     XCAM_ASSERT (result_count > 0);
    397 
    398     return XCAM_RETURN_NO_ERROR;
    399 }
    400 
    401 
    402 static XCamReturn
    403 xcam_analyze (XCamSmartAnalysisContext *context, XCamVideoBuffer *buffer, XCam3aResultHead *results[], uint32_t *res_count)
    404 {
    405     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    406     if (!buffer) {
    407         return XCAM_RETURN_ERROR_PARAM;
    408     }
    409 
    410     XCamSmartAnalyerContext *analysis_context = XSMART_ANALYSIS_CONTEXT_CAST (context);
    411     XCAM_ASSERT (analysis_context);
    412 
    413     SmartPtr<SampleHandler> handler = analysis_context->get_handler ();
    414     XCAM_ASSERT (handler.ptr ());
    415 
    416     ret = handler->analyze(buffer);
    417     if (ret != XCAM_RETURN_NO_ERROR) {
    418         XCAM_LOG_WARNING ("buffer analyze failed");
    419     }
    420 
    421     xcam_get_results (context, results, res_count);
    422     return ret;
    423 }
    424 
    425 static void
    426 xcam_free_results (XCamSmartAnalysisContext *context, XCam3aResultHead *results[], uint32_t res_count)
    427 {
    428     XCAM_UNUSED (context);
    429     for (uint32_t i = 0; i < res_count; ++i) {
    430         if (results[i])
    431             free_3a_result (results[i]);
    432     }
    433 }
    434 
    435 XCAM_BEGIN_DECLARE
    436 
    437 XCamSmartAnalysisDescription xcam_smart_analysis_desciption = {
    438     XCAM_VERSION,
    439     sizeof (XCamSmartAnalysisDescription),
    440     XCAM_SMART_PLUGIN_PRIORITY_DEFAULT,
    441     "sample test",
    442     xcam_create_context,
    443     xcam_destroy_context,
    444     xcam_update_params,
    445     xcam_analyze,
    446     xcam_free_results
    447 };
    448 
    449 XCAM_END_DECLARE
    450 
    451