// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "media/formats/mp4/es_descriptor.h" #include "media/base/bit_reader.h" #include "media/base/buffer_writer.h" #include "media/formats/mp4/rcheck.h" namespace edash_packager { namespace media { namespace { // ISO/IEC 14496-1:2004 Section 7.2.6.6 Table 6: StreamType values. enum StreamType { kForbiddenStreamType = 0x00, kObjectDescriptorStreamType = 0x01, kClockReferenceStreamType = 0x02, kSceneDescriptionStreamType = 0x03, kVisualStreamType = 0x04, kAudioStreamType = 0x05, kMPEG7StreamType = 0x06, kIPMPStreamType = 0x07, kObjectContentInfoStreamType = 0x08, kMPEGJStreamType = 0x09, kInteractionStream = 0x0A, kIPMPToolStreamType = 0x0B, }; // ISO/IEC 14496-1:2004 Section 7.3.2.3 Table 12: ISO SL Config Descriptor. enum SLPredefinedTags { kSLPredefinedNull = 0x01, kSLPredefinedMP4 = 0x02, }; // The elementary stream size is specific by up to 4 bytes. // The MSB of a byte indicates if there are more bytes for the size. bool ReadESSize(BitReader* reader, uint32_t* size) { uint8_t msb; uint8_t byte; *size = 0; for (size_t i = 0; i < 4; ++i) { RCHECK(reader->ReadBits(1, &msb)); RCHECK(reader->ReadBits(7, &byte)); *size = (*size << 7) + byte; if (msb == 0) break; } return true; } // Descryptor Header Size: 1 byte tag and 1 byte size (we don't support // multi-bytes size for now). const size_t kHeaderSize = 2; const size_t kMaxDecoderSpecificInfoSize = 64; } // namespace namespace mp4 { ESDescriptor::ESDescriptor() : esid_(0), object_type_(kForbidden) {} ESDescriptor::~ESDescriptor() {} bool ESDescriptor::Parse(const std::vector& data) { BitReader reader(&data[0], data.size()); uint8_t tag; uint32_t size; uint8_t stream_dependency_flag; uint8_t url_flag; uint8_t ocr_stream_flag; uint16_t dummy; RCHECK(reader.ReadBits(8, &tag)); RCHECK(tag == kESDescrTag); RCHECK(ReadESSize(&reader, &size)); RCHECK(reader.ReadBits(16, &esid_)); // ES_ID RCHECK(reader.ReadBits(1, &stream_dependency_flag)); RCHECK(reader.ReadBits(1, &url_flag)); RCHECK(!url_flag); // We don't support url flag RCHECK(reader.ReadBits(1, &ocr_stream_flag)); RCHECK(reader.ReadBits(5, &dummy)); // streamPriority if (stream_dependency_flag) RCHECK(reader.ReadBits(16, &dummy)); // dependsOn_ES_ID if (ocr_stream_flag) RCHECK(reader.ReadBits(16, &dummy)); // OCR_ES_Id RCHECK(ParseDecoderConfigDescriptor(&reader)); return true; } bool ESDescriptor::ParseDecoderConfigDescriptor(BitReader* reader) { uint8_t tag; uint32_t size; uint64_t dummy; RCHECK(reader->ReadBits(8, &tag)); RCHECK(tag == kDecoderConfigDescrTag); RCHECK(ReadESSize(reader, &size)); RCHECK(reader->ReadBits(8, &object_type_)); RCHECK(reader->ReadBits(64, &dummy)); RCHECK(reader->ReadBits(32, &dummy)); RCHECK(ParseDecoderSpecificInfo(reader)); return true; } bool ESDescriptor::ParseDecoderSpecificInfo(BitReader* reader) { DCHECK(reader); uint8_t tag; uint32_t size; RCHECK(reader->ReadBits(8, &tag)); RCHECK(tag == kDecoderSpecificInfoTag); RCHECK(ReadESSize(reader, &size)); decoder_specific_info_.resize(size); for (uint32_t i = 0; i < size; ++i) RCHECK(reader->ReadBits(8, &decoder_specific_info_[i])); return true; } void ESDescriptor::Write(BufferWriter* writer) const { DCHECK(writer); CHECK_LT(decoder_specific_info_.size(), kMaxDecoderSpecificInfoSize); const std::vector kEmptyDecodingBufferSize(3, 0); const uint32_t kUnknownBitrate = 0; const uint8_t kNoEsFlags = 0; const uint8_t decoder_specific_info_size = decoder_specific_info_.size(); // 6 bit stream type. The last bit is reserved with 1. const uint8_t stream_type = (kAudioStreamType << 2) | 1; const uint8_t decoder_config_size = decoder_specific_info_size + kHeaderSize + sizeof(uint8_t) + // object_type_. sizeof(stream_type) + kEmptyDecodingBufferSize.size() + sizeof(kUnknownBitrate) * 2; const uint8_t sl_config_size = sizeof(uint8_t); // predefined. const uint8_t es_size = decoder_config_size + kHeaderSize + sl_config_size + kHeaderSize + sizeof(esid_) + sizeof(kNoEsFlags); writer->AppendInt(static_cast(kESDescrTag)); writer->AppendInt(es_size); writer->AppendInt(esid_); writer->AppendInt(kNoEsFlags); writer->AppendInt(static_cast(kDecoderConfigDescrTag)); writer->AppendInt(decoder_config_size); writer->AppendInt(static_cast(object_type_)); writer->AppendInt(stream_type); writer->AppendVector(kEmptyDecodingBufferSize); writer->AppendInt(kUnknownBitrate); // max_bitrate. writer->AppendInt(kUnknownBitrate); // avg_bitrate. writer->AppendInt(static_cast(kDecoderSpecificInfoTag)); writer->AppendInt(decoder_specific_info_size); writer->AppendVector(decoder_specific_info_); writer->AppendInt(static_cast(kSLConfigTag)); writer->AppendInt(sl_config_size); writer->AppendInt(static_cast(kSLPredefinedMP4)); } size_t ESDescriptor::ComputeSize() const { // A bit magical. Refer to ESDescriptor::Write for details. const uint8_t decoder_specific_info_size = decoder_specific_info_.size(); const uint8_t decoder_config_size = decoder_specific_info_size + kHeaderSize + sizeof(uint8_t) * 5 + sizeof(uint32_t) * 2; const uint8_t sl_config_size = sizeof(uint8_t); const uint8_t es_size = decoder_config_size + kHeaderSize + sl_config_size + kHeaderSize + sizeof(esid_) + sizeof(uint8_t); return es_size + kHeaderSize; } } // namespace mp4 } // namespace media } // namespace edash_packager