| 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 |