| 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 ea96f25a1e40110750b769334f43bac3a06cf5f2..692422ec447184d36ee3262cfd00df9d63d057ae 100644
|
| --- a/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc
|
| +++ b/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc
|
| @@ -76,23 +76,18 @@ void InitializeFFmpeg() {
|
|
|
| #endif // defined(WEBRTC_INITIALIZE_FFMPEG)
|
|
|
| -// 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
|
| -// reference counted and freed by FFmpeg using |AVFreeBuffer2|.
|
| -// TODO(hbos): Use a frame pool for better performance instead of create/free.
|
| -// Could be owned by decoder, |static_cast<H264DecoderImpl*>(context->opaque)|.
|
| -// 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) {
|
| + // Set in |InitDecode|.
|
| + H264DecoderImpl* decoder = static_cast<H264DecoderImpl*>(context->opaque);
|
| + // 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.
|
| @@ -120,25 +115,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);
|
| + 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;
|
| @@ -161,10 +149,16 @@ int AVGetBuffer2(AVCodecContext* context, AVFrame* av_frame, int flags) {
|
| return 0;
|
| }
|
|
|
| -} // namespace
|
| +void H264DecoderImpl::AVFreeBuffer2(void* opaque, uint8_t* data) {
|
| + // The buffer pool recycles the buffer used by |video_frame| when there are no
|
| + // more references to it. |video_frame| is a thin buffer holder and is not
|
| + // recycled.
|
| + VideoFrame* video_frame = static_cast<VideoFrame*>(opaque);
|
| + delete video_frame;
|
| +}
|
|
|
| -H264DecoderImpl::H264DecoderImpl()
|
| - : decoded_image_callback_(nullptr) {
|
| +H264DecoderImpl::H264DecoderImpl() : pool_(true),
|
| + decoded_image_callback_(nullptr) {
|
| }
|
|
|
| H264DecoderImpl::~H264DecoderImpl() {
|
| @@ -209,13 +203,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
|
|
|