| 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/ffmpeg/ffmpeg_common.h" | 5 #include "media/ffmpeg/ffmpeg_common.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/sha1.h" | 8 #include "base/sha1.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 break; | 398 break; |
| 399 default: | 399 default: |
| 400 DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8, | 400 DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8, |
| 401 config->bits_per_channel()); | 401 config->bits_per_channel()); |
| 402 break; | 402 break; |
| 403 } | 403 } |
| 404 | 404 |
| 405 return true; | 405 return true; |
| 406 } | 406 } |
| 407 | 407 |
| 408 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> |
| 409 AVStreamToAVCodecContext(const AVStream* stream) { |
| 410 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context( |
| 411 avcodec_alloc_context3(nullptr)); |
| 412 if (avcodec_parameters_to_context(codec_context.get(), stream->codecpar) < |
| 413 0) { |
| 414 return nullptr; |
| 415 } |
| 416 |
| 417 return codec_context; |
| 418 } |
| 419 |
| 408 bool AVStreamToAudioDecoderConfig(const AVStream* stream, | 420 bool AVStreamToAudioDecoderConfig(const AVStream* stream, |
| 409 AudioDecoderConfig* config) { | 421 AudioDecoderConfig* config) { |
| 422 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context( |
| 423 AVStreamToAVCodecContext(stream)); |
| 424 if (!codec_context) |
| 425 return false; |
| 426 |
| 410 return AVCodecContextToAudioDecoderConfig( | 427 return AVCodecContextToAudioDecoderConfig( |
| 411 stream->codec, GetEncryptionScheme(stream), config); | 428 codec_context.get(), GetEncryptionScheme(stream), config); |
| 412 } | 429 } |
| 413 | 430 |
| 414 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config, | 431 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config, |
| 415 AVCodecContext* codec_context) { | 432 AVCodecContext* codec_context) { |
| 416 codec_context->codec_type = AVMEDIA_TYPE_AUDIO; | 433 codec_context->codec_type = AVMEDIA_TYPE_AUDIO; |
| 417 codec_context->codec_id = AudioCodecToCodecID(config.codec(), | 434 codec_context->codec_id = AudioCodecToCodecID(config.codec(), |
| 418 config.sample_format()); | 435 config.sample_format()); |
| 419 codec_context->sample_fmt = SampleFormatToAVSampleFormat( | 436 codec_context->sample_fmt = SampleFormatToAVSampleFormat( |
| 420 config.sample_format()); | 437 config.sample_format()); |
| 421 | 438 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 434 av_malloc(config.extra_data().size() + FF_INPUT_BUFFER_PADDING_SIZE)); | 451 av_malloc(config.extra_data().size() + FF_INPUT_BUFFER_PADDING_SIZE)); |
| 435 memcpy(codec_context->extradata, &config.extra_data()[0], | 452 memcpy(codec_context->extradata, &config.extra_data()[0], |
| 436 config.extra_data().size()); | 453 config.extra_data().size()); |
| 437 memset(codec_context->extradata + config.extra_data().size(), '\0', | 454 memset(codec_context->extradata + config.extra_data().size(), '\0', |
| 438 FF_INPUT_BUFFER_PADDING_SIZE); | 455 FF_INPUT_BUFFER_PADDING_SIZE); |
| 439 } | 456 } |
| 440 } | 457 } |
| 441 | 458 |
| 442 bool AVStreamToVideoDecoderConfig(const AVStream* stream, | 459 bool AVStreamToVideoDecoderConfig(const AVStream* stream, |
| 443 VideoDecoderConfig* config) { | 460 VideoDecoderConfig* config) { |
| 444 // Anticipating AVStream.codec.coded_{width,height} will be inaccessible in | 461 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context( |
| 445 // ffmpeg soon, just use the width and height, padded below, as hints of the | 462 AVStreamToAVCodecContext(stream)); |
| 446 // coded size. | 463 if (!codec_context) |
| 447 gfx::Size coded_size(stream->codec->width, stream->codec->height); | 464 return false; |
| 465 |
| 466 // AVStream.codec->coded_{width,height} access is deprecated in ffmpeg. |
| 467 // Use just the width and height as hints of coded size. |
| 468 gfx::Size coded_size(codec_context->width, codec_context->height); |
| 448 | 469 |
| 449 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true | 470 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true |
| 450 // for now, but may not always be true forever. Fix this in the future. | 471 // for now, but may not always be true forever. Fix this in the future. |
| 451 gfx::Rect visible_rect(stream->codec->width, stream->codec->height); | 472 gfx::Rect visible_rect(codec_context->width, codec_context->height); |
| 452 | 473 |
| 453 AVRational aspect_ratio = { 1, 1 }; | 474 AVRational aspect_ratio = { 1, 1 }; |
| 454 if (stream->sample_aspect_ratio.num) | 475 if (stream->sample_aspect_ratio.num) |
| 455 aspect_ratio = stream->sample_aspect_ratio; | 476 aspect_ratio = stream->sample_aspect_ratio; |
| 456 else if (stream->codec->sample_aspect_ratio.num) | 477 else if (codec_context->sample_aspect_ratio.num) |
| 457 aspect_ratio = stream->codec->sample_aspect_ratio; | 478 aspect_ratio = codec_context->sample_aspect_ratio; |
| 458 | 479 |
| 459 VideoCodec codec = CodecIDToVideoCodec(stream->codec->codec_id); | 480 VideoCodec codec = CodecIDToVideoCodec(codec_context->codec_id); |
| 460 | 481 |
| 461 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 482 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
| 462 if (codec == kCodecVP8) | 483 if (codec == kCodecVP8) |
| 463 profile = VP8PROFILE_ANY; | 484 profile = VP8PROFILE_ANY; |
| 464 else if (codec == kCodecVP9) | 485 else if (codec == kCodecVP9) |
| 465 // TODO(servolk): Find a way to obtain actual VP9 profile from FFmpeg. | 486 // TODO(servolk): Find a way to obtain actual VP9 profile from FFmpeg. |
| 466 // crbug.com/592074 | 487 // crbug.com/592074 |
| 467 profile = VP9PROFILE_PROFILE0; | 488 profile = VP9PROFILE_PROFILE0; |
| 468 else | 489 else |
| 469 profile = ProfileIDToVideoCodecProfile(stream->codec->profile); | 490 profile = ProfileIDToVideoCodecProfile(codec_context->profile); |
| 470 | 491 |
| 471 // Without the FFmpeg h264 decoder, AVFormat is unable to get the profile, so | 492 // Without the FFmpeg h264 decoder, AVFormat is unable to get the profile, so |
| 472 // default to baseline and let the VDA fail later if it doesn't support the | 493 // default to baseline and let the VDA fail later if it doesn't support the |
| 473 // real profile. This is alright because if the FFmpeg h264 decoder isn't | 494 // real profile. This is alright because if the FFmpeg h264 decoder isn't |
| 474 // enabled, there is no fallback if the VDA fails. | 495 // enabled, there is no fallback if the VDA fails. |
| 475 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) | 496 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) |
| 476 if (codec == kCodecH264) | 497 if (codec == kCodecH264) |
| 477 profile = H264PROFILE_BASELINE; | 498 profile = H264PROFILE_BASELINE; |
| 478 #endif | 499 #endif |
| 479 | 500 |
| 480 gfx::Size natural_size = GetNaturalSize( | 501 gfx::Size natural_size = GetNaturalSize( |
| 481 visible_rect.size(), aspect_ratio.num, aspect_ratio.den); | 502 visible_rect.size(), aspect_ratio.num, aspect_ratio.den); |
| 482 | 503 |
| 483 VideoPixelFormat format = | 504 VideoPixelFormat format = |
| 484 AVPixelFormatToVideoPixelFormat(stream->codec->pix_fmt); | 505 AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt); |
| 485 // The format and coded size may be unknown if FFmpeg is compiled without | 506 // The format and coded size may be unknown if FFmpeg is compiled without |
| 486 // video decoders. | 507 // video decoders. |
| 487 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) | 508 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) |
| 488 if (format == PIXEL_FORMAT_UNKNOWN) | 509 if (format == PIXEL_FORMAT_UNKNOWN) |
| 489 format = PIXEL_FORMAT_YV12; | 510 format = PIXEL_FORMAT_YV12; |
| 490 if (coded_size == gfx::Size(0, 0)) | 511 if (coded_size == gfx::Size(0, 0)) |
| 491 coded_size = visible_rect.size(); | 512 coded_size = visible_rect.size(); |
| 492 #endif | 513 #endif |
| 493 | 514 |
| 494 if (codec == kCodecVP9) { | 515 if (codec == kCodecVP9) { |
| 495 // TODO(tomfinegan): libavcodec doesn't know about VP9. | 516 // TODO(tomfinegan): libavcodec doesn't know about VP9. |
| 496 format = PIXEL_FORMAT_YV12; | 517 format = PIXEL_FORMAT_YV12; |
| 497 coded_size = visible_rect.size(); | 518 coded_size = visible_rect.size(); |
| 498 } | 519 } |
| 499 | 520 |
| 500 // Pad out |coded_size| for subsampled YUV formats. | 521 // Pad out |coded_size| for subsampled YUV formats. |
| 501 if (format != PIXEL_FORMAT_YV24) { | 522 if (format != PIXEL_FORMAT_YV24) { |
| 502 coded_size.set_width((coded_size.width() + 1) / 2 * 2); | 523 coded_size.set_width((coded_size.width() + 1) / 2 * 2); |
| 503 if (format != PIXEL_FORMAT_YV16) | 524 if (format != PIXEL_FORMAT_YV16) |
| 504 coded_size.set_height((coded_size.height() + 1) / 2 * 2); | 525 coded_size.set_height((coded_size.height() + 1) / 2 * 2); |
| 505 } | 526 } |
| 506 | 527 |
| 507 AVDictionaryEntry* webm_alpha = | 528 AVDictionaryEntry* webm_alpha = |
| 508 av_dict_get(stream->metadata, "alpha_mode", nullptr, 0); | 529 av_dict_get(stream->metadata, "alpha_mode", nullptr, 0); |
| 509 if (webm_alpha && !strcmp(webm_alpha->value, "1")) { | 530 if (webm_alpha && !strcmp(webm_alpha->value, "1")) { |
| 510 format = PIXEL_FORMAT_YV12A; | 531 format = PIXEL_FORMAT_YV12A; |
| 511 } | 532 } |
| 512 | 533 |
| 513 // Prefer the color space found by libavcodec if available. | 534 // Prefer the color space found by libavcodec if available. |
| 514 ColorSpace color_space = AVColorSpaceToColorSpace(stream->codec->colorspace, | 535 ColorSpace color_space = AVColorSpaceToColorSpace(codec_context->colorspace, |
| 515 stream->codec->color_range); | 536 codec_context->color_range); |
| 516 if (color_space == COLOR_SPACE_UNSPECIFIED) { | 537 if (color_space == COLOR_SPACE_UNSPECIFIED) { |
| 517 // Otherwise, assume that SD video is usually Rec.601, and HD is usually | 538 // Otherwise, assume that SD video is usually Rec.601, and HD is usually |
| 518 // Rec.709. | 539 // Rec.709. |
| 519 color_space = (natural_size.height() < 720) ? COLOR_SPACE_SD_REC601 | 540 color_space = (natural_size.height() < 720) ? COLOR_SPACE_SD_REC601 |
| 520 : COLOR_SPACE_HD_REC709; | 541 : COLOR_SPACE_HD_REC709; |
| 521 } | 542 } |
| 522 | 543 |
| 523 // AVStream occasionally has invalid extra data. See http://crbug.com/517163 | 544 // AVCodecContext occasionally has invalid extra data. See |
| 524 if ((stream->codec->extradata_size == 0) != | 545 // http://crbug.com/517163 |
| 525 (stream->codec->extradata == nullptr)) { | 546 if (codec_context->extradata != nullptr && |
| 526 LOG(ERROR) << __func__ | 547 codec_context->extradata_size == 0) { |
| 527 << (stream->codec->extradata == nullptr ? " NULL" : " Non-Null") | 548 LOG(ERROR) << __func__ << " Non-Null extra data cannot have size of 0."; |
| 528 << " extra data cannot have size of " | |
| 529 << stream->codec->extradata_size << "."; | |
| 530 return false; | 549 return false; |
| 531 } | 550 } |
| 551 CHECK_EQ(codec_context->extradata == nullptr, |
| 552 codec_context->extradata_size == 0); |
| 532 | 553 |
| 533 std::vector<uint8_t> extra_data; | 554 std::vector<uint8_t> extra_data; |
| 534 if (stream->codec->extradata_size > 0) { | 555 if (codec_context->extradata_size > 0) { |
| 535 extra_data.assign(stream->codec->extradata, | 556 extra_data.assign(codec_context->extradata, |
| 536 stream->codec->extradata + stream->codec->extradata_size); | 557 codec_context->extradata + codec_context->extradata_size); |
| 537 } | 558 } |
| 538 config->Initialize(codec, profile, format, color_space, coded_size, | 559 config->Initialize(codec, profile, format, color_space, coded_size, |
| 539 visible_rect, natural_size, extra_data, | 560 visible_rect, natural_size, extra_data, |
| 540 GetEncryptionScheme(stream)); | 561 GetEncryptionScheme(stream)); |
| 541 return true; | 562 return true; |
| 542 } | 563 } |
| 543 | 564 |
| 544 void VideoDecoderConfigToAVCodecContext( | 565 void VideoDecoderConfigToAVCodecContext( |
| 545 const VideoDecoderConfig& config, | 566 const VideoDecoderConfig& config, |
| 546 AVCodecContext* codec_context) { | 567 AVCodecContext* codec_context) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 return COLOR_SPACE_HD_REC709; | 747 return COLOR_SPACE_HD_REC709; |
| 727 case AVCOL_SPC_SMPTE170M: | 748 case AVCOL_SPC_SMPTE170M: |
| 728 case AVCOL_SPC_BT470BG: | 749 case AVCOL_SPC_BT470BG: |
| 729 return COLOR_SPACE_SD_REC601; | 750 return COLOR_SPACE_SD_REC601; |
| 730 default: | 751 default: |
| 731 DVLOG(1) << "Unknown AVColorSpace: " << color_space; | 752 DVLOG(1) << "Unknown AVColorSpace: " << color_space; |
| 732 } | 753 } |
| 733 return COLOR_SPACE_UNSPECIFIED; | 754 return COLOR_SPACE_UNSPECIFIED; |
| 734 } | 755 } |
| 735 | 756 |
| 736 bool FFmpegUTCDateToTime(const char* date_utc, base::Time* out) { | |
| 737 DCHECK(date_utc); | |
| 738 DCHECK(out); | |
| 739 | |
| 740 std::vector<base::StringPiece> fields = base::SplitStringPiece( | |
| 741 date_utc, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 742 if (fields.size() != 2) | |
| 743 return false; | |
| 744 | |
| 745 std::vector<base::StringPiece> date_fields = base::SplitStringPiece( | |
| 746 fields[0], "-", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 747 if (date_fields.size() != 3) | |
| 748 return false; | |
| 749 | |
| 750 // TODO(acolwell): Update this parsing code when FFmpeg returns sub-second | |
| 751 // information. | |
| 752 std::vector<base::StringPiece> time_fields = base::SplitStringPiece( | |
| 753 fields[1], ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 754 if (time_fields.size() != 3) | |
| 755 return false; | |
| 756 | |
| 757 base::Time::Exploded exploded; | |
| 758 exploded.millisecond = 0; | |
| 759 // This field cannot be uninitialized. Unless not modified, make it 0 here | |
| 760 // then. | |
| 761 exploded.day_of_week = 0; | |
| 762 if (base::StringToInt(date_fields[0], &exploded.year) && | |
| 763 base::StringToInt(date_fields[1], &exploded.month) && | |
| 764 base::StringToInt(date_fields[2], &exploded.day_of_month) && | |
| 765 base::StringToInt(time_fields[0], &exploded.hour) && | |
| 766 base::StringToInt(time_fields[1], &exploded.minute) && | |
| 767 base::StringToInt(time_fields[2], &exploded.second)) { | |
| 768 if (base::Time::FromUTCExploded(exploded, out)) | |
| 769 return true; | |
| 770 } | |
| 771 | |
| 772 return false; | |
| 773 } | |
| 774 | |
| 775 int32_t HashCodecName(const char* codec_name) { | 757 int32_t HashCodecName(const char* codec_name) { |
| 776 // Use the first 32-bits from the SHA1 hash as the identifier. | 758 // Use the first 32-bits from the SHA1 hash as the identifier. |
| 777 int32_t hash; | 759 int32_t hash; |
| 778 memcpy(&hash, base::SHA1HashString(codec_name).substr(0, 4).c_str(), 4); | 760 memcpy(&hash, base::SHA1HashString(codec_name).substr(0, 4).c_str(), 4); |
| 779 return hash; | 761 return hash; |
| 780 } | 762 } |
| 781 | 763 |
| 782 #define TEST_PRIMARY(P) \ | 764 #define TEST_PRIMARY(P) \ |
| 783 static_assert( \ | 765 static_assert( \ |
| 784 static_cast<int>(gfx::ColorSpace::PrimaryID::P) == AVCOL_PRI_##P, \ | 766 static_cast<int>(gfx::ColorSpace::PrimaryID::P) == AVCOL_PRI_##P, \ |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 TEST_COLORSPACE(RESERVED); | 813 TEST_COLORSPACE(RESERVED); |
| 832 TEST_COLORSPACE(FCC); | 814 TEST_COLORSPACE(FCC); |
| 833 TEST_COLORSPACE(BT470BG); | 815 TEST_COLORSPACE(BT470BG); |
| 834 TEST_COLORSPACE(SMPTE170M); | 816 TEST_COLORSPACE(SMPTE170M); |
| 835 TEST_COLORSPACE(SMPTE240M); | 817 TEST_COLORSPACE(SMPTE240M); |
| 836 TEST_COLORSPACE(YCOCG); | 818 TEST_COLORSPACE(YCOCG); |
| 837 TEST_COLORSPACE(BT2020_NCL); | 819 TEST_COLORSPACE(BT2020_NCL); |
| 838 TEST_COLORSPACE(BT2020_CL); | 820 TEST_COLORSPACE(BT2020_CL); |
| 839 | 821 |
| 840 } // namespace media | 822 } // namespace media |
| OLD | NEW |