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

Unified Diff: media/filters/ffmpeg_video_decoder.cc

Issue 10451051: Provide a Chrome-owned buffer to FFmpeg for video decoding, instead of (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 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
Index: media/filters/ffmpeg_video_decoder.cc
===================================================================
--- media/filters/ffmpeg_video_decoder.cc (revision 139175)
+++ media/filters/ffmpeg_video_decoder.cc (working copy)
@@ -59,6 +59,74 @@
frame_rate_denominator_(0) {
}
+int FFmpegVideoDecoder::AllocBuffer(VideoFrame **ptr)
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 no doco, no unittest, single call-site ==> inline
+{
+ VideoFrame::Format format = PixelFormatToVideoFormat(codec_context_->pix_fmt);
+ int w = codec_context_->width;
+ int h = codec_context_->height;
+ int ret, strides[4];
+ avcodec_align_dimensions(codec_context_, &w, &h);
+ if ((ret = av_image_check_size(w, h, 0, NULL)) < 0)
+ return ret;
+ if ((ret = av_image_fill_linesizes(strides, codec_context_->pix_fmt, w)) < 0)
+ return ret;
+ VideoFrame *buf = new VideoFrame::VideoFrame(format, codec_context_->width,
+ codec_context_->height,
+ kNoTimestamp(), kNoTimestamp());
+ if ((ret = buf->AllocateAlignedWithStrides(strides, h)) < 0) {
+ free(buf);
+ return ret;
+ }
+ *ptr = buf;
+ return 0;
+}
+
+int FFmpegVideoDecoder::GetVideoBuffer(AVFrame *frame)
+{
+ VideoFrame *buf;
+ int ret = AllocBuffer(&buf);
+ if (ret < 0)
+ return ret;
+
+ buf->AddRef();
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 AddRef() is almost never the right thing to call.
+ frame->opaque = buf;
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 This sort of ascii-art alignment isn't adding anyt
+ frame->type = FF_BUFFER_TYPE_USER;
+ frame->pkt_pts = codec_context_->pkt ? codec_context_->pkt->pts : AV_NOPTS_VALUE;
+ frame->width = codec_context_->width;
+ frame->height = codec_context_->height;
+ frame->format = codec_context_->pix_fmt;
+
+ for (int i = 0; i < (buf->format() == media::VideoFrame::RGB32 ? 1 : 3); i++) {
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 I think you're assuming either RGB32 or YV12/YV16.
+ frame->base[i] =
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 Un-style-ish. Repeat buf->data(i)
+ frame->data[i] = buf->data(i);
+ frame->linesize[i] = buf->stride(i);
+ }
+
+ return 0;
+}
+
+static int c_GetVideoBuffer(AVCodecContext *s, AVFrame *frame)
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 the "c_" prefix is un-style-ish.
+{
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 opening braces go on previous line (here and elsew
+ FFmpegVideoDecoder *vd = (FFmpegVideoDecoder *) s->opaque;
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 This isn't used until l.114, so it can be done the
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 use static_cast<>() instead of c-style casts (here
+ if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 When will this be true? (can you drop the "then" c
+ return avcodec_default_get_buffer(s, frame);
+ } else {
+ return vd->GetVideoBuffer(frame);
+ }
+}
+
+static void c_ReleaseVideoBuffer(AVCodecContext *s, AVFrame *frame)
+{
+ if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
+ avcodec_default_release_buffer(s, frame);
+ } else {
+ VideoFrame *buf = (media::VideoFrame *) frame->opaque;
+ buf->Release();
+ memset(frame->data, 0, sizeof(frame->data));
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 why? (also, do you really mean to only set the fir
+ frame->opaque = NULL;
+ }
+}
+
void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& status_cb,
const StatisticsCB& statistics_cb) {
@@ -102,6 +170,10 @@
codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
codec_context_->err_recognition = AV_EF_CAREFUL;
codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
+ codec_context_->opaque = this;
+ codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
+ codec_context_->get_buffer = c_GetVideoBuffer;
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 Depending on ffmpeg dispatches these callbacks, it
+ codec_context_->release_buffer = c_ReleaseVideoBuffer;
AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
if (!codec) {
@@ -356,11 +428,15 @@
return false;
}
- // We've got a frame! Make sure we have a place to store it.
- *video_frame = AllocateVideoFrame();
- if (!(*video_frame)) {
- LOG(ERROR) << "Failed to allocate video frame";
- return false;
+ if (!(codec_context_->flags & CODEC_FLAG_EMU_EDGE)) {
Ami GONE FROM CHROMIUM 2012/05/26 22:52:34 Drop this test here and elsewhere?
+ // We've got a frame! Make sure we have a place to store it.
+ *video_frame = AllocateVideoFrame();
+ if (!(*video_frame)) {
+ LOG(ERROR) << "Failed to allocate video frame";
+ return false;
+ }
+ } else {
+ *video_frame = (media::VideoFrame *) av_frame_->opaque;
}
// Determine timestamp and calculate the duration based on the repeat picture
@@ -381,19 +457,21 @@
(*video_frame)->SetDuration(
ConvertFromTimeBase(doubled_time_base, 2 + av_frame_->repeat_pict));
- // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
- // output, meaning the data is only valid until the next
- // avcodec_decode_video() call.
- int y_rows = codec_context_->height;
- int uv_rows = codec_context_->height;
- if (codec_context_->pix_fmt == PIX_FMT_YUV420P) {
- uv_rows /= 2;
+ if (!(codec_context_->flags & CODEC_FLAG_EMU_EDGE)) {
+ // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
+ // output, meaning the data is only valid until the next
+ // avcodec_decode_video() call.
+ int y_rows = codec_context_->height;
+ int uv_rows = codec_context_->height;
+ if (codec_context_->pix_fmt == PIX_FMT_YUV420P) {
+ uv_rows /= 2;
+ }
+
+ CopyYPlane(av_frame_->data[0], av_frame_->linesize[0], y_rows, *video_frame);
+ CopyUPlane(av_frame_->data[1], av_frame_->linesize[1], uv_rows, *video_frame);
+ CopyVPlane(av_frame_->data[2], av_frame_->linesize[2], uv_rows, *video_frame);
}
- CopyYPlane(av_frame_->data[0], av_frame_->linesize[0], y_rows, *video_frame);
- CopyUPlane(av_frame_->data[1], av_frame_->linesize[1], uv_rows, *video_frame);
- CopyVPlane(av_frame_->data[2], av_frame_->linesize[2], uv_rows, *video_frame);
-
return true;
}
« media/filters/ffmpeg_video_decoder.h ('K') | « media/filters/ffmpeg_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698