Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / filters / h265_parser.cc
blob30a8233c1432d6513d0420a54661f2bbb2625218
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/logging.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/stl_util.h"
9 #include "media/base/decrypt_config.h"
10 #include "media/filters/h265_parser.h"
12 namespace media {
14 #define READ_BITS_OR_RETURN(num_bits, out) \
15 do { \
16 int _out; \
17 if (!br_.ReadBits(num_bits, &_out)) { \
18 DVLOG(1) \
19 << "Error in stream: unexpected EOS while trying to read " #out; \
20 return kInvalidStream; \
21 } \
22 *out = _out; \
23 } while (0)
25 #define TRUE_OR_RETURN(a) \
26 do { \
27 if (!(a)) { \
28 DVLOG(1) << "Error in stream: invalid value, expected " << #a; \
29 return kInvalidStream; \
30 } \
31 } while (0)
33 H265NALU::H265NALU() {
34 memset(this, 0, sizeof(*this));
37 H265Parser::H265Parser() {
38 Reset();
41 H265Parser::~H265Parser() {
44 void H265Parser::Reset() {
45 stream_ = NULL;
46 bytes_left_ = 0;
47 encrypted_ranges_.clear();
50 void H265Parser::SetStream(const uint8* stream, off_t stream_size) {
51 std::vector<SubsampleEntry> subsamples;
52 SetEncryptedStream(stream, stream_size, subsamples);
55 void H265Parser::SetEncryptedStream(
56 const uint8* stream, off_t stream_size,
57 const std::vector<SubsampleEntry>& subsamples) {
58 DCHECK(stream);
59 DCHECK_GT(stream_size, 0);
61 stream_ = stream;
62 bytes_left_ = stream_size;
64 encrypted_ranges_.clear();
65 const uint8* start = stream;
66 const uint8* stream_end = stream_ + bytes_left_;
67 for (size_t i = 0; i < subsamples.size() && start < stream_end; ++i) {
68 start += subsamples[i].clear_bytes;
70 const uint8* end = std::min(start + subsamples[i].cypher_bytes, stream_end);
71 encrypted_ranges_.Add(start, end);
72 start = end;
76 bool H265Parser::LocateNALU(off_t* nalu_size, off_t* start_code_size) {
77 // Find the start code of next NALU.
78 off_t nalu_start_off = 0;
79 off_t annexb_start_code_size = 0;
81 if (!H264Parser::FindStartCodeInClearRanges(stream_, bytes_left_,
82 encrypted_ranges_,
83 &nalu_start_off,
84 &annexb_start_code_size)) {
85 DVLOG(4) << "Could not find start code, end of stream?";
86 return false;
89 // Move the stream to the beginning of the NALU (pointing at the start code).
90 stream_ += nalu_start_off;
91 bytes_left_ -= nalu_start_off;
93 const uint8* nalu_data = stream_ + annexb_start_code_size;
94 off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size;
95 if (max_nalu_data_size <= 0) {
96 DVLOG(3) << "End of stream";
97 return false;
100 // Find the start code of next NALU;
101 // if successful, |nalu_size_without_start_code| is the number of bytes from
102 // after previous start code to before this one;
103 // if next start code is not found, it is still a valid NALU since there
104 // are some bytes left after the first start code: all the remaining bytes
105 // belong to the current NALU.
106 off_t next_start_code_size = 0;
107 off_t nalu_size_without_start_code = 0;
108 if (!H264Parser::FindStartCodeInClearRanges(nalu_data, max_nalu_data_size,
109 encrypted_ranges_,
110 &nalu_size_without_start_code,
111 &next_start_code_size)) {
112 nalu_size_without_start_code = max_nalu_data_size;
114 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
115 *start_code_size = annexb_start_code_size;
116 return true;
119 H265Parser::Result H265Parser::AdvanceToNextNALU(H265NALU* nalu) {
120 off_t start_code_size;
121 off_t nalu_size_with_start_code;
122 if (!LocateNALU(&nalu_size_with_start_code, &start_code_size)) {
123 DVLOG(4) << "Could not find next NALU, bytes left in stream: "
124 << bytes_left_;
125 return kEOStream;
128 nalu->data = stream_ + start_code_size;
129 nalu->size = nalu_size_with_start_code - start_code_size;
130 DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code;
132 // Initialize bit reader at the start of found NALU.
133 if (!br_.Initialize(nalu->data, nalu->size))
134 return kEOStream;
136 // Move parser state to after this NALU, so next time AdvanceToNextNALU
137 // is called, we will effectively be skipping it;
138 // other parsing functions will use the position saved
139 // in bit reader for parsing, so we don't have to remember it here.
140 stream_ += nalu_size_with_start_code;
141 bytes_left_ -= nalu_size_with_start_code;
143 // Read NALU header, skip the forbidden_zero_bit, but check for it.
144 int data;
145 READ_BITS_OR_RETURN(1, &data);
146 TRUE_OR_RETURN(data == 0);
148 READ_BITS_OR_RETURN(6, &nalu->nal_unit_type);
149 READ_BITS_OR_RETURN(6, &nalu->nuh_layer_id);
150 READ_BITS_OR_RETURN(3, &nalu->nuh_temporal_id_plus1);
152 DVLOG(4) << "NALU type: " << static_cast<int>(nalu->nal_unit_type)
153 << " at: " << reinterpret_cast<const void*>(nalu->data)
154 << " size: " << nalu->size;
156 return kOk;
159 } // namespace media