format == VideoFrame::YV12J);
gfx::Size size(codec_context->width, codec_context->height);
- int ret;
- if ((ret = av_image_check_size(size.width(), size.height(), 0, NULL)) < 0)
+ const int ret = av_image_check_size(size.width(), size.height(), 0, NULL);
+ if (ret < 0)
return ret;
gfx::Size natural_size;
natural_size = config_.natural_size();
}
- if (!VideoFrame::IsValidConfig(format, size, gfx::Rect(size), natural_size))
+ // FFmpeg has specific requirements on the allocation size of the frame. The
+ // following logic replicates FFmpeg's allocation strategy to ensure buffers
+ // are not overread / overwritten. See ff_init_buffer_info() for details.
+ //
+ // When lowres is non-zero, dimensions should be divided by 2^(lowres), but
+ // since we don't use this, just DCHECK that it's zero.
+ DCHECK_EQ(codec_context->lowres, 0);
+ gfx::Size coded_size(std::max(size.width(), codec_context->coded_width),
+ std::max(size.height(), codec_context->coded_height));
+
+ if (!VideoFrame::IsValidConfig(
+ format, coded_size, gfx::Rect(size), natural_size))
return AVERROR(EINVAL);
- scoped_refptr<VideoFrame> video_frame =
- frame_pool_.CreateFrame(format, size, gfx::Rect(size),
- natural_size, kNoTimestamp());
+ scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
+ format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp());
for (int i = 0; i < 3; i++) {
frame->base[i] = video_frame->data(i);
frame->opaque = NULL;
video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque));
frame->type = FF_BUFFER_TYPE_USER;
- frame->width = codec_context->width;
- frame->height = codec_context->height;
+ frame->width = coded_size.width();
+ frame->height = coded_size.height();
frame->format = codec_context->pix_fmt;
return 0;
}
void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
+ bool low_delay,
const PipelineStatusCB& status_cb) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(decode_cb_.is_null());
- DCHECK(reset_cb_.is_null());
DCHECK(!config.is_encrypted());
FFmpegGlue::InitializeFFmpeg();
config_ = config;
PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
- if (!config.IsValidConfig() || !ConfigureDecoder()) {
+ if (!config.IsValidConfig() || !ConfigureDecoder(low_delay)) {
initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
return;
}
void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(reset_cb_.is_null());
- reset_cb_ = BindToCurrentLoop(closure);
-
- // Defer the reset if a decode is pending.
- if (!decode_cb_.is_null())
- return;
-
- DoReset();
-}
-
-void FFmpegVideoDecoder::DoReset() {
DCHECK(decode_cb_.is_null());
avcodec_flush_buffers(codec_context_.get());
state_ = kNormal;
- base::ResetAndReturn(&reset_cb_).Run();
+ task_runner_->PostTask(FROM_HERE, closure);
}
-void FFmpegVideoDecoder::Stop(const base::Closure& closure) {
+void FFmpegVideoDecoder::Stop() {
DCHECK(task_runner_->BelongsToCurrentThread());
- base::ScopedClosureRunner runner(BindToCurrentLoop(closure));
if (state_ == kUninitialized)
return;
- if (!decode_cb_.is_null()) {
- base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL);
- // Reset is pending only when decode is pending.
- if (!reset_cb_.is_null())
- base::ResetAndReturn(&reset_cb_).Run();
- }
-
ReleaseFFmpegResources();
state_ = kUninitialized;
}
DCHECK_NE(state_, kUninitialized);
DCHECK_NE(state_, kDecodeFinished);
DCHECK_NE(state_, kError);
- DCHECK(reset_cb_.is_null());
DCHECK(!decode_cb_.is_null());
DCHECK(buffer);
}
*video_frame = static_cast<VideoFrame*>(av_frame_->opaque);
- (*video_frame)->SetTimestamp(
+ (*video_frame)->set_timestamp(
base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque));
return true;
av_frame_.reset();
}
-bool FFmpegVideoDecoder::ConfigureDecoder() {
+bool FFmpegVideoDecoder::ConfigureDecoder(bool low_delay) {
// Release existing decoder resources if necessary.
ReleaseFFmpegResources();
// for damaged macroblocks, and set our error detection sensitivity.
codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
+ codec_context_->thread_type = low_delay ? FF_THREAD_SLICE : FF_THREAD_FRAME;
codec_context_->opaque = this;
codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
codec_context_->get_buffer = GetVideoBufferImpl;