7 #include <packager/media/formats/mp2t/pes_packet_generator.h>
13 #include <absl/log/check.h>
15 #include <packager/macros/logging.h>
16 #include <packager/media/base/audio_stream_info.h>
17 #include <packager/media/base/buffer_writer.h>
18 #include <packager/media/base/media_sample.h>
19 #include <packager/media/base/video_stream_info.h>
20 #include <packager/media/codecs/aac_audio_specific_config.h>
21 #include <packager/media/codecs/nal_unit_to_byte_stream_converter.h>
22 #include <packager/media/codecs/nalu_reader.h>
23 #include <packager/media/formats/mp2t/pes_packet.h>
30 const uint8_t kVideoStreamId = 0xE0;
31 const uint8_t kAacAudioStreamId = 0xC0;
32 const uint8_t kAc3AudioStreamId = 0xBD;
33 const double kTsTimescale = 90000.0;
37 int32_t transport_stream_timestamp_offset)
38 : transport_stream_timestamp_offset_(transport_stream_timestamp_offset) {}
40 PesPacketGenerator::~PesPacketGenerator() {}
44 stream_type_ = stream_info.stream_type();
46 if (stream_type_ == kStreamVideo) {
49 if (video_stream_info.codec() != Codec::kCodecH264) {
50 NOTIMPLEMENTED() <<
"Video codec " << video_stream_info.codec()
51 <<
" is not supported.";
54 timescale_scale_ = kTsTimescale / video_stream_info.time_scale();
56 return converter_->Initialize(video_stream_info.codec_config().data(),
57 video_stream_info.codec_config().size());
59 if (stream_type_ == kStreamAudio) {
62 timescale_scale_ = kTsTimescale / audio_stream_info.time_scale();
63 if (audio_stream_info.codec() == Codec::kCodecAAC) {
64 audio_stream_id_ = kAacAudioStreamId;
66 return adts_converter_->Parse(audio_stream_info.codec_config());
68 if (audio_stream_info.codec() == Codec::kCodecAC3 ||
69 audio_stream_info.codec() == Codec::kCodecEAC3 ||
70 audio_stream_info.codec() == Codec::kCodecMP3) {
71 audio_stream_id_ = kAc3AudioStreamId;
75 NOTIMPLEMENTED() <<
"Audio codec " << audio_stream_info.codec()
76 <<
" is not supported yet.";
80 NOTIMPLEMENTED() <<
"Stream type: " << stream_type_ <<
" not implemented.";
85 if (!current_processing_pes_)
86 current_processing_pes_.reset(
new PesPacket());
89 sample.pts() * timescale_scale_ + transport_stream_timestamp_offset_;
91 sample.dts() * timescale_scale_ + transport_stream_timestamp_offset_;
93 if (pts < 0 || dts < 0) {
94 LOG(ERROR) <<
"Seeing negative timestamp (" << pts <<
"," << dts <<
")"
95 <<
" after applying offset "
96 << transport_stream_timestamp_offset_
97 <<
". Please check if it is expected. Adjust "
98 "--transport_stream_timestamp_offset_ms if needed.";
102 current_processing_pes_->set_is_key_frame(sample.is_key_frame());
103 current_processing_pes_->set_pts(pts);
104 current_processing_pes_->set_dts(dts);
105 if (stream_type_ == kStreamVideo) {
107 std::vector<SubsampleEntry> subsamples;
108 if (sample.decrypt_config())
109 subsamples = sample.decrypt_config()->subsamples();
110 const bool kEscapeEncryptedNalu =
true;
111 std::vector<uint8_t> byte_stream;
112 if (!converter_->ConvertUnitToByteStreamWithSubsamples(
113 sample.data(), sample.data_size(), sample.is_key_frame(),
114 kEscapeEncryptedNalu, &byte_stream, &subsamples)) {
115 LOG(ERROR) <<
"Failed to convert sample to byte stream.";
119 current_processing_pes_->mutable_data()->swap(byte_stream);
120 current_processing_pes_->set_stream_id(kVideoStreamId);
121 pes_packets_.push_back(std::move(current_processing_pes_));
124 DCHECK_EQ(stream_type_, kStreamAudio);
126 std::vector<uint8_t> audio_frame;
129 if (adts_converter_) {
130 if (!adts_converter_->ConvertToADTS(sample.data(), sample.data_size(),
134 audio_frame.assign(sample.data(), sample.data() + sample.data_size());
139 current_processing_pes_->mutable_data()->swap(audio_frame);
140 current_processing_pes_->set_stream_id(audio_stream_id_);
141 pes_packets_.push_back(std::move(current_processing_pes_));
146 return pes_packets_.size();
150 DCHECK(!pes_packets_.empty());
151 std::unique_ptr<PesPacket> pes = std::move(pes_packets_.front());
152 pes_packets_.pop_front();
All the methods that are virtual are virtual for mocking.