Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Unified Diff: media/filters/omx_video_decode_engine.cc

Issue 3014059: media: recycle buffers/direct rendering etc. (third patch) (Closed)
Patch Set: code review Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/omx_video_decode_engine.h ('k') | media/filters/video_renderer_base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/omx_video_decode_engine.cc
diff --git a/media/filters/omx_video_decode_engine.cc b/media/filters/omx_video_decode_engine.cc
index b1d7762721f4763ea633e20cfa54745e8d320b14..358e00587369671f4cef045b9208d5b344ab952e 100644
--- a/media/filters/omx_video_decode_engine.cc
+++ b/media/filters/omx_video_decode_engine.cc
@@ -16,17 +16,10 @@
#include "media/filters/omx_video_decode_engine.h"
-#include <algorithm>
-#include <string>
-
-#include "base/callback.h"
#include "base/logging.h"
#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "media/base/buffers.h"
-#include "media/base/callback.h"
-#include "media/ffmpeg/ffmpeg_common.h"
namespace media {
@@ -41,15 +34,21 @@ OmxVideoDecodeEngine::OmxVideoDecodeEngine()
input_pending_request_(0),
input_queue_has_eos_(false),
input_has_fed_eos_(false),
+ input_port_flushed_(false),
output_buffer_count_(0),
output_buffer_size_(0),
output_port_(0),
+ output_buffers_at_component_(0),
+ output_pending_request_(0),
output_eos_(false),
+ output_port_flushed_(false),
il_state_(kIlNone),
expected_il_state_(kIlNone),
client_state_(kClientNotInitialized),
component_handle_(NULL),
need_free_input_buffers_(false),
+ need_free_output_buffers_(false),
+ flush_pending_(false),
output_frames_allocated_(false),
need_setup_output_port_(false) {
// TODO(wjia): change uses_egl_image_ to runtime setup
@@ -67,13 +66,11 @@ OmxVideoDecodeEngine::~OmxVideoDecodeEngine() {
client_state_ == kClientStopped);
DCHECK_EQ(il_state_, kIlNone);
DCHECK_EQ(0u, input_buffers_.size());
- DCHECK_EQ(0u, output_buffers_.size());
DCHECK(free_input_buffers_.empty());
DCHECK(available_input_buffers_.empty());
DCHECK_EQ(0, input_buffers_at_component_);
+ DCHECK_EQ(0, output_buffers_at_component_);
DCHECK(output_frames_.empty());
- DCHECK(available_output_frames_.empty());
- DCHECK(output_frames_ready_.empty());
}
template <typename T>
@@ -126,6 +123,7 @@ void OmxVideoDecodeEngine::Initialize(
void OmxVideoDecodeEngine::EmptyThisBuffer(scoped_refptr<Buffer> buffer) {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK(!free_input_buffers_.empty());
+ DCHECK_GT(input_pending_request_, 0);
--input_pending_request_;
@@ -146,7 +144,10 @@ void OmxVideoDecodeEngine::EmptyThisBuffer(scoped_refptr<Buffer> buffer) {
omx_buffer->pBuffer = const_cast<OMX_U8*>(buffer->GetData());
omx_buffer->nFilledLen = buffer->GetDataSize();
omx_buffer->nAllocLen = omx_buffer->nFilledLen;
- omx_buffer->nFlags |= input_queue_has_eos_ ? OMX_BUFFERFLAG_EOS : 0;
+ if (input_queue_has_eos_)
+ omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;
+ else
+ omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
omx_buffer->nTimeStamp = buffer->GetTimestamp().InMicroseconds();
omx_buffer->pAppPrivate = buffer.get();
buffer->AddRef();
@@ -155,7 +156,7 @@ void OmxVideoDecodeEngine::EmptyThisBuffer(scoped_refptr<Buffer> buffer) {
// Try to feed buffers into the decoder.
EmptyBufferTask();
- if (il_state_ == kIlPause && input_pending_request_ == 0)
+ if (flush_pending_ && input_pending_request_ == 0)
StartFlush();
}
@@ -163,8 +164,12 @@ void OmxVideoDecodeEngine::Flush() {
DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(il_state_, kIlExecuting);
- client_state_ = kClientFlushing;
+ if (il_state_ != kIlExecuting) {
+ event_handler_->OnFlushComplete();
+ return;
+ }
+ client_state_ = kClientFlushing;
expected_il_state_ = kIlPause;
OnStateSetEventFunc = &OmxVideoDecodeEngine::PauseFromExecuting;
TransitionToState(OMX_StatePause);
@@ -176,37 +181,32 @@ void OmxVideoDecodeEngine::PauseFromExecuting(OMX_STATETYPE state) {
OnStateSetEventFunc = NULL;
il_state_ = kIlPause;
- if (input_pending_request_ == 0 ) {
+ if (input_pending_request_ == 0)
StartFlush();
- }
+ else
+ flush_pending_ = true;
}
void OmxVideoDecodeEngine::StartFlush() {
DCHECK_EQ(message_loop_, MessageLoop::current());
-
- if (client_state_ != kClientFlushing) {
- // TODO(jiesun): how to prevent initial seek.
- event_handler_->OnFlushComplete();
- return;
- }
-
- // TODO(jiesun): return buffers to filter who allocate them.
- while (!output_frames_ready_.empty())
- output_frames_ready_.pop();
+ DCHECK_EQ(input_pending_request_, 0);
+ DLOG(INFO) << "StartFlush";
while (!available_input_buffers_.empty())
available_input_buffers_.pop();
- input_port_flushed_ = false;
- output_port_flushed_ = false;
+ flush_pending_ = false;
+
+ // Flush input port first.
OnFlushEventFunc = &OmxVideoDecodeEngine::PortFlushDone;
OMX_ERRORTYPE omxresult;
omxresult = OMX_SendCommand(component_handle_,
OMX_CommandFlush,
- OMX_ALL, 0);
+ input_port_, 0);
}
bool OmxVideoDecodeEngine::InputPortFlushed() {
+ DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(client_state_, kClientFlushing);
// Port flushed is defined by OpenMAX component had signal flush done and
// We had all buffers returned from demuxer and OpenMAX component.
@@ -215,40 +215,64 @@ bool OmxVideoDecodeEngine::InputPortFlushed() {
}
bool OmxVideoDecodeEngine::OutputPortFlushed() {
+ DCHECK_EQ(message_loop_, MessageLoop::current());
DCHECK_EQ(client_state_, kClientFlushing);
// Port flushed is defined by OpenMAX component had signal flush done and
// We had all buffers returned from renderer and OpenMAX component.
- // TODO(jiesun): egl image path may use different value.
- return output_port_flushed_ /*&&
- available_output_frames_.size() == output_buffer_count_*/;
+ return output_port_flushed_ && output_pending_request_ == 0;
}
void OmxVideoDecodeEngine::ComponentFlushDone() {
- // use these flags to ensure only callback once.
+ DCHECK_EQ(message_loop_, MessageLoop::current());
+ DLOG(INFO) << "Component had been flushed!";
+
if (input_port_flushed_ && output_port_flushed_) {
event_handler_->OnFlushComplete();
input_port_flushed_ = false;
output_port_flushed_ = false;
-
- InitialReadBuffer();
- OnStateSetEventFunc = &OmxVideoDecodeEngine::DoneSetStateExecuting;
- TransitionToState(OMX_StateExecuting);
}
}
void OmxVideoDecodeEngine::PortFlushDone(int port) {
- if (port == input_port_ || port == static_cast<int>(OMX_ALL))
+ DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_NE(port, static_cast<int>(OMX_ALL));
+
+ if (port == input_port_) {
+ DLOG(INFO) << "Input Port had been flushed";
+ DCHECK_EQ(input_buffers_at_component_, 0);
input_port_flushed_ = true;
- if (port == output_port_ || port == static_cast<int>(OMX_ALL))
+ // Flush output port next.
+ OMX_ERRORTYPE omxresult;
+ omxresult = OMX_SendCommand(component_handle_,
+ OMX_CommandFlush,
+ output_port_, 0);
+ return;
+ }
+
+ if (port == output_port_) {
+ DLOG(INFO) << "Output Port had been flushed";
+ DCHECK_EQ(output_buffers_at_component_, 0);
+
output_port_flushed_ = true;
+ }
- if (InputPortFlushed() && OutputPortFlushed())
+ if (kClientFlushing == client_state_ &&
+ InputPortFlushed() && OutputPortFlushed())
ComponentFlushDone();
}
void OmxVideoDecodeEngine::Seek() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- // TODO(jiesun): add real logic here.
+
+ DCHECK(client_state_ == kClientFlushing || // After a flush
+ client_state_ == kClientInitializing); // After an initialize.
+
+ if (client_state_ == kClientFlushing) {
+ InitialReadBuffer();
+ OnStateSetEventFunc = &OmxVideoDecodeEngine::DoneSetStateExecuting;
+ TransitionToState(OMX_StateExecuting);
+ }
+
event_handler_->OnSeekComplete();
}
@@ -267,7 +291,7 @@ void OmxVideoDecodeEngine::Uninitialize() {
}
// TODO(wjia): add more state checking
- if (kClientRunning == client_state_) {
+ if (kClientRunning == client_state_ || kClientFlushing == client_state_) {
client_state_ = kClientStopping;
DeinitFromExecuting(OMX_StateExecuting);
}
@@ -277,13 +301,6 @@ void OmxVideoDecodeEngine::Uninitialize() {
// client_state_ = kClientStopping;
}
-void OmxVideoDecodeEngine::OnFormatChange(
- const OmxConfigurator::MediaFormat& input_format,
- const OmxConfigurator::MediaFormat& output_format) {
- // TODO(jiesun): We should not need this for here, because width and height
- // are already known from upper layer of the stack.
-}
-
void OmxVideoDecodeEngine::FinishEmptyBuffer(scoped_refptr<Buffer> buffer) {
DCHECK_EQ(message_loop_, MessageLoop::current());
@@ -295,43 +312,20 @@ void OmxVideoDecodeEngine::FinishEmptyBuffer(scoped_refptr<Buffer> buffer) {
void OmxVideoDecodeEngine::FinishFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK(buffer);
scoped_refptr<VideoFrame> frame;
- // EOF
- if (!buffer) {
- VideoFrame::CreateEmptyFrame(&frame);
- event_handler_->OnFillBufferCallback(frame);
- return;
- }
-
- if (uses_egl_image_) {
- frame = static_cast<VideoFrame*>(buffer->pAppPrivate);
- } else {
- VideoFrame::CreateFrame(GetSurfaceFormat(),
- width_, height_,
- StreamSample::kInvalidTimestamp,
- StreamSample::kInvalidTimestamp,
- &frame);
- if (!frame.get()) {
- // TODO(jiesun): this is also an error case handled as normal.
- return;
- }
+ frame = static_cast<VideoFrame*>(buffer->pAppPrivate);
- // TODO(jiesun): Assume YUV 420 format.
- const int pixels = width_ * height_;
- memcpy(frame->data(VideoFrame::kYPlane), buffer->pBuffer, pixels);
- memcpy(frame->data(VideoFrame::kUPlane), buffer->pBuffer + pixels,
- pixels / 4);
- memcpy(frame->data(VideoFrame::kVPlane),
- buffer->pBuffer + pixels + pixels / 4,
- pixels / 4);
- }
+ // We should not flush buffer to renderer during decoder flushing if decoder
+ // provides the buffer allocator.
+ if (kClientFlushing == client_state_ && !uses_egl_image_) return;
frame->SetTimestamp(base::TimeDelta::FromMicroseconds(buffer->nTimeStamp));
frame->SetDuration(frame->GetTimestamp() - last_pts_);
last_pts_ = frame->GetTimestamp();
-
event_handler_->OnFillBufferCallback(frame);
+ output_pending_request_--;
}
void OmxVideoDecodeEngine::OnStopDone() {
@@ -346,7 +340,6 @@ void OmxVideoDecodeEngine::InitializeTask() {
il_state_ = kIlNone;
expected_il_state_ = kIlLoaded;
- input_port_enabled_ = true;
output_port_state_ = kPortEnabled;
if (!CreateComponent()) {
StopOnError();
@@ -587,7 +580,8 @@ void OmxVideoDecodeEngine::DoneSetStateIdle(OMX_STATETYPE state) {
// Event callback during initialization to handle DoneStateSet to executing
void OmxVideoDecodeEngine::DoneSetStateExecuting(OMX_STATETYPE state) {
DCHECK_EQ(message_loop_, MessageLoop::current());
- DCHECK_EQ(client_state_, kClientInitializing);
+ DCHECK(client_state_ == kClientInitializing ||
+ client_state_ == kClientFlushing);
DCHECK_EQ(OMX_StateExecuting, state);
DLOG(INFO) << "OMX video decode engine is in Executing";
@@ -606,13 +600,14 @@ void OmxVideoDecodeEngine::DoneSetStateExecuting(OMX_STATETYPE state) {
// and outside allocator.
void OmxVideoDecodeEngine::FillThisBuffer(
scoped_refptr<VideoFrame> video_frame) {
-
- // TODO(wjia): merge buffer recycling for EGLImage and system memory path.
- if (!video_frame.get() || VideoFrame::TYPE_EGL_IMAGE != video_frame->type())
- return;
+ DCHECK(video_frame.get() && !video_frame->IsEndOfStream());
+ output_pending_request_++;
if (!CanAcceptOutput()) {
- event_handler_->OnFillBufferCallback(video_frame);
+ if (uses_egl_image_) { // return it to owner.
+ output_pending_request_--;
+ event_handler_->OnFillBufferCallback(video_frame);
+ }
return;
}
@@ -620,11 +615,17 @@ void OmxVideoDecodeEngine::FillThisBuffer(
if (omx_buffer) {
if (kClientRunning == client_state_) {
SendOutputBufferToComponent(omx_buffer);
- } else {
- available_output_frames_.push(omx_buffer);
+ } else if (kClientFlushing == client_state_) {
+ if (uses_egl_image_) { // return it to owner.
+ output_pending_request_--;
+ event_handler_->OnFillBufferCallback(video_frame);
+ }
+ if (InputPortFlushed() && OutputPortFlushed())
+ ComponentFlushDone();
}
} else {
DCHECK(!output_frames_allocated_);
+ DCHECK(uses_egl_image_);
output_frames_.push_back(std::make_pair(video_frame,
static_cast<OMX_BUFFERHEADERTYPE*>(NULL)));
}
@@ -690,7 +691,6 @@ void OmxVideoDecodeEngine::OnPortSettingsChangedRun(int port,
output_format.video_header.height = port_format.format.video.nFrameHeight;
output_format.video_header.width = port_format.format.video.nFrameWidth;
output_format.video_header.stride = port_format.format.video.nStride;
- // OnFormatChange(input_format, output_format);
output_buffer_count_ = port_format.nBufferCountActual;
output_buffer_size_ = port_format.nBufferSize;
@@ -794,7 +794,10 @@ void OmxVideoDecodeEngine::DeinitFromIdle(OMX_STATETYPE state) {
else
need_free_input_buffers_ = true;
- FreeOutputBuffers();
+ if (!output_buffers_at_component_)
+ FreeOutputBuffers();
+ else
+ need_free_output_buffers_ = true;
}
void OmxVideoDecodeEngine::DeinitFromLoaded(OMX_STATETYPE state) {
@@ -831,6 +834,11 @@ void OmxVideoDecodeEngine::StopOnError() {
DeinitFromIdle(OMX_StateIdle);
} else if (kIlLoaded == expected_il_state_) {
DeinitFromLoaded(OMX_StateLoaded);
+ } else if (kIlPause == expected_il_state_) {
+ // TODO(jiesun): Make sure this works.
+ DeinitFromExecuting(OMX_StateExecuting);
+ } else {
+ NOTREACHED();
}
}
@@ -862,7 +870,6 @@ bool OmxVideoDecodeEngine::AllocateInputBuffers() {
// allocation case is similar to EGLImage
bool OmxVideoDecodeEngine::AllocateOutputBuffers() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- // DCHECK_EQ(output_buffer_count_, static_cast<int>(output_frames_.size()));
if (uses_egl_image_ && !output_frames_allocated_) {
DLOG(INFO) << "Output frames are not allocated yet";
@@ -872,30 +879,59 @@ bool OmxVideoDecodeEngine::AllocateOutputBuffers() {
for (int i = 0; i < output_buffer_count_; ++i) {
OMX_BUFFERHEADERTYPE* buffer;
+ scoped_refptr<VideoFrame> video_frame;
OMX_ERRORTYPE error;
if (uses_egl_image_) {
OutputFrame output_frame = output_frames_[i];
- scoped_refptr<VideoFrame> video_frame = output_frame.first;
+ video_frame = output_frame.first;
DCHECK(!output_frame.second);
error = OMX_UseEGLImage(component_handle_, &buffer, output_port_,
video_frame.get(), video_frame->private_buffer());
if (error != OMX_ErrorNone)
return false;
output_frames_[i].second = buffer;
- available_output_frames_.push(buffer);
} else {
- error =
- OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
- NULL, output_buffer_size_);
+ error = OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
+ NULL, output_buffer_size_);
if (error != OMX_ErrorNone)
return false;
- output_buffers_.push_back(buffer);
+ video_frame = CreateOmxBufferVideoFrame(buffer);
+ output_frames_.push_back(std::make_pair(video_frame, buffer));
+ buffer->pAppPrivate = video_frame.get();
}
}
return true;
}
+scoped_refptr<VideoFrame> OmxVideoDecodeEngine::CreateOmxBufferVideoFrame(
+ OMX_BUFFERHEADERTYPE* omx_buffer) {
+ scoped_refptr<VideoFrame> video_frame;
+ uint8* data[VideoFrame::kMaxPlanes];
+ int32 strides[VideoFrame::kMaxPlanes];
+
+ memset(data, 0, sizeof(data));
+ memset(strides, 0, sizeof(strides));
+ // TODO(jiesun): chroma format 4:2:0 only and 3 planes.
+ data[0] = omx_buffer->pBuffer;
+ data[1] = data[0] + width_ * height_;
+ data[2] = data[1] + width_ * height_ / 4;
+ strides[0] = width_;
+ strides[1] = strides[2] = width_ >> 1;
+
+ VideoFrame::CreateFrameExternal(
+ VideoFrame::TYPE_OMXBUFFERHEAD,
+ VideoFrame::YV12,
+ width_, height_, 3,
+ data, strides,
+ StreamSample::kInvalidTimestamp,
+ StreamSample::kInvalidTimestamp,
+ omx_buffer,
+ &video_frame);
+
+ return video_frame;
+}
+
void OmxVideoDecodeEngine::FreeInputBuffers() {
DCHECK_EQ(message_loop_, MessageLoop::current());
@@ -916,26 +952,23 @@ void OmxVideoDecodeEngine::FreeInputBuffers() {
for (size_t i = 0; i < input_buffers_.size(); ++i)
OMX_FreeBuffer(component_handle_, input_port_, input_buffers_[i]);
input_buffers_.clear();
+
+ need_free_input_buffers_ = false;
}
void OmxVideoDecodeEngine::FreeOutputBuffers() {
DCHECK_EQ(message_loop_, MessageLoop::current());
// Calls to OMX to free buffers.
- if (uses_egl_image_) {
- for (size_t i = 0; i < output_frames_.size(); ++i) {
- OMX_BUFFERHEADERTYPE* omx_buffer = output_frames_[i].second;
- if (omx_buffer) {
- OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
- }
- }
- output_frames_.clear();
- output_frames_allocated_ = false;
- } else {
- for (size_t i = 0; i < output_buffers_.size(); ++i)
- OMX_FreeBuffer(component_handle_, output_port_, output_buffers_[i]);
- output_buffers_.clear();
+ for (size_t i = 0; i < output_frames_.size(); ++i) {
+ OMX_BUFFERHEADERTYPE* omx_buffer = output_frames_[i].second;
+ CHECK(omx_buffer);
+ OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
}
+ output_frames_.clear();
+ output_frames_allocated_ = false;
+
+ need_free_output_buffers_ = false;
}
bool OmxVideoDecodeEngine::ConfigureIOPorts() {
@@ -982,8 +1015,7 @@ bool OmxVideoDecodeEngine::CanEmptyBuffer() {
// We can call empty buffer while we are in executing and EOS has
// not been sent
return (il_state_ == kIlExecuting &&
- !input_has_fed_eos_ &&
- input_port_enabled_);
+ !input_has_fed_eos_);
}
bool OmxVideoDecodeEngine::CanFillBuffer() {
@@ -1007,7 +1039,8 @@ bool OmxVideoDecodeEngine::CanAcceptOutput() {
return (kClientError != client_state_ &&
kClientStopping != client_state_ &&
kClientStopped != client_state_ &&
- output_port_state_ == kPortEnabled);
+ output_port_state_ == kPortEnabled &&
+ !output_eos_);
}
// TODO(wjia): There are several things need to be done here:
@@ -1043,29 +1076,14 @@ void OmxVideoDecodeEngine::EmptyBufferTask() {
}
}
-void OmxVideoDecodeEngine::FulfillOneRead() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
-
- if (!output_frames_ready_.empty()) {
- OMX_BUFFERHEADERTYPE *buffer = output_frames_ready_.front();
- output_frames_ready_.pop();
-
- // If the buffer is real then send it to downstream.
- // Otherwise if it is an end-of-stream buffer then just drop it.
- if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
- // We intentionally drop last frame because it could be garbage.
- FinishFillBuffer(static_cast<OMX_BUFFERHEADERTYPE*>(NULL));
- } else {
- FinishFillBuffer(buffer);
- // In non-EGLImage path, OMX_BUFFERHEADERTYPEs are immediately recycled.
- if (!uses_egl_image_) SendOutputBufferToComponent(buffer);
- }
- }
-}
-
void OmxVideoDecodeEngine::InitialReadBuffer() {
DCHECK_EQ(message_loop_, MessageLoop::current());
+ input_queue_has_eos_ = false;
+ input_has_fed_eos_ = false;
+ output_eos_ = false;
+
+ DLOG(INFO) << "OmxVideoDecodeEngine::InitialReadBuffer";
for (size_t i = 0; i < free_input_buffers_.size(); i++)
FinishEmptyBuffer(NULL);
}
@@ -1077,28 +1095,12 @@ void OmxVideoDecodeEngine::InitialFillBuffer() {
if (!CanFillBuffer())
return;
+ DLOG(INFO) << "OmxVideoDecodeEngine::InitialFillBuffer";
+
// Ask the decoder to fill the output buffers.
- if (uses_egl_image_) {
- while (!available_output_frames_.empty()) {
- OMX_BUFFERHEADERTYPE* omx_buffer = available_output_frames_.front();
- available_output_frames_.pop();
- SendOutputBufferToComponent(omx_buffer);
- }
- } else {
- for (size_t i = 0; i < output_buffers_.size(); ++i) {
- OMX_BUFFERHEADERTYPE* omx_buffer = output_buffers_[i];
- omx_buffer->nOutputPortIndex = output_port_;
- // Need to clear the EOS flag.
- omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
- omx_buffer->pAppPrivate = this;
- OMX_ERRORTYPE ret = OMX_FillThisBuffer(component_handle_, omx_buffer);
-
- if (OMX_ErrorNone != ret) {
- LOG(ERROR) << "OMX_FillThisBuffer() failed with result " << ret;
- client_state_ = kClientError;
- return;
- }
- }
+ for (uint32 i = 0; i < output_frames_.size(); ++i) {
+ OMX_BUFFERHEADERTYPE* omx_buffer = output_frames_[i].second;
+ SendOutputBufferToComponent(omx_buffer);
}
}
@@ -1150,6 +1152,8 @@ void OmxVideoDecodeEngine::SendOutputBufferToComponent(
// clear EOS flag.
omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ omx_buffer->nOutputPortIndex = output_port_;
+ output_buffers_at_component_++;
OMX_ERRORTYPE ret = OMX_FillThisBuffer(component_handle_, omx_buffer);
if (OMX_ErrorNone != ret) {
@@ -1189,8 +1193,10 @@ void OmxVideoDecodeEngine::EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) {
free_input_buffers_.push(buffer);
input_buffers_at_component_--;
- if (need_free_input_buffers_ && !input_buffers_at_component_)
+ if (need_free_input_buffers_ && !input_buffers_at_component_) {
FreeInputBuffers();
+ return;
+ }
// Try to feed more data into the decoder.
EmptyBufferTask();
@@ -1202,9 +1208,24 @@ void OmxVideoDecodeEngine::EmptyBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) {
void OmxVideoDecodeEngine::FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) {
DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_GT(output_buffers_at_component_, 0);
+
+ output_buffers_at_component_--;
- if (!CanAcceptOutput())
+ if (need_free_output_buffers_ && !output_buffers_at_component_) {
+ FreeOutputBuffers();
return;
+ }
+
+ if (!CanAcceptOutput()) {
+ if (uses_egl_image_) {
+ scoped_refptr<VideoFrame> frame;
+ frame = static_cast<VideoFrame*>(buffer->pAppPrivate);
+ event_handler_->OnFillBufferCallback(frame);
+ output_pending_request_--;
+ }
+ return;
+ }
// This buffer is received with decoded frame. Enqueue it and make it
// ready to be consumed by reads.
@@ -1214,12 +1235,14 @@ void OmxVideoDecodeEngine::FillBufferDoneTask(OMX_BUFFERHEADERTYPE* buffer) {
DLOG(INFO) << "Output has EOS";
}
- // TODO(jiesun): return this buffer to allocator?
- if (client_state_ != kClientFlushing)
- output_frames_ready_.push(buffer);
+ FinishFillBuffer(buffer);
- // Try to fulfill one read request.
- FulfillOneRead();
+ if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ // Singal end of stream.
+ scoped_refptr<VideoFrame> frame;
+ VideoFrame::CreateEmptyFrame(&frame);
+ event_handler_->OnFillBufferCallback(frame);
+ }
if (client_state_ == kClientFlushing &&
InputPortFlushed() && OutputPortFlushed())
@@ -1246,7 +1269,7 @@ void OmxVideoDecodeEngine::EventHandlerCompleteTask(OMX_EVENTTYPE event,
} else if (cmd == OMX_CommandFlush) {
(this->*OnFlushEventFunc)(data2);
} else {
- LOG(ERROR) << "Unknown command completed\n";
+ LOG(ERROR) << "Unknown command completed\n" << data1;
}
break;
}
« no previous file with comments | « media/filters/omx_video_decode_engine.h ('k') | media/filters/video_renderer_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698