Chromium Code Reviews| 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" |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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], µseconds)) | |
| 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 Loading... | |
| 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 |
| OLD | NEW |