5 #include "packager/media/formats/wvm/wvm_media_parser.h"
11 #include "packager/base/strings/string_number_conversions.h"
12 #include "packager/media/base/aes_decryptor.h"
13 #include "packager/media/base/audio_stream_info.h"
14 #include "packager/media/base/key_source.h"
15 #include "packager/media/base/media_sample.h"
16 #include "packager/media/base/status.h"
17 #include "packager/media/base/video_stream_info.h"
18 #include "packager/media/filters/avc_decoder_configuration.h"
19 #include "packager/media/formats/mp2t/adts_header.h"
20 #include "packager/media/formats/mp4/aac_audio_specific_config.h"
21 #include "packager/media/formats/mp4/es_descriptor.h"
23 #define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \
24 && (x != 0xF0) && (x != 0xF2) && (x != 0xF8) \
28 const uint32_t kMpeg2ClockRate = 90000;
29 const uint32_t kPesOptPts = 0x80;
30 const uint32_t kPesOptDts = 0x40;
31 const uint32_t kPesOptAlign = 0x04;
32 const uint32_t kPsmStreamId = 0xBC;
33 const uint32_t kPaddingStreamId = 0xBE;
34 const uint32_t kIndexMagic = 0x49444d69;
35 const uint32_t kIndexStreamId = 0xBF;
36 const uint32_t kIndexVersion4HeaderSize = 12;
37 const uint32_t kEcmStreamId = 0xF0;
38 const uint32_t kV2MetadataStreamId = 0xF1;
39 const uint32_t kScramblingBitsMask = 0x30;
40 const uint32_t kStartCode1 = 0x00;
41 const uint32_t kStartCode2 = 0x00;
42 const uint32_t kStartCode3 = 0x01;
43 const uint32_t kStartCode4Pack = 0xBA;
44 const uint32_t kStartCode4System = 0xBB;
45 const uint32_t kStartCode4ProgramEnd = 0xB9;
46 const uint32_t kPesStreamIdVideoMask = 0xF0;
47 const uint32_t kPesStreamIdVideo = 0xE0;
48 const uint32_t kPesStreamIdAudioMask = 0xE0;
49 const uint32_t kPesStreamIdAudio = 0xC0;
50 const uint32_t kVersion4 = 4;
51 const int kAdtsHeaderMinSize = 7;
52 const uint8_t kAacSampleSizeBits = 16;
54 const uint8_t kNaluLengthSize = 4;
57 const uint32_t kDefaultSamplingFrequency = 100;
58 const uint16_t kEcmSizeBytes = 80;
59 const uint32_t kInitializationVectorSizeBytes = 16;
61 const uint32_t kEcmContentKeySizeBytes = 16;
62 const uint32_t kEcmDCPFlagsSizeBytes = 3;
63 const uint32_t kEcmCCIFlagsSizeBytes = 1;
64 const uint32_t kEcmFlagsSizeBytes =
65 kEcmCCIFlagsSizeBytes + kEcmDCPFlagsSizeBytes;
66 const uint32_t kEcmPaddingSizeBytes = 12;
67 const uint32_t kAssetKeySizeBytes = 16;
69 const uint8_t kDefaultAudioStreamId = kPesStreamIdAudio;
70 const uint8_t kDefaultVideoStreamId = kPesStreamIdVideo;
87 namespace edash_packager {
91 WvmMediaParser::WvmMediaParser()
92 : is_initialized_(false),
93 parse_state_(StartCode1),
96 metadata_is_complete_(false),
97 current_program_id_(0),
99 prev_pes_stream_id_(0),
100 pes_packet_bytes_(0),
103 prev_pes_flags_1_(0),
104 pes_header_data_bytes_(0),
108 index_program_id_(0),
110 crypto_unit_start_pos_(0),
112 decryption_key_source_(NULL) {
115 WvmMediaParser::~WvmMediaParser() {}
117 void WvmMediaParser::Init(
const InitCB& init_cb,
118 const NewSampleCB& new_sample_cb,
120 DCHECK(!is_initialized_);
121 DCHECK(!init_cb.is_null());
122 DCHECK(!new_sample_cb.is_null());
123 decryption_key_source_ = decryption_key_source;
125 new_sample_cb_ = new_sample_cb;
128 bool WvmMediaParser::Parse(
const uint8_t* buf,
int size) {
129 uint32_t num_bytes, prev_size;
130 num_bytes = prev_size = 0;
131 const uint8_t* read_ptr = buf;
132 const uint8_t* end = read_ptr + size;
134 while (read_ptr < end) {
135 switch (parse_state_) {
137 if (*read_ptr == kStartCode1) {
138 parse_state_ = StartCode2;
142 if (*read_ptr == kStartCode2) {
143 parse_state_ = StartCode3;
145 parse_state_ = StartCode1;
149 if (*read_ptr == kStartCode3) {
150 parse_state_ = StartCode4;
152 parse_state_ = StartCode1;
157 case kStartCode4Pack:
158 parse_state_ = PackHeader1;
160 case kStartCode4System:
161 parse_state_ = SystemHeader1;
163 case kStartCode4ProgramEnd:
164 parse_state_ = ProgramEnd;
167 parse_state_ = PesStreamId;
172 parse_state_ = PackHeader2;
175 parse_state_ = PackHeader3;
178 parse_state_ = PackHeader4;
181 parse_state_ = PackHeader5;
184 parse_state_ = PackHeader6;
187 parse_state_ = PackHeader7;
190 parse_state_ = PackHeader8;
193 parse_state_ = PackHeader9;
196 parse_state_ = PackHeader10;
199 skip_bytes_ = *read_ptr & 0x07;
200 parse_state_ = PackHeaderStuffingSkip;
203 skip_bytes_ = *read_ptr;
205 parse_state_ = SystemHeader2;
208 skip_bytes_ |= *read_ptr;
209 parse_state_ = SystemHeaderSkip;
211 case PackHeaderStuffingSkip:
212 if ((end - read_ptr) >= (int32_t)skip_bytes_) {
213 read_ptr += skip_bytes_;
215 parse_state_ = StartCode1;
217 skip_bytes_ -= (end - read_ptr);
221 case SystemHeaderSkip:
222 if ((end - read_ptr) >= (int32_t)skip_bytes_) {
223 read_ptr += skip_bytes_;
225 parse_state_ = StartCode1;
227 uint32_t remaining_size = end - read_ptr;
228 skip_bytes_ -= remaining_size;
233 pes_stream_id_ = *read_ptr;
234 if (!metadata_is_complete_ &&
235 (pes_stream_id_ != kPsmStreamId) &&
236 (pes_stream_id_ != kIndexStreamId) &&
237 (pes_stream_id_ != kEcmStreamId) &&
238 (pes_stream_id_ != kV2MetadataStreamId) &&
239 (pes_stream_id_ != kPaddingStreamId)) {
240 metadata_is_complete_ =
true;
242 parse_state_ = PesPacketLength1;
244 case PesPacketLength1:
245 pes_packet_bytes_ = *read_ptr;
246 pes_packet_bytes_ <<= 8;
247 parse_state_ = PesPacketLength2;
249 case PesPacketLength2:
250 pes_packet_bytes_ |= *read_ptr;
251 if (HAS_HEADER_EXTENSION(pes_stream_id_)) {
252 parse_state_ = PesExtension1;
254 pes_flags_1_ = pes_flags_2_ = 0;
255 pes_header_data_bytes_ = 0;
256 parse_state_ = PesPayload;
260 prev_pes_flags_1_ = pes_flags_1_;
261 pes_flags_1_ = *read_ptr;
263 parse_state_ = PesExtension2;
266 pes_flags_2_ = *read_ptr;
268 parse_state_ = PesExtension3;
271 pes_header_data_bytes_ = *read_ptr;
273 if (pes_flags_2_ & kPesOptPts) {
276 parse_state_ = PesHeaderData;
280 timestamp_ = (*read_ptr & 0x0E);
281 --pes_header_data_bytes_;
287 timestamp_ |= *read_ptr;
288 --pes_header_data_bytes_;
294 timestamp_ |= *read_ptr >> 1;
295 --pes_header_data_bytes_;
301 timestamp_ |= *read_ptr;
302 --pes_header_data_bytes_;
308 timestamp_ |= *read_ptr >> 1;
310 --pes_header_data_bytes_;
312 if (pes_flags_2_ & kPesOptDts) {
316 parse_state_ = PesHeaderData;
320 timestamp_ = (*read_ptr & 0x0E);
321 --pes_header_data_bytes_;
327 timestamp_ |= *read_ptr;
328 --pes_header_data_bytes_;
334 timestamp_ |= *read_ptr >> 1;
335 --pes_header_data_bytes_;
341 timestamp_ |= *read_ptr;
342 --pes_header_data_bytes_;
348 timestamp_ |= *read_ptr >> 1;
350 --pes_header_data_bytes_;
352 parse_state_ = PesHeaderData;
355 num_bytes = end - read_ptr;
356 if (num_bytes >= pes_header_data_bytes_) {
357 num_bytes = pes_header_data_bytes_;
358 parse_state_ = PesPayload;
360 pes_header_data_bytes_ -= num_bytes;
361 pes_packet_bytes_ -= num_bytes;
362 read_ptr += num_bytes;
365 switch (pes_stream_id_) {
368 parse_state_ = PsmPayload;
370 case kPaddingStreamId:
371 parse_state_ = Padding;
375 parse_state_ = EcmPayload;
378 parse_state_ = IndexPayload;
381 if (!DemuxNextPes(
false)) {
384 parse_state_ = EsPayload;
388 num_bytes = end - read_ptr;
389 if (num_bytes >= pes_packet_bytes_) {
390 num_bytes = pes_packet_bytes_;
391 parse_state_ = StartCode1;
394 pes_packet_bytes_ -= num_bytes;
395 prev_size = psm_data_.size();
396 psm_data_.resize(prev_size + num_bytes);
397 memcpy(&psm_data_[prev_size], read_ptr, num_bytes);
399 read_ptr += num_bytes;
402 num_bytes = end - read_ptr;
403 if (num_bytes >= pes_packet_bytes_) {
404 num_bytes = pes_packet_bytes_;
405 parse_state_ = StartCode1;
408 pes_packet_bytes_ -= num_bytes;
409 prev_size = ecm_.size();
410 ecm_.resize(prev_size + num_bytes);
411 memcpy(&ecm_[prev_size], read_ptr, num_bytes);
413 if ((pes_packet_bytes_ == 0) && !ecm_.empty()) {
418 read_ptr += num_bytes;
421 num_bytes = end - read_ptr;
422 if (num_bytes >= pes_packet_bytes_) {
423 num_bytes = pes_packet_bytes_;
424 parse_state_ = StartCode1;
427 pes_packet_bytes_ -= num_bytes;
428 prev_size = index_data_.size();
429 index_data_.resize(prev_size + num_bytes);
430 memcpy(&index_data_[prev_size], read_ptr, num_bytes);
432 if (pes_packet_bytes_ == 0 && !index_data_.empty()) {
433 if (!metadata_is_complete_) {
434 if (!ParseIndexEntry()) {
439 read_ptr += num_bytes;
442 num_bytes = end - read_ptr;
443 if (num_bytes >= pes_packet_bytes_) {
444 num_bytes = pes_packet_bytes_;
445 parse_state_ = StartCode1;
447 pes_packet_bytes_ -= num_bytes;
448 if (pes_stream_id_ != kV2MetadataStreamId) {
449 sample_data_.resize(sample_data_.size() + num_bytes);
450 memcpy(&sample_data_[sample_data_.size() - num_bytes], read_ptr,
453 prev_pes_stream_id_ = pes_stream_id_;
454 read_ptr += num_bytes;
457 num_bytes = end - read_ptr;
458 if (num_bytes >= pes_packet_bytes_) {
459 num_bytes = pes_packet_bytes_;
460 parse_state_ = StartCode1;
462 pes_packet_bytes_ -= num_bytes;
463 read_ptr += num_bytes;
466 parse_state_ = StartCode1;
467 metadata_is_complete_ =
true;
468 if (!DemuxNextPes(
true)) {
476 parse_state_ = StartCode1;
477 prev_media_sample_data_.Reset();
478 current_program_id_++;
491 bool WvmMediaParser::EmitLastSample(uint32_t stream_id,
492 scoped_refptr<MediaSample>& new_sample) {
493 std::string key = base::UintToString(current_program_id_)
495 .append(base::UintToString(stream_id));
496 std::map<std::string, uint32_t>::iterator it =
497 program_demux_stream_map_.find(key);
498 if (it == program_demux_stream_map_.end())
500 return EmitSample(stream_id, (*it).second, new_sample,
true);
503 bool WvmMediaParser::EmitPendingSamples() {
505 while (!media_sample_queue_.empty()) {
506 DemuxStreamIdMediaSample& demux_stream_media_sample =
507 media_sample_queue_.front();
508 if (!EmitSample(demux_stream_media_sample.parsed_audio_or_video_stream_id,
509 demux_stream_media_sample.demux_stream_id,
510 demux_stream_media_sample.media_sample,
514 media_sample_queue_.pop_front();
519 bool WvmMediaParser::Flush() {
522 if (prev_media_sample_data_.audio_sample != NULL) {
523 if (!EmitLastSample(prev_pes_stream_id_,
524 prev_media_sample_data_.audio_sample)) {
525 LOG(ERROR) <<
"Did not emit last sample for audio stream with ID = "
526 << prev_pes_stream_id_;
530 if (prev_media_sample_data_.video_sample != NULL) {
531 if (!EmitLastSample(prev_pes_stream_id_,
532 prev_media_sample_data_.video_sample)) {
533 LOG(ERROR) <<
"Did not emit last sample for video stream with ID = "
534 << prev_pes_stream_id_;
541 bool WvmMediaParser::ParseIndexEntry() {
544 if (current_program_id_ > 0) {
547 uint32_t index_size = 0;
548 if (index_data_.size() < kIndexVersion4HeaderSize) {
552 const uint8_t* read_ptr = index_data_.data();
553 if (ntohlFromBuffer(read_ptr) != kIndexMagic) {
559 uint32_t version = ntohlFromBuffer(read_ptr);
561 if (version == kVersion4) {
562 index_size = kIndexVersion4HeaderSize + ntohlFromBuffer(read_ptr);
563 if (index_data_.size() < index_size) {
567 read_ptr +=
sizeof(uint32_t);
570 uint32_t index_metadata_max_size = index_size - kIndexVersion4HeaderSize;
571 if (index_metadata_max_size <
sizeof(uint8_t)) {
576 uint64_t track_duration = 0;
577 int16_t trick_play_rate = 0;
578 uint32_t sampling_frequency = kDefaultSamplingFrequency;
579 uint32_t time_scale = kMpeg2ClockRate;
580 uint16_t video_width = 0;
581 uint16_t video_height = 0;
582 uint32_t pixel_width = 0;
583 uint32_t pixel_height = 0;
584 uint8_t nalu_length_size = kNaluLengthSize;
585 uint8_t num_channels = 0;
586 int audio_pes_stream_id = 0;
587 int video_pes_stream_id = 0;
588 bool has_video =
false;
589 bool has_audio =
false;
590 std::vector<uint8_t> audio_codec_config;
591 std::vector<uint8_t> video_codec_config;
592 uint8_t num_index_entries = *read_ptr;
594 --index_metadata_max_size;
596 for (uint8_t idx = 0; idx < num_index_entries; ++idx) {
597 if (index_metadata_max_size < (2 *
sizeof(uint8_t)) +
sizeof(uint32_t)) {
600 uint8_t tag = *read_ptr;
602 uint8_t type = *read_ptr;
604 uint32_t length = ntohlFromBuffer(read_ptr);
605 read_ptr +=
sizeof(uint32_t);
606 index_metadata_max_size -= (2 *
sizeof(uint8_t)) +
sizeof(uint32_t);
607 if (index_metadata_max_size < length) {
612 std::vector<uint8_t> binary_data;
613 switch (Type(type)) {
615 if (length ==
sizeof(uint8_t)) {
616 tagtype = GetTag(tag, length, read_ptr, &value);
622 if (length ==
sizeof(int8_t)) {
623 tagtype = GetTag(tag, length, read_ptr, &value);
629 if (length ==
sizeof(uint16_t)) {
630 tagtype = GetTag(tag, length, read_ptr, &value);
636 if (length ==
sizeof(int16_t)) {
637 tagtype = GetTag(tag, length, read_ptr, &value);
643 if (length ==
sizeof(uint32_t)) {
644 tagtype = GetTag(tag, length, read_ptr, &value);
650 if (length ==
sizeof(int32_t)) {
651 tagtype = GetTag(tag, length, read_ptr, &value);
657 if (length ==
sizeof(uint64_t)) {
658 tagtype = GetTag(tag, length, read_ptr, &value);
664 if (length ==
sizeof(int64_t)) {
665 tagtype = GetTag(tag, length, read_ptr, &value);
671 case Type_BinaryData:
672 binary_data.assign(read_ptr, read_ptr + length);
681 track_duration = value;
683 case TrackTrickPlayRate:
684 trick_play_rate = value;
687 video_pes_stream_id = value;
690 audio_pes_stream_id = value;
693 video_width = (uint16_t)value;
696 video_height = (uint16_t)value;
698 case AudioNumChannels:
699 num_channels = (uint8_t)value;
707 case VideoPixelWidth:
708 pixel_width =
static_cast<uint32_t
>(value);
710 case VideoPixelHeight:
711 pixel_height =
static_cast<uint32_t
>(value);
713 case Audio_EsDescriptor: {
714 mp4::ESDescriptor descriptor;
715 if (!descriptor.Parse(binary_data)) {
717 "Could not extract AudioSpecificConfig from ES_Descriptor";
720 audio_codec_config = descriptor.decoder_specific_info();
723 case Audio_EC3SpecificData:
724 case Audio_DtsSpecificData:
725 case Audio_AC3SpecificData:
726 LOG(ERROR) <<
"Audio type not supported.";
728 case AVCDecoderConfigurationRecord:
729 video_codec_config = binary_data;
736 index_metadata_max_size -= length;
739 index_size = read_ptr - index_data_.data();
742 VideoCodec video_codec = kCodecH264;
743 stream_infos_.push_back(
new VideoStreamInfo(
744 stream_id_count_, time_scale, track_duration, video_codec,
745 std::string(), std::string(), video_width, video_height, pixel_width,
746 pixel_height, trick_play_rate, nalu_length_size,
747 video_codec_config.data(), video_codec_config.size(),
true));
748 program_demux_stream_map_[base::UintToString(index_program_id_) +
":" +
749 base::UintToString(video_pes_stream_id ?
750 video_pes_stream_id :
751 kDefaultVideoStreamId)] =
755 AudioCodec audio_codec = kCodecAAC;
757 stream_infos_.push_back(
new AudioStreamInfo(
758 stream_id_count_, time_scale, track_duration, audio_codec,
759 std::string(), std::string(), kAacSampleSizeBits, num_channels,
760 sampling_frequency, 0, 0, audio_codec_config.data(),
761 audio_codec_config.size(),
true));
762 program_demux_stream_map_[base::UintToString(index_program_id_) +
":" +
763 base::UintToString(audio_pes_stream_id ?
764 audio_pes_stream_id :
765 kDefaultAudioStreamId)] =
775 bool WvmMediaParser::DemuxNextPes(
bool is_program_end) {
776 bool output_encrypted_sample =
false;
777 if (!sample_data_.empty() && (prev_pes_flags_1_ & kScramblingBitsMask)) {
779 if (!content_decryptor_) {
780 output_encrypted_sample =
true;
782 content_decryptor_->Crypt(&sample_data_[crypto_unit_start_pos_],
783 sample_data_.size() - crypto_unit_start_pos_,
784 &sample_data_[crypto_unit_start_pos_]);
789 if ((pes_flags_2_ & kPesOptPts) || is_program_end) {
790 if (!sample_data_.empty()) {
791 if (!Output(output_encrypted_sample)) {
795 StartMediaSampleDemux();
798 crypto_unit_start_pos_ = sample_data_.size();
802 void WvmMediaParser::StartMediaSampleDemux() {
803 bool is_key_frame = ((pes_flags_1_ & kPesOptAlign) != 0);
805 media_sample_->set_dts(dts_);
806 media_sample_->set_pts(pts_);
807 media_sample_->set_is_key_frame(is_key_frame);
809 sample_data_.clear();
812 bool WvmMediaParser::Output(
bool output_encrypted_sample) {
813 if (output_encrypted_sample) {
814 media_sample_->set_data(sample_data_.data(), sample_data_.size());
815 media_sample_->set_is_encrypted(
true);
817 if ((prev_pes_stream_id_ & kPesStreamIdVideoMask) == kPesStreamIdVideo) {
819 std::vector<uint8_t> nal_unit_stream;
820 if (!byte_to_unit_stream_converter_.ConvertByteStreamToNalUnitStream(
821 sample_data_.data(), sample_data_.size(), &nal_unit_stream)) {
822 LOG(ERROR) <<
"Could not convert h.264 byte stream sample";
825 media_sample_->set_data(nal_unit_stream.data(), nal_unit_stream.size());
826 if (!is_initialized_) {
829 std::vector<uint8_t> decoder_config_record;
830 byte_to_unit_stream_converter_.GetDecoderConfigurationRecord(
831 &decoder_config_record);
832 for (uint32_t i = 0; i < stream_infos_.size(); i++) {
833 if (stream_infos_[i]->stream_type() == media::kStreamVideo &&
834 stream_infos_[i]->codec_string().empty()) {
835 const std::vector<uint8_t>* stream_config;
836 if (stream_infos_[i]->extra_data().empty()) {
839 stream_infos_[i]->set_extra_data(decoder_config_record);
840 stream_config = &decoder_config_record;
843 stream_config = &stream_infos_[i]->extra_data();
845 DCHECK(stream_config);
847 VideoStreamInfo* video_stream_info =
848 reinterpret_cast<VideoStreamInfo*
>(stream_infos_[i].get());
849 AVCDecoderConfiguration avc_config;
850 if (!avc_config.Parse(*stream_config)) {
851 LOG(WARNING) <<
"Failed to parse AVCDecoderConfigurationRecord. "
852 "Using computed configuration record instead.";
853 video_stream_info->set_extra_data(decoder_config_record);
854 if (!avc_config.Parse(decoder_config_record)) {
855 LOG(ERROR) <<
"Failed to parse AVCDecoderConfigurationRecord.";
859 video_stream_info->set_codec_string(avc_config.GetCodecString());
861 if (avc_config.pixel_width() != video_stream_info->pixel_width() ||
862 avc_config.pixel_height() !=
863 video_stream_info->pixel_height()) {
864 LOG_IF(WARNING, video_stream_info->pixel_width() != 0 ||
865 video_stream_info->pixel_height() != 0)
866 <<
"Pixel aspect ratio in WVM metadata ("
867 << video_stream_info->pixel_width() <<
","
868 << video_stream_info->pixel_height()
869 <<
") does not match with SAR in "
870 "AVCDecoderConfigurationRecord ("
871 << avc_config.pixel_width() <<
","
872 << avc_config.pixel_height()
873 <<
"). Use AVCDecoderConfigurationRecord.";
874 video_stream_info->set_pixel_width(avc_config.pixel_width());
875 video_stream_info->set_pixel_height(avc_config.pixel_height());
877 if (avc_config.coded_width() != video_stream_info->width() ||
878 avc_config.coded_height() != video_stream_info->height()) {
879 LOG(WARNING) <<
"Resolution in WVM metadata ("
880 << video_stream_info->width() <<
","
881 << video_stream_info->height()
882 <<
") does not match with resolution in "
883 "AVCDecoderConfigurationRecord ("
884 << avc_config.coded_width() <<
","
885 << avc_config.coded_height()
886 <<
"). Use AVCDecoderConfigurationRecord.";
887 video_stream_info->set_width(avc_config.coded_width());
888 video_stream_info->set_height(avc_config.coded_height());
893 }
else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) ==
897 sample_data_.data(), kAdtsHeaderMinSize);
898 media::mp2t::AdtsHeader adts_header;
899 const uint8_t* frame_ptr = sample_data_.data();
900 if (!adts_header.Parse(frame_ptr, frame_size)) {
901 LOG(ERROR) <<
"Could not parse ADTS header";
904 size_t header_size = adts_header.GetAdtsHeaderSize(frame_ptr,
906 media_sample_->set_data(frame_ptr + header_size,
907 frame_size - header_size);
908 if (!is_initialized_) {
909 for (uint32_t i = 0; i < stream_infos_.size(); i++) {
910 if (stream_infos_[i]->stream_type() == media::kStreamAudio &&
911 stream_infos_[i]->codec_string().empty()) {
912 AudioStreamInfo* audio_stream_info =
913 reinterpret_cast<AudioStreamInfo*
>(stream_infos_[i].get());
914 if (audio_stream_info->extra_data().empty()) {
917 audio_stream_info->set_sampling_frequency(
918 adts_header.GetSamplingFrequency());
919 std::vector<uint8_t> audio_specific_config;
920 if (!adts_header.GetAudioSpecificConfig(&audio_specific_config)) {
921 LOG(ERROR) <<
"Could not compute AACaudiospecificconfig";
924 audio_stream_info->set_extra_data(audio_specific_config);
925 audio_stream_info->set_codec_string(
927 kCodecAAC, adts_header.GetObjectType()));
931 mp4::AACAudioSpecificConfig aac_config;
932 if (!aac_config.Parse(stream_infos_[i]->extra_data())) {
933 LOG(ERROR) <<
"Could not parse AACAudioSpecificconfig";
936 audio_stream_info->set_sampling_frequency(aac_config.frequency());
937 audio_stream_info->set_codec_string(
939 kCodecAAC, aac_config.audio_object_type()));
947 if (!is_initialized_) {
948 bool all_streams_have_config =
true;
950 for (uint32_t i = 0; i < stream_infos_.size(); i++) {
951 if (stream_infos_[i]->codec_string().empty()) {
952 all_streams_have_config =
false;
956 if (all_streams_have_config) {
957 init_cb_.Run(stream_infos_);
958 is_initialized_ =
true;
962 DCHECK_GT(media_sample_->data_size(), 0UL);
963 std::string key = base::UintToString(current_program_id_).append(
":")
964 .append(base::UintToString(prev_pes_stream_id_));
965 std::map<std::string, uint32_t>::iterator it =
966 program_demux_stream_map_.find(key);
967 if (it == program_demux_stream_map_.end()) {
972 DemuxStreamIdMediaSample demux_stream_media_sample;
973 demux_stream_media_sample.parsed_audio_or_video_stream_id =
975 demux_stream_media_sample.demux_stream_id = (*it).second;
976 demux_stream_media_sample.media_sample = media_sample_;
978 if (!is_initialized_) {
979 media_sample_queue_.push_back(demux_stream_media_sample);
982 while (!media_sample_queue_.empty()) {
983 if (!EmitPendingSamples())
987 if (!EmitSample(prev_pes_stream_id_, (*it).second, media_sample_,
false))
993 bool WvmMediaParser::EmitSample(uint32_t parsed_audio_or_video_stream_id,
995 scoped_refptr<MediaSample>& new_sample,
999 if ((parsed_audio_or_video_stream_id & kPesStreamIdVideoMask) ==
1000 kPesStreamIdVideo) {
1001 new_sample->set_duration(prev_media_sample_data_.video_sample_duration);
1002 }
else if ((parsed_audio_or_video_stream_id & kPesStreamIdAudioMask) ==
1003 kPesStreamIdAudio) {
1004 new_sample->set_duration(prev_media_sample_data_.audio_sample_duration);
1006 if (!new_sample_cb_.Run(stream_id, new_sample)) {
1007 LOG(ERROR) <<
"Failed to process the last sample.";
1015 if ((parsed_audio_or_video_stream_id & kPesStreamIdVideoMask) ==
1016 kPesStreamIdVideo) {
1017 if (prev_media_sample_data_.video_sample == NULL) {
1018 prev_media_sample_data_.video_sample = new_sample;
1019 prev_media_sample_data_.video_stream_id = stream_id;
1022 prev_media_sample_data_.video_sample->set_duration(
1023 new_sample->dts() - prev_media_sample_data_.video_sample->dts());
1024 prev_media_sample_data_.video_sample_duration =
1025 prev_media_sample_data_.video_sample->duration();
1026 if (!new_sample_cb_.Run(prev_media_sample_data_.video_stream_id,
1027 prev_media_sample_data_.video_sample)) {
1028 LOG(ERROR) <<
"Failed to process the video sample.";
1031 prev_media_sample_data_.video_sample = new_sample;
1032 prev_media_sample_data_.video_stream_id = stream_id;
1033 }
else if ((parsed_audio_or_video_stream_id & kPesStreamIdAudioMask) ==
1034 kPesStreamIdAudio) {
1035 if (prev_media_sample_data_.audio_sample == NULL) {
1036 prev_media_sample_data_.audio_sample = new_sample;
1037 prev_media_sample_data_.audio_stream_id = stream_id;
1040 prev_media_sample_data_.audio_sample->set_duration(
1041 new_sample->dts() - prev_media_sample_data_.audio_sample->dts());
1042 prev_media_sample_data_.audio_sample_duration =
1043 prev_media_sample_data_.audio_sample->duration();
1044 if (!new_sample_cb_.Run(prev_media_sample_data_.audio_stream_id,
1045 prev_media_sample_data_.audio_sample)) {
1046 LOG(ERROR) <<
"Failed to process the audio sample.";
1049 prev_media_sample_data_.audio_sample = new_sample;
1050 prev_media_sample_data_.audio_stream_id = stream_id;
1055 bool WvmMediaParser::GetAssetKey(
const uint32_t asset_id,
1056 EncryptionKey* encryption_key) {
1057 DCHECK(decryption_key_source_);
1058 Status status = decryption_key_source_->FetchKeys(asset_id);
1060 LOG(ERROR) <<
"Fetch Key(s) failed for AssetID = " << asset_id
1061 <<
", error = " << status;
1065 status = decryption_key_source_->GetKey(KeySource::TRACK_TYPE_HD,
1068 LOG(ERROR) <<
"Fetch Key(s) failed for AssetID = " << asset_id
1069 <<
", error = " << status;
1076 bool WvmMediaParser::ProcessEcm() {
1078 if (!decryption_key_source_)
1081 if (current_program_id_ > 0) {
1084 if (ecm_.size() != kEcmSizeBytes) {
1085 LOG(ERROR) <<
"Unexpected ECM size = " << ecm_.size()
1086 <<
", expected size = " << kEcmSizeBytes;
1089 const uint8_t* ecm_data = ecm_.data();
1091 ecm_data +=
sizeof(uint32_t);
1092 ecm_data +=
sizeof(uint32_t);
1093 ecm_data +=
sizeof(uint32_t);
1094 uint32_t asset_id = ntohlFromBuffer(ecm_data);
1095 if (asset_id == 0) {
1096 LOG(ERROR) <<
"AssetID in ECM is not valid.";
1099 ecm_data +=
sizeof(uint32_t);
1100 EncryptionKey encryption_key;
1101 if (!GetAssetKey(asset_id, &encryption_key)) {
1104 if (encryption_key.key.size() < kAssetKeySizeBytes) {
1105 LOG(ERROR) <<
"Asset Key size of " << encryption_key.key.size()
1106 <<
" for AssetID = " << asset_id
1107 <<
" is less than minimum asset key size.";
1113 std::vector<uint8_t> asset_key(
1114 encryption_key.key.begin(),
1115 encryption_key.key.begin() + kAssetKeySizeBytes);
1116 std::vector<uint8_t> iv(kInitializationVectorSizeBytes);
1117 AesCbcDecryptor asset_decryptor(kCtsPadding, !kChainAcrossCalls);
1118 if (!asset_decryptor.InitializeWithIv(asset_key, iv)) {
1119 LOG(ERROR) <<
"Failed to initialize asset_decryptor.";
1123 const size_t content_key_buffer_size =
1124 kEcmFlagsSizeBytes + kEcmContentKeySizeBytes +
1125 kEcmPaddingSizeBytes;
1126 std::vector<uint8_t> content_key_buffer(content_key_buffer_size);
1127 CHECK(asset_decryptor.Crypt(ecm_data, content_key_buffer_size,
1128 content_key_buffer.data()));
1130 std::vector<uint8_t> decrypted_content_key_vec(
1131 content_key_buffer.begin() + 4,
1132 content_key_buffer.begin() + 20);
1133 scoped_ptr<AesCbcDecryptor> content_decryptor(
1134 new AesCbcDecryptor(kCtsPadding, !kChainAcrossCalls));
1135 if (!content_decryptor->InitializeWithIv(decrypted_content_key_vec, iv)) {
1136 LOG(ERROR) <<
"Failed to initialize content decryptor.";
1140 content_decryptor_ = content_decryptor.Pass();
1144 DemuxStreamIdMediaSample::DemuxStreamIdMediaSample() :
1146 parsed_audio_or_video_stream_id(0) {}
1148 DemuxStreamIdMediaSample::~DemuxStreamIdMediaSample() {}
1150 PrevSampleData::PrevSampleData() {
1154 PrevSampleData::~PrevSampleData() {}
1156 void PrevSampleData::Reset() {
1157 audio_sample = NULL;
1158 video_sample = NULL;
1159 audio_stream_id = 0;
1160 video_stream_id = 0;
1161 audio_sample_duration = 0;
1162 video_sample_duration = 0;