Shaka Packager SDK
Loading...
Searching...
No Matches
wvm_media_parser.cc
1// Copyright 2014 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 <packager/media/formats/wvm/wvm_media_parser.h>
6
7#include <cstddef>
8#include <cstdint>
9#include <cstring>
10#include <map>
11#include <memory>
12#include <string>
13#include <utility>
14#include <vector>
15
16#include <absl/base/internal/endian.h>
17#include <absl/log/check.h>
18#include <absl/log/log.h>
19#include <absl/strings/str_format.h>
20
21#include <packager/media/base/aes_cryptor.h>
22#include <packager/media/base/aes_decryptor.h>
23#include <packager/media/base/aes_encryptor.h>
24#include <packager/media/base/audio_stream_info.h>
25#include <packager/media/base/fourccs.h>
26#include <packager/media/base/key_source.h>
27#include <packager/media/base/media_sample.h>
28#include <packager/media/base/stream_info.h>
29#include <packager/media/base/video_stream_info.h>
30#include <packager/media/codecs/aac_audio_specific_config.h>
31#include <packager/media/codecs/avc_decoder_configuration_record.h>
32#include <packager/media/codecs/es_descriptor.h>
33#include <packager/media/formats/mp2t/adts_header.h>
34#include <packager/status.h>
35
36#define HAS_HEADER_EXTENSION(x) \
37 ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) && (x != 0xF0) && (x != 0xF2) && \
38 (x != 0xF8) && (x != 0xFF))
39
40namespace {
41const uint32_t kMpeg2ClockRate = 90000;
42const uint32_t kPesOptPts = 0x80;
43const uint32_t kPesOptDts = 0x40;
44const uint32_t kPesOptAlign = 0x04;
45const uint32_t kPsmStreamId = 0xBC;
46const uint32_t kPaddingStreamId = 0xBE;
47const uint32_t kIndexMagic = 0x49444d69;
48const uint32_t kIndexStreamId = 0xBF; // private_stream_2
49const uint32_t kIndexVersion4HeaderSize = 12;
50const uint32_t kEcmStreamId = 0xF0;
51const uint32_t kV2MetadataStreamId = 0xF1; // EMM_stream
52const uint32_t kScramblingBitsMask = 0x30;
53const uint32_t kStartCode1 = 0x00;
54const uint32_t kStartCode2 = 0x00;
55const uint32_t kStartCode3 = 0x01;
56const uint32_t kStartCode4Pack = 0xBA;
57const uint32_t kStartCode4System = 0xBB;
58const uint32_t kStartCode4ProgramEnd = 0xB9;
59const uint32_t kPesStreamIdVideoMask = 0xF0;
60const uint32_t kPesStreamIdVideo = 0xE0;
61const uint32_t kPesStreamIdAudioMask = 0xE0;
62const uint32_t kPesStreamIdAudio = 0xC0;
63const uint32_t kVersion4 = 4;
64const uint8_t kAacSampleSizeBits = 16;
65// Applies to all video streams.
66const uint8_t kNaluLengthSize = 4; // unit is bytes.
67// Placeholder sampling frequency for all audio streams, which
68// will be overwritten after filter parsing.
69const uint32_t kDefaultSamplingFrequency = 100;
70const uint16_t kEcmSizeBytes = 80;
71const uint32_t kInitializationVectorSizeBytes = 16;
72// ECM fields for processing.
73const uint32_t kEcmContentKeySizeBytes = 16;
74const uint32_t kEcmDCPFlagsSizeBytes = 3;
75const uint32_t kEcmCCIFlagsSizeBytes = 1;
76const uint32_t kEcmFlagsSizeBytes =
77 kEcmCCIFlagsSizeBytes + kEcmDCPFlagsSizeBytes;
78const uint32_t kEcmPaddingSizeBytes = 12;
79const uint32_t kAssetKeySizeBytes = 16;
80// Default audio and video PES stream IDs.
81const uint8_t kDefaultAudioStreamId = kPesStreamIdAudio;
82const uint8_t kDefaultVideoStreamId = kPesStreamIdVideo;
83
84enum Type {
85 Type_void = 0,
86 Type_uint8 = 1,
87 Type_int8 = 2,
88 Type_uint16 = 3,
89 Type_int16 = 4,
90 Type_uint32 = 5,
91 Type_int32 = 6,
92 Type_uint64 = 7,
93 Type_int64 = 8,
94 Type_string = 9,
95 Type_BinaryData = 10
96};
97} // namespace
98
99namespace shaka {
100namespace media {
101namespace wvm {
102
103WvmMediaParser::WvmMediaParser()
104 : is_initialized_(false),
105 parse_state_(StartCode1),
106 skip_bytes_(0),
107 metadata_is_complete_(false),
108 current_program_id_(0),
109 pes_stream_id_(0),
110 prev_pes_stream_id_(0),
111 pes_packet_bytes_(0),
112 pes_flags_1_(0),
113 pes_flags_2_(0),
114 prev_pes_flags_1_(0),
115 pes_header_data_bytes_(0),
116 timestamp_(0),
117 pts_(0),
118 dts_(0),
119 index_program_id_(0),
120 media_sample_(NULL),
121 crypto_unit_start_pos_(0),
122 stream_id_count_(0),
123 decryption_key_source_(NULL) {}
124
125WvmMediaParser::~WvmMediaParser() {}
126
127void WvmMediaParser::Init(const InitCB& init_cb,
128 const NewMediaSampleCB& new_media_sample_cb,
129 const NewTextSampleCB& new_text_sample_cb,
130 KeySource* decryption_key_source) {
131 DCHECK(!is_initialized_);
132 DCHECK(init_cb != nullptr);
133 DCHECK(new_media_sample_cb != nullptr);
134 decryption_key_source_ = decryption_key_source;
135 init_cb_ = init_cb;
136 new_sample_cb_ = new_media_sample_cb;
137}
138
139bool WvmMediaParser::Parse(const uint8_t* buf, int size) {
140 size_t num_bytes = 0;
141 size_t prev_size = 0;
142 const uint8_t* read_ptr = buf;
143 const uint8_t* end = read_ptr + size;
144
145 while (read_ptr < end) {
146 switch (parse_state_) {
147 case StartCode1:
148 if (*read_ptr == kStartCode1) {
149 parse_state_ = StartCode2;
150 }
151 break;
152 case StartCode2:
153 if (*read_ptr == kStartCode2) {
154 parse_state_ = StartCode3;
155 } else {
156 parse_state_ = StartCode1;
157 }
158 break;
159 case StartCode3:
160 if (*read_ptr == kStartCode3) {
161 parse_state_ = StartCode4;
162 } else {
163 parse_state_ = StartCode1;
164 }
165 break;
166 case StartCode4:
167 switch (*read_ptr) {
168 case kStartCode4Pack:
169 parse_state_ = PackHeader1;
170 break;
171 case kStartCode4System:
172 parse_state_ = SystemHeader1;
173 break;
174 case kStartCode4ProgramEnd:
175 parse_state_ = ProgramEnd;
176 continue;
177 default:
178 parse_state_ = PesStreamId;
179 continue;
180 }
181 break;
182 case PackHeader1:
183 parse_state_ = PackHeader2;
184 break;
185 case PackHeader2:
186 parse_state_ = PackHeader3;
187 break;
188 case PackHeader3:
189 parse_state_ = PackHeader4;
190 break;
191 case PackHeader4:
192 parse_state_ = PackHeader5;
193 break;
194 case PackHeader5:
195 parse_state_ = PackHeader6;
196 break;
197 case PackHeader6:
198 parse_state_ = PackHeader7;
199 break;
200 case PackHeader7:
201 parse_state_ = PackHeader8;
202 break;
203 case PackHeader8:
204 parse_state_ = PackHeader9;
205 break;
206 case PackHeader9:
207 parse_state_ = PackHeader10;
208 break;
209 case PackHeader10:
210 skip_bytes_ = *read_ptr & 0x07;
211 parse_state_ = PackHeaderStuffingSkip;
212 break;
213 case SystemHeader1:
214 skip_bytes_ = *read_ptr;
215 skip_bytes_ <<= 8;
216 parse_state_ = SystemHeader2;
217 break;
218 case SystemHeader2:
219 skip_bytes_ |= *read_ptr;
220 parse_state_ = SystemHeaderSkip;
221 break;
222 case PackHeaderStuffingSkip:
223 if (end >= skip_bytes_ + read_ptr) {
224 read_ptr += skip_bytes_;
225 skip_bytes_ = 0;
226 parse_state_ = StartCode1;
227 } else {
228 skip_bytes_ -= (end - read_ptr);
229 read_ptr = end;
230 }
231 continue;
232 case SystemHeaderSkip:
233 if (end >= skip_bytes_ + read_ptr) {
234 read_ptr += skip_bytes_;
235 skip_bytes_ = 0;
236 parse_state_ = StartCode1;
237 } else {
238 uint32_t remaining_size = end - read_ptr;
239 skip_bytes_ -= remaining_size;
240 read_ptr = end;
241 }
242 continue;
243 case PesStreamId:
244 pes_stream_id_ = *read_ptr;
245 if (!metadata_is_complete_ && (pes_stream_id_ != kPsmStreamId) &&
246 (pes_stream_id_ != kIndexStreamId) &&
247 (pes_stream_id_ != kEcmStreamId) &&
248 (pes_stream_id_ != kV2MetadataStreamId) &&
249 (pes_stream_id_ != kPaddingStreamId)) {
250 metadata_is_complete_ = true;
251 }
252 parse_state_ = PesPacketLength1;
253 break;
254 case PesPacketLength1:
255 pes_packet_bytes_ = *read_ptr;
256 pes_packet_bytes_ <<= 8;
257 parse_state_ = PesPacketLength2;
258 break;
259 case PesPacketLength2:
260 pes_packet_bytes_ |= *read_ptr;
261 if (HAS_HEADER_EXTENSION(pes_stream_id_)) {
262 parse_state_ = PesExtension1;
263 } else {
264 prev_pes_flags_1_ = pes_flags_1_;
265 pes_flags_1_ = pes_flags_2_ = 0;
266 pes_header_data_bytes_ = 0;
267 parse_state_ = PesPayload;
268 }
269 break;
270 case PesExtension1:
271 prev_pes_flags_1_ = pes_flags_1_;
272 pes_flags_1_ = *read_ptr;
273 --pes_packet_bytes_;
274 parse_state_ = PesExtension2;
275 break;
276 case PesExtension2:
277 pes_flags_2_ = *read_ptr;
278 --pes_packet_bytes_;
279 parse_state_ = PesExtension3;
280 break;
281 case PesExtension3:
282 pes_header_data_bytes_ = *read_ptr;
283 --pes_packet_bytes_;
284 if (pes_flags_2_ & kPesOptPts) {
285 parse_state_ = Pts1;
286 } else {
287 parse_state_ = PesHeaderData;
288 }
289 break;
290 case Pts1:
291 timestamp_ = (*read_ptr & 0x0E);
292 --pes_header_data_bytes_;
293 --pes_packet_bytes_;
294 parse_state_ = Pts2;
295 break;
296 case Pts2:
297 timestamp_ <<= 7;
298 timestamp_ |= *read_ptr;
299 --pes_header_data_bytes_;
300 --pes_packet_bytes_;
301 parse_state_ = Pts3;
302 break;
303 case Pts3:
304 timestamp_ <<= 7;
305 timestamp_ |= *read_ptr >> 1;
306 --pes_header_data_bytes_;
307 --pes_packet_bytes_;
308 parse_state_ = Pts4;
309 break;
310 case Pts4:
311 timestamp_ <<= 8;
312 timestamp_ |= *read_ptr;
313 --pes_header_data_bytes_;
314 --pes_packet_bytes_;
315 parse_state_ = Pts5;
316 break;
317 case Pts5:
318 timestamp_ <<= 7;
319 timestamp_ |= *read_ptr >> 1;
320 pts_ = timestamp_;
321 --pes_header_data_bytes_;
322 --pes_packet_bytes_;
323 if (pes_flags_2_ & kPesOptDts) {
324 parse_state_ = Dts1;
325 } else {
326 dts_ = pts_;
327 parse_state_ = PesHeaderData;
328 }
329 break;
330 case Dts1:
331 timestamp_ = (*read_ptr & 0x0E);
332 --pes_header_data_bytes_;
333 --pes_packet_bytes_;
334 parse_state_ = Dts2;
335 break;
336 case Dts2:
337 timestamp_ <<= 7;
338 timestamp_ |= *read_ptr;
339 --pes_header_data_bytes_;
340 --pes_packet_bytes_;
341 parse_state_ = Dts3;
342 break;
343 case Dts3:
344 timestamp_ <<= 7;
345 timestamp_ |= *read_ptr >> 1;
346 --pes_header_data_bytes_;
347 --pes_packet_bytes_;
348 parse_state_ = Dts4;
349 break;
350 case Dts4:
351 timestamp_ <<= 8;
352 timestamp_ |= *read_ptr;
353 --pes_header_data_bytes_;
354 --pes_packet_bytes_;
355 parse_state_ = Dts5;
356 break;
357 case Dts5:
358 timestamp_ <<= 7;
359 timestamp_ |= *read_ptr >> 1;
360 dts_ = timestamp_;
361 --pes_header_data_bytes_;
362 --pes_packet_bytes_;
363 parse_state_ = PesHeaderData;
364 break;
365 case PesHeaderData:
366 num_bytes = end - read_ptr;
367 if (num_bytes >= pes_header_data_bytes_) {
368 num_bytes = pes_header_data_bytes_;
369 parse_state_ = PesPayload;
370 }
371 pes_header_data_bytes_ -= num_bytes;
372 pes_packet_bytes_ -= num_bytes;
373 read_ptr += num_bytes;
374 continue;
375 case PesPayload:
376 switch (pes_stream_id_) {
377 case kPsmStreamId:
378 psm_data_.clear();
379 parse_state_ = PsmPayload;
380 continue;
381 case kPaddingStreamId:
382 parse_state_ = Padding;
383 continue;
384 case kEcmStreamId:
385 ecm_.clear();
386 parse_state_ = EcmPayload;
387 continue;
388 case kIndexStreamId:
389 parse_state_ = IndexPayload;
390 continue;
391 default:
392 if (!DemuxNextPes(false)) {
393 return false;
394 }
395 parse_state_ = EsPayload;
396 }
397 continue;
398 case PsmPayload:
399 num_bytes = end - read_ptr;
400 if (num_bytes >= pes_packet_bytes_) {
401 num_bytes = pes_packet_bytes_;
402 parse_state_ = StartCode1;
403 }
404 if (num_bytes > 0) {
405 pes_packet_bytes_ -= num_bytes;
406 prev_size = psm_data_.size();
407 psm_data_.resize(prev_size + num_bytes);
408 memcpy(&psm_data_[prev_size], read_ptr, num_bytes);
409 }
410 read_ptr += num_bytes;
411 continue;
412 case EcmPayload:
413 num_bytes = end - read_ptr;
414 if (num_bytes >= pes_packet_bytes_) {
415 num_bytes = pes_packet_bytes_;
416 parse_state_ = StartCode1;
417 }
418 if (num_bytes > 0) {
419 pes_packet_bytes_ -= num_bytes;
420 prev_size = ecm_.size();
421 ecm_.resize(prev_size + num_bytes);
422 memcpy(&ecm_[prev_size], read_ptr, num_bytes);
423 }
424 if ((pes_packet_bytes_ == 0) && !ecm_.empty()) {
425 if (!ProcessEcm()) {
426 return (false);
427 }
428 }
429 read_ptr += num_bytes;
430 continue;
431 case IndexPayload:
432 num_bytes = end - read_ptr;
433 if (num_bytes >= pes_packet_bytes_) {
434 num_bytes = pes_packet_bytes_;
435 parse_state_ = StartCode1;
436 }
437 if (num_bytes > 0) {
438 pes_packet_bytes_ -= num_bytes;
439 prev_size = index_data_.size();
440 index_data_.resize(prev_size + num_bytes);
441 memcpy(&index_data_[prev_size], read_ptr, num_bytes);
442 }
443 if (pes_packet_bytes_ == 0 && !index_data_.empty()) {
444 if (!metadata_is_complete_) {
445 if (!ParseIndexEntry()) {
446 return false;
447 }
448 }
449 }
450 read_ptr += num_bytes;
451 continue;
452 case EsPayload:
453 num_bytes = end - read_ptr;
454 if (num_bytes >= pes_packet_bytes_) {
455 num_bytes = pes_packet_bytes_;
456 parse_state_ = StartCode1;
457 }
458 pes_packet_bytes_ -= num_bytes;
459 if (pes_stream_id_ != kV2MetadataStreamId) {
460 sample_data_.resize(sample_data_.size() + num_bytes);
461 memcpy(&sample_data_[sample_data_.size() - num_bytes], read_ptr,
462 num_bytes);
463 }
464 prev_pes_stream_id_ = pes_stream_id_;
465 read_ptr += num_bytes;
466 continue;
467 case Padding:
468 num_bytes = end - read_ptr;
469 if (num_bytes >= pes_packet_bytes_) {
470 num_bytes = pes_packet_bytes_;
471 parse_state_ = StartCode1;
472 }
473 pes_packet_bytes_ -= num_bytes;
474 read_ptr += num_bytes;
475 continue;
476 case ProgramEnd:
477 parse_state_ = StartCode1;
478 metadata_is_complete_ = true;
479 if (!DemuxNextPes(true)) {
480 return false;
481 }
482 if (!Flush()) {
483 return false;
484 }
485 // Reset.
486 dts_ = pts_ = 0;
487 parse_state_ = StartCode1;
488 prev_media_sample_data_.Reset();
489 current_program_id_++;
490 ecm_.clear();
491 index_data_.clear();
492 psm_data_.clear();
493 break;
494 default:
495 break;
496 }
497 ++read_ptr;
498 }
499 return true;
500}
501
502bool WvmMediaParser::EmitLastSample(
503 uint32_t stream_id,
504 const std::shared_ptr<MediaSample>& new_sample) {
505 std::string key = absl::StrFormat("%u:%u", current_program_id_, stream_id);
506 std::map<std::string, uint32_t>::iterator it =
507 program_demux_stream_map_.find(key);
508 if (it == program_demux_stream_map_.end())
509 return false;
510 return EmitSample(stream_id, (*it).second, new_sample, true);
511}
512
513bool WvmMediaParser::EmitPendingSamples() {
514 // Emit queued samples which were built when not initialized.
515 while (!media_sample_queue_.empty()) {
516 DemuxStreamIdMediaSample& demux_stream_media_sample =
517 media_sample_queue_.front();
518 if (!EmitSample(demux_stream_media_sample.parsed_audio_or_video_stream_id,
519 demux_stream_media_sample.demux_stream_id,
520 demux_stream_media_sample.media_sample, false)) {
521 return false;
522 }
523 media_sample_queue_.pop_front();
524 }
525 return true;
526}
527
528bool WvmMediaParser::Flush() {
529 // Flush the last audio and video sample for current program.
530 // Reset the streamID when successfully emitted.
531 if (prev_media_sample_data_.audio_sample != NULL) {
532 if (!EmitLastSample(prev_pes_stream_id_,
533 prev_media_sample_data_.audio_sample)) {
534 LOG(ERROR) << "Did not emit last sample for audio stream with ID = "
535 << prev_pes_stream_id_;
536 return false;
537 }
538 }
539 if (prev_media_sample_data_.video_sample != NULL) {
540 if (!EmitLastSample(prev_pes_stream_id_,
541 prev_media_sample_data_.video_sample)) {
542 LOG(ERROR) << "Did not emit last sample for video stream with ID = "
543 << prev_pes_stream_id_;
544 return false;
545 }
546 }
547 return true;
548}
549
550bool WvmMediaParser::ParseIndexEntry() {
551 // Do not parse index entry at the beginning of any track *after* the first
552 // track.
553 if (current_program_id_ > 0) {
554 return true;
555 }
556 uint32_t index_size = 0;
557 if (index_data_.size() < kIndexVersion4HeaderSize) {
558 return false;
559 }
560
561 const uint8_t* read_ptr = index_data_.data();
562 if (absl::big_endian::Load32(read_ptr) != kIndexMagic) {
563 index_data_.clear();
564 return false;
565 }
566 read_ptr += 4;
567
568 uint32_t version = absl::big_endian::Load32(read_ptr);
569 read_ptr += 4;
570 if (version == kVersion4) {
571 index_size = kIndexVersion4HeaderSize + absl::big_endian::Load32(read_ptr);
572 if (index_data_.size() < index_size) {
573 // We do not yet have the full index. Keep accumulating index data.
574 return true;
575 }
576 read_ptr += sizeof(uint32_t);
577
578 // Index metadata
579 uint32_t index_metadata_max_size = index_size - kIndexVersion4HeaderSize;
580 if (index_metadata_max_size < sizeof(uint8_t)) {
581 index_data_.clear();
582 return false;
583 }
584
585 int64_t track_duration = 0;
586 uint32_t trick_play_factor = 0;
587 uint32_t sampling_frequency = kDefaultSamplingFrequency;
588 int32_t time_scale = kMpeg2ClockRate;
589 uint16_t video_width = 0;
590 uint16_t video_height = 0;
591 uint32_t pixel_width = 0;
592 uint32_t pixel_height = 0;
593 uint8_t nalu_length_size = kNaluLengthSize;
594 uint8_t num_channels = 0;
595 int audio_pes_stream_id = 0;
596 int video_pes_stream_id = 0;
597 bool has_video = false;
598 bool has_audio = false;
599 std::vector<uint8_t> audio_codec_config;
600 std::vector<uint8_t> video_codec_config;
601 uint8_t num_index_entries = *read_ptr;
602 ++read_ptr;
603 --index_metadata_max_size;
604
605 for (uint8_t idx = 0; idx < num_index_entries; ++idx) {
606 if (index_metadata_max_size < (2 * sizeof(uint8_t)) + sizeof(uint32_t)) {
607 return false;
608 }
609 uint8_t tag = *read_ptr;
610 ++read_ptr;
611 uint8_t type = *read_ptr;
612 ++read_ptr;
613 uint32_t length = absl::big_endian::Load32(read_ptr);
614 read_ptr += sizeof(uint32_t);
615 index_metadata_max_size -= (2 * sizeof(uint8_t)) + sizeof(uint32_t);
616 if (index_metadata_max_size < length) {
617 return false;
618 }
619 int64_t value = 0;
620 Tag tagtype = Unset;
621 std::vector<uint8_t> binary_data;
622 switch (Type(type)) {
623 case Type_uint8:
624 if (length == sizeof(uint8_t)) {
625 tagtype = GetTag(tag, length, read_ptr, &value);
626 } else {
627 return false;
628 }
629 break;
630 case Type_int8:
631 if (length == sizeof(int8_t)) {
632 tagtype = GetTag(tag, length, read_ptr, &value);
633 } else {
634 return false;
635 }
636 break;
637 case Type_uint16:
638 if (length == sizeof(uint16_t)) {
639 tagtype = GetTag(tag, length, read_ptr, &value);
640 } else {
641 return false;
642 }
643 break;
644 case Type_int16:
645 if (length == sizeof(int16_t)) {
646 tagtype = GetTag(tag, length, read_ptr, &value);
647 } else {
648 return false;
649 }
650 break;
651 case Type_uint32:
652 if (length == sizeof(uint32_t)) {
653 tagtype = GetTag(tag, length, read_ptr, &value);
654 } else {
655 return false;
656 }
657 break;
658 case Type_int32:
659 if (length == sizeof(int32_t)) {
660 tagtype = GetTag(tag, length, read_ptr, &value);
661 } else {
662 return false;
663 }
664 break;
665 case Type_uint64:
666 if (length == sizeof(uint64_t)) {
667 tagtype = GetTag(tag, length, read_ptr, &value);
668 } else {
669 return false;
670 }
671 break;
672 case Type_int64:
673 if (length == sizeof(int64_t)) {
674 tagtype = GetTag(tag, length, read_ptr, &value);
675 } else {
676 return false;
677 }
678 break;
679 case Type_string:
680 case Type_BinaryData:
681 binary_data.assign(read_ptr, read_ptr + length);
682 tagtype = Tag(tag);
683 break;
684 default:
685 break;
686 }
687
688 switch (tagtype) {
689 case TrackDuration:
690 track_duration = value;
691 break;
692 case TrackTrickPlayFactor:
693 trick_play_factor = value;
694 break;
695 case VideoStreamId:
696 video_pes_stream_id = value;
697 break;
698 case AudioStreamId:
699 audio_pes_stream_id = value;
700 break;
701 case VideoWidth:
702 video_width = (uint16_t)value;
703 break;
704 case VideoHeight:
705 video_height = (uint16_t)value;
706 break;
707 case AudioNumChannels:
708 num_channels = (uint8_t)value;
709 break;
710 case VideoType:
711 has_video = true;
712 break;
713 case AudioType:
714 has_audio = true;
715 break;
716 case VideoPixelWidth:
717 pixel_width = static_cast<uint32_t>(value);
718 break;
719 case VideoPixelHeight:
720 pixel_height = static_cast<uint32_t>(value);
721 break;
722 case Audio_EsDescriptor: {
723 ESDescriptor descriptor;
724 if (!descriptor.Parse(binary_data)) {
725 LOG(ERROR)
726 << "Could not extract AudioSpecificConfig from ES_Descriptor";
727 return false;
728 }
729 audio_codec_config = descriptor.decoder_config_descriptor()
730 .decoder_specific_info_descriptor()
731 .data();
732 break;
733 }
734 case Audio_EC3SpecificData:
735 case Audio_DtsSpecificData:
736 case Audio_AC3SpecificData:
737 LOG(ERROR) << "Audio type not supported.";
738 return false;
739 case Video_AVCDecoderConfigurationRecord:
740 video_codec_config = binary_data;
741 break;
742 default:
743 break;
744 }
745
746 read_ptr += length;
747 index_metadata_max_size -= length;
748 }
749 // End Index metadata
750 index_size = read_ptr - index_data_.data();
751
752 if (has_video) {
753 stream_infos_.emplace_back(new VideoStreamInfo(
754 stream_id_count_, time_scale, track_duration, kCodecH264,
755 byte_to_unit_stream_converter_.stream_format(), std::string(),
756 video_codec_config.data(), video_codec_config.size(), video_width,
757 video_height, pixel_width, pixel_height, 0 /* color_primaries */,
758 0 /*matrix_coefficients */, 0 /* transfer_characteristics */,
759 trick_play_factor, nalu_length_size, std::string(),
760 decryption_key_source_ ? false : true));
761 program_demux_stream_map_[absl::StrFormat(
762 "%u:%u", index_program_id_,
763 video_pes_stream_id ? video_pes_stream_id : kDefaultVideoStreamId)] =
764 stream_id_count_++;
765 }
766 if (has_audio) {
767 const Codec audio_codec = kCodecAAC;
768 // TODO(beil): Pass in max and average bitrate in wvm container.
769 stream_infos_.emplace_back(new AudioStreamInfo(
770 stream_id_count_, time_scale, track_duration, audio_codec,
771 std::string(), audio_codec_config.data(), audio_codec_config.size(),
772 kAacSampleSizeBits, num_channels, sampling_frequency,
773 0 /* seek preroll */, 0 /* codec delay */, 0 /* max bitrate */,
774 0 /* avg bitrate */, std::string(),
775 decryption_key_source_ ? false : true));
776 program_demux_stream_map_[absl::StrFormat(
777 "%u:%u", index_program_id_,
778 audio_pes_stream_id ? audio_pes_stream_id : kDefaultAudioStreamId)] =
779 stream_id_count_++;
780 }
781 }
782
783 index_program_id_++;
784 index_data_.clear();
785 return true;
786}
787
788bool WvmMediaParser::DemuxNextPes(bool is_program_end) {
789 bool output_encrypted_sample = false;
790 if (!sample_data_.empty() && (prev_pes_flags_1_ & kScramblingBitsMask)) {
791 // Decrypt crypto unit.
792 if (!content_decryptor_) {
793 output_encrypted_sample = true;
794 } else {
795 size_t output_size = content_decryptor_->RequiredOutputSize(
796 sample_data_.size() - crypto_unit_start_pos_);
797 content_decryptor_->Crypt(&sample_data_[crypto_unit_start_pos_],
798 sample_data_.size() - crypto_unit_start_pos_,
799 &sample_data_[crypto_unit_start_pos_],
800 &output_size);
801 }
802 }
803 // Demux media sample if we are at program end or if we are not at a
804 // continuation PES.
805 if ((pes_flags_2_ & kPesOptPts) || is_program_end) {
806 if (!sample_data_.empty()) {
807 if (!Output(output_encrypted_sample)) {
808 return false;
809 }
810 }
811 StartMediaSampleDemux();
812 }
813
814 crypto_unit_start_pos_ = sample_data_.size();
815 return true;
816}
817
818void WvmMediaParser::StartMediaSampleDemux() {
819 bool is_key_frame = ((pes_flags_1_ & kPesOptAlign) != 0);
820 media_sample_ = MediaSample::CreateEmptyMediaSample();
821 media_sample_->set_dts(dts_);
822 media_sample_->set_pts(pts_);
823 media_sample_->set_is_key_frame(is_key_frame);
824
825 sample_data_.clear();
826}
827
828bool WvmMediaParser::Output(bool output_encrypted_sample) {
829 if (output_encrypted_sample) {
830 media_sample_->SetData(sample_data_.data(), sample_data_.size());
831 media_sample_->set_is_encrypted(true);
832 } else {
833 if ((prev_pes_stream_id_ & kPesStreamIdVideoMask) == kPesStreamIdVideo) {
834 // Convert video stream to unit stream and get config.
835 std::vector<uint8_t> nal_unit_stream;
836 if (!byte_to_unit_stream_converter_.ConvertByteStreamToNalUnitStream(
837 sample_data_.data(), sample_data_.size(), &nal_unit_stream)) {
838 LOG(ERROR) << "Could not convert h.264 byte stream sample";
839 return false;
840 }
841 media_sample_->SetData(nal_unit_stream.data(), nal_unit_stream.size());
842 if (!is_initialized_) {
843 // Set extra data for video stream from AVC Decoder Config Record.
844 // Also, set codec string from the AVC Decoder Config Record.
845 std::vector<uint8_t> decoder_config_record;
846 byte_to_unit_stream_converter_.GetDecoderConfigurationRecord(
847 &decoder_config_record);
848 for (uint32_t i = 0; i < stream_infos_.size(); i++) {
849 if (stream_infos_[i]->stream_type() == kStreamVideo &&
850 stream_infos_[i]->codec_string().empty()) {
851 const std::vector<uint8_t>* stream_config;
852 if (stream_infos_[i]->codec_config().empty()) {
853 // Decoder config record not available for stream. Use the one
854 // computed from the first video stream.
855 stream_infos_[i]->set_codec_config(decoder_config_record);
856 stream_config = &decoder_config_record;
857 } else {
858 // Use stream-specific config record.
859 stream_config = &stream_infos_[i]->codec_config();
860 }
861 DCHECK(stream_config);
862
863 VideoStreamInfo* video_stream_info =
864 reinterpret_cast<VideoStreamInfo*>(stream_infos_[i].get());
865 AVCDecoderConfigurationRecord avc_config;
866 if (!avc_config.Parse(*stream_config)) {
867 LOG(WARNING) << "Failed to parse AVCDecoderConfigurationRecord. "
868 "Using computed configuration record instead.";
869 video_stream_info->set_codec_config(decoder_config_record);
870 if (!avc_config.Parse(decoder_config_record)) {
871 LOG(ERROR) << "Failed to parse AVCDecoderConfigurationRecord.";
872 return false;
873 }
874 }
875 const FourCC codec_fourcc =
876 byte_to_unit_stream_converter_.stream_format() ==
877 H26xStreamFormat::kNalUnitStreamWithParameterSetNalus
878 ? FOURCC_avc3
879 : FOURCC_avc1;
880 video_stream_info->set_codec_string(
881 avc_config.GetCodecString(codec_fourcc));
882
883 if (avc_config.pixel_width() != video_stream_info->pixel_width() ||
884 avc_config.pixel_height() !=
885 video_stream_info->pixel_height()) {
886 LOG_IF(WARNING, video_stream_info->pixel_width() != 0 ||
887 video_stream_info->pixel_height() != 0)
888 << "Pixel aspect ratio in WVM metadata ("
889 << video_stream_info->pixel_width() << ","
890 << video_stream_info->pixel_height()
891 << ") does not match with SAR in "
892 "AVCDecoderConfigurationRecord ("
893 << avc_config.pixel_width() << ","
894 << avc_config.pixel_height()
895 << "). Use AVCDecoderConfigurationRecord.";
896 video_stream_info->set_pixel_width(avc_config.pixel_width());
897 video_stream_info->set_pixel_height(avc_config.pixel_height());
898 }
899 if (avc_config.coded_width() != video_stream_info->width() ||
900 avc_config.coded_height() != video_stream_info->height()) {
901 LOG(WARNING) << "Resolution in WVM metadata ("
902 << video_stream_info->width() << ","
903 << video_stream_info->height()
904 << ") does not match with resolution in "
905 "AVCDecoderConfigurationRecord ("
906 << avc_config.coded_width() << ","
907 << avc_config.coded_height()
908 << "). Use AVCDecoderConfigurationRecord.";
909 video_stream_info->set_width(avc_config.coded_width());
910 video_stream_info->set_height(avc_config.coded_height());
911 }
912 }
913 }
914 }
915 } else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) ==
916 kPesStreamIdAudio) {
917 // Set data on the audio stream.
918 mp2t::AdtsHeader adts_header;
919 const uint8_t* frame_ptr = sample_data_.data();
920 if (!adts_header.Parse(frame_ptr, sample_data_.size())) {
921 LOG(ERROR) << "Could not parse ADTS header";
922 return false;
923 }
924 media_sample_->SetData(
925 frame_ptr + adts_header.GetHeaderSize(),
926 adts_header.GetFrameSize() - adts_header.GetHeaderSize());
927 if (!is_initialized_) {
928 for (uint32_t i = 0; i < stream_infos_.size(); i++) {
929 if (stream_infos_[i]->stream_type() == kStreamAudio &&
930 stream_infos_[i]->codec_string().empty()) {
931 AudioStreamInfo* audio_stream_info =
932 reinterpret_cast<AudioStreamInfo*>(stream_infos_[i].get());
933 if (audio_stream_info->codec_config().empty()) {
934 // Set AudioStreamInfo fields using information from the ADTS
935 // header.
936 audio_stream_info->set_sampling_frequency(
937 adts_header.GetSamplingFrequency());
938 std::vector<uint8_t> audio_specific_config;
939 adts_header.GetAudioSpecificConfig(&audio_specific_config);
940 audio_stream_info->set_codec_config(audio_specific_config);
941 audio_stream_info->set_codec_string(
942 AudioStreamInfo::GetCodecString(kCodecAAC,
943 adts_header.GetObjectType()));
944 } else {
945 // Set AudioStreamInfo fields using information from the
946 // AACAudioSpecificConfig record.
947 AACAudioSpecificConfig aac_config;
948 if (!aac_config.Parse(stream_infos_[i]->codec_config())) {
949 LOG(ERROR) << "Could not parse AACAudioSpecificconfig";
950 return false;
951 }
952 audio_stream_info->set_sampling_frequency(
953 aac_config.GetSamplesPerSecond());
954 audio_stream_info->set_codec_string(
955 AudioStreamInfo::GetCodecString(
956 kCodecAAC, aac_config.GetAudioObjectType()));
957 }
958 }
959 }
960 }
961 }
962 }
963
964 if (!is_initialized_) {
965 bool all_streams_have_config = true;
966 // Check if all collected stream infos have codec_config set.
967 for (uint32_t i = 0; i < stream_infos_.size(); i++) {
968 if (stream_infos_[i]->codec_string().empty()) {
969 all_streams_have_config = false;
970 break;
971 }
972 }
973 if (all_streams_have_config) {
974 init_cb_(stream_infos_);
975 is_initialized_ = true;
976 }
977 }
978
979 DCHECK_GT(media_sample_->data_size(), 0UL);
980 std::string key =
981 absl::StrFormat("%u:%u", current_program_id_, prev_pes_stream_id_);
982 std::map<std::string, uint32_t>::iterator it =
983 program_demux_stream_map_.find(key);
984 if (it == program_demux_stream_map_.end()) {
985 // TODO(ramjic): Log error message here and in other error cases through
986 // this method.
987 return false;
988 }
989 DemuxStreamIdMediaSample demux_stream_media_sample;
990 demux_stream_media_sample.parsed_audio_or_video_stream_id =
991 prev_pes_stream_id_;
992 demux_stream_media_sample.demux_stream_id = (*it).second;
993 demux_stream_media_sample.media_sample = media_sample_;
994 // Check if sample can be emitted.
995 if (!is_initialized_) {
996 media_sample_queue_.push_back(demux_stream_media_sample);
997 } else {
998 // flush the sample queue and emit all queued samples.
999 while (!media_sample_queue_.empty()) {
1000 if (!EmitPendingSamples())
1001 return false;
1002 }
1003 // Emit current sample.
1004 if (!EmitSample(prev_pes_stream_id_, (*it).second, media_sample_, false))
1005 return false;
1006 }
1007 return true;
1008}
1009
1010bool WvmMediaParser::EmitSample(uint32_t parsed_audio_or_video_stream_id,
1011 uint32_t stream_id,
1012 const std::shared_ptr<MediaSample>& new_sample,
1013 bool isLastSample) {
1014 DCHECK(new_sample);
1015 if (isLastSample) {
1016 if ((parsed_audio_or_video_stream_id & kPesStreamIdVideoMask) ==
1017 kPesStreamIdVideo) {
1018 new_sample->set_duration(prev_media_sample_data_.video_sample_duration);
1019 } else if ((parsed_audio_or_video_stream_id & kPesStreamIdAudioMask) ==
1020 kPesStreamIdAudio) {
1021 new_sample->set_duration(prev_media_sample_data_.audio_sample_duration);
1022 }
1023 if (!new_sample_cb_(stream_id, new_sample)) {
1024 LOG(ERROR) << "Failed to process the last sample.";
1025 return false;
1026 }
1027 return true;
1028 }
1029
1030 // Cannot emit current sample. Compute duration first and then,
1031 // emit previous sample.
1032 if ((parsed_audio_or_video_stream_id & kPesStreamIdVideoMask) ==
1033 kPesStreamIdVideo) {
1034 if (prev_media_sample_data_.video_sample == NULL) {
1035 prev_media_sample_data_.video_sample = new_sample;
1036 prev_media_sample_data_.video_stream_id = stream_id;
1037 return true;
1038 }
1039 prev_media_sample_data_.video_sample->set_duration(
1040 new_sample->dts() - prev_media_sample_data_.video_sample->dts());
1041 prev_media_sample_data_.video_sample_duration =
1042 prev_media_sample_data_.video_sample->duration();
1043 if (!new_sample_cb_(prev_media_sample_data_.video_stream_id,
1044 prev_media_sample_data_.video_sample)) {
1045 LOG(ERROR) << "Failed to process the video sample.";
1046 return false;
1047 }
1048 prev_media_sample_data_.video_sample = new_sample;
1049 prev_media_sample_data_.video_stream_id = stream_id;
1050 } else if ((parsed_audio_or_video_stream_id & kPesStreamIdAudioMask) ==
1051 kPesStreamIdAudio) {
1052 if (prev_media_sample_data_.audio_sample == NULL) {
1053 prev_media_sample_data_.audio_sample = new_sample;
1054 prev_media_sample_data_.audio_stream_id = stream_id;
1055 return true;
1056 }
1057 prev_media_sample_data_.audio_sample->set_duration(
1058 new_sample->dts() - prev_media_sample_data_.audio_sample->dts());
1059 prev_media_sample_data_.audio_sample_duration =
1060 prev_media_sample_data_.audio_sample->duration();
1061 if (!new_sample_cb_(prev_media_sample_data_.audio_stream_id,
1062 prev_media_sample_data_.audio_sample)) {
1063 LOG(ERROR) << "Failed to process the audio sample.";
1064 return false;
1065 }
1066 prev_media_sample_data_.audio_sample = new_sample;
1067 prev_media_sample_data_.audio_stream_id = stream_id;
1068 }
1069 return true;
1070}
1071
1072bool WvmMediaParser::GetAssetKey(const uint8_t* asset_id,
1073 EncryptionKey* encryption_key) {
1074 DCHECK(decryption_key_source_);
1075 Status status = decryption_key_source_->FetchKeys(
1076 EmeInitDataType::WIDEVINE_CLASSIC,
1077 std::vector<uint8_t>(asset_id, asset_id + sizeof(uint32_t)));
1078 if (!status.ok()) {
1079 LOG(ERROR) << "Fetch Key(s) failed for AssetID = "
1080 << absl::big_endian::Load32(asset_id) << ", error = " << status;
1081 return false;
1082 }
1083
1084 const char kHdStreamLabel[] = "HD";
1085 status = decryption_key_source_->GetKey(kHdStreamLabel, encryption_key);
1086 if (!status.ok()) {
1087 LOG(ERROR) << "Fetch Key(s) failed for AssetID = "
1088 << absl::big_endian::Load32(asset_id) << ", error = " << status;
1089 return false;
1090 }
1091
1092 return true;
1093}
1094
1095bool WvmMediaParser::ProcessEcm() {
1096 // An error will be returned later if the samples need to be decrypted.
1097 if (!decryption_key_source_)
1098 return true;
1099
1100 if (current_program_id_ > 0) {
1101 return true;
1102 }
1103 if (ecm_.size() != kEcmSizeBytes) {
1104 LOG(ERROR) << "Unexpected ECM size = " << ecm_.size()
1105 << ", expected size = " << kEcmSizeBytes;
1106 return false;
1107 }
1108 const uint8_t* ecm_data = ecm_.data();
1109 DCHECK(ecm_data);
1110 ecm_data += sizeof(uint32_t); // old version field - skip.
1111 ecm_data += sizeof(uint32_t); // clear lead - skip.
1112 ecm_data += sizeof(uint32_t); // system id(includes ECM version) - skip.
1113 EncryptionKey encryption_key;
1114 if (!GetAssetKey(ecm_data, &encryption_key)) {
1115 return false;
1116 }
1117 if (encryption_key.key.size() < kAssetKeySizeBytes) {
1118 LOG(ERROR) << "Asset Key size of " << encryption_key.key.size()
1119 << " for AssetID = " << absl::big_endian::Load32(ecm_data)
1120 << " is less than minimum asset key size.";
1121 return false;
1122 }
1123 ecm_data += sizeof(uint32_t); // asset_id.
1124 // Legacy WVM content may have asset keys > 16 bytes.
1125 // Use only the first 16 bytes of the asset key to get
1126 // the content key.
1127 std::vector<uint8_t> asset_key(
1128 encryption_key.key.begin(),
1129 encryption_key.key.begin() + kAssetKeySizeBytes);
1130 // WVM format always uses all zero IV.
1131 std::vector<uint8_t> zero_iv(kInitializationVectorSizeBytes, 0);
1132 AesCbcDecryptor asset_decryptor(kCtsPadding, AesCryptor::kUseConstantIv);
1133 if (!asset_decryptor.InitializeWithIv(asset_key, zero_iv)) {
1134 LOG(ERROR) << "Failed to initialize asset_decryptor.";
1135 return false;
1136 }
1137
1138 const size_t content_key_buffer_size =
1139 kEcmFlagsSizeBytes + kEcmContentKeySizeBytes +
1140 kEcmPaddingSizeBytes; // flags + contentKey + padding.
1141
1142 size_t output_size =
1143 asset_decryptor.RequiredOutputSize(content_key_buffer_size);
1144 std::vector<uint8_t> content_key_buffer(output_size);
1145 CHECK(asset_decryptor.Crypt(ecm_data, content_key_buffer_size,
1146 content_key_buffer.data(), &output_size));
1147
1148 std::vector<uint8_t> decrypted_content_key_vec(
1149 content_key_buffer.begin() + 4, content_key_buffer.begin() + 20);
1150 std::unique_ptr<AesCbcDecryptor> content_decryptor(
1151 new AesCbcDecryptor(kCtsPadding, AesCryptor::kUseConstantIv));
1152 if (!content_decryptor->InitializeWithIv(decrypted_content_key_vec,
1153 zero_iv)) {
1154 LOG(ERROR) << "Failed to initialize content decryptor.";
1155 return false;
1156 }
1157
1158 content_decryptor_ = std::move(content_decryptor);
1159 return true;
1160}
1161
1162DemuxStreamIdMediaSample::DemuxStreamIdMediaSample()
1163 : demux_stream_id(0), parsed_audio_or_video_stream_id(0) {}
1164
1165DemuxStreamIdMediaSample::~DemuxStreamIdMediaSample() {}
1166
1167PrevSampleData::PrevSampleData() {
1168 Reset();
1169}
1170
1171PrevSampleData::~PrevSampleData() {}
1172
1173void PrevSampleData::Reset() {
1174 audio_sample = NULL;
1175 video_sample = NULL;
1176 audio_stream_id = 0;
1177 video_stream_id = 0;
1178 audio_sample_duration = 0;
1179 video_sample_duration = 0;
1180}
1181
1182} // namespace wvm
1183} // namespace media
1184} // namespace shaka
KeySource is responsible for encryption key acquisition.
Definition key_source.h:56
std::function< bool(uint32_t track_id, std::shared_ptr< MediaSample > media_sample)> NewMediaSampleCB
std::function< bool(uint32_t track_id, std::shared_ptr< TextSample > text_sample)> NewTextSampleCB
std::function< void(const std::vector< std::shared_ptr< StreamInfo > > &stream_info)> InitCB
All the methods that are virtual are virtual for mocking.