7 #include "packager/media/base/demuxer.h"
9 #include "packager/base/bind.h"
10 #include "packager/base/logging.h"
11 #include "packager/media/base/decryptor_source.h"
12 #include "packager/media/base/key_source.h"
13 #include "packager/media/base/media_sample.h"
14 #include "packager/media/base/media_stream.h"
15 #include "packager/media/base/stream_info.h"
16 #include "packager/media/file/file.h"
17 #include "packager/media/formats/mp2t/mp2t_media_parser.h"
18 #include "packager/media/formats/mp4/mp4_media_parser.h"
19 #include "packager/media/formats/webm/webm_media_parser.h"
20 #include "packager/media/formats/webvtt/webvtt_media_parser.h"
21 #include "packager/media/formats/wvm/wvm_media_parser.h"
25 const size_t kInitBufSize = 0x10000;
26 const size_t kBufSize = 0x200000;
30 const size_t kQueuedSamplesLimit = 10000;
37 : file_name_(file_name),
39 init_event_received_(false),
40 container_name_(CONTAINER_UNKNOWN),
41 buffer_(new uint8_t[kBufSize]),
51 key_source_ = std::move(key_source);
56 DCHECK(!init_event_received_);
58 LOG(INFO) <<
"Initialize Demuxer for file '" << file_name_ <<
"'.";
60 media_file_ =
File::Open(file_name_.c_str(),
"r");
62 return Status(error::FILE_FAILURE,
63 "Cannot open file for reading " + file_name_);
67 size_t bytes_read = 0;
68 while (bytes_read < kInitBufSize) {
70 media_file_->
Read(buffer_.get() + bytes_read, kInitBufSize);
72 return Status(error::FILE_FAILURE,
"Cannot read file " + file_name_);
75 bytes_read += read_result;
77 container_name_ = DetermineContainer(buffer_.get(), bytes_read);
80 switch (container_name_) {
84 case CONTAINER_MPEG2TS:
87 case CONTAINER_MPEG2PS:
93 case CONTAINER_WEBVTT:
98 return Status(error::UNIMPLEMENTED,
"Container not supported.");
101 parser_->Init(base::Bind(&Demuxer::ParserInitEvent, base::Unretained(
this)),
102 base::Bind(&Demuxer::NewSampleEvent, base::Unretained(
this)),
106 if (container_name_ == CONTAINER_MOV)
109 if (!parser_->Parse(buffer_.get(), bytes_read)) {
110 init_parsing_status_ =
111 Status(error::PARSER_FAILURE,
"Cannot parse media file " + file_name_);
115 while (!init_event_received_ && init_parsing_status_.ok())
116 init_parsing_status_ =
Parse();
118 return init_event_received_ ? Status::OK : init_parsing_status_;
121 void Demuxer::ParserInitEvent(
122 const std::vector<scoped_refptr<StreamInfo>>& stream_infos) {
123 init_event_received_ =
true;
124 for (
const scoped_refptr<StreamInfo>& stream_info : stream_infos)
125 streams_.emplace_back(
new MediaStream(stream_info,
this));
128 Demuxer::QueuedSample::QueuedSample(uint32_t local_track_id,
129 scoped_refptr<MediaSample> local_sample)
130 : track_id(local_track_id), sample(local_sample) {}
131 Demuxer::QueuedSample::~QueuedSample() {}
133 bool Demuxer::NewSampleEvent(uint32_t track_id,
134 const scoped_refptr<MediaSample>& sample) {
135 if (!init_event_received_) {
136 if (queued_samples_.size() >= kQueuedSamplesLimit) {
137 LOG(ERROR) <<
"Queued samples limit reached: " << kQueuedSamplesLimit;
140 queued_samples_.push_back(QueuedSample(track_id, sample));
143 while (!queued_samples_.empty()) {
144 if (!PushSample(queued_samples_.front().track_id,
145 queued_samples_.front().sample)) {
148 queued_samples_.pop_front();
150 return PushSample(track_id, sample);
153 bool Demuxer::PushSample(uint32_t track_id,
154 const scoped_refptr<MediaSample>& sample) {
155 for (
const std::unique_ptr<MediaStream>& stream : streams_) {
156 if (track_id == stream->info()->track_id()) {
157 Status status = stream->PushSample(sample);
159 LOG(ERROR) <<
"Demuxer::PushSample failed with " << status;
163 LOG(ERROR) <<
"Track " << track_id <<
" not found.";
170 LOG(INFO) <<
"Demuxer::Run() on file '" << file_name_ <<
"'.";
173 for (
const std::unique_ptr<MediaStream>& stream : streams_) {
174 status = stream->Start(MediaStream::kPush);
179 while (!cancelled_ && (status =
Parse()).ok())
182 if (cancelled_ && status.ok())
183 return Status(error::CANCELLED,
"Demuxer run cancelled");
185 if (status.error_code() == error::END_OF_STREAM) {
188 for (
const std::unique_ptr<MediaStream>& stream : streams_) {
189 status = stream->PushSample(sample);
204 if (!init_parsing_status_.ok())
205 return init_parsing_status_;
207 int64_t bytes_read = media_file_->
Read(buffer_.get(), kBufSize);
208 if (bytes_read == 0) {
209 if (!parser_->Flush())
210 return Status(error::PARSER_FAILURE,
"Failed to flush.");
211 return Status(error::END_OF_STREAM,
"");
212 }
else if (bytes_read < 0) {
213 return Status(error::FILE_FAILURE,
"Cannot read file " + file_name_);
216 return parser_->Parse(buffer_.get(), bytes_read)
218 :
Status(error::PARSER_FAILURE,
219 "Cannot parse media file " + file_name_);