blob: 9a6c0a7fee9fe0ecf0005d8dee3fc2203c62aac1 [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_VIDEO_OMX_VIDEO_DECODE_ENGINE_H_
#define MEDIA_VIDEO_OMX_VIDEO_DECODE_ENGINE_H_
#include <queue>
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/scoped_ptr.h"
#include "media/omx/omx_configurator.h"
#include "media/video/video_decode_engine.h"
#include "third_party/openmax/il/OMX_Component.h"
#include "third_party/openmax/il/OMX_Core.h"
#include "third_party/openmax/il/OMX_Video.h"
namespace media {
class OmxVideoDecodeEngine : public VideoDecodeEngine {
public:
OmxVideoDecodeEngine();
virtual ~OmxVideoDecodeEngine();
// Implementation of the VideoDecodeEngine Interface.
virtual void Initialize(MessageLoop* message_loop,
VideoDecodeEngine::EventHandler* event_handler,
VideoDecodeContext* context,
const VideoCodecConfig& config);
virtual void ConsumeVideoSample(scoped_refptr<Buffer> buffer);
virtual void ProduceVideoFrame(scoped_refptr<VideoFrame> frame);
virtual void Uninitialize();
virtual void Flush();
virtual void Seek();
// Subclass can provide a different value.
virtual int current_omx_spec_version() const;
private:
enum OmxIlState {
kIlNone,
kIlLoaded,
kIlIdle,
kIlExecuting,
kIlPause,
kIlInvalid,
kIlUnknown,
};
enum OmxIlClientState {
kClientNotInitialized,
kClientInitializing,
kClientRunning,
kClientStopping,
kClientStopped,
kClientPausing,
kClientFlushing,
kClientError,
};
enum OmxIlPortState {
kPortDisabled,
kPortEnabling,
kPortEnabled,
kPortDisabling,
};
typedef Callback0::Type Callback;
// calls into other classes
void FinishEmptyBuffer(scoped_refptr<Buffer> buffer);
void FinishFillBuffer(OMX_BUFFERHEADERTYPE* buffer);
// Helper method to perform tasks when this object is stopped.
void OnStopDone();
// Transition method sequence for initialization
bool CreateComponent();
void DoneSetStateIdle(OMX_STATETYPE state);
void DoneSetStateExecuting(OMX_STATETYPE state);
void OnPortSettingsChangedRun(int port, OMX_INDEXTYPE index);
void OnPortDisableEventRun(int port);
void SetupOutputPort();
void OnPortEnableEventRun(int port);
// Transition methods for shutdown
void DeinitFromExecuting(OMX_STATETYPE state);
void DeinitFromIdle(OMX_STATETYPE state);
void DeinitFromLoaded(OMX_STATETYPE state);
void PauseFromExecuting(OMX_STATETYPE state);
void StartFlush();
void PortFlushDone(int port);
void ComponentFlushDone();
void StopOnError();
void InitializeTask();
// Methods to free input and output buffers.
bool AllocateInputBuffers();
bool AllocateOutputBuffers();
void FreeInputBuffers();
void FreeOutputBuffers();
void FreeInputQueue();
// Helper method to configure port format at LOADED state.
bool ConfigureIOPorts();
// Determine whether we can issue fill buffer or empty buffer
// to the decoder based on the current state and port state.
bool CanEmptyBuffer();
bool CanFillBuffer();
// Determine whether we can use |input_queue_| and |output_queue_|
// based on the current state.
bool CanAcceptInput();
bool CanAcceptOutput();
bool InputPortFlushed();
bool OutputPortFlushed();
// Method to send input buffers to component
void EmptyBufferTask();
// Method doing initial reads to get bit stream from demuxer.
void InitialReadBuffer();
// Method doing initial fills to kick start the decoding process.
void InitialFillBuffer();
// helper functions
void ChangePort(OMX_COMMANDTYPE cmd, int port_index);
OMX_BUFFERHEADERTYPE* FindOmxBuffer(scoped_refptr<VideoFrame> video_frame);
OMX_STATETYPE GetComponentState();
void SendOutputBufferToComponent(OMX_BUFFERHEADERTYPE *omx_buffer);
bool TransitionToState(OMX_STATETYPE new_state);
virtual VideoFrame::Format GetSurfaceFormat() const;
// Method to handle events
void EventHandlerCompleteTask(OMX_EVENTTYPE event,
OMX_U32 data1,
OMX_U32 data2);
// Method to receive buffers from component's input port
void EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer);
// Method to receive buffers from component's output port
void FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer);
// The following three methods are static callback methods
// for the OMX component. When these callbacks are received, the
// call is delegated to the three internal methods above.
static OMX_ERRORTYPE EventHandler(OMX_HANDLETYPE component,
OMX_PTR priv_data,
OMX_EVENTTYPE event,
OMX_U32 data1, OMX_U32 data2,
OMX_PTR event_data);
static OMX_ERRORTYPE EmptyBufferCallback(OMX_HANDLETYPE component,
OMX_PTR priv_data,
OMX_BUFFERHEADERTYPE* buffer);
static OMX_ERRORTYPE FillBufferCallback(OMX_HANDLETYPE component,
OMX_PTR priv_data,
OMX_BUFFERHEADERTYPE* buffer);
// Member function pointers to respond to events
void (OmxVideoDecodeEngine::*OnPortDisableEventFunc)(int port);
void (OmxVideoDecodeEngine::*OnPortEnableEventFunc)(int port);
void (OmxVideoDecodeEngine::*OnStateSetEventFunc)(OMX_STATETYPE state);
void (OmxVideoDecodeEngine::*OnFlushEventFunc)(int port);
// Helper function
scoped_refptr<VideoFrame> CreateOmxBufferVideoFrame(
OMX_BUFFERHEADERTYPE* omx_buffer);
size_t width_;
size_t height_;
MessageLoop* message_loop_;
std::vector<OMX_BUFFERHEADERTYPE*> input_buffers_;
int input_buffer_count_;
int input_buffer_size_;
int input_port_;
int input_buffers_at_component_;
int input_pending_request_;
bool input_queue_has_eos_;
bool input_has_fed_eos_;
bool input_port_flushed_;
int output_buffer_count_;
int output_buffer_size_;
int output_port_;
int output_buffers_at_component_;
int output_pending_request_;
bool output_eos_;
bool output_port_flushed_;
bool uses_egl_image_;
base::TimeDelta last_pts_;
// |il_state_| records the current component state. During state transition
// |expected_il_state_| is the next state that the component will transition
// to. After a state transition is completed, |il_state_| equals
// |expected_il_state_|. Inequality can be used to detect a state transition.
// These two members are read and written only on |message_loop_|.
OmxIlState il_state_;
OmxIlState expected_il_state_;
OmxIlClientState client_state_;
OMX_HANDLETYPE component_handle_;
scoped_ptr<media::OmxConfigurator> configurator_;
// Free input OpenMAX buffers that can be used to take input bitstream from
// demuxer.
std::queue<OMX_BUFFERHEADERTYPE*> free_input_buffers_;
// Available input OpenMAX buffers that we can use to issue
// OMX_EmptyThisBuffer() call.
std::queue<OMX_BUFFERHEADERTYPE*> available_input_buffers_;
// flag for freeing input/output buffers
bool need_free_input_buffers_;
bool need_free_output_buffers_;
// for calling flush callback only once.
bool flush_pending_;
// For output buffer recycling cases.
typedef std::pair<scoped_refptr<VideoFrame>,
OMX_BUFFERHEADERTYPE*> OutputFrame;
std::vector<OutputFrame> output_frames_;
bool output_frames_allocated_;
// port related
bool need_setup_output_port_;
OmxIlPortState output_port_state_;
VideoDecodeEngine::EventHandler* event_handler_;
DISALLOW_COPY_AND_ASSIGN(OmxVideoDecodeEngine);
};
} // namespace media
#endif // MEDIA_VIDEO_OMX_VIDEO_DECODE_ENGINE_H_