OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/ffmpeg/ffmpeg_common.h" | 5 #include "media/ffmpeg/ffmpeg_common.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 | 8 |
9 namespace media { | 9 namespace media { |
10 | 10 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 NOTREACHED() << "Unsupported bits_per_channel: " << bits_per_channel; | 60 NOTREACHED() << "Unsupported bits_per_channel: " << bits_per_channel; |
61 } | 61 } |
62 case kCodecVorbis: | 62 case kCodecVorbis: |
63 return CODEC_ID_VORBIS; | 63 return CODEC_ID_VORBIS; |
64 default: | 64 default: |
65 NOTREACHED(); | 65 NOTREACHED(); |
66 } | 66 } |
67 return CODEC_ID_NONE; | 67 return CODEC_ID_NONE; |
68 } | 68 } |
69 | 69 |
| 70 static VideoCodec CodecIDToVideoCodec(CodecID codec_id) { |
| 71 switch (codec_id) { |
| 72 case CODEC_ID_VC1: |
| 73 return kCodecVC1; |
| 74 case CODEC_ID_H264: |
| 75 return kCodecH264; |
| 76 case CODEC_ID_THEORA: |
| 77 return kCodecTheora; |
| 78 case CODEC_ID_MPEG2VIDEO: |
| 79 return kCodecMPEG2; |
| 80 case CODEC_ID_MPEG4: |
| 81 return kCodecMPEG4; |
| 82 case CODEC_ID_VP8: |
| 83 return kCodecVP8; |
| 84 default: |
| 85 NOTREACHED(); |
| 86 } |
| 87 return kUnknownVideoCodec; |
| 88 } |
| 89 |
| 90 static CodecID VideoCodecToCodecID(VideoCodec video_codec) { |
| 91 switch (video_codec) { |
| 92 case kUnknownVideoCodec: |
| 93 return CODEC_ID_NONE; |
| 94 case kCodecVC1: |
| 95 return CODEC_ID_VC1; |
| 96 case kCodecH264: |
| 97 return CODEC_ID_H264; |
| 98 case kCodecTheora: |
| 99 return CODEC_ID_THEORA; |
| 100 case kCodecMPEG2: |
| 101 return CODEC_ID_MPEG2VIDEO; |
| 102 case kCodecMPEG4: |
| 103 return CODEC_ID_MPEG4; |
| 104 case kCodecVP8: |
| 105 return CODEC_ID_VP8; |
| 106 default: |
| 107 NOTREACHED(); |
| 108 } |
| 109 return CODEC_ID_NONE; |
| 110 } |
| 111 |
70 void AVCodecContextToAudioDecoderConfig( | 112 void AVCodecContextToAudioDecoderConfig( |
71 const AVCodecContext* codec_context, | 113 const AVCodecContext* codec_context, |
72 AudioDecoderConfig* config) { | 114 AudioDecoderConfig* config) { |
73 DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO); | 115 DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO); |
74 | 116 |
75 AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id); | 117 AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id); |
76 int bits_per_channel = av_get_bits_per_sample_fmt(codec_context->sample_fmt); | 118 int bits_per_channel = av_get_bits_per_sample_fmt(codec_context->sample_fmt); |
77 ChannelLayout channel_layout = | 119 ChannelLayout channel_layout = |
78 ChannelLayoutToChromeChannelLayout(codec_context->channel_layout, | 120 ChannelLayoutToChromeChannelLayout(codec_context->channel_layout, |
79 codec_context->channels); | 121 codec_context->channels); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 memcpy(codec_context->extradata, config.extra_data(), | 163 memcpy(codec_context->extradata, config.extra_data(), |
122 config.extra_data_size()); | 164 config.extra_data_size()); |
123 memset(codec_context->extradata + config.extra_data_size(), '\0', | 165 memset(codec_context->extradata + config.extra_data_size(), '\0', |
124 FF_INPUT_BUFFER_PADDING_SIZE); | 166 FF_INPUT_BUFFER_PADDING_SIZE); |
125 } else { | 167 } else { |
126 codec_context->extradata = NULL; | 168 codec_context->extradata = NULL; |
127 codec_context->extradata_size = 0; | 169 codec_context->extradata_size = 0; |
128 } | 170 } |
129 } | 171 } |
130 | 172 |
131 VideoCodec CodecIDToVideoCodec(CodecID codec_id) { | 173 void AVStreamToVideoDecoderConfig( |
132 switch (codec_id) { | 174 const AVStream* stream, |
133 case CODEC_ID_VC1: | 175 VideoDecoderConfig* config) { |
134 return kCodecVC1; | 176 gfx::Size coded_size(stream->codec->coded_width, stream->codec->coded_height); |
135 case CODEC_ID_H264: | 177 |
136 return kCodecH264; | 178 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true |
137 case CODEC_ID_THEORA: | 179 // for now, but may not always be true forever. Fix this in the future. |
138 return kCodecTheora; | 180 gfx::Rect visible_rect(stream->codec->width, stream->codec->height); |
139 case CODEC_ID_MPEG2VIDEO: | 181 |
140 return kCodecMPEG2; | 182 AVRational aspect_ratio = { 1, 1 }; |
141 case CODEC_ID_MPEG4: | 183 if (stream->sample_aspect_ratio.num) |
142 return kCodecMPEG4; | 184 aspect_ratio = stream->sample_aspect_ratio; |
143 case CODEC_ID_VP8: | 185 else if (stream->codec->sample_aspect_ratio.num) |
144 return kCodecVP8; | 186 aspect_ratio = stream->codec->sample_aspect_ratio; |
145 default: | 187 |
146 NOTREACHED(); | 188 config->Initialize(CodecIDToVideoCodec(stream->codec->codec_id), |
147 } | 189 PixelFormatToVideoFormat(stream->codec->pix_fmt), |
148 return kUnknownVideoCodec; | 190 coded_size, visible_rect, |
| 191 stream->r_frame_rate.num, |
| 192 stream->r_frame_rate.den, |
| 193 aspect_ratio.num, |
| 194 aspect_ratio.den, |
| 195 stream->codec->extradata, |
| 196 stream->codec->extradata_size); |
149 } | 197 } |
150 | 198 |
151 CodecID VideoCodecToCodecID(VideoCodec video_codec) { | 199 void VideoDecoderConfigToAVCodecContext( |
152 switch (video_codec) { | 200 const VideoDecoderConfig& config, |
153 case kUnknownVideoCodec: | 201 AVCodecContext* codec_context) { |
154 return CODEC_ID_NONE; | 202 codec_context->codec_type = AVMEDIA_TYPE_VIDEO; |
155 case kCodecVC1: | 203 codec_context->codec_id = VideoCodecToCodecID(config.codec()); |
156 return CODEC_ID_VC1; | 204 codec_context->coded_width = config.coded_size().width(); |
157 case kCodecH264: | 205 codec_context->coded_height = config.coded_size().height(); |
158 return CODEC_ID_H264; | 206 codec_context->pix_fmt = VideoFormatToPixelFormat(config.format()); |
159 case kCodecTheora: | 207 |
160 return CODEC_ID_THEORA; | 208 if (config.extra_data()) { |
161 case kCodecMPEG2: | 209 codec_context->extradata_size = config.extra_data_size(); |
162 return CODEC_ID_MPEG2VIDEO; | 210 codec_context->extradata = reinterpret_cast<uint8_t*>( |
163 case kCodecMPEG4: | 211 av_malloc(config.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE)); |
164 return CODEC_ID_MPEG4; | 212 memcpy(codec_context->extradata, config.extra_data(), |
165 case kCodecVP8: | 213 config.extra_data_size()); |
166 return CODEC_ID_VP8; | 214 memset(codec_context->extradata + config.extra_data_size(), '\0', |
167 default: | 215 FF_INPUT_BUFFER_PADDING_SIZE); |
168 NOTREACHED(); | 216 } else { |
| 217 codec_context->extradata = NULL; |
| 218 codec_context->extradata_size = 0; |
169 } | 219 } |
170 return CODEC_ID_NONE; | |
171 } | 220 } |
172 | 221 |
173 ChannelLayout ChannelLayoutToChromeChannelLayout(int64_t layout, | 222 ChannelLayout ChannelLayoutToChromeChannelLayout(int64_t layout, |
174 int channels) { | 223 int channels) { |
175 switch (layout) { | 224 switch (layout) { |
176 case CH_LAYOUT_MONO: | 225 case CH_LAYOUT_MONO: |
177 return CHANNEL_LAYOUT_MONO; | 226 return CHANNEL_LAYOUT_MONO; |
178 case CH_LAYOUT_STEREO: | 227 case CH_LAYOUT_STEREO: |
179 return CHANNEL_LAYOUT_STEREO; | 228 return CHANNEL_LAYOUT_STEREO; |
180 case CH_LAYOUT_2_1: | 229 case CH_LAYOUT_2_1: |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 case VideoFrame::YV16: | 281 case VideoFrame::YV16: |
233 return PIX_FMT_YUV422P; | 282 return PIX_FMT_YUV422P; |
234 case VideoFrame::YV12: | 283 case VideoFrame::YV12: |
235 return PIX_FMT_YUV420P; | 284 return PIX_FMT_YUV420P; |
236 default: | 285 default: |
237 NOTREACHED() << "Unsupported VideoFrame Format: " << video_format; | 286 NOTREACHED() << "Unsupported VideoFrame Format: " << video_format; |
238 } | 287 } |
239 return PIX_FMT_NONE; | 288 return PIX_FMT_NONE; |
240 } | 289 } |
241 | 290 |
242 base::TimeDelta GetFrameDuration(AVStream* stream) { | 291 base::TimeDelta GetFrameDuration(const VideoDecoderConfig& config) { |
243 AVRational time_base = { stream->r_frame_rate.den, stream->r_frame_rate.num }; | 292 AVRational time_base = { |
| 293 config.frame_rate_denominator(), |
| 294 config.frame_rate_numerator() |
| 295 }; |
244 return ConvertFromTimeBase(time_base, 1); | 296 return ConvertFromTimeBase(time_base, 1); |
245 } | 297 } |
246 | 298 |
247 gfx::Size GetNaturalSize(AVStream* stream) { | |
248 double aspect_ratio = 1.0; | |
249 | |
250 if (stream->sample_aspect_ratio.num) | |
251 aspect_ratio = av_q2d(stream->sample_aspect_ratio); | |
252 else if (stream->codec->sample_aspect_ratio.num) | |
253 aspect_ratio = av_q2d(stream->codec->sample_aspect_ratio); | |
254 | |
255 int height = stream->codec->height; | |
256 int width = floor(stream->codec->width * aspect_ratio + 0.5); | |
257 | |
258 // An even width makes things easier for YV12 and appears to be the behavior | |
259 // expected by WebKit layout tests. | |
260 return gfx::Size(width & ~1, height); | |
261 } | |
262 | |
263 void DestroyAVFormatContext(AVFormatContext* format_context) { | 299 void DestroyAVFormatContext(AVFormatContext* format_context) { |
264 DCHECK(format_context); | 300 DCHECK(format_context); |
265 | 301 |
266 // Iterate each stream and destroy each one of them. | 302 // Iterate each stream and destroy each one of them. |
267 if (format_context->streams) { | 303 if (format_context->streams) { |
268 int streams = format_context->nb_streams; | 304 int streams = format_context->nb_streams; |
269 for (int i = 0; i < streams; ++i) { | 305 for (int i = 0; i < streams; ++i) { |
270 AVStream* stream = format_context->streams[i]; | 306 AVStream* stream = format_context->streams[i]; |
271 | 307 |
272 // The conditions for calling avcodec_close(): | 308 // The conditions for calling avcodec_close(): |
273 // 1. AVStream is alive. | 309 // 1. AVStream is alive. |
274 // 2. AVCodecContext in AVStream is alive. | 310 // 2. AVCodecContext in AVStream is alive. |
275 // 3. AVCodec in AVCodecContext is alive. | 311 // 3. AVCodec in AVCodecContext is alive. |
276 // Notice that closing a codec context without prior avcodec_open() will | 312 // Notice that closing a codec context without prior avcodec_open() will |
277 // result in a crash in FFmpeg. | 313 // result in a crash in FFmpeg. |
278 if (stream && stream->codec && stream->codec->codec) { | 314 if (stream && stream->codec && stream->codec->codec) { |
279 stream->discard = AVDISCARD_ALL; | 315 stream->discard = AVDISCARD_ALL; |
280 avcodec_close(stream->codec); | 316 avcodec_close(stream->codec); |
281 } | 317 } |
282 } | 318 } |
283 } | 319 } |
284 | 320 |
285 // Then finally cleanup the format context. | 321 // Then finally cleanup the format context. |
286 av_close_input_file(format_context); | 322 av_close_input_file(format_context); |
287 } | 323 } |
288 | 324 |
289 } // namespace media | 325 } // namespace media |
OLD | NEW |