7 #include "packager/media/base/demuxer.h"
11 #include "packager/base/bind.h"
12 #include "packager/base/logging.h"
13 #include "packager/base/strings/string_number_conversions.h"
14 #include "packager/media/base/decryptor_source.h"
15 #include "packager/media/base/key_source.h"
16 #include "packager/media/base/media_sample.h"
17 #include "packager/media/base/stream_info.h"
18 #include "packager/media/file/file.h"
19 #include "packager/media/formats/mp2t/mp2t_media_parser.h"
20 #include "packager/media/formats/mp4/mp4_media_parser.h"
21 #include "packager/media/formats/webm/webm_media_parser.h"
22 #include "packager/media/formats/webvtt/webvtt_media_parser.h"
23 #include "packager/media/formats/wvm/wvm_media_parser.h"
27 const size_t kInitBufSize = 0x10000;
28 const size_t kBufSize = 0x200000;
32 const size_t kQueuedSamplesLimit = 10000;
33 const int kInvalidStreamIndex = -1;
34 const int kBaseVideoOutputStreamIndex = 0x100;
35 const int kBaseAudioOutputStreamIndex = 0x200;
37 std::string GetStreamLabel(
int stream_index) {
38 switch (stream_index) {
39 case kBaseVideoOutputStreamIndex:
41 case kBaseAudioOutputStreamIndex:
44 return base::IntToString(stream_index);
48 bool GetStreamIndex(
const std::string& stream_label,
int* stream_index) {
50 if (stream_label ==
"video") {
51 *stream_index = kBaseVideoOutputStreamIndex;
52 }
else if (stream_label ==
"audio") {
53 *stream_index = kBaseAudioOutputStreamIndex;
56 if (!base::StringToInt(stream_label, stream_index)) {
57 LOG(ERROR) <<
"Invalid argument --stream=" << stream_label <<
"; "
58 <<
"should be 'audio', 'video', or a number";
71 : file_name_(file_name), buffer_(new uint8_t[kBufSize]) {}
79 key_source_ = std::move(key_source);
83 LOG(INFO) <<
"Demuxer::Run() on file '" << file_name_ <<
"'.";
84 Status status = InitializeParser();
87 while (!all_streams_ready_ && status.ok())
91 if (all_streams_ready_ && output_handlers().empty())
94 for (
const auto& pair : output_handlers()) {
95 if (std::find(stream_indexes_.begin(), stream_indexes_.end(), pair.first) ==
96 stream_indexes_.end()) {
97 LOG(ERROR) <<
"Invalid argument, stream=" << GetStreamLabel(pair.first)
99 return Status(error::INVALID_ARGUMENT,
"Stream not available");
103 while (!cancelled_ && status.ok())
105 if (cancelled_ && status.ok())
106 return Status(error::CANCELLED,
"Demuxer run cancelled");
108 if (status.error_code() == error::END_OF_STREAM) {
109 for (
int stream_index : stream_indexes_) {
124 std::shared_ptr<MediaHandler> handler) {
125 int stream_index = kInvalidStreamIndex;
126 if (!GetStreamIndex(stream_label, &stream_index)) {
127 return Status(error::INVALID_ARGUMENT,
128 "Invalid stream: " + stream_label);
134 const std::string& language_override) {
135 int stream_index = kInvalidStreamIndex;
136 if (!GetStreamIndex(stream_label, &stream_index))
137 LOG(WARNING) <<
"Invalid stream for language override " << stream_label;
138 language_overrides_[stream_index] = language_override;
141 Demuxer::QueuedSample::QueuedSample(uint32_t local_track_id,
142 std::shared_ptr<MediaSample> local_sample)
143 : track_id(local_track_id), sample(local_sample) {}
145 Demuxer::QueuedSample::~QueuedSample() {}
147 Status Demuxer::InitializeParser() {
148 DCHECK(!media_file_);
149 DCHECK(!all_streams_ready_);
151 LOG(INFO) <<
"Initialize Demuxer for file '" << file_name_ <<
"'.";
153 media_file_ =
File::Open(file_name_.c_str(),
"r");
155 return Status(error::FILE_FAILURE,
156 "Cannot open file for reading " + file_name_);
160 size_t bytes_read = 0;
161 while (bytes_read < kInitBufSize) {
162 int64_t read_result =
163 media_file_->
Read(buffer_.get() + bytes_read, kInitBufSize);
165 return Status(error::FILE_FAILURE,
"Cannot read file " + file_name_);
166 if (read_result == 0)
168 bytes_read += read_result;
170 container_name_ = DetermineContainer(buffer_.get(), bytes_read);
173 switch (container_name_) {
175 parser_.reset(
new mp4::MP4MediaParser());
177 case CONTAINER_MPEG2TS:
178 parser_.reset(
new mp2t::Mp2tMediaParser());
180 case CONTAINER_MPEG2PS:
181 parser_.reset(
new wvm::WvmMediaParser());
184 parser_.reset(
new WebMMediaParser());
186 case CONTAINER_WEBVTT:
187 parser_.reset(
new WebVttMediaParser());
191 return Status(error::UNIMPLEMENTED,
"Container not supported.");
194 parser_->Init(base::Bind(&Demuxer::ParserInitEvent, base::Unretained(
this)),
195 base::Bind(&Demuxer::NewSampleEvent, base::Unretained(
this)),
199 if (container_name_ == CONTAINER_MOV)
200 static_cast<mp4::MP4MediaParser*
>(parser_.get())->LoadMoov(file_name_);
201 if (!parser_->Parse(buffer_.get(), bytes_read)) {
202 return Status(error::PARSER_FAILURE,
203 "Cannot parse media file " + file_name_);
208 void Demuxer::ParserInitEvent(
209 const std::vector<std::shared_ptr<StreamInfo>>& stream_infos) {
210 if (dump_stream_info_) {
211 printf(
"\nFile \"%s\":\n", file_name_.c_str());
212 printf(
"Found %zu stream(s).\n", stream_infos.size());
213 for (
size_t i = 0; i < stream_infos.size(); ++i)
214 printf(
"Stream [%zu] %s\n", i, stream_infos[i]->ToString().c_str());
217 int base_stream_index = 0;
218 bool video_handler_set =
219 output_handlers().find(kBaseVideoOutputStreamIndex) !=
220 output_handlers().end();
221 bool audio_handler_set =
222 output_handlers().find(kBaseAudioOutputStreamIndex) !=
223 output_handlers().end();
224 for (
const std::shared_ptr<StreamInfo>& stream_info : stream_infos) {
225 int stream_index = base_stream_index;
226 if (video_handler_set && stream_info->stream_type() == kStreamVideo) {
227 stream_index = kBaseVideoOutputStreamIndex;
229 video_handler_set =
false;
231 if (audio_handler_set && stream_info->stream_type() == kStreamAudio) {
232 stream_index = kBaseAudioOutputStreamIndex;
234 audio_handler_set =
false;
237 const bool handler_set =
238 output_handlers().find(stream_index) != output_handlers().end();
240 track_id_to_stream_index_map_[stream_info->track_id()] = stream_index;
241 stream_indexes_.push_back(stream_index);
242 auto iter = language_overrides_.find(stream_index);
243 if (iter != language_overrides_.end() &&
244 stream_info->stream_type() != kStreamVideo) {
245 stream_info->set_language(iter->second);
249 track_id_to_stream_index_map_[stream_info->track_id()] =
254 all_streams_ready_ =
true;
257 bool Demuxer::NewSampleEvent(uint32_t track_id,
258 const std::shared_ptr<MediaSample>& sample) {
259 if (!all_streams_ready_) {
260 if (queued_samples_.size() >= kQueuedSamplesLimit) {
261 LOG(ERROR) <<
"Queued samples limit reached: " << kQueuedSamplesLimit;
264 queued_samples_.push_back(QueuedSample(track_id, sample));
267 while (!queued_samples_.empty()) {
268 if (!PushSample(queued_samples_.front().track_id,
269 queued_samples_.front().sample)) {
272 queued_samples_.pop_front();
274 return PushSample(track_id, sample);
277 bool Demuxer::PushSample(uint32_t track_id,
278 const std::shared_ptr<MediaSample>& sample) {
279 auto stream_index_iter = track_id_to_stream_index_map_.find(track_id);
280 if (stream_index_iter == track_id_to_stream_index_map_.end()) {
281 LOG(ERROR) <<
"Track " << track_id <<
" not found.";
284 if (stream_index_iter->second == kInvalidStreamIndex)
288 LOG(ERROR) <<
"Failed to process sample " << stream_index_iter->second
294 Status Demuxer::Parse() {
299 int64_t bytes_read = media_file_->
Read(buffer_.get(), kBufSize);
300 if (bytes_read == 0) {
301 if (!parser_->Flush())
302 return Status(error::PARSER_FAILURE,
"Failed to flush.");
303 return Status(error::END_OF_STREAM,
"");
304 }
else if (bytes_read < 0) {
305 return Status(error::FILE_FAILURE,
"Cannot read file " + file_name_);
308 return parser_->Parse(buffer_.get(), bytes_read)
310 : Status(error::PARSER_FAILURE,
311 "Cannot parse media file " + file_name_);