/*
* smart_analysis_handler.cpp - smart analysis handler
*
* Copyright (c) 2015 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Zong Wei <wei.zong@intel.com>
* Wind Yuan <feng.yuan@intel.com>
*/
#include "smart_analysis_handler.h"
#include "smart_analyzer_loader.h"
#include "smart_analyzer.h"
#include "video_buffer.h"
namespace XCam {
SmartAnalysisHandler::SmartHandlerMap SmartAnalysisHandler::_handler_map;
Mutex SmartAnalysisHandler::_handler_map_lock;
SmartAnalysisHandler::SmartAnalysisHandler (XCamSmartAnalysisDescription *desc, SmartPtr<SmartAnalyzerLoader> &loader, const char *name)
: _desc (desc)
, _loader (loader)
, _analyzer (NULL)
, _name (NULL)
, _context (NULL)
, _async_mode (false)
{
if (name)
_name = strndup (name, XCAM_MAX_STR_SIZE);
}
SmartAnalysisHandler::~SmartAnalysisHandler ()
{
if (is_valid ())
destroy_context ();
if (_name)
xcam_free (_name);
}
XCamReturn
SmartAnalysisHandler::create_context (SmartPtr<SmartAnalysisHandler> &self)
{
XCamSmartAnalysisContext *context = NULL;
XCamReturn ret = XCAM_RETURN_NO_ERROR;
uint32_t async_mode = 0;
XCAM_ASSERT (!_context);
XCAM_ASSERT (self.ptr () == this);
if ((ret = _desc->create_context (&context, &async_mode, NULL)) != XCAM_RETURN_NO_ERROR) {
XCAM_LOG_WARNING ("smart handler(%s) lib create context failed", XCAM_STR(get_name()));
return ret;
}
if (!context) {
XCAM_LOG_WARNING ("smart handler(%s) lib create context failed with NULL context", XCAM_STR(get_name()));
return XCAM_RETURN_ERROR_UNKNOWN;
}
_async_mode = async_mode;
XCAM_LOG_INFO ("create smart analysis context(%s)", XCAM_STR(get_name()));
SmartLock locker (_handler_map_lock);
_handler_map[context] = self;
_context = context;
return XCAM_RETURN_NO_ERROR;
}
void
SmartAnalysisHandler::destroy_context ()
{
XCamSmartAnalysisContext *context;
{
SmartLock locker (_handler_map_lock);
context = _context;
_context = NULL;
if (context)
_handler_map.erase (context);
}
if (context && _desc && _desc->destroy_context) {
_desc->destroy_context (context);
XCAM_LOG_INFO ("destroy smart analysis context(%s)", XCAM_STR(get_name()));
}
}
XCamReturn
SmartAnalysisHandler::post_aync_results (
XCamSmartAnalysisContext *context,
const XCamVideoBuffer *buffer,
XCam3aResultHead *results[], uint32_t res_count)
{
SmartPtr<SmartAnalysisHandler> handler = NULL;
XCAM_ASSERT (context);
{
SmartLock locker (_handler_map_lock);
SmartHandlerMap::iterator i_h = _handler_map.find (context);
if (i_h != _handler_map.end ())
handler = i_h->second;
}
if (!handler.ptr ()) {
XCAM_LOG_WARNING ("can't find a proper smart analyzer handler, please check context pointer");
return XCAM_RETURN_ERROR_PARAM;
}
return handler->post_smart_results (buffer, results, res_count);
}
XCamReturn
SmartAnalysisHandler::post_smart_results (const XCamVideoBuffer *buffer, XCam3aResultHead *results[], uint32_t res_count)
{
X3aResultList result_list;
XCamReturn ret = convert_results (results, res_count, result_list);
XCAM_FAIL_RETURN (
WARNING,
ret == XCAM_RETURN_NO_ERROR,
ret,
"smart handler convert results failed in async mode");
if (_analyzer)
_analyzer->post_smart_results (result_list, (buffer ? buffer->timestamp : InvalidTimestamp));
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
SmartAnalysisHandler::update_params (XCamSmartAnalysisParam ¶ms)
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
XCAM_ASSERT (_context);
ret = _desc->update_params (_context, ¶ms);
XCAM_FAIL_RETURN (WARNING,
ret == XCAM_RETURN_NO_ERROR,
ret,
"smart handler(%s) update parameters failed", XCAM_STR(get_name()));
return ret;
}
XCamReturn
SmartAnalysisHandler::analyze (const SmartPtr<VideoBuffer> &buffer, X3aResultList &results)
{
XCAM_LOG_DEBUG ("smart handler(%s) analyze", XCAM_STR(get_name()));
XCamReturn ret = XCAM_RETURN_NO_ERROR;
XCamVideoBuffer *video_buffer = convert_to_external_buffer (buffer);
XCam3aResultHead *res_array[XCAM_3A_MAX_RESULT_COUNT];
uint32_t res_count = XCAM_3A_MAX_RESULT_COUNT;
XCAM_ASSERT (buffer.ptr ());
XCAM_ASSERT (_context);
XCAM_ASSERT (video_buffer);
xcam_mem_clear (res_array);
ret = _desc->analyze (_context, video_buffer, res_array, &res_count);
XCAM_ASSERT (video_buffer->unref);
video_buffer->unref (video_buffer);
XCAM_FAIL_RETURN (WARNING,
ret == XCAM_RETURN_NO_ERROR,
ret,
"smart handler(%s) calculation failed", XCAM_STR(get_name()));
if (res_count > 0 && res_array[0]) {
ret = convert_results (res_array, res_count, results);
XCAM_FAIL_RETURN (WARNING,
ret == XCAM_RETURN_NO_ERROR,
ret,
"smart handler(%s) convert_results failed", XCAM_STR(get_name()));
_desc->free_results (_context, res_array, res_count);
}
return ret;
}
XCamReturn
SmartAnalysisHandler::convert_results (XCam3aResultHead *from[], uint32_t from_count, X3aResultList &to)
{
for (uint32_t i = 0; i < from_count; ++i) {
SmartPtr<X3aResult> standard_res =
X3aResultFactory::instance ()->create_3a_result (from[i]);
to.push_back (standard_res);
}
return XCAM_RETURN_NO_ERROR;
}
}