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"
14 #define READ_BITS_OR_RETURN(num_bits, out) \
17 if (!br_.ReadBits(num_bits, &_out)) { \
19 << "Error in stream: unexpected EOS while trying to read " #out; \
20 return kInvalidStream; \
25 #define TRUE_OR_RETURN(a) \
28 DVLOG(1) << "Error in stream: invalid value, expected " << #a; \
29 return kInvalidStream; \
33 H265NALU::H265NALU() {
34 memset(this, 0, sizeof(*this));
37 H265Parser::H265Parser() {
41 H265Parser::~H265Parser() {
44 void H265Parser::Reset() {
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
) {
59 DCHECK_GT(stream_size
, 0);
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
);
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_
,
84 &annexb_start_code_size
)) {
85 DVLOG(4) << "Could not find start code, end of stream?";
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";
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
,
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
;
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: "
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
))
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.
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
;