OLD | NEW |
---|---|
(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 | |
OLD | NEW |