/* * 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 */ #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 device) { if (is_running()) return false; XCAM_ASSERT (device.ptr () && !_device.ptr ()); _device = device; return true; } bool DeviceManager::set_event_device (SmartPtr device) { if (is_running()) return false; XCAM_ASSERT (device.ptr () && !_subdevice.ptr ()); _subdevice = device; return true; } bool DeviceManager::set_3a_analyzer (SmartPtr analyzer) { if (is_running()) return false; XCAM_ASSERT (analyzer.ptr () && !_3a_analyzer.ptr ()); _3a_analyzer = analyzer; return true; } bool DeviceManager::set_smart_analyzer (SmartPtr analyzer) { if (is_running()) return false; XCAM_ASSERT (analyzer.ptr () && !_smart_analyzer.ptr ()); _smart_analyzer = analyzer; return true; } bool DeviceManager::add_image_processor (SmartPtr processor) { if (is_running()) return false; XCAM_ASSERT (processor.ptr ()); return _3a_process_center->insert_processor (processor); } bool DeviceManager::set_poll_thread (SmartPtr 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 &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 &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 &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 &buf) { ImageProcessCallback::process_buffer_done (processor, buf); handle_buffer (buf); } void DeviceManager::process_buffer_failed (ImageProcessor *processor, const SmartPtr &buf) { ImageProcessCallback::process_buffer_failed (processor, buf); } void DeviceManager::process_image_result_done (ImageProcessor *processor, const SmartPtr &result) { ImageProcessCallback::process_image_result_done (processor, result); } void DeviceManager::post_message (XCamMessageType type, int64_t timestamp, const char *msg) { SmartPtr 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 msg = _msg_queue.pop (msg_time_out); if (!msg.ptr ()) return XCAM_RETURN_ERROR_THREAD; handle_message (msg); return XCAM_RETURN_NO_ERROR; } };