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

Unified Diff: media/filters/video_decoder_impl.cc

Issue 2854002: merge video_decoder_impl.cc and ffmpeg_video_decoder.cc (Closed)
Patch Set: remove comments Created 10 years, 6 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/video_decoder_impl.h ('k') | media/media.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/video_decoder_impl.cc
diff --git a/media/filters/video_decoder_impl.cc b/media/filters/video_decoder_impl.cc
deleted file mode 100644
index 5f3dbf02b13cabe9b53e1a9bed7c204397ee401b..0000000000000000000000000000000000000000
--- a/media/filters/video_decoder_impl.cc
+++ /dev/null
@@ -1,246 +0,0 @@
-// 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.
-
-#include "media/filters/video_decoder_impl.h"
-
-#include "base/task.h"
-#include "media/base/filters.h"
-#include "media/base/limits.h"
-#include "media/base/video_frame.h"
-#include "media/ffmpeg/ffmpeg_common.h"
-#include "media/filters/ffmpeg_interfaces.h"
-#include "media/filters/video_decode_engine.h"
-#include "media/ffmpeg/ffmpeg_util.h"
-
-namespace media {
-
-VideoDecoderImpl::VideoDecoderImpl(VideoDecodeEngine* engine)
- : width_(0),
- height_(0),
- time_base_(new AVRational()),
- state_(kNormal),
- decode_engine_(engine) {
-}
-
-VideoDecoderImpl::~VideoDecoderImpl() {
-}
-
-void VideoDecoderImpl::DoInitialize(DemuxerStream* demuxer_stream,
- bool* success,
- Task* done_cb) {
- AutoTaskRunner done_runner(done_cb);
- *success = false;
-
- // Get the AVStream by querying for the provider interface.
- AVStreamProvider* av_stream_provider;
- if (!demuxer_stream->QueryInterface(&av_stream_provider)) {
- return;
- }
- AVStream* av_stream = av_stream_provider->GetAVStream();
-
- time_base_->den = av_stream->r_frame_rate.num;
- time_base_->num = av_stream->r_frame_rate.den;
-
- // TODO(ajwong): We don't need these extra variables if |media_format_| has
- // them. Remove.
- width_ = av_stream->codec->width;
- height_ = av_stream->codec->height;
- if (width_ > Limits::kMaxDimension ||
- height_ > Limits::kMaxDimension ||
- (width_ * height_) > Limits::kMaxCanvas) {
- return;
- }
-
- // Only set kMimeType when derived class has not done so.
- if (!media_format_.Contains(MediaFormat::kMimeType))
- media_format_.SetAsString(MediaFormat::kMimeType,
- mime_type::kUncompressedVideo);
- media_format_.SetAsInteger(MediaFormat::kWidth, width_);
- media_format_.SetAsInteger(MediaFormat::kHeight, height_);
-
- decode_engine_->Initialize(
- message_loop(),
- av_stream,
- NewCallback(this, &VideoDecoderImpl::OnEmptyBufferDone),
- NewCallback(this, &VideoDecoderImpl::OnDecodeComplete),
- NewRunnableMethod(this,
- &VideoDecoderImpl::OnInitializeComplete,
- success,
- done_runner.release()));
-}
-
-void VideoDecoderImpl::OnInitializeComplete(bool* success, Task* done_cb) {
- AutoTaskRunner done_runner(done_cb);
-
- *success = decode_engine_->state() == VideoDecodeEngine::kNormal;
-}
-
-void VideoDecoderImpl::DoSeek(base::TimeDelta time, Task* done_cb) {
- // Everything in the presentation time queue is invalid, clear the queue.
- while (!pts_heap_.IsEmpty())
- pts_heap_.Pop();
-
- // We're back where we started. It should be completely safe to flush here
- // since DecoderBase uses |expecting_discontinuous_| to verify that the next
- // time DoDecode() is called we will have a discontinuous buffer.
- //
- // TODO(ajwong): Should we put a guard here to prevent leaving kError.
- state_ = kNormal;
-
- decode_engine_->Flush(done_cb);
-}
-
-void VideoDecoderImpl::DoDecode(Buffer* buffer) {
- // TODO(ajwong): This DoDecode() and OnDecodeComplete() set of functions is
- // too complicated to easily unittest. The test becomes fragile. Try to
- // find a way to reorganize into smaller units for testing.
-
- // During decode, because reads are issued asynchronously, it is possible to
- // receive multiple end of stream buffers since each read is acked. When the
- // first end of stream buffer is read, FFmpeg may still have frames queued
- // up in the decoder so we need to go through the decode loop until it stops
- // giving sensible data. After that, the decoder should output empty
- // frames. There are three states the decoder can be in:
- //
- // kNormal: This is the starting state. Buffers are decoded. Decode errors
- // are discarded.
- // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2
- // until no more data is returned to flush out remaining
- // frames. The input buffer is ignored at this point.
- // kDecodeFinished: All calls return empty frames.
- //
- // These are the possible state transitions.
- //
- // kNormal -> kFlushCodec:
- // When buffer->IsEndOfStream() is first true.
- // kNormal -> kDecodeFinished:
- // A catastrophic failure occurs, and decoding needs to stop.
- // kFlushCodec -> kDecodeFinished:
- // When avcodec_decode_video2() returns 0 data or errors out.
- // (any state) -> kNormal:
- // Any time buffer->IsDiscontinuous() is true.
- //
- // If the decoding is finished, we just always return empty frames.
- if (state_ == kDecodeFinished) {
- EnqueueEmptyFrame();
- OnEmptyBufferDone(NULL);
- return;
- }
-
- // Transition to kFlushCodec on the first end of stream buffer.
- if (state_ == kNormal && buffer->IsEndOfStream()) {
- state_ = kFlushCodec;
- }
-
- // Push all incoming timestamps into the priority queue as long as we have
- // not yet received an end of stream buffer. It is important that this line
- // stay below the state transition into kFlushCodec done above.
- //
- // TODO(ajwong): This push logic, along with the pop logic below needs to
- // be reevaluated to correctly handle decode errors.
- if (state_ == kNormal &&
- buffer->GetTimestamp() != StreamSample::kInvalidTimestamp) {
- pts_heap_.Push(buffer->GetTimestamp());
- }
-
- // Otherwise, attempt to decode a single frame.
- decode_engine_->EmptyThisBuffer(buffer);
-}
-
-void VideoDecoderImpl::OnDecodeComplete(scoped_refptr<VideoFrame> video_frame) {
- if (video_frame.get()) {
- // If we actually got data back, enqueue a frame.
- last_pts_ = FindPtsAndDuration(*time_base_, &pts_heap_, last_pts_,
- video_frame.get());
-
- video_frame->SetTimestamp(last_pts_.timestamp);
- video_frame->SetDuration(last_pts_.duration);
- EnqueueVideoFrame(video_frame);
- } else {
- // When in kFlushCodec, any errored decode, or a 0-lengthed frame,
- // is taken as a signal to stop decoding.
- if (state_ == kFlushCodec) {
- state_ = kDecodeFinished;
- EnqueueEmptyFrame();
- }
- }
-
- OnEmptyBufferDone(NULL);
-}
-
-void VideoDecoderImpl::OnEmptyBufferDone(scoped_refptr<Buffer> buffer) {
- // TODO(jiesun): what |DecodeBase::OnDecodeComplete| done is just
- // what should be done in EmptyThisBufferCallback.
- // Currently we just ignore the returned buffer.
- DecoderBase<VideoDecoder, VideoFrame>::OnDecodeComplete();
-}
-
-void VideoDecoderImpl::EnqueueVideoFrame(
- const scoped_refptr<VideoFrame>& video_frame) {
- EnqueueResult(video_frame);
-}
-
-void VideoDecoderImpl::EnqueueEmptyFrame() {
- scoped_refptr<VideoFrame> video_frame;
- VideoFrame::CreateEmptyFrame(&video_frame);
- EnqueueResult(video_frame);
-}
-
-VideoDecoderImpl::TimeTuple VideoDecoderImpl::FindPtsAndDuration(
- const AVRational& time_base,
- PtsHeap* pts_heap,
- const TimeTuple& last_pts,
- const VideoFrame* frame) {
- TimeTuple pts;
-
- // First search the VideoFrame for the pts. This is the most authoritative.
- // Make a special exclusion for the value pts == 0. Though this is
- // technically a valid value, it seems a number of FFmpeg codecs will
- // mistakenly always set pts to 0.
- //
- // TODO(scherkus): FFmpegVideoDecodeEngine should be able to detect this
- // situation and set the timestamp to kInvalidTimestamp.
- DCHECK(frame);
- base::TimeDelta timestamp = frame->GetTimestamp();
- if (timestamp != StreamSample::kInvalidTimestamp &&
- timestamp.ToInternalValue() != 0) {
- pts.timestamp = timestamp;
- } else if (!pts_heap->IsEmpty()) {
- // If the frame did not have pts, try to get the pts from the |pts_heap|.
- pts.timestamp = pts_heap->Top();
- pts_heap->Pop();
- } else if (last_pts.timestamp != StreamSample::kInvalidTimestamp &&
- last_pts.duration != StreamSample::kInvalidTimestamp) {
- // Guess assuming this frame was the same as the last frame.
- pts.timestamp = last_pts.timestamp + last_pts.duration;
- } else {
- // Now we really have no clue!!! Mark an invalid timestamp and let the
- // video renderer handle it (i.e., drop frame).
- pts.timestamp = StreamSample::kInvalidTimestamp;
- }
-
- // Fill in the duration, using the frame itself as the authoratative source.
- base::TimeDelta duration = frame->GetDuration();
- if (duration != StreamSample::kInvalidTimestamp &&
- duration.ToInternalValue() != 0) {
- pts.duration = duration;
- } else {
- // Otherwise assume a normal frame duration.
- pts.duration = ConvertTimestamp(time_base, 1);
- }
-
- return pts;
-}
-
-void VideoDecoderImpl::SignalPipelineError() {
- host()->SetError(PIPELINE_ERROR_DECODE);
- state_ = kDecodeFinished;
-}
-
-void VideoDecoderImpl::SetVideoDecodeEngineForTest(
- VideoDecodeEngine* engine) {
- decode_engine_.reset(engine);
-}
-
-} // namespace media
« no previous file with comments | « media/filters/video_decoder_impl.h ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698