7 #include "packager/media/base/demuxer.h"
9 #include "packager/base/bind.h"
10 #include "packager/base/logging.h"
11 #include "packager/base/stl_util.h"
12 #include "packager/media/base/decryptor_source.h"
13 #include "packager/media/base/key_source.h"
14 #include "packager/media/base/media_sample.h"
15 #include "packager/media/base/media_stream.h"
16 #include "packager/media/base/stream_info.h"
17 #include "packager/media/file/file.h"
18 #include "packager/media/formats/mp2t/mp2t_media_parser.h"
19 #include "packager/media/formats/mp4/mp4_media_parser.h"
20 #include "packager/media/formats/webm/webm_media_parser.h"
21 #include "packager/media/formats/webvtt/webvtt_media_parser.h"
22 #include "packager/media/formats/wvm/wvm_media_parser.h"
26 const size_t kInitBufSize = 0x10000;
27 const size_t kBufSize = 0x200000;
31 const size_t kQueuedSamplesLimit = 10000;
34 namespace edash_packager {
38 : file_name_(file_name),
40 init_event_received_(false),
41 container_name_(CONTAINER_UNKNOWN),
42 buffer_(new uint8_t[kBufSize]),
49 STLDeleteElements(&streams_);
53 key_source_ = key_source.Pass();
58 DCHECK(!init_event_received_);
60 LOG(INFO) <<
"Initialize Demuxer for file '" << file_name_ <<
"'.";
62 media_file_ =
File::Open(file_name_.c_str(),
"r");
64 return Status(error::FILE_FAILURE,
65 "Cannot open file for reading " + file_name_);
69 size_t bytes_read = 0;
70 while (bytes_read < kInitBufSize) {
72 media_file_->
Read(buffer_.get() + bytes_read, kInitBufSize);
74 return Status(error::FILE_FAILURE,
"Cannot read file " + file_name_);
77 bytes_read += read_result;
79 container_name_ = DetermineContainer(buffer_.get(), bytes_read);
82 switch (container_name_) {
86 case CONTAINER_MPEG2TS:
89 case CONTAINER_MPEG2PS:
95 case CONTAINER_WEBVTT:
100 return Status(error::UNIMPLEMENTED,
"Container not supported.");
103 parser_->Init(base::Bind(&Demuxer::ParserInitEvent, base::Unretained(
this)),
104 base::Bind(&Demuxer::NewSampleEvent, base::Unretained(
this)),
108 if (container_name_ == CONTAINER_MOV)
111 if (!parser_->Parse(buffer_.get(), bytes_read)) {
112 init_parsing_status_ =
113 Status(error::PARSER_FAILURE,
"Cannot parse media file " + file_name_);
117 while (!init_event_received_ && init_parsing_status_.ok())
118 init_parsing_status_ =
Parse();
120 return init_event_received_ ? Status::OK : init_parsing_status_;
123 void Demuxer::ParserInitEvent(
124 const std::vector<scoped_refptr<StreamInfo> >& streams) {
125 init_event_received_ =
true;
127 std::vector<scoped_refptr<StreamInfo> >::const_iterator it =
streams.begin();
128 for (; it !=
streams.end(); ++it) {
133 Demuxer::QueuedSample::QueuedSample(uint32_t local_track_id,
134 scoped_refptr<MediaSample> local_sample)
135 : track_id(local_track_id), sample(local_sample) {}
136 Demuxer::QueuedSample::~QueuedSample() {}
138 bool Demuxer::NewSampleEvent(uint32_t track_id,
139 const scoped_refptr<MediaSample>& sample) {
140 if (!init_event_received_) {
141 if (queued_samples_.size() >= kQueuedSamplesLimit) {
142 LOG(ERROR) <<
"Queued samples limit reached: " << kQueuedSamplesLimit;
145 queued_samples_.push_back(QueuedSample(track_id, sample));
148 while (!queued_samples_.empty()) {
149 if (!PushSample(queued_samples_.front().track_id,
150 queued_samples_.front().sample)) {
153 queued_samples_.pop_front();
155 return PushSample(track_id, sample);
158 bool Demuxer::PushSample(uint32_t track_id,
159 const scoped_refptr<MediaSample>& sample) {
160 std::vector<MediaStream*>::iterator it = streams_.begin();
161 for (; it != streams_.end(); ++it) {
162 if (track_id == (*it)->info()->track_id()) {
163 Status status = (*it)->PushSample(sample);
165 LOG(ERROR) <<
"Demuxer::PushSample failed with " << status;
169 LOG(ERROR) <<
"Track " << track_id <<
" not found.";
176 LOG(INFO) <<
"Demuxer::Run() on file '" << file_name_ <<
"'.";
179 for (std::vector<MediaStream*>::iterator it = streams_.begin();
180 it != streams_.end();
182 status = (*it)->Start(MediaStream::kPush);
187 while (!cancelled_ && (status =
Parse()).ok())
190 if (cancelled_ && status.ok())
191 return Status(error::CANCELLED,
"Demuxer run cancelled");
193 if (status.error_code() == error::END_OF_STREAM) {
196 for (std::vector<MediaStream*>::iterator it = streams_.begin();
197 it != streams_.end();
199 status = (*it)->PushSample(sample);
214 if (!init_parsing_status_.ok())
215 return init_parsing_status_;
217 int64_t bytes_read = media_file_->
Read(buffer_.get(), kBufSize);
218 if (bytes_read == 0) {
219 if (!parser_->Flush())
220 return Status(error::PARSER_FAILURE,
"Failed to flush.");
221 return Status(error::END_OF_STREAM,
"");
222 }
else if (bytes_read < 0) {
223 return Status(error::FILE_FAILURE,
"Cannot read file " + file_name_);
226 return parser_->Parse(buffer_.get(), bytes_read)
228 :
Status(error::PARSER_FAILURE,
229 "Cannot parse media file " + file_name_);