OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/filters/ffmpeg_video_decoder.h" | 5 #include "media/filters/ffmpeg_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 int flags) { | 59 int flags) { |
60 FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque); | 60 FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque); |
61 return decoder->GetVideoBuffer(s, frame, flags); | 61 return decoder->GetVideoBuffer(s, frame, flags); |
62 } | 62 } |
63 | 63 |
64 static void ReleaseVideoBufferImpl(void* opaque, uint8* data) { | 64 static void ReleaseVideoBufferImpl(void* opaque, uint8* data) { |
65 scoped_refptr<VideoFrame> video_frame; | 65 scoped_refptr<VideoFrame> video_frame; |
66 video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque)); | 66 video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque)); |
67 } | 67 } |
68 | 68 |
69 static size_t RoundUp(size_t value, size_t alignment) { | |
70 // Check that |alignment| is a power of 2. | |
71 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); | |
72 return ((value + (alignment - 1)) & ~(alignment - 1)); | |
73 } | |
74 | |
69 FFmpegVideoDecoder::FFmpegVideoDecoder( | 75 FFmpegVideoDecoder::FFmpegVideoDecoder( |
70 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
71 : task_runner_(task_runner), state_(kUninitialized) {} | 77 : task_runner_(task_runner), state_(kUninitialized) {} |
72 | 78 |
73 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context, | 79 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context, |
74 AVFrame* frame, | 80 AVFrame* frame, |
75 int flags) { | 81 int flags) { |
76 // Don't use |codec_context_| here! With threaded decoding, | 82 // Don't use |codec_context_| here! With threaded decoding, |
77 // it will contain unsynchronized width/height/pix_fmt values, | 83 // it will contain unsynchronized width/height/pix_fmt values, |
78 // whereas |codec_context| contains the current threads's | 84 // whereas |codec_context| contains the current threads's |
(...skipping 18 matching lines...) Expand all Loading... | |
97 } else { | 103 } else { |
98 natural_size = config_.natural_size(); | 104 natural_size = config_.natural_size(); |
99 } | 105 } |
100 | 106 |
101 // FFmpeg has specific requirements on the allocation size of the frame. The | 107 // FFmpeg has specific requirements on the allocation size of the frame. The |
102 // following logic replicates FFmpeg's allocation strategy to ensure buffers | 108 // following logic replicates FFmpeg's allocation strategy to ensure buffers |
103 // are not overread / overwritten. See ff_init_buffer_info() for details. | 109 // are not overread / overwritten. See ff_init_buffer_info() for details. |
104 // | 110 // |
105 // When lowres is non-zero, dimensions should be divided by 2^(lowres), but | 111 // When lowres is non-zero, dimensions should be divided by 2^(lowres), but |
106 // since we don't use this, just DCHECK that it's zero. | 112 // since we don't use this, just DCHECK that it's zero. |
113 // | |
114 // Always round up to a multiple of two to match VideoFrame restrictions on | |
115 // frame alignment. | |
107 DCHECK_EQ(codec_context->lowres, 0); | 116 DCHECK_EQ(codec_context->lowres, 0); |
108 gfx::Size coded_size(std::max(size.width(), codec_context->coded_width), | 117 gfx::Size coded_size( |
109 std::max(size.height(), codec_context->coded_height)); | 118 RoundUp(std::max(size.width(), codec_context->coded_width), 2), |
119 RoundUp(std::max(size.height(), codec_context->coded_height), 2)); | |
110 | 120 |
111 if (!VideoFrame::IsValidConfig( | 121 if (!VideoFrame::IsValidConfig( |
scherkus (not reviewing)
2014/06/06 21:25:50
was this check failing with that test clip?
DaleCurtis
2014/06/06 21:33:06
Yes.
| |
112 format, coded_size, gfx::Rect(size), natural_size)) | 122 format, coded_size, gfx::Rect(size), natural_size)) |
113 return AVERROR(EINVAL); | 123 return AVERROR(EINVAL); |
114 | 124 |
115 scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame( | 125 scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame( |
116 format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp()); | 126 format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp()); |
117 | 127 |
118 for (int i = 0; i < 3; i++) { | 128 for (int i = 0; i < 3; i++) { |
119 frame->data[i] = video_frame->data(i); | 129 frame->data[i] = video_frame->data(i); |
120 frame->linesize[i] = video_frame->stride(i); | 130 frame->linesize[i] = video_frame->stride(i); |
121 } | 131 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
364 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 374 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
365 ReleaseFFmpegResources(); | 375 ReleaseFFmpegResources(); |
366 return false; | 376 return false; |
367 } | 377 } |
368 | 378 |
369 av_frame_.reset(av_frame_alloc()); | 379 av_frame_.reset(av_frame_alloc()); |
370 return true; | 380 return true; |
371 } | 381 } |
372 | 382 |
373 } // namespace media | 383 } // namespace media |
OLD | NEW |