Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: media/filters/h265_parser.cc

Issue 816353010: Implemented HEVC video demuxing and parsing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved back h265_parser_unittest.cc in media/BUILD.gn Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/h265_parser.h ('k') | media/filters/h265_parser_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "base/logging.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/stl_util.h"
8
9 #include "media/base/decrypt_config.h"
10 #include "media/filters/h265_parser.h"
11
12 namespace media {
13
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)
24
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)
32
33 H265NALU::H265NALU() {
34 memset(this, 0, sizeof(*this));
35 }
36
37 H265Parser::H265Parser() {
38 Reset();
39 }
40
41 H265Parser::~H265Parser() {
42 }
43
44 void H265Parser::Reset() {
45 stream_ = NULL;
46 bytes_left_ = 0;
47 encrypted_ranges_.clear();
48 }
49
50 void H265Parser::SetStream(const uint8* stream, off_t stream_size) {
51 std::vector<SubsampleEntry> subsamples;
52 SetEncryptedStream(stream, stream_size, subsamples);
53 }
54
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);
60
61 stream_ = stream;
62 bytes_left_ = stream_size;
63
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;
69
70 const uint8* end = std::min(start + subsamples[i].cypher_bytes, stream_end);
71 encrypted_ranges_.Add(start, end);
72 start = end;
73 }
74 }
75
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;
80
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;
87 }
88
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;
92
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;
98 }
99
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;
113 }
114 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
115 *start_code_size = annexb_start_code_size;
116 return true;
117 }
118
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;
126 }
127
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;
131
132 // Initialize bit reader at the start of found NALU.
133 if (!br_.Initialize(nalu->data, nalu->size))
134 return kEOStream;
135
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;
142
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);
147
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);
151
152 DVLOG(4) << "NALU type: " << static_cast<int>(nalu->nal_unit_type)
153 << " at: " << reinterpret_cast<const void*>(nalu->data)
154 << " size: " << nalu->size;
155
156 return kOk;
157 }
158
159 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/h265_parser.h ('k') | media/filters/h265_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698