Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: media/ffmpeg/ffmpeg_common.cc

Issue 2497603003: Roll src/third_party/ffmpeg/ 3c7a09882..cdf4accee (3188 commits). (Closed)
Patch Set: Rebase (liberato@'s pipeline_integration_test_base conflicted; using liberato@'s now here) Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "build/build_config.h" 12 #include "build/build_config.h"
13 #include "media/base/audio_decoder_config.h" 13 #include "media/base/audio_decoder_config.h"
14 #include "media/base/decoder_buffer.h" 14 #include "media/base/decoder_buffer.h"
15 #include "media/base/encryption_scheme.h" 15 #include "media/base/encryption_scheme.h"
16 #include "media/base/media_util.h" 16 #include "media/base/media_util.h"
17 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
18 #include "media/base/video_util.h" 18 #include "media/base/video_util.h"
19 #include "media/media_features.h" 19 #include "media/media_features.h"
20 20
21 namespace media { 21 namespace media {
22 22
23 namespace { 23 namespace {
24 24
25 gfx::Size GetCodedSize(AVCodecContext* context) {
DaleCurtis 2016/11/14 17:58:20 Do we need this function? It seems like we should
wolenetz 2016/11/15 02:15:35 We record stats including coded size (perhaps we d
26 DCHECK(context);
27
28 // Open a temporary decode, to try to get coded size if codec is supported.
29 AVCodec* codec = avcodec_find_decoder(context->codec_id);
DaleCurtis 2016/11/14 17:58:21 Doesn't this need to be released?
wolenetz 2016/11/15 02:15:35 No. Rather, the caller's management of |context|'s
30 if (codec && avcodec_open2(context, codec, NULL) >= 0 &&
31 context->coded_width > 0 && context->coded_height > 0) {
32 return gfx::Size(context->coded_width, context->coded_height);
33 }
34
35 // Otherwise, either ffmpeg does not support decode of the codec or opening
36 // the decoder failed. Default to the width/height. If a decoder other than
37 // ffmpeg is used, it will need to figure out the correct coded size.
38 return gfx::Size(context->width, context->height);
39 }
40
25 EncryptionScheme GetEncryptionScheme(const AVStream* stream) { 41 EncryptionScheme GetEncryptionScheme(const AVStream* stream) {
26 AVDictionaryEntry* key = 42 AVDictionaryEntry* key =
27 av_dict_get(stream->metadata, "enc_key_id", nullptr, 0); 43 av_dict_get(stream->metadata, "enc_key_id", nullptr, 0);
28 return key ? AesCtrEncryptionScheme() : Unencrypted(); 44 return key ? AesCtrEncryptionScheme() : Unencrypted();
29 } 45 }
30 46
31 } // namespace 47 } // namespace
32 48
33 // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are 49 // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are
34 // padded. Check here to ensure FFmpeg only receives data padded to its 50 // padded. Check here to ensure FFmpeg only receives data padded to its
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8, 416 DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8,
401 config->bits_per_channel()); 417 config->bits_per_channel());
402 break; 418 break;
403 } 419 }
404 420
405 return true; 421 return true;
406 } 422 }
407 423
408 bool AVStreamToAudioDecoderConfig(const AVStream* stream, 424 bool AVStreamToAudioDecoderConfig(const AVStream* stream,
409 AudioDecoderConfig* config) { 425 AudioDecoderConfig* config) {
426 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context(
DaleCurtis 2016/11/14 17:58:20 Seems this could be extracted to a helper function
wolenetz 2016/11/15 02:15:35 SGTM. I was beginning to think similar :) Done.
427 avcodec_alloc_context3(NULL));
428 if (!codec_context ||
429 avcodec_parameters_to_context(codec_context.get(), stream->codecpar) <
430 0) {
431 return false;
432 }
433
410 return AVCodecContextToAudioDecoderConfig( 434 return AVCodecContextToAudioDecoderConfig(
411 stream->codec, GetEncryptionScheme(stream), config); 435 codec_context.get(), GetEncryptionScheme(stream), config);
412 } 436 }
413 437
414 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config, 438 void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config,
415 AVCodecContext* codec_context) { 439 AVCodecContext* codec_context) {
416 codec_context->codec_type = AVMEDIA_TYPE_AUDIO; 440 codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
417 codec_context->codec_id = AudioCodecToCodecID(config.codec(), 441 codec_context->codec_id = AudioCodecToCodecID(config.codec(),
418 config.sample_format()); 442 config.sample_format());
419 codec_context->sample_fmt = SampleFormatToAVSampleFormat( 443 codec_context->sample_fmt = SampleFormatToAVSampleFormat(
420 config.sample_format()); 444 config.sample_format());
421 445
(...skipping 12 matching lines...) Expand all
434 av_malloc(config.extra_data().size() + FF_INPUT_BUFFER_PADDING_SIZE)); 458 av_malloc(config.extra_data().size() + FF_INPUT_BUFFER_PADDING_SIZE));
435 memcpy(codec_context->extradata, &config.extra_data()[0], 459 memcpy(codec_context->extradata, &config.extra_data()[0],
436 config.extra_data().size()); 460 config.extra_data().size());
437 memset(codec_context->extradata + config.extra_data().size(), '\0', 461 memset(codec_context->extradata + config.extra_data().size(), '\0',
438 FF_INPUT_BUFFER_PADDING_SIZE); 462 FF_INPUT_BUFFER_PADDING_SIZE);
439 } 463 }
440 } 464 }
441 465
442 bool AVStreamToVideoDecoderConfig(const AVStream* stream, 466 bool AVStreamToVideoDecoderConfig(const AVStream* stream,
443 VideoDecoderConfig* config) { 467 VideoDecoderConfig* config) {
444 gfx::Size coded_size(stream->codec->coded_width, stream->codec->coded_height); 468 std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context(
469 avcodec_alloc_context3(NULL));
470 if (!codec_context ||
471 avcodec_parameters_to_context(codec_context.get(), stream->codecpar) <
472 0) {
473 return false;
474 }
475
476 // This call will attempt to open a decoder to further populate
477 // |codec_context|.
478 gfx::Size coded_size(GetCodedSize(codec_context.get()));
445 479
446 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true 480 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true
447 // for now, but may not always be true forever. Fix this in the future. 481 // for now, but may not always be true forever. Fix this in the future.
448 gfx::Rect visible_rect(stream->codec->width, stream->codec->height); 482 gfx::Rect visible_rect(codec_context->width, codec_context->height);
449 483
450 AVRational aspect_ratio = { 1, 1 }; 484 AVRational aspect_ratio = { 1, 1 };
451 if (stream->sample_aspect_ratio.num) 485 if (stream->sample_aspect_ratio.num)
452 aspect_ratio = stream->sample_aspect_ratio; 486 aspect_ratio = stream->sample_aspect_ratio;
453 else if (stream->codec->sample_aspect_ratio.num) 487 else if (codec_context->sample_aspect_ratio.num)
454 aspect_ratio = stream->codec->sample_aspect_ratio; 488 aspect_ratio = codec_context->sample_aspect_ratio;
455 489
456 VideoCodec codec = CodecIDToVideoCodec(stream->codec->codec_id); 490 VideoCodec codec = CodecIDToVideoCodec(codec_context->codec_id);
457 491
458 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; 492 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
459 if (codec == kCodecVP8) 493 if (codec == kCodecVP8)
460 profile = VP8PROFILE_ANY; 494 profile = VP8PROFILE_ANY;
461 else if (codec == kCodecVP9) 495 else if (codec == kCodecVP9)
462 // TODO(servolk): Find a way to obtain actual VP9 profile from FFmpeg. 496 // TODO(servolk): Find a way to obtain actual VP9 profile from FFmpeg.
463 // crbug.com/592074 497 // crbug.com/592074
464 profile = VP9PROFILE_PROFILE0; 498 profile = VP9PROFILE_PROFILE0;
465 else 499 else
466 profile = ProfileIDToVideoCodecProfile(stream->codec->profile); 500 profile = ProfileIDToVideoCodecProfile(codec_context->profile);
467 501
468 // Without the FFmpeg h264 decoder, AVFormat is unable to get the profile, so 502 // Without the FFmpeg h264 decoder, AVFormat is unable to get the profile, so
469 // default to baseline and let the VDA fail later if it doesn't support the 503 // default to baseline and let the VDA fail later if it doesn't support the
470 // real profile. This is alright because if the FFmpeg h264 decoder isn't 504 // real profile. This is alright because if the FFmpeg h264 decoder isn't
471 // enabled, there is no fallback if the VDA fails. 505 // enabled, there is no fallback if the VDA fails.
472 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) 506 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS)
473 if (codec == kCodecH264) 507 if (codec == kCodecH264)
474 profile = H264PROFILE_BASELINE; 508 profile = H264PROFILE_BASELINE;
475 #endif 509 #endif
476 510
477 gfx::Size natural_size = GetNaturalSize( 511 gfx::Size natural_size = GetNaturalSize(
478 visible_rect.size(), aspect_ratio.num, aspect_ratio.den); 512 visible_rect.size(), aspect_ratio.num, aspect_ratio.den);
479 513
480 VideoPixelFormat format = 514 VideoPixelFormat format =
481 AVPixelFormatToVideoPixelFormat(stream->codec->pix_fmt); 515 AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt);
482 // The format and coded size may be unknown if FFmpeg is compiled without 516 // The format and coded size may be unknown if FFmpeg is compiled without
483 // video decoders. 517 // video decoders.
484 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS) 518 #if defined(DISABLE_FFMPEG_VIDEO_DECODERS)
485 if (format == PIXEL_FORMAT_UNKNOWN) 519 if (format == PIXEL_FORMAT_UNKNOWN)
486 format = PIXEL_FORMAT_YV12; 520 format = PIXEL_FORMAT_YV12;
487 if (coded_size == gfx::Size(0, 0)) 521 if (coded_size == gfx::Size(0, 0))
488 coded_size = visible_rect.size(); 522 coded_size = visible_rect.size();
489 #endif 523 #endif
490 524
491 if (codec == kCodecVP9) { 525 if (codec == kCodecVP9) {
492 // TODO(tomfinegan): libavcodec doesn't know about VP9. 526 // TODO(tomfinegan): libavcodec doesn't know about VP9.
493 format = PIXEL_FORMAT_YV12; 527 format = PIXEL_FORMAT_YV12;
494 coded_size = visible_rect.size(); 528 coded_size = visible_rect.size();
495 } 529 }
496 530
497 // Pad out |coded_size| for subsampled YUV formats. 531 // Pad out |coded_size| for subsampled YUV formats.
498 if (format != PIXEL_FORMAT_YV24) { 532 if (format != PIXEL_FORMAT_YV24) {
499 coded_size.set_width((coded_size.width() + 1) / 2 * 2); 533 coded_size.set_width((coded_size.width() + 1) / 2 * 2);
500 if (format != PIXEL_FORMAT_YV16) 534 if (format != PIXEL_FORMAT_YV16)
501 coded_size.set_height((coded_size.height() + 1) / 2 * 2); 535 coded_size.set_height((coded_size.height() + 1) / 2 * 2);
502 } 536 }
503 537
504 AVDictionaryEntry* webm_alpha = 538 AVDictionaryEntry* webm_alpha =
505 av_dict_get(stream->metadata, "alpha_mode", nullptr, 0); 539 av_dict_get(stream->metadata, "alpha_mode", nullptr, 0);
506 if (webm_alpha && !strcmp(webm_alpha->value, "1")) { 540 if (webm_alpha && !strcmp(webm_alpha->value, "1")) {
507 format = PIXEL_FORMAT_YV12A; 541 format = PIXEL_FORMAT_YV12A;
508 } 542 }
509 543
510 // Prefer the color space found by libavcodec if available. 544 // Prefer the color space found by libavcodec if available.
511 ColorSpace color_space = AVColorSpaceToColorSpace(stream->codec->colorspace, 545 ColorSpace color_space = AVColorSpaceToColorSpace(codec_context->colorspace,
512 stream->codec->color_range); 546 codec_context->color_range);
513 if (color_space == COLOR_SPACE_UNSPECIFIED) { 547 if (color_space == COLOR_SPACE_UNSPECIFIED) {
514 // Otherwise, assume that SD video is usually Rec.601, and HD is usually 548 // Otherwise, assume that SD video is usually Rec.601, and HD is usually
515 // Rec.709. 549 // Rec.709.
516 color_space = (natural_size.height() < 720) ? COLOR_SPACE_SD_REC601 550 color_space = (natural_size.height() < 720) ? COLOR_SPACE_SD_REC601
517 : COLOR_SPACE_HD_REC709; 551 : COLOR_SPACE_HD_REC709;
518 } 552 }
519 553
520 // AVStream occasionally has invalid extra data. See http://crbug.com/517163 554 // AVCodecContext occasionally has invalid extra data. See
521 if ((stream->codec->extradata_size == 0) != 555 // http://crbug.com/517163
522 (stream->codec->extradata == nullptr)) { 556 if (codec_context->extradata != nullptr &&
523 LOG(ERROR) << __func__ 557 codec_context->extradata_size == 0) {
524 << (stream->codec->extradata == nullptr ? " NULL" : " Non-Null") 558 LOG(ERROR) << __func__ << " Non-Null extra data cannot have size of 0.";
525 << " extra data cannot have size of "
526 << stream->codec->extradata_size << ".";
527 return false; 559 return false;
528 } 560 }
561 CHECK_EQ(codec_context->extradata == nullptr,
562 codec_context->extradata_size == 0);
529 563
530 std::vector<uint8_t> extra_data; 564 std::vector<uint8_t> extra_data;
531 if (stream->codec->extradata_size > 0) { 565 if (codec_context->extradata_size > 0) {
532 extra_data.assign(stream->codec->extradata, 566 extra_data.assign(codec_context->extradata,
533 stream->codec->extradata + stream->codec->extradata_size); 567 codec_context->extradata + codec_context->extradata_size);
534 } 568 }
535 config->Initialize(codec, profile, format, color_space, coded_size, 569 config->Initialize(codec, profile, format, color_space, coded_size,
536 visible_rect, natural_size, extra_data, 570 visible_rect, natural_size, extra_data,
537 GetEncryptionScheme(stream)); 571 GetEncryptionScheme(stream));
538 return true; 572 return true;
539 } 573 }
540 574
541 void VideoDecoderConfigToAVCodecContext( 575 void VideoDecoderConfigToAVCodecContext(
542 const VideoDecoderConfig& config, 576 const VideoDecoderConfig& config,
543 AVCodecContext* codec_context) { 577 AVCodecContext* codec_context) {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 default: 761 default:
728 DVLOG(1) << "Unknown AVColorSpace: " << color_space; 762 DVLOG(1) << "Unknown AVColorSpace: " << color_space;
729 } 763 }
730 return COLOR_SPACE_UNSPECIFIED; 764 return COLOR_SPACE_UNSPECIFIED;
731 } 765 }
732 766
733 bool FFmpegUTCDateToTime(const char* date_utc, base::Time* out) { 767 bool FFmpegUTCDateToTime(const char* date_utc, base::Time* out) {
734 DCHECK(date_utc); 768 DCHECK(date_utc);
735 DCHECK(out); 769 DCHECK(out);
736 770
771 // Note, base::Time::FromUTCString(date_utc, out) would work for parsing a
DaleCurtis 2016/11/14 17:58:20 Is it really worth having our own implementation?
wolenetz 2016/11/15 02:15:35 Yeah, I tried that first, and found the leniency f
772 // valid FFmpegUTC strictly standardized |date_utc|, but it is more flexible
773 // to allowing missing pieces and having different formats. This method
774 // enforces stricter format expectation of FFmpeg.
737 std::vector<base::StringPiece> fields = base::SplitStringPiece( 775 std::vector<base::StringPiece> fields = base::SplitStringPiece(
738 date_utc, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); 776 date_utc, "T", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
739 if (fields.size() != 2) 777 if (fields.size() != 2)
740 return false; 778 return false;
741 779
742 std::vector<base::StringPiece> date_fields = base::SplitStringPiece( 780 std::vector<base::StringPiece> date_fields = base::SplitStringPiece(
743 fields[0], "-", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); 781 fields[0], "-", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
744 if (date_fields.size() != 3) 782 if (date_fields.size() != 3)
745 return false; 783 return false;
746 784
747 // TODO(acolwell): Update this parsing code when FFmpeg returns sub-second
748 // information.
749 std::vector<base::StringPiece> time_fields = base::SplitStringPiece( 785 std::vector<base::StringPiece> time_fields = base::SplitStringPiece(
750 fields[1], ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); 786 fields[1], ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
751 if (time_fields.size() != 3) 787 if (time_fields.size() != 2)
788 return false;
789
790 std::vector<base::StringPiece> hms_fields = base::SplitStringPiece(
791 time_fields[0], ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
792 if (hms_fields.size() != 3)
793 return false;
794
795 std::vector<base::StringPiece> subsecond_fields = base::SplitStringPiece(
796 time_fields[1], "Z", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
797 if (subsecond_fields.size() != 2 || subsecond_fields[0].length() != 6 ||
798 !subsecond_fields[1].empty()) {
799 return false;
800 }
801
802 int microseconds;
803 if (!base::StringToInt(subsecond_fields[0], &microseconds))
752 return false; 804 return false;
753 805
754 base::Time::Exploded exploded; 806 base::Time::Exploded exploded;
755 exploded.millisecond = 0;
756 // This field cannot be uninitialized. Unless not modified, make it 0 here 807 // This field cannot be uninitialized. Unless not modified, make it 0 here
757 // then. 808 // then.
758 exploded.day_of_week = 0; 809 exploded.day_of_week = 0;
810
811 exploded.millisecond = microseconds / base::Time::kMicrosecondsPerMillisecond;
759 if (base::StringToInt(date_fields[0], &exploded.year) && 812 if (base::StringToInt(date_fields[0], &exploded.year) &&
760 base::StringToInt(date_fields[1], &exploded.month) && 813 base::StringToInt(date_fields[1], &exploded.month) &&
761 base::StringToInt(date_fields[2], &exploded.day_of_month) && 814 base::StringToInt(date_fields[2], &exploded.day_of_month) &&
762 base::StringToInt(time_fields[0], &exploded.hour) && 815 base::StringToInt(hms_fields[0], &exploded.hour) &&
763 base::StringToInt(time_fields[1], &exploded.minute) && 816 base::StringToInt(hms_fields[1], &exploded.minute) &&
764 base::StringToInt(time_fields[2], &exploded.second)) { 817 base::StringToInt(hms_fields[2], &exploded.second)) {
765 if (base::Time::FromUTCExploded(exploded, out)) 818 if (base::Time::FromUTCExploded(exploded, out)) {
819 *out += base::TimeDelta::FromMicroseconds(
820 microseconds % base::Time::kMicrosecondsPerMillisecond);
766 return true; 821 return true;
822 }
767 } 823 }
768 824
769 return false; 825 return false;
770 } 826 }
771 827
772 int32_t HashCodecName(const char* codec_name) { 828 int32_t HashCodecName(const char* codec_name) {
773 // Use the first 32-bits from the SHA1 hash as the identifier. 829 // Use the first 32-bits from the SHA1 hash as the identifier.
774 int32_t hash; 830 int32_t hash;
775 memcpy(&hash, base::SHA1HashString(codec_name).substr(0, 4).c_str(), 4); 831 memcpy(&hash, base::SHA1HashString(codec_name).substr(0, 4).c_str(), 4);
776 return hash; 832 return hash;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 TEST_COLORSPACE(RESERVED); 884 TEST_COLORSPACE(RESERVED);
829 TEST_COLORSPACE(FCC); 885 TEST_COLORSPACE(FCC);
830 TEST_COLORSPACE(BT470BG); 886 TEST_COLORSPACE(BT470BG);
831 TEST_COLORSPACE(SMPTE170M); 887 TEST_COLORSPACE(SMPTE170M);
832 TEST_COLORSPACE(SMPTE240M); 888 TEST_COLORSPACE(SMPTE240M);
833 TEST_COLORSPACE(YCOCG); 889 TEST_COLORSPACE(YCOCG);
834 TEST_COLORSPACE(BT2020_NCL); 890 TEST_COLORSPACE(BT2020_NCL);
835 TEST_COLORSPACE(BT2020_CL); 891 TEST_COLORSPACE(BT2020_CL);
836 892
837 } // namespace media 893 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698