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

Unified Diff: webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc

Issue 1645543003: H264: Improve FFmpeg decoder performance by using I420BufferPool. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Added comments about why we zero-initialize Created 4 years, 11 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: webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc
diff --git a/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc b/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc
index 75d2bfa73245a050aa9688e53b0f0fe1538884b0..4d1bd2d75b454252cbc6b58f6d8209b663e3c736 100644
--- a/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc
+++ b/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc
@@ -77,11 +77,7 @@ void InitializeFFmpeg() {
#endif // !defined(WEBRTC_CHROMIUM_BUILD)
-// Called by FFmpeg when it is done with a frame buffer, see AVGetBuffer2.
-void AVFreeBuffer2(void* opaque, uint8_t* data) {
- VideoFrame* video_frame = static_cast<VideoFrame*>(opaque);
- delete video_frame;
-}
+} // namespace
// Called by FFmpeg when it needs a frame buffer to store decoded frames in.
// The VideoFrames returned by FFmpeg at |Decode| originate from here. They are
@@ -90,10 +86,17 @@ void AVFreeBuffer2(void* opaque, uint8_t* data) {
// Could be owned by decoder, |static_cast<H264DecoderImpl*>(context->opaque)|.
stefan-webrtc 2016/02/01 14:02:09 Should this comment be removed now?
hbos 2016/02/02 16:13:03 Done.
// Consider verifying that the buffer was allocated by us to avoid unsafe type
// cast. See https://bugs.chromium.org/p/webrtc/issues/detail?id=5428.
-int AVGetBuffer2(AVCodecContext* context, AVFrame* av_frame, int flags) {
- RTC_CHECK_EQ(context->pix_fmt, kPixelFormat); // Same as in InitDecode.
+int H264DecoderImpl::AVGetBuffer2(
+ AVCodecContext* context, AVFrame* av_frame, int flags) {
+ H264DecoderImpl* decoder =
+ reinterpret_cast<H264DecoderImpl*>(context->opaque);
hbos 2016/01/29 10:16:56 To reinterpret_cast or static_cast, that is the qu
hbos 2016/02/02 16:13:03 static_cast, that is the answer.
+
+ // DCHECK values set in |InitDecode|.
+ RTC_DCHECK(decoder);
+ RTC_DCHECK_EQ(context->pix_fmt, kPixelFormat);
// Necessary capability to be allowed to provide our own buffers.
- RTC_CHECK(context->codec->capabilities | AV_CODEC_CAP_DR1);
+ RTC_DCHECK(context->codec->capabilities | AV_CODEC_CAP_DR1);
+
// |av_frame->width| and |av_frame->height| are set by FFmpeg. These are the
// actual image's dimensions and may be different from |context->width| and
// |context->coded_width| due to reordering.
@@ -121,25 +124,18 @@ int AVGetBuffer2(AVCodecContext* context, AVFrame* av_frame, int flags) {
// The video frame is stored in |video_frame|. |av_frame| is FFmpeg's version
// of a video frame and will be set up to reference |video_frame|'s buffers.
VideoFrame* video_frame = new VideoFrame();
- int stride_y = width;
- int stride_uv = (width + 1) / 2;
- RTC_CHECK_EQ(0, video_frame->CreateEmptyFrame(
- width, height, stride_y, stride_uv, stride_uv));
- int total_size = video_frame->allocated_size(kYPlane) +
- video_frame->allocated_size(kUPlane) +
- video_frame->allocated_size(kVPlane);
- RTC_DCHECK_EQ(total_size, stride_y * height +
- (stride_uv + stride_uv) * ((height + 1) / 2));
-
// FFmpeg expects the initial allocation to be zero-initialized according to
- // http://crbug.com/390941.
- // Using a single |av_frame->buf| - YUV is required to be a continuous blob of
- // memory. We can zero-initialize with one memset operation for all planes.
+ // http://crbug.com/390941. Our pool is set up to zero-initialize new buffers.
+ video_frame->set_video_frame_buffer(
+ decoder->pool_.CreateBuffer(width, height));
+ // DCHECK that we have a continuous buffer as is required.
RTC_DCHECK_EQ(video_frame->buffer(kUPlane),
video_frame->buffer(kYPlane) + video_frame->allocated_size(kYPlane));
RTC_DCHECK_EQ(video_frame->buffer(kVPlane),
video_frame->buffer(kUPlane) + video_frame->allocated_size(kUPlane));
- memset(video_frame->buffer(kYPlane), 0, total_size);
stefan-webrtc 2016/02/01 14:02:09 The memset you did in the pool doesn't memset the
hbos 2016/02/02 16:13:03 That memset and this memset are the same. See prev
+ int total_size = video_frame->allocated_size(kYPlane) +
+ video_frame->allocated_size(kUPlane) +
+ video_frame->allocated_size(kVPlane);
av_frame->format = context->pix_fmt;
av_frame->reordered_opaque = context->reordered_opaque;
@@ -162,10 +158,14 @@ int AVGetBuffer2(AVCodecContext* context, AVFrame* av_frame, int flags) {
return 0;
}
-} // namespace
+// Called by FFmpeg when it is done with a frame buffer, see AVGetBuffer2.
+void H264DecoderImpl::AVFreeBuffer2(void* opaque, uint8_t* data) {
+ VideoFrame* video_frame = static_cast<VideoFrame*>(opaque);
+ delete video_frame;
stefan-webrtc 2016/02/01 14:02:09 Seems odd that we delete frames when we are using
hbos 2016/02/02 16:13:03 Added a comment explaining why.
+}
-H264DecoderImpl::H264DecoderImpl()
- : decoded_image_callback_(nullptr) {
+H264DecoderImpl::H264DecoderImpl() : pool_(true),
+ decoded_image_callback_(nullptr) {
}
H264DecoderImpl::~H264DecoderImpl() {
@@ -208,13 +208,15 @@ int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
av_context_->extradata = nullptr;
av_context_->extradata_size = 0;
+ // If this is ever increased, look at |av_context_->thread_safe_callbacks| and
+ // make it possible to disable the thread checker in the frame buffer pool.
av_context_->thread_count = 1;
av_context_->thread_type = FF_THREAD_SLICE;
- // FFmpeg will get video buffers from our AVGetBuffer2, memory managed by us.
+ // Function used by FFmpeg to get buffers to store decoded frames in.
av_context_->get_buffer2 = AVGetBuffer2;
- // get_buffer2 is called with the context, there |opaque| can be used to get a
- // pointer |this|.
+ // |get_buffer2| is called with the context, there |opaque| can be used to get
+ // a pointer |this|.
av_context_->opaque = this;
// Use ref counted frames (av_frame_unref).
av_context_->refcounted_frames = 1; // true

Powered by Google App Engine
This is Rietveld 408576698