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

Side by Side Diff: media/mpeg2/ts_packet.cc

Issue 23566013: Mpeg2 TS stream parser for media source. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments from patch set #3 Created 7 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "media/mpeg2/ts_packet.h"
6
7 #include "base/memory/scoped_ptr.h"
8 #include "media/base/bit_reader.h"
9 #include "media/mpeg2/mpeg2ts_common.h"
10
11 namespace media {
12 namespace mpeg2ts {
13
14 namespace {
15
16 const uint8 kTsHeaderSyncword = 0x47;
damienv1 2013/09/10 04:10:02 static
damienv1 2013/09/10 21:03:48 Done.
17
18 } // namespace
19
20 // static
21 int TsPacket::Sync(const uint8* buf, int size) {
22 int k = 0;
23 for (; k < size; k++) {
24 // Verify that we have 4 syncwords in a row when possible,
25 // this should improve synchronization robustness.
26 // TODO(damienv): Consider the case where there is garbage
27 // between TS packets.
28 bool is_header = true;
29 for (int i = 0; i < 4; i++) {
30 int idx = k + i * kPacketSize;
31 if (idx >= size)
32 break;
33 if (buf[idx] != kTsHeaderSyncword) {
34 DVLOG(LOG_LEVEL_TS)
35 << "ByteSync" << idx << ": "
36 << std::hex << static_cast<int>(buf[idx]) << std::dec;
37 is_header = false;
38 break;
39 }
40 }
41 if (is_header) {
42 break;
43 }
44 }
45
46 LOG_IF(WARNING, k != 0) << "SYNC: nbytes_skipped=" << k;
47 return k;
48 }
49
50 // static
51 TsPacket* TsPacket::Parse(const uint8* buf, int size) {
52 if (size < kPacketSize) {
53 LOG(WARNING) << "Buffer does not hold one full TS packet:"
54 << " buffer_size=" << size;
55 return NULL;
56 }
57
58 DCHECK_EQ(buf[0], kTsHeaderSyncword);
59 if (buf[0] != kTsHeaderSyncword) {
60 LOG(WARNING) << "Not on a TS syncword:"
61 << " buf[0]="
62 << std::hex << static_cast<int>(buf[0]) << std::dec;
63 return NULL;
64 }
65
66 scoped_ptr<TsPacket> ts_packet(new TsPacket());
67 BitReader bit_reader(buf, kPacketSize);
68
69 bool status = ts_packet->ParseHeader(&bit_reader);
70 if (!status) {
71 LOG(WARNING) << "Parsing header failed";
72 return NULL;
73 }
74 ts_packet->payload_ = (buf + ts_packet->GetPayloadOffset());
75
76 return ts_packet.release();
77 }
78
79 TsPacket::TsPacket() {
80 }
81
82 TsPacket::~TsPacket() {
83 }
84
85 bool TsPacket::ParseHeader(BitReader* bit_reader) {
86 payload_size_ = kPacketSize;
87
88 // Read the TS header: 4 bytes.
89 int syncword;
90 DCHECK(bit_reader->ReadBits(8, &syncword));
91 bool transport_error_indicator;
92 DCHECK(bit_reader->ReadBits(1, &transport_error_indicator));
93 DCHECK(bit_reader->ReadBits(1, &payload_unit_start_indicator_));
94 bool transport_priority;
95 DCHECK(bit_reader->ReadBits(1, &transport_priority));
96 DCHECK(bit_reader->ReadBits(13, &pid_));
97 int transport_scrambling_control;
98 DCHECK(bit_reader->ReadBits(2, &transport_scrambling_control));
99 int adaptation_field_control;
100 DCHECK(bit_reader->ReadBits(2, &adaptation_field_control));
101 DCHECK(bit_reader->ReadBits(4, &continuity_counter_));
102 payload_size_ -= 4;
103
104 // Default values when no adaptation field.
105 discontinuity_indicator_ = false;
106 random_access_indicator_ = false;
107
108 // Done since no adaptation field.
109 if ((adaptation_field_control & 0x2) == 0) {
110 return true;
111 }
112
113 // Read the adaptation field if needed.
114 int adaptation_field_length;
115 DCHECK(bit_reader->ReadBits(8, &adaptation_field_length));
116 DVLOG(LOG_LEVEL_TS) << "adaptation_field_length=" << adaptation_field_length;
117 payload_size_ -= 1;
118 if ((adaptation_field_control & 0x1) == 0 &&
119 adaptation_field_length != 183) {
120 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
121 return false;
122 }
123 if ((adaptation_field_control & 0x1) == 1 &&
124 adaptation_field_length > 182) {
125 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
126 // This is not allowed by the spec.
127 // However, some badly encoded streams are using
128 // adaptation_field_length = 183
129 // return false;
130 }
131
132 if (adaptation_field_length == 0) {
133 // adaptation_field_length = '0' is for inserting a single stuffing byte
134 // in the adaptation field of a transport stream packet.
135 return true;
136 }
137
138 bool status = ParseAdaptationField(bit_reader, adaptation_field_length);
139 payload_size_ -= adaptation_field_length;
140 return status;
141 }
142
143 bool TsPacket::ParseAdaptationField(BitReader* bit_reader,
144 int adaptation_field_length) {
145 DCHECK_GT(adaptation_field_length, 0);
146
147 DCHECK(bit_reader->ReadBits(1, &discontinuity_indicator_));
148 DCHECK(bit_reader->ReadBits(1, &random_access_indicator_));
149 bool elementary_stream_priority_indicator;
150 DCHECK(bit_reader->ReadBits(1, &elementary_stream_priority_indicator));
151 bool pcr_flag;
152 DCHECK(bit_reader->ReadBits(1, &pcr_flag));
153 bool opcr_flag;
154 DCHECK(bit_reader->ReadBits(1, &opcr_flag));
155 bool splicing_point_flag;
156 DCHECK(bit_reader->ReadBits(1, &splicing_point_flag));
157 bool transport_private_data_flag;
158 DCHECK(bit_reader->ReadBits(1, &transport_private_data_flag));
159 bool adaptation_field_extension_flag;
160 DCHECK(bit_reader->ReadBits(1, &adaptation_field_extension_flag));
161 adaptation_field_length -= 1;
162
163 if (pcr_flag) {
164 if (adaptation_field_length < 6) {
165 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
166 return false;
167 }
168 int64 program_clock_reference_base;
169 DCHECK(bit_reader->ReadBits(33, &program_clock_reference_base));
170 int reserved;
171 DCHECK(bit_reader->ReadBits(6, &reserved));
172 int program_clock_reference_extension;
173 DCHECK(bit_reader->ReadBits(9, &program_clock_reference_extension));
174 adaptation_field_length -= 6;
175 }
176
177 if (opcr_flag) {
178 if (adaptation_field_length < 6) {
179 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
180 return false;
181 }
182 int64 original_program_clock_reference_base;
183 DCHECK(bit_reader->ReadBits(33, &original_program_clock_reference_base));
184 int reserved;
185 DCHECK(bit_reader->ReadBits(6, &reserved));
186 int original_program_clock_reference_extension;
187 DCHECK(
188 bit_reader->ReadBits(9, &original_program_clock_reference_extension));
189 adaptation_field_length -= 6;
190 }
191
192 if (splicing_point_flag) {
193 if (adaptation_field_length < 1) {
194 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
195 return false;
196 }
197 int splice_countdown;
198 DCHECK(bit_reader->ReadBits(8, &splice_countdown));
199 adaptation_field_length -= 1;
200 }
201
202 if (transport_private_data_flag) {
203 if (adaptation_field_length < 1) {
204 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
205 return false;
206 }
207 int transport_private_data_length;
208 DCHECK(bit_reader->ReadBits(8, &transport_private_data_length));
209 adaptation_field_length -= 1;
210
211 if (adaptation_field_length < transport_private_data_length) {
212 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length
213 << " transport_private_data_length="
214 << transport_private_data_length;
215 return false;
216 }
217 for (int k = 0; k < transport_private_data_length; k++) {
218 int private_data_byte;
219 DCHECK(bit_reader->ReadBits(8, &private_data_byte));
220 }
221 adaptation_field_length -= transport_private_data_length;
222 }
223
224 if (adaptation_field_extension_flag) {
225 if (adaptation_field_length < 1) {
226 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
227 return false;
228 }
229 int adaptation_field_extension_length;
230 DCHECK(bit_reader->ReadBits(8, &adaptation_field_extension_length));
231 adaptation_field_length -= 1;
232
233 if (adaptation_field_length < adaptation_field_extension_length) {
234 LOG(WARNING) << "adaptation_field_length=" << adaptation_field_length;
235 return false;
236 }
237 for (int k = 0; k < adaptation_field_extension_length; k++) {
238 int dummy_byte;
239 DCHECK(bit_reader->ReadBits(8, &dummy_byte));
240 }
241 adaptation_field_length -= adaptation_field_extension_length;
242 }
243
244 for (int k = 0; k < adaptation_field_length; k++) {
245 int stuffing_byte;
246 DCHECK(bit_reader->ReadBits(8, &stuffing_byte));
247 if (stuffing_byte != 0xff) {
248 LOG(WARNING) << "Invalid stuffing byte = " << stuffing_byte;
249 return false;
250 }
251 }
252
253 DVLOG(LOG_LEVEL_TS) << "random_access_indicator=" << random_access_indicator_;
254 return true;
255 }
256
257 const uint8* TsPacket::GetPayload() const {
258 return payload_;
259 }
260
261 int TsPacket::GetPayloadOffset() const {
262 return (kPacketSize - payload_size_);
263 }
264
265 int TsPacket::GetPayloadSize() const {
266 return payload_size_;
267 }
268
269 } // namespace mpeg2ts
270 } // namespace media
271
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698