| Index: media/formats/mp2t/descriptors.cc
|
| diff --git a/media/formats/mp2t/descriptors.cc b/media/formats/mp2t/descriptors.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7808ef4494281368a9cf1819a5fc1c871ec8f3c2
|
| --- /dev/null
|
| +++ b/media/formats/mp2t/descriptors.cc
|
| @@ -0,0 +1,153 @@
|
| +// Copyright 2015 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/mp2t/descriptors.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "base/logging.h"
|
| +#include "media/base/bit_reader.h"
|
| +#include "media/formats/mp2t/mp2t_common.h"
|
| +
|
| +namespace media {
|
| +namespace mp2t {
|
| +
|
| +namespace {
|
| +
|
| +// Tag values for various kinds of descriptors for which there is specific
|
| +// parsing support herein.
|
| +enum DescriptorTag {
|
| + DESCRIPTOR_TAG_REGISTRATION = 5,
|
| + DESCRIPTOR_TAG_CA = 9,
|
| + DESCRIPTOR_TAG_PRIVATE_DATA_INDICATOR = 15,
|
| +};
|
| +
|
| +const int kCASystemIdCenc = 0x6365; // 'ce'
|
| +
|
| +class StringBitReader : public BitReader {
|
| + public:
|
| + StringBitReader(const std::string& input);
|
| + ~StringBitReader() override;
|
| +};
|
| +
|
| +StringBitReader::StringBitReader(const std::string& input)
|
| + : BitReader(reinterpret_cast<const uint8_t*>(input.data()), input.size()) {}
|
| +
|
| +StringBitReader::~StringBitReader() {}
|
| +
|
| +} // namespace
|
| +
|
| +Descriptors::Descriptors() {}
|
| +
|
| +Descriptors::~Descriptors() {}
|
| +
|
| +bool Descriptors::Read(BitReader* reader, int size) {
|
| + DCHECK(reader);
|
| + DCHECK(size >= 0);
|
| + descriptors_.clear();
|
| + if (size == 0)
|
| + return true;
|
| + int initial_bits_read = reader->bits_read();
|
| + int bits_read = 0;
|
| + int bits_available = reader->bits_available();
|
| + int size_in_bits = 8 * size;
|
| + if (size_in_bits > bits_available)
|
| + return false;
|
| + bits_available = size_in_bits;
|
| + do {
|
| + int tag;
|
| + size_t length;
|
| + RCHECK(reader->ReadBits(8, &tag));
|
| + RCHECK(reader->ReadBits(8, &length));
|
| + char data[256];
|
| + for (size_t i = 0; i < length; i++) {
|
| + RCHECK(reader->ReadBits(8, &data[i]));
|
| + }
|
| + descriptors_.insert(Descriptor(tag, std::string(data, length)));
|
| + bits_read = reader->bits_read() - initial_bits_read;
|
| + } while (bits_read < bits_available);
|
| + return bits_read == bits_available;
|
| +}
|
| +
|
| +bool Descriptors::HasRegistrationDescriptor(
|
| + int64_t* format_identifier,
|
| + std::string* additional_info) const {
|
| + DCHECK(format_identifier);
|
| + DCHECK(additional_info);
|
| + auto search = descriptors_.find(DESCRIPTOR_TAG_REGISTRATION);
|
| + if (search == descriptors_.end())
|
| + return false;
|
| + const std::string& data = search->second;
|
| + StringBitReader reader(data);
|
| + RCHECK(reader.ReadBits(32, format_identifier));
|
| + size_t extra_bits = reader.bits_available();
|
| + RCHECK(extra_bits % 8 == 0);
|
| + RCHECK(reader.ReadString(extra_bits, additional_info));
|
| + return true;
|
| +}
|
| +
|
| +bool Descriptors::HasCADescriptor(int* system_id,
|
| + int* pid,
|
| + std::string* private_data) const {
|
| + DCHECK(system_id);
|
| + DCHECK(pid);
|
| + DCHECK(private_data);
|
| + auto search = descriptors_.find(DESCRIPTOR_TAG_CA);
|
| + if (search == descriptors_.end())
|
| + return false;
|
| + const std::string& data = search->second;
|
| + StringBitReader reader(data);
|
| + RCHECK(reader.ReadBits(16, system_id));
|
| + RCHECK(reader.SkipBits(3));
|
| + RCHECK(reader.ReadBits(13, pid));
|
| + size_t extra_bits = reader.bits_available();
|
| + RCHECK(extra_bits % 8 == 0);
|
| + RCHECK(reader.ReadString(extra_bits, private_data));
|
| + return true;
|
| +}
|
| +
|
| +bool Descriptors::HasCADescriptorCenc(int* ca_pid, int* pssh_pid) const {
|
| + DCHECK(ca_pid);
|
| + DCHECK(pssh_pid);
|
| + int system_id;
|
| + std::string private_data;
|
| + if (!HasCADescriptor(&system_id, ca_pid, &private_data))
|
| + return false;
|
| + if (system_id != kCASystemIdCenc)
|
| + return false;
|
| + StringBitReader reader(private_data);
|
| + uint32_t scheme_type;
|
| + uint32_t scheme_version;
|
| + int num_systems;
|
| + int encryption_algorithm;
|
| + char pssh_system_id[16];
|
| + // TODO(dougsteed). Currently we don't check many of the following values.
|
| + // When we flesh out this implementation to cover all of ISO/IEC 23001-9 we
|
| + // will need to use and check these values.
|
| + RCHECK(reader.ReadBits(32, &scheme_type));
|
| + RCHECK(reader.ReadBits(32, &scheme_version));
|
| + RCHECK(reader.ReadBits(8, &num_systems));
|
| + RCHECK(num_systems == 1);
|
| + RCHECK(reader.ReadBits(24, &encryption_algorithm));
|
| + for (size_t i = 0; i < 16; i++) {
|
| + RCHECK(reader.ReadBits(8, &pssh_system_id[i]));
|
| + }
|
| + RCHECK(reader.ReadBits(13, pssh_pid));
|
| + return true;
|
| +}
|
| +
|
| +bool Descriptors::HasPrivateDataIndicator(int64_t value) const {
|
| + int64_t private_data_indicator;
|
| + auto search = descriptors_.find(DESCRIPTOR_TAG_PRIVATE_DATA_INDICATOR);
|
| + if (search == descriptors_.end())
|
| + return false;
|
| + const std::string& data = search->second;
|
| + StringBitReader reader(data);
|
| + RCHECK(reader.ReadBits(32, &private_data_indicator));
|
| + RCHECK(reader.bits_available() == 0);
|
| + return private_data_indicator == value;
|
| +}
|
| +
|
| +} // namespace mp2t
|
| +} // namespace media
|
|
|