Support HEVC in mp4 parser and muxer
Issue #46 Change-Id: I36bf8418a335181ad71509e6e0cccdce210467f0
This commit is contained in:
parent
8c53995335
commit
4c10755d40
|
@ -84,6 +84,13 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4')
|
self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4')
|
||||||
self._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-golden.mpd')
|
self._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-golden.mpd')
|
||||||
|
|
||||||
|
def testPackageHevcWithEncryption(self):
|
||||||
|
self.packager.Package(self._GetStreams(['video'],
|
||||||
|
test_file='bear-640x360-hevc.mp4'),
|
||||||
|
self._GetFlags(encryption=True))
|
||||||
|
self._DiffGold(self.output[0], 'bear-640x360-hevc-v-cenc-golden.mp4')
|
||||||
|
self._DiffGold(self.mpd_output, 'bear-640x360-hevc-v-cenc-golden.mpd')
|
||||||
|
|
||||||
def testPackageWithEncryptionAndRandomIv(self):
|
def testPackageWithEncryptionAndRandomIv(self):
|
||||||
self.packager.Package(self._GetStreams(['audio', 'video']),
|
self.packager.Package(self._GetStreams(['audio', 'video']),
|
||||||
self._GetFlags(encryption=True, random_iv=True))
|
self._GetFlags(encryption=True, random_iv=True))
|
||||||
|
@ -198,13 +205,14 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
self._AssertStreamInfo(self.output[0], 'is_encrypted: true')
|
self._AssertStreamInfo(self.output[0], 'is_encrypted: true')
|
||||||
self._AssertStreamInfo(self.output[1], 'is_encrypted: true')
|
self._AssertStreamInfo(self.output[1], 'is_encrypted: true')
|
||||||
|
|
||||||
def _GetStreams(self, stream_descriptors, live = False):
|
def _GetStreams(self, stream_descriptors, live = False,
|
||||||
|
test_file = 'bear-640x360.mp4'):
|
||||||
streams = []
|
streams = []
|
||||||
self.output = []
|
self.output = []
|
||||||
|
|
||||||
test_data_dir = os.path.join(
|
test_data_dir = os.path.join(
|
||||||
test_env.SRC_DIR, 'packager', 'media', 'test', 'data')
|
test_env.SRC_DIR, 'packager', 'media', 'test', 'data')
|
||||||
input = os.path.join(test_data_dir, 'bear-640x360.mp4')
|
input = os.path.join(test_data_dir, test_file)
|
||||||
for stream_descriptor in stream_descriptors:
|
for stream_descriptor in stream_descriptors:
|
||||||
if live:
|
if live:
|
||||||
# This is still output prefix actually.
|
# This is still output prefix actually.
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.7694332599639893S">
|
||||||
|
<Period>
|
||||||
|
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subSegmentAlignment="true" par="16:9">
|
||||||
|
<Representation id="0" bandwidth="264624" codecs="hev1.1.6.L63.80" mimeType="video/mp4" sar="1:1" width="640" height="360" frameRate="30000/1001">
|
||||||
|
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
|
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||||
|
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||||
|
</ContentProtection>
|
||||||
|
<BaseURL>output_video.mp4</BaseURL>
|
||||||
|
<SegmentBase indexRange="2721-2764" timescale="30000">
|
||||||
|
<Initialization range="0-2720"/>
|
||||||
|
</SegmentBase>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
</Period>
|
||||||
|
</MPD>
|
|
@ -21,6 +21,10 @@ std::string VideoCodecToString(VideoCodec video_codec) {
|
||||||
switch (video_codec) {
|
switch (video_codec) {
|
||||||
case kCodecH264:
|
case kCodecH264:
|
||||||
return "H264";
|
return "H264";
|
||||||
|
case kCodecHEV1:
|
||||||
|
return "HEV1";
|
||||||
|
case kCodecHVC1:
|
||||||
|
return "HVC1";
|
||||||
case kCodecVC1:
|
case kCodecVC1:
|
||||||
return "VC1";
|
return "VC1";
|
||||||
case kCodecMPEG2:
|
case kCodecMPEG2:
|
||||||
|
|
|
@ -15,6 +15,8 @@ namespace media {
|
||||||
enum VideoCodec {
|
enum VideoCodec {
|
||||||
kUnknownVideoCodec = 0,
|
kUnknownVideoCodec = 0,
|
||||||
kCodecH264,
|
kCodecH264,
|
||||||
|
kCodecHEV1,
|
||||||
|
kCodecHVC1,
|
||||||
kCodecVC1,
|
kCodecVC1,
|
||||||
kCodecMPEG2,
|
kCodecMPEG2,
|
||||||
kCodecMPEG4,
|
kCodecMPEG4,
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
'sources': [
|
'sources': [
|
||||||
'avc_decoder_configuration.cc',
|
'avc_decoder_configuration.cc',
|
||||||
'avc_decoder_configuration.h',
|
'avc_decoder_configuration.h',
|
||||||
|
'hevc_decoder_configuration.cc',
|
||||||
|
'hevc_decoder_configuration.h',
|
||||||
'h264_bit_reader.cc',
|
'h264_bit_reader.cc',
|
||||||
'h264_bit_reader.h',
|
'h264_bit_reader.h',
|
||||||
'h264_byte_to_unit_stream_converter.cc',
|
'h264_byte_to_unit_stream_converter.cc',
|
||||||
|
@ -36,6 +38,7 @@
|
||||||
'h264_bit_reader_unittest.cc',
|
'h264_bit_reader_unittest.cc',
|
||||||
'h264_byte_to_unit_stream_converter_unittest.cc',
|
'h264_byte_to_unit_stream_converter_unittest.cc',
|
||||||
'h264_parser_unittest.cc',
|
'h264_parser_unittest.cc',
|
||||||
|
'hevc_decoder_configuration_unittest.cc',
|
||||||
'vp_codec_configuration_unittest.cc',
|
'vp_codec_configuration_unittest.cc',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
// Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#include "packager/media/filters/hevc_decoder_configuration.h"
|
||||||
|
|
||||||
|
#include "packager/base/stl_util.h"
|
||||||
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
#include "packager/base/strings/string_util.h"
|
||||||
|
#include "packager/media/base/buffer_reader.h"
|
||||||
|
#include "packager/media/formats/mp4/rcheck.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// ISO/IEC 14496-15:2014 Annex E.
|
||||||
|
std::string GeneralProfileSpaceAsString(uint8_t general_profile_space) {
|
||||||
|
switch (general_profile_space) {
|
||||||
|
case 0:
|
||||||
|
return "";
|
||||||
|
case 1:
|
||||||
|
return "A";
|
||||||
|
case 2:
|
||||||
|
return "B";
|
||||||
|
case 3:
|
||||||
|
return "C";
|
||||||
|
default:
|
||||||
|
LOG(WARNING) << "Unexpected general_profile_space "
|
||||||
|
<< general_profile_space;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TrimLeadingZeros(const std::string& str) {
|
||||||
|
DCHECK_GT(str.size(), 0u);
|
||||||
|
for (size_t i = 0; i < str.size(); ++i) {
|
||||||
|
if (str[i] == '0') continue;
|
||||||
|
return str.substr(i);
|
||||||
|
}
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the 32 bits input, but in reverse bit order, i.e. bit [31] as the most
|
||||||
|
// significant bit, followed by, bit [30], and down to bit [0] as the least
|
||||||
|
// significant bit, where bits [i] for i in the range of 0 to 31, inclusive, are
|
||||||
|
// specified in ISO/IEC 23008‐2, encoded in hexadecimal (leading zeroes may be
|
||||||
|
// omitted).
|
||||||
|
std::string ReverseBitsAndHexEncode(uint32_t x) {
|
||||||
|
x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1);
|
||||||
|
x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2);
|
||||||
|
x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4);
|
||||||
|
const uint8_t bytes[] = {static_cast<uint8_t>(x & 0xFF),
|
||||||
|
static_cast<uint8_t>((x >> 8) & 0xFF),
|
||||||
|
static_cast<uint8_t>((x >> 16) & 0xFF),
|
||||||
|
static_cast<uint8_t>((x >> 24) & 0xFF)};
|
||||||
|
return TrimLeadingZeros(base::HexEncode(bytes, arraysize(bytes)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CodecAsString(VideoCodec codec) {
|
||||||
|
switch (codec) {
|
||||||
|
case kCodecHEV1:
|
||||||
|
return "hev1";
|
||||||
|
case kCodecHVC1:
|
||||||
|
return "hvc1";
|
||||||
|
default:
|
||||||
|
LOG(WARNING) << "Unknown codec: " << codec;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
HEVCDecoderConfiguration::HEVCDecoderConfiguration()
|
||||||
|
: version_(0),
|
||||||
|
general_profile_space_(0),
|
||||||
|
general_tier_flag_(false),
|
||||||
|
general_profile_idc_(0),
|
||||||
|
general_profile_compatibility_flags_(0),
|
||||||
|
general_level_idc_(0),
|
||||||
|
length_size_(0) {}
|
||||||
|
|
||||||
|
HEVCDecoderConfiguration::~HEVCDecoderConfiguration() {}
|
||||||
|
|
||||||
|
bool HEVCDecoderConfiguration::Parse(const std::vector<uint8_t>& data) {
|
||||||
|
BufferReader reader(vector_as_array(&data), data.size());
|
||||||
|
|
||||||
|
uint8_t profile_indication = 0;
|
||||||
|
uint8_t length_size_minus_one = 0;
|
||||||
|
uint8_t num_of_arrays = 0;
|
||||||
|
RCHECK(reader.Read1(&version_) && version_ == 1 &&
|
||||||
|
reader.Read1(&profile_indication) &&
|
||||||
|
reader.Read4(&general_profile_compatibility_flags_) &&
|
||||||
|
reader.ReadToVector(&general_constraint_indicator_flags_, 6) &&
|
||||||
|
reader.Read1(&general_level_idc_) &&
|
||||||
|
reader.SkipBytes(8) && // Skip uninterested fields.
|
||||||
|
reader.Read1(&length_size_minus_one) &&
|
||||||
|
reader.Read1(&num_of_arrays));
|
||||||
|
|
||||||
|
general_profile_space_ = profile_indication >> 6;
|
||||||
|
RCHECK(general_profile_space_ <= 3u);
|
||||||
|
general_tier_flag_ = ((profile_indication >> 5) & 1) == 1;
|
||||||
|
general_profile_idc_ = profile_indication & 0x1f;
|
||||||
|
|
||||||
|
length_size_ = (length_size_minus_one & 0x3) + 1;
|
||||||
|
|
||||||
|
// TODO(kqyang): Parse SPS to get resolutions.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HEVCDecoderConfiguration::GetCodecString(VideoCodec codec) const {
|
||||||
|
// ISO/IEC 14496-15:2014 Annex E.
|
||||||
|
std::vector<std::string> fields;
|
||||||
|
fields.push_back(CodecAsString(codec));
|
||||||
|
fields.push_back(GeneralProfileSpaceAsString(general_profile_space_) +
|
||||||
|
base::IntToString(general_profile_idc_));
|
||||||
|
fields.push_back(
|
||||||
|
ReverseBitsAndHexEncode(general_profile_compatibility_flags_));
|
||||||
|
fields.push_back((general_tier_flag_ ? "H" : "L") +
|
||||||
|
base::IntToString(general_level_idc_));
|
||||||
|
|
||||||
|
// Remove trailing bytes that are zero.
|
||||||
|
std::vector<uint8_t> constraints = general_constraint_indicator_flags_;
|
||||||
|
size_t size = constraints.size();
|
||||||
|
for (; size > 0; --size) {
|
||||||
|
if (constraints[size - 1] != 0) break;
|
||||||
|
}
|
||||||
|
constraints.resize(size);
|
||||||
|
for (uint8_t constraint : constraints)
|
||||||
|
fields.push_back(TrimLeadingZeros(base::HexEncode(&constraint, 1)));
|
||||||
|
|
||||||
|
return base::JoinString(fields, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#ifndef MEDIA_FILTERS_HEVC_DECODER_CONFIGURATION_H_
|
||||||
|
#define MEDIA_FILTERS_HEVC_DECODER_CONFIGURATION_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "packager/base/macros.h"
|
||||||
|
#include "packager/media/base/video_stream_info.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
/// Class for parsing HEVC decoder configuration.
|
||||||
|
class HEVCDecoderConfiguration {
|
||||||
|
public:
|
||||||
|
HEVCDecoderConfiguration();
|
||||||
|
~HEVCDecoderConfiguration();
|
||||||
|
|
||||||
|
/// Parses input to extract HEVC decoder configuration data.
|
||||||
|
/// @return false if there is parsing errors.
|
||||||
|
bool Parse(const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
|
/// @return The codec string.
|
||||||
|
std::string GetCodecString(VideoCodec codec) const;
|
||||||
|
|
||||||
|
/// @return The size of the NAL unit length field.
|
||||||
|
uint8_t length_size() { return length_size_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t version_;
|
||||||
|
uint8_t general_profile_space_;
|
||||||
|
bool general_tier_flag_;
|
||||||
|
uint8_t general_profile_idc_;
|
||||||
|
uint32_t general_profile_compatibility_flags_;
|
||||||
|
std::vector<uint8_t> general_constraint_indicator_flags_;
|
||||||
|
uint8_t general_level_idc_;
|
||||||
|
uint8_t length_size_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(HEVCDecoderConfiguration);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
|
#endif // MEDIA_FILTERS_HEVC_DECODER_CONFIGURATION_H_
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#include "packager/media/filters/hevc_decoder_configuration.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
TEST(HEVCDecoderConfigurationTest, Success) {
|
||||||
|
const uint8_t kHevcDecoderConfigurationData[] = {
|
||||||
|
0x01, 0x02, 0x20, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3F, 0xF0, 0x00, 0xFC, 0xFD, 0xFA, 0xFA, 0x00, 0x00, 0x0F, 0x04, 0x20,
|
||||||
|
0x00, 0x01, 0x00, 0x18, 0x40, 0x01, 0x0C, 0x01, 0xFF, 0xFF, 0x02, 0x20,
|
||||||
|
0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
|
||||||
|
0x3F, 0x99, 0x98, 0x09, 0x21, 0x00, 0x01, 0x00, 0x29, 0x42, 0x01, 0x01,
|
||||||
|
0x02, 0x20, 0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
HEVCDecoderConfiguration hevc_config;
|
||||||
|
ASSERT_TRUE(hevc_config.Parse(
|
||||||
|
std::vector<uint8_t>(kHevcDecoderConfigurationData,
|
||||||
|
kHevcDecoderConfigurationData +
|
||||||
|
arraysize(kHevcDecoderConfigurationData))));
|
||||||
|
|
||||||
|
EXPECT_EQ(4u, hevc_config.length_size());
|
||||||
|
|
||||||
|
EXPECT_EQ("hev1.2.4.L63.90", hevc_config.GetCodecString(kCodecHEV1));
|
||||||
|
EXPECT_EQ("hvc1.2.4.L63.90", hevc_config.GetCodecString(kCodecHVC1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HEVCDecoderConfigurationTest, FailOnInsufficientData) {
|
||||||
|
const uint8_t kHevcDecoderConfigurationData[] = {0x01, 0x02, 0x20, 0x00};
|
||||||
|
|
||||||
|
HEVCDecoderConfiguration hevc_config;
|
||||||
|
ASSERT_FALSE(hevc_config.Parse(
|
||||||
|
std::vector<uint8_t>(kHevcDecoderConfigurationData,
|
||||||
|
kHevcDecoderConfigurationData +
|
||||||
|
arraysize(kHevcDecoderConfigurationData))));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
|
@ -37,6 +37,7 @@ const uint16_t kVideoDepth = 0x0018;
|
||||||
|
|
||||||
const uint32_t kCompressorNameSize = 32u;
|
const uint32_t kCompressorNameSize = 32u;
|
||||||
const char kAvcCompressorName[] = "\012AVC Coding";
|
const char kAvcCompressorName[] = "\012AVC Coding";
|
||||||
|
const char kHevcCompressorName[] = "\013HEVC Coding";
|
||||||
const char kVpcCompressorName[] = "\012VPC Coding";
|
const char kVpcCompressorName[] = "\012VPC Coding";
|
||||||
|
|
||||||
// Utility functions to check if the 64bit integers can fit in 32bit integer.
|
// Utility functions to check if the 64bit integers can fit in 32bit integer.
|
||||||
|
@ -950,6 +951,12 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
||||||
kAvcCompressorName,
|
kAvcCompressorName,
|
||||||
kAvcCompressorName + arraysize(kAvcCompressorName));
|
kAvcCompressorName + arraysize(kAvcCompressorName));
|
||||||
break;
|
break;
|
||||||
|
case FOURCC_HEV1:
|
||||||
|
case FOURCC_HVC1:
|
||||||
|
compressor_name.assign(
|
||||||
|
kHevcCompressorName,
|
||||||
|
kHevcCompressorName + arraysize(kHevcCompressorName));
|
||||||
|
break;
|
||||||
case FOURCC_VP08:
|
case FOURCC_VP08:
|
||||||
case FOURCC_VP09:
|
case FOURCC_VP09:
|
||||||
case FOURCC_VP10:
|
case FOURCC_VP10:
|
||||||
|
@ -1001,6 +1008,10 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
||||||
case FOURCC_AVC1:
|
case FOURCC_AVC1:
|
||||||
codec_config_record.box_type = FOURCC_AVCC;
|
codec_config_record.box_type = FOURCC_AVCC;
|
||||||
break;
|
break;
|
||||||
|
case FOURCC_HEV1:
|
||||||
|
case FOURCC_HVC1:
|
||||||
|
codec_config_record.box_type = FOURCC_HVCC;
|
||||||
|
break;
|
||||||
case FOURCC_VP08:
|
case FOURCC_VP08:
|
||||||
case FOURCC_VP09:
|
case FOURCC_VP09:
|
||||||
case FOURCC_VP10:
|
case FOURCC_VP10:
|
||||||
|
@ -1680,7 +1691,9 @@ bool SampleToGroup::ReadWrite(BoxBuffer* buffer) {
|
||||||
|
|
||||||
if (grouping_type != FOURCC_SEIG) {
|
if (grouping_type != FOURCC_SEIG) {
|
||||||
DCHECK(buffer->Reading());
|
DCHECK(buffer->Reading());
|
||||||
DLOG(WARNING) << "Sample group '" << grouping_type << "' is not supported.";
|
DLOG(WARNING) << "Sample group "
|
||||||
|
<< FourCCToString(static_cast<FourCC>(grouping_type))
|
||||||
|
<< " is not supported.";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,10 @@ enum FourCC {
|
||||||
FOURCC_FRMA = 0x66726d61,
|
FOURCC_FRMA = 0x66726d61,
|
||||||
FOURCC_FTYP = 0x66747970,
|
FOURCC_FTYP = 0x66747970,
|
||||||
FOURCC_HDLR = 0x68646c72,
|
FOURCC_HDLR = 0x68646c72,
|
||||||
|
FOURCC_HEV1 = 0x68657631,
|
||||||
FOURCC_HINT = 0x68696e74,
|
FOURCC_HINT = 0x68696e74,
|
||||||
|
FOURCC_HVC1 = 0x68766331,
|
||||||
|
FOURCC_HVCC = 0x68766343,
|
||||||
FOURCC_ISO6 = 0x69736f36,
|
FOURCC_ISO6 = 0x69736f36,
|
||||||
FOURCC_IODS = 0x696f6473,
|
FOURCC_IODS = 0x696f6473,
|
||||||
FOURCC_MDAT = 0x6d646174,
|
FOURCC_MDAT = 0x6d646174,
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "packager/media/file/file.h"
|
#include "packager/media/file/file.h"
|
||||||
#include "packager/media/file/file_closer.h"
|
#include "packager/media/file/file_closer.h"
|
||||||
#include "packager/media/filters/avc_decoder_configuration.h"
|
#include "packager/media/filters/avc_decoder_configuration.h"
|
||||||
|
#include "packager/media/filters/hevc_decoder_configuration.h"
|
||||||
#include "packager/media/filters/vp_codec_configuration.h"
|
#include "packager/media/filters/vp_codec_configuration.h"
|
||||||
#include "packager/media/formats/mp4/box_definitions.h"
|
#include "packager/media/formats/mp4/box_definitions.h"
|
||||||
#include "packager/media/formats/mp4/box_reader.h"
|
#include "packager/media/formats/mp4/box_reader.h"
|
||||||
|
@ -43,6 +44,10 @@ VideoCodec FourCCToCodec(FourCC fourcc) {
|
||||||
switch (fourcc) {
|
switch (fourcc) {
|
||||||
case FOURCC_AVC1:
|
case FOURCC_AVC1:
|
||||||
return kCodecH264;
|
return kCodecH264;
|
||||||
|
case FOURCC_HEV1:
|
||||||
|
return kCodecHEV1;
|
||||||
|
case FOURCC_HVC1:
|
||||||
|
return kCodecHVC1;
|
||||||
case FOURCC_VP08:
|
case FOURCC_VP08:
|
||||||
return kCodecVP8;
|
return kCodecVP8;
|
||||||
case FOURCC_VP09:
|
case FOURCC_VP09:
|
||||||
|
@ -419,6 +424,17 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FOURCC_HEV1:
|
||||||
|
case FOURCC_HVC1: {
|
||||||
|
HEVCDecoderConfiguration hevc_config;
|
||||||
|
if (!hevc_config.Parse(entry.codec_config_record.data)) {
|
||||||
|
LOG(ERROR) << "Failed to parse hevc.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
codec_string = hevc_config.GetCodecString(video_codec);
|
||||||
|
nalu_length_size = hevc_config.length_size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case FOURCC_VP08:
|
case FOURCC_VP08:
|
||||||
case FOURCC_VP09:
|
case FOURCC_VP09:
|
||||||
case FOURCC_VP10: {
|
case FOURCC_VP10: {
|
||||||
|
|
|
@ -44,6 +44,10 @@ FourCC CodecToFourCC(VideoCodec codec) {
|
||||||
switch (codec) {
|
switch (codec) {
|
||||||
case kCodecH264:
|
case kCodecH264:
|
||||||
return FOURCC_AVC1;
|
return FOURCC_AVC1;
|
||||||
|
case kCodecHEV1:
|
||||||
|
return FOURCC_HEV1;
|
||||||
|
case kCodecHVC1:
|
||||||
|
return FOURCC_HVC1;
|
||||||
case kCodecVP8:
|
case kCodecVP8:
|
||||||
return FOURCC_VP08;
|
return FOURCC_VP08;
|
||||||
case kCodecVP9:
|
case kCodecVP9:
|
||||||
|
|
|
@ -31,6 +31,7 @@ bear-1280x720_ptswraparound.ts - Same as bear-1280x720.ts, with a timestamp wrap
|
||||||
// ISO-BMFF streams.
|
// ISO-BMFF streams.
|
||||||
bear-1280x720.mp4 - AVC + AAC encode, mulitplexed into an ISOBMFF container.
|
bear-1280x720.mp4 - AVC + AAC encode, mulitplexed into an ISOBMFF container.
|
||||||
bear-640x360.mp4 - Same as above, but in a different resolution.
|
bear-640x360.mp4 - Same as above, but in a different resolution.
|
||||||
|
bear-640x360-hevc.mp4 - Same content, but encoded with HEVC.
|
||||||
bear-320x180.mp4 - Same as above, but in a different resolution.
|
bear-320x180.mp4 - Same as above, but in a different resolution.
|
||||||
bear-640x360-trailing-moov.mp4 - Same content, but with moov box in the end.
|
bear-640x360-trailing-moov.mp4 - Same content, but with moov box in the end.
|
||||||
bear-640x360-av_frag.mp4 - Same content, but in fragmented mp4.
|
bear-640x360-av_frag.mp4 - Same content, but in fragmented mp4.
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue