blob: 6b92f5d28a0ec39564eda5520425daa924b1ef55 [file] [log] [blame]
/*
* device_manager.h - device manager
*
* Copyright (c) 2014-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: Wind Yuan <feng.yuan@intel.com>
*/
#include "device_manager.h"
#include "poll_thread.h"
#include "xcam_thread.h"
#include "x3a_image_process_center.h"
#include "x3a_analyzer_manager.h"
#define XCAM_FAILED_STOP(exp, msg, ...) \
if ((exp) != XCAM_RETURN_NO_ERROR) { \
XCAM_LOG_ERROR (msg, ## __VA_ARGS__); \
stop (); \
return ret; \
}
namespace XCam {
class MessageThread
: public Thread
{
public:
explicit MessageThread (DeviceManager *dev_manager)
: Thread ("MessageThread")
, _manager (dev_manager)
{}
protected:
virtual bool loop ();
DeviceManager *_manager;
};
bool
MessageThread::loop()
{
XCamReturn ret = _manager->message_loop();
if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_ERROR_TIMEOUT)
return true;
return false;
}
XCamMessage::XCamMessage (XCamMessageType type, int64_t timestamp, const char *message)
: timestamp (timestamp)
, msg_id (type)
, msg (NULL)
{
if (message)
this->msg = strndup (message, XCAM_MAX_STR_SIZE);
}
XCamMessage::~XCamMessage ()
{
if (msg)
xcam_free (msg);
}
DeviceManager::DeviceManager()
: _has_3a (true)
, _is_running (false)
{
_3a_process_center = new X3aImageProcessCenter;
XCAM_LOG_DEBUG ("~DeviceManager construction");
}
DeviceManager::~DeviceManager()
{
XCAM_LOG_DEBUG ("~DeviceManager destruction");
}
bool
DeviceManager::set_capture_device (SmartPtr<V4l2Device> device)
{
if (is_running())
return false;
XCAM_ASSERT (device.ptr () && !_device.ptr ());
_device = device;
return true;
}
bool
DeviceManager::set_event_device (SmartPtr<V4l2SubDevice> device)
{
if (is_running())
return false;
XCAM_ASSERT (device.ptr () && !_subdevice.ptr ());
_subdevice = device;
return true;
}
bool
DeviceManager::set_3a_analyzer (SmartPtr<X3aAnalyzer> analyzer)
{
if (is_running())
return false;
XCAM_ASSERT (analyzer.ptr () && !_3a_analyzer.ptr ());
_3a_analyzer = analyzer;
return true;
}
bool
DeviceManager::set_smart_analyzer (SmartPtr<SmartAnalyzer> analyzer)
{
if (is_running())
return false;
XCAM_ASSERT (analyzer.ptr () && !_smart_analyzer.ptr ());
_smart_analyzer = analyzer;
return true;
}
bool
DeviceManager::add_image_processor (SmartPtr<ImageProcessor> processor)
{
if (is_running())
return false;
XCAM_ASSERT (processor.ptr ());
return _3a_process_center->insert_processor (processor);
}
bool
DeviceManager::set_poll_thread (SmartPtr<PollThread> thread)
{
if (is_running ())
return false;
XCAM_ASSERT (thread.ptr () && !_poll_thread.ptr ());
_poll_thread = thread;
return true;
}
XCamReturn
DeviceManager::start ()
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
// start device
XCAM_ASSERT (_device->is_opened());
if (!_device.ptr() || !_device->is_opened()) {
XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_FILE, "capture device not ready");
}
XCAM_FAILED_STOP (ret = _device->start(), "capture device start failed");
//start subdevice
//XCAM_ASSERT (_subdevice->is_opened());
if (_subdevice.ptr()) {
if (!_subdevice->is_opened())
XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_FILE, "event device not ready");
XCAM_FAILED_STOP (ret = _subdevice->start(), "start event device failed");
}
if (_has_3a) {
// Initialize and start analyzer
uint32_t width = 0, height = 0;
uint32_t fps_n = 0, fps_d = 0;
double framerate = 30.0;
if (!_3a_analyzer.ptr()) {
_3a_analyzer = X3aAnalyzerManager::instance()->create_analyzer();
if (!_3a_analyzer.ptr()) {
XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_PARAM, "create analyzer failed");
}
}
if (_3a_analyzer->prepare_handlers () != XCAM_RETURN_NO_ERROR) {
XCAM_FAILED_STOP (ret = XCAM_RETURN_ERROR_PARAM, "prepare analyzer handler failed");
}
_3a_analyzer->set_results_callback (this);
_device->get_size (width, height);
_device->get_framerate (fps_n, fps_d);
if (fps_d)
framerate = (double)fps_n / (double)fps_d;
XCAM_FAILED_STOP (
ret = _3a_analyzer->init (width, height, framerate),
"initialize analyzer failed");
XCAM_FAILED_STOP (ret = _3a_analyzer->start (), "start analyzer failed");
if (_smart_analyzer.ptr()) {
if (_smart_analyzer->prepare_handlers () != XCAM_RETURN_NO_ERROR) {
XCAM_LOG_INFO ("prepare smart analyzer handler failed");
}
_smart_analyzer->set_results_callback (this);
if (_smart_analyzer->init (width, height, framerate) != XCAM_RETURN_NO_ERROR) {
XCAM_LOG_INFO ("initialize smart analyzer failed");
}
if (_smart_analyzer->start () != XCAM_RETURN_NO_ERROR) {
XCAM_LOG_INFO ("start smart analyzer failed");
}
}
if (!_3a_process_center->has_processors ()) {
XCAM_LOG_ERROR ("image processors empty");
}
_3a_process_center->set_image_callback(this);
XCAM_FAILED_STOP (ret = _3a_process_center->start (), "3A process center start failed");
}
//Initialize and start poll thread
XCAM_ASSERT (_poll_thread.ptr ());
_poll_thread->set_capture_device (_device);
if (_subdevice.ptr ())
_poll_thread->set_event_device (_subdevice);
_poll_thread->set_poll_callback (this);
_poll_thread->set_stats_callback (this);
XCAM_FAILED_STOP (ret = _poll_thread->start(), "start poll failed");
_is_running = true;
XCAM_LOG_DEBUG ("Device manager started");
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
DeviceManager::stop ()
{
_is_running = false;
if (_poll_thread.ptr())
_poll_thread->stop ();
if (_3a_analyzer.ptr()) {
_3a_analyzer->stop ();
_3a_analyzer->deinit ();
}
if (_smart_analyzer.ptr()) {
_smart_analyzer->stop ();
_smart_analyzer->deinit ();
}
if (_3a_process_center.ptr())
_3a_process_center->stop ();
if (_subdevice.ptr ())
_subdevice->stop ();
_device->stop ();
_poll_thread.release ();
XCAM_LOG_DEBUG ("Device manager stopped");
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
DeviceManager::x3a_stats_ready (const SmartPtr<X3aStats> &stats)
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
X3aResultList results;
XCAM_ASSERT (_3a_analyzer.ptr());
ret = _3a_analyzer->push_3a_stats (stats);
XCAM_FAIL_RETURN (ERROR,
ret == XCAM_RETURN_NO_ERROR,
ret,
"analyze 3a statistics failed");
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
DeviceManager::dvs_stats_ready ()
{
XCAM_ASSERT (false);
// TODO
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
DeviceManager::scaled_image_ready (const SmartPtr<VideoBuffer> &buffer)
{
XCamReturn ret = XCAM_RETURN_NO_ERROR;
if (!_smart_analyzer.ptr()) {
return XCAM_RETURN_NO_ERROR;
}
ret = _smart_analyzer->push_buffer (buffer);
XCAM_FAIL_RETURN (
ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
"push frame buffer failed");
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
DeviceManager::poll_buffer_ready (SmartPtr<VideoBuffer> &buf)
{
if (_has_3a) {
if (_3a_process_center->put_buffer (buf) == false)
return XCAM_RETURN_ERROR_UNKNOWN;
}
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
DeviceManager::poll_buffer_failed (int64_t timestamp, const char *msg)
{
post_message (XCAM_MESSAGE_BUF_ERROR, timestamp, msg);
return XCAM_RETURN_NO_ERROR;
}
void
DeviceManager::x3a_calculation_done (XAnalyzer *analyzer, X3aResultList &results)
{
XCamReturn ret = _3a_process_center->put_3a_results (results);
if (ret != XCAM_RETURN_NO_ERROR && ret != XCAM_RETURN_BYPASS) {
XCAM_LOG_WARNING ("apply 3a results failed");
return;
}
AnalyzerCallback::x3a_calculation_done (analyzer, results);
}
void
DeviceManager::x3a_calculation_failed (XAnalyzer *analyzer, int64_t timestamp, const char *msg)
{
AnalyzerCallback::x3a_calculation_failed (analyzer, timestamp, msg);
}
void
DeviceManager::process_buffer_done (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf)
{
ImageProcessCallback::process_buffer_done (processor, buf);
handle_buffer (buf);
}
void
DeviceManager::process_buffer_failed (ImageProcessor *processor, const SmartPtr<VideoBuffer> &buf)
{
ImageProcessCallback::process_buffer_failed (processor, buf);
}
void
DeviceManager::process_image_result_done (ImageProcessor *processor, const SmartPtr<X3aResult> &result)
{
ImageProcessCallback::process_image_result_done (processor, result);
}
void
DeviceManager::post_message (XCamMessageType type, int64_t timestamp, const char *msg)
{
SmartPtr<XCamMessage> new_msg = new XCamMessage (type, timestamp, msg);
_msg_queue.push (new_msg);
}
XCamReturn
DeviceManager::message_loop ()
{
const static int32_t msg_time_out = -1; //wait until wakeup
SmartPtr<XCamMessage> msg = _msg_queue.pop (msg_time_out);
if (!msg.ptr ())
return XCAM_RETURN_ERROR_THREAD;
handle_message (msg);
return XCAM_RETURN_NO_ERROR;
}
};