Make Muxer::Initialize and Muxer::Finalize private

User should not need to care about how and when to call these APIs.
Internal code should call them automatically.

Change-Id: Ibc85a709d4e82ecc7b477986cabf09dcfc2e100c
This commit is contained in:
Kongqun Yang 2014-04-09 10:34:55 -07:00 committed by KongQun Yang
parent 2498da675a
commit 833f27f687
7 changed files with 77 additions and 60 deletions

View File

@ -172,11 +172,7 @@ bool AddStreamToMuxer(const std::vector<MediaStream*>& streams, Muxer* muxer) {
LOG(ERROR) << "No " << FLAGS_stream << " stream found in the input.";
return false;
}
Status status = muxer->AddStream(stream);
if (!status.ok()) {
LOG(ERROR) << "Muxer failed to add stream: " << status.ToString();
return false;
}
muxer->AddStream(stream);
return true;
}
@ -234,23 +230,12 @@ bool RunPackager(const std::string& input) {
}
muxer->SetEncryptorSource(encryptor_source.get(), FLAGS_clear_lead);
status = muxer->Initialize();
if (!status.ok()) {
LOG(ERROR) << "Muxer failed to initialize: " << status.ToString();
return false;
}
// Start remuxing process.
status = demuxer.Run();
if (!status.ok()) {
LOG(ERROR) << "Remuxing failed: " << status.ToString();
return false;
}
status = muxer->Finalize();
if (!status.ok()) {
LOG(ERROR) << "Muxer failed to finalize: " << status.ToString();
return false;
}
printf("Packaging completed successfully.\n");
return true;

View File

@ -11,6 +11,7 @@
#include "base/stl_util.h"
#include "media/base/container_names.h"
#include "media/base/decryptor_source.h"
#include "media/base/media_sample.h"
#include "media/base/media_stream.h"
#include "media/base/stream_info.h"
#include "media/file/file.h"
@ -37,13 +38,13 @@ Demuxer::~Demuxer() {
}
Status Demuxer::Initialize() {
DCHECK(media_file_ == NULL);
DCHECK(!media_file_);
DCHECK(!init_event_received_);
media_file_ = File::Open(file_name_.c_str(), "r");
if (media_file_ == NULL) {
if (!media_file_) {
return Status(error::FILE_FAILURE,
"Cannot open file for read " + file_name_);
"Cannot open file for reading " + file_name_);
}
// Determine media container.
@ -119,13 +120,25 @@ Status Demuxer::Run() {
while ((status = Parse()).ok())
continue;
return status.Matches(Status(error::END_OF_STREAM, "")) ? Status::OK : status;
if (status.error_code() == error::END_OF_STREAM) {
// Push EOS sample to muxer to indicate end of stream.
const scoped_refptr<MediaSample>& sample = MediaSample::CreateEOSBuffer();
for (std::vector<MediaStream*>::iterator it = streams_.begin();
it != streams_.end();
++it) {
status = (*it)->PushSample(sample);
if (!status.ok())
return status;
}
}
return status;
}
Status Demuxer::Parse() {
DCHECK(media_file_ != NULL);
DCHECK(parser_ != NULL);
DCHECK(buffer_ != NULL);
DCHECK(media_file_);
DCHECK(parser_);
DCHECK(buffer_);
int64 bytes_read = media_file_->Read(buffer_.get(), kBufSize);
if (bytes_read <= 0) {

View File

@ -15,6 +15,7 @@ namespace media {
Muxer::Muxer(const MuxerOptions& options)
: options_(options),
encryptor_source_(NULL),
initialized_(false),
clear_lead_in_seconds_(0),
muxer_listener_(NULL),
clock_(NULL) {}
@ -27,10 +28,10 @@ void Muxer::SetEncryptorSource(EncryptorSource* encryptor_source,
clear_lead_in_seconds_ = clear_lead_in_seconds;
}
Status Muxer::AddStream(MediaStream* stream) {
void Muxer::AddStream(MediaStream* stream) {
DCHECK(stream);
stream->Connect(this);
streams_.push_back(stream);
return Status::OK;
}
Status Muxer::Run() {
@ -55,16 +56,36 @@ Status Muxer::Run() {
status = AddSample(streams_[current_stream_id], sample);
// Switch to next stream if the current stream is ready for fragmentation.
if (status.Matches(Status(error::FRAGMENT_FINALIZED, ""))) {
if (status.error_code() == error::FRAGMENT_FINALIZED) {
current_stream_id = (current_stream_id + 1) % streams_.size();
status.Clear();
}
}
return status.Matches(Status(error::END_OF_STREAM, "")) ? Status::OK : status;
// Finalize the muxer after reaching end of stream.
return status.error_code() == error::END_OF_STREAM ? Finalize() : status;
}
void Muxer::SetMuxerListener(media::event::MuxerListener* muxer_listener) {
muxer_listener_ = muxer_listener;
}
Status Muxer::AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) {
DCHECK(std::find(streams_.begin(), streams_.end(), stream) != streams_.end());
if (!initialized_) {
Status status = Initialize();
if (!status.ok())
return status;
initialized_ = true;
}
if (sample->end_of_stream()) {
// EOS sample should be sent only when the sample was pushed from Demuxer
// to Muxer. In this case, there should be only one stream in Muxer.
DCHECK_EQ(1u, streams_.size());
return Finalize();
}
return DoAddSample(stream, sample);
}
} // namespace media

View File

@ -38,26 +38,18 @@ class Muxer {
explicit Muxer(const MuxerOptions& options);
virtual ~Muxer();
/// Set encryptor source. Should be called before calling Initialize().
/// @param encryptor_source should not be NULL.
/// Set encryptor source.
/// @param encryptor_source points to the encryptor source to be injected.
/// Should not be NULL.
/// @param clear_lead_in_seconds specifies clear lead duration in seconds.
void SetEncryptorSource(EncryptorSource* encryptor_source,
double clear_lead_in_seconds);
/// Initialize the muxer. Must be called after connecting all the streams.
virtual Status Initialize() = 0;
/// Final clean up.
virtual Status Finalize() = 0;
/// Add video/audio stream.
virtual Status AddStream(MediaStream* stream);
/// Add new media sample.
virtual Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) = 0;
void AddStream(MediaStream* stream);
/// Drive the remuxing from muxer side (pull).
virtual Status Run();
Status Run();
/// Set a MuxerListener event handler for this object.
/// @param muxer_listener should not be NULL.
@ -83,9 +75,26 @@ class Muxer {
base::Clock* clock() { return clock_; }
private:
friend class MediaStream; // Needed to access AddSample.
// Add new media sample.
Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample);
// Initialize the muxer.
virtual Status Initialize() = 0;
// Final clean up.
virtual Status Finalize() = 0;
// AddSample implementation.
virtual Status DoAddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) = 0;
MuxerOptions options_;
std::vector<MediaStream*> streams_;
EncryptorSource* encryptor_source_;
bool initialized_;
double clear_lead_in_seconds_;
event::MuxerListener* muxer_listener_;

View File

@ -127,8 +127,8 @@ Status MP4Muxer::Finalize() {
return Status::OK;
}
Status MP4Muxer::AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) {
Status MP4Muxer::DoAddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) {
DCHECK(segmenter_);
return segmenter_->AddSample(stream, sample);
}

View File

@ -34,15 +34,13 @@ class MP4Muxer : public Muxer {
explicit MP4Muxer(const MuxerOptions& options);
virtual ~MP4Muxer();
/// @name Muxer implementation overrides.
/// @{
private:
// Muxer implementation overrides.
virtual Status Initialize() OVERRIDE;
virtual Status Finalize() OVERRIDE;
virtual Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) OVERRIDE;
/// @}
virtual Status DoAddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) OVERRIDE;
private:
// Generate Audio/Video Track atom.
void InitializeTrak(const StreamInfo* info, Track* trak);
void GenerateAudioTrak(const AudioStreamInfo* audio_info,

View File

@ -157,12 +157,10 @@ void PackagerTestBasic::Remux(const std::string& input,
new mp4::MP4Muxer(SetupOptions(video_output, single_segment)));
muxer_video->set_clock(&fake_clock_);
ASSERT_OK(muxer_video->AddStream(FindFirstVideoStream(demuxer.streams())));
muxer_video->AddStream(FindFirstVideoStream(demuxer.streams()));
if (enable_encryption)
muxer_video->SetEncryptorSource(&encryptor_source, kClearLeadInSeconds);
ASSERT_OK(muxer_video->Initialize());
}
scoped_ptr<Muxer> muxer_audio;
@ -171,21 +169,14 @@ void PackagerTestBasic::Remux(const std::string& input,
new mp4::MP4Muxer(SetupOptions(audio_output, single_segment)));
muxer_audio->set_clock(&fake_clock_);
ASSERT_OK(muxer_audio->AddStream(FindFirstAudioStream(demuxer.streams())));
muxer_audio->AddStream(FindFirstAudioStream(demuxer.streams()));
if (enable_encryption)
muxer_video->SetEncryptorSource(&encryptor_source, kClearLeadInSeconds);
ASSERT_OK(muxer_audio->Initialize());
}
// Start remuxing process.
ASSERT_OK(demuxer.Run());
if (muxer_video)
ASSERT_OK(muxer_video->Finalize());
if (muxer_audio)
ASSERT_OK(muxer_audio->Finalize());
}
TEST_P(PackagerTestBasic, MP4MuxerSingleSegmentUnencrypted) {