Update client of EncryptorSource due to refactoring

This CL also includes two related changes:
  1. Support serialization of raw PSSH box;
  2. Refactor segmenter interface a bit.

Change-Id: I668aa01a5a5ff524ad6fe74976339a3fd499120a
This commit is contained in:
Kongqun Yang 2014-04-18 15:00:30 -07:00
parent 107145c693
commit f059d926d7
15 changed files with 248 additions and 200 deletions

View File

@ -15,7 +15,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "media/base/demuxer.h"
#include "media/base/fixed_encryptor_source.h"
#include "media/base/media_stream.h"
#include "media/base/muxer_options.h"
#include "media/base/request_signer.h"
@ -76,27 +75,11 @@ scoped_ptr<EncryptorSource> CreateEncryptorSource() {
}
}
WidevineEncryptorSource::TrackType track_type =
WidevineEncryptorSource::GetTrackTypeFromString(FLAGS_track_type);
if (track_type == WidevineEncryptorSource::TRACK_TYPE_UNKNOWN) {
LOG(ERROR) << "Unknown track_type specified.";
return scoped_ptr<EncryptorSource>();
}
encryptor_source.reset(new WidevineEncryptorSource(
FLAGS_server_url, FLAGS_content_id, track_type, signer.Pass()));
FLAGS_server_url, FLAGS_content_id, signer.Pass()));
} else if (FLAGS_enable_fixed_key_encryption) {
encryptor_source.reset(
new FixedEncryptorSource(FLAGS_key_id, FLAGS_key, FLAGS_pssh));
}
if (encryptor_source) {
Status status = encryptor_source->Initialize();
if (!status.ok()) {
LOG(ERROR) << "Encryptor source failed to initialize: "
<< status.ToString();
return scoped_ptr<EncryptorSource>();
}
encryptor_source = EncryptorSource::CreateFromHexStrings(
FLAGS_key_id, FLAGS_key, FLAGS_pssh, "");
}
return encryptor_source.Pass();
}
@ -229,7 +212,15 @@ bool RunPackager(const std::string& input) {
if (!encryptor_source)
return false;
}
muxer->SetEncryptorSource(encryptor_source.get(), FLAGS_clear_lead);
EncryptorSource::TrackType track_type =
EncryptorSource::GetTrackTypeFromString(FLAGS_track_type);
if (track_type != EncryptorSource::TRACK_TYPE_SD &&
track_type != EncryptorSource::TRACK_TYPE_HD) {
LOG(ERROR) << "FLAGS_track_type should be either 'SD' or 'HD'";
return false;
}
muxer->SetEncryptorSource(
encryptor_source.get(), track_type, FLAGS_clear_lead);
// Start remuxing process.
status = demuxer.Run();

View File

@ -20,7 +20,7 @@ DEFINE_bool(enable_widevine_encryption,
"--aes_signing_iv) or RSA signing key (--rsa_signing_key_path).");
DEFINE_string(server_url, "", "License server url.");
DEFINE_string(content_id, "", "Content Id.");
DEFINE_string(track_type, "SD", "Track type: HD, SD or AUDIO.");
DEFINE_string(track_type, "SD", "Track type: SD or HD.");
DEFINE_string(signer, "", "The name of the signer.");
DEFINE_string(aes_signing_key,
"",

View File

@ -16,6 +16,7 @@ Muxer::Muxer(const MuxerOptions& options)
: options_(options),
encryptor_source_(NULL),
initialized_(false),
track_type_(EncryptorSource::TRACK_TYPE_SD),
clear_lead_in_seconds_(0),
muxer_listener_(NULL),
clock_(NULL) {}
@ -23,8 +24,10 @@ Muxer::Muxer(const MuxerOptions& options)
Muxer::~Muxer() {}
void Muxer::SetEncryptorSource(EncryptorSource* encryptor_source,
EncryptorSource::TrackType track_type,
double clear_lead_in_seconds) {
encryptor_source_ = encryptor_source;
track_type_ = track_type;
clear_lead_in_seconds_ = clear_lead_in_seconds;
}

View File

@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "media/base/encryptor_source.h"
#include "media/base/muxer_options.h"
#include "media/base/status.h"
@ -41,8 +42,11 @@ class Muxer {
/// Set encryptor source.
/// @param encryptor_source points to the encryptor source to be injected.
/// Should not be NULL.
/// @param track_type should be either SD or HD. It affects whether SD key or
/// HD key is used to encrypt the video content.
/// @param clear_lead_in_seconds specifies clear lead duration in seconds.
void SetEncryptorSource(EncryptorSource* encryptor_source,
EncryptorSource::TrackType track_type,
double clear_lead_in_seconds);
/// Add video/audio stream.
@ -70,6 +74,7 @@ class Muxer {
protected:
const MuxerOptions& options() const { return options_; }
EncryptorSource* encryptor_source() { return encryptor_source_; }
EncryptorSource::TrackType track_type() const { return track_type_; }
double clear_lead_in_seconds() const { return clear_lead_in_seconds_; }
event::MuxerListener* muxer_listener() { return muxer_listener_; }
base::Clock* clock() { return clock_; }
@ -95,6 +100,7 @@ class Muxer {
std::vector<MediaStream*> streams_;
EncryptorSource* encryptor_source_;
bool initialized_;
EncryptorSource::TrackType track_type_;
double clear_lead_in_seconds_;
event::MuxerListener* muxer_listener_;

View File

@ -90,6 +90,12 @@ ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; }
bool ProtectionSystemSpecificHeader::ReadWrite(BoxBuffer* buffer) {
if (!buffer->Reading() && !raw_box.empty()) {
// Write the raw box directly.
buffer->writer()->AppendVector(raw_box);
return true;
}
uint32 size = data.size();
RCHECK(FullBox::ReadWrite(buffer) &&
buffer->ReadWriteVector(&system_id, 16) &&
@ -108,7 +114,10 @@ bool ProtectionSystemSpecificHeader::ReadWrite(BoxBuffer* buffer) {
}
uint32 ProtectionSystemSpecificHeader::ComputeSize() {
atom_size = kFullBoxSize + system_id.size() + sizeof(uint32) + data.size();
if (!raw_box.empty())
atom_size = raw_box.size();
else
atom_size = kFullBoxSize + system_id.size() + sizeof(uint32) + data.size();
return atom_size;
}

View File

@ -733,7 +733,7 @@ class BoxDefinitionsTestGeneral : public testing::Test {
typedef testing::Types<
FileType,
SegmentType,
// ProtectionSystemSpecificHeader, // Not fully parsed.
ProtectionSystemSpecificHeader,
SampleAuxiliaryInformationOffset,
SampleAuxiliaryInformationSize,
OriginalFormat,
@ -854,8 +854,17 @@ TEST_F(BoxDefinitionsTest, ProtectionSystemSpecificHeader) {
ProtectionSystemSpecificHeader pssh_readback;
ASSERT_TRUE(ReadBack(&pssh_readback));
// PSSH does not parse data.
ASSERT_EQ(pssh.system_id, pssh_readback.system_id);
ASSERT_EQ(pssh, pssh_readback);
pssh_readback.raw_box[15] += 1;
pssh_readback.Write(this->buffer_.get());
ProtectionSystemSpecificHeader pssh_readback2;
ASSERT_TRUE(ReadBack(&pssh_readback2));
// If raw_box is set, raw_box will be written instead.
ASSERT_FALSE(pssh_readback == pssh_readback2);
ASSERT_EQ(pssh_readback.raw_box, pssh_readback2.raw_box);
}
TEST_F(BoxDefinitionsTest, CompactSampleSize_FieldSize16) {

View File

@ -23,9 +23,6 @@
#include "media/formats/mp4/single_segment_segmenter.h"
namespace {
// The version of cenc implemented here. CENC 4.
const int kCencSchemeVersion = 0x00010000;
// Sets the range start and end value from offset and size.
// |start| and |end| are for byte-range-spec specified in RFC2616.
void SetStartAndEndFromOffsetAndSize(size_t offset,
@ -93,11 +90,6 @@ Status MP4Muxer::Initialize() {
}
}
if (IsEncryptionRequired()) {
moov->pssh.resize(1);
GeneratePssh(&moov->pssh[0]);
}
if (options().single_segment) {
segmenter_.reset(
new SingleSegmentSegmenter(options(), ftyp.Pass(), moov.Pass()));
@ -107,7 +99,7 @@ Status MP4Muxer::Initialize() {
}
Status segmenter_initialized = segmenter_->Initialize(
encryptor_source(), clear_lead_in_seconds(), streams());
streams(), encryptor_source(), track_type(), clear_lead_in_seconds());
if (!segmenter_initialized.ok())
return segmenter_initialized;
@ -169,17 +161,6 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
trak->media.information.sample_table.description;
sample_description.type = kVideo;
sample_description.video_entries.push_back(video);
if (IsEncryptionRequired()) {
DCHECK(encryptor_source());
// Add a second entry for clear content if needed.
if (clear_lead_in_seconds() > 0)
sample_description.video_entries.push_back(video);
VideoSampleEntry& encrypted_video = sample_description.video_entries[0];
GenerateSinf(&encrypted_video.sinf, encrypted_video.format);
encrypted_video.format = FOURCC_ENCV;
}
}
void MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info,
@ -209,33 +190,6 @@ void MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info,
trak->media.information.sample_table.description;
sample_description.type = kAudio;
sample_description.audio_entries.push_back(audio);
if (IsEncryptionRequired()) {
DCHECK(encryptor_source());
// Add a second entry for clear content if needed.
if (clear_lead_in_seconds() > 0)
sample_description.audio_entries.push_back(audio);
AudioSampleEntry& encrypted_audio = sample_description.audio_entries[0];
GenerateSinf(&encrypted_audio.sinf, encrypted_audio.format);
encrypted_audio.format = FOURCC_ENCA;
}
}
void MP4Muxer::GeneratePssh(ProtectionSystemSpecificHeader* pssh) {
DCHECK(encryptor_source());
pssh->system_id = encryptor_source()->key_system_id();
pssh->data = encryptor_source()->pssh();
}
void MP4Muxer::GenerateSinf(ProtectionSchemeInfo* sinf, FourCC old_type) {
DCHECK(encryptor_source());
sinf->format.format = old_type;
sinf->type.type = FOURCC_CENC;
sinf->type.version = kCencSchemeVersion;
sinf->info.track_encryption.is_encrypted = true;
sinf->info.track_encryption.default_iv_size = encryptor_source()->iv_size();
sinf->info.track_encryption.default_kid = encryptor_source()->key_id();
}
void MP4Muxer::GetStreamInfo(std::vector<StreamInfo*>* stream_infos) {
@ -320,7 +274,7 @@ void MP4Muxer::FireOnMediaEndEvent() {
index_range_end,
duration_seconds,
file_size,
IsEncryptionRequired());
encryptor_source());
}
uint64 MP4Muxer::IsoTimeNow() {

View File

@ -50,15 +50,6 @@ class MP4Muxer : public Muxer {
Track* trak,
uint32 track_id);
// Generate Pssh atom.
void GeneratePssh(ProtectionSystemSpecificHeader* pssh);
// Generates a sinf atom with CENC encryption parameters.
void GenerateSinf(ProtectionSchemeInfo* sinf, FourCC old_type);
// Should we enable encrytion?
bool IsEncryptionRequired() { return (encryptor_source() != NULL); }
// Helper functions for events.
void GetStreamInfo(std::vector<StreamInfo*>* stream_infos);

View File

@ -30,34 +30,6 @@ MultiSegmentSegmenter::MultiSegmentSegmenter(const MuxerOptions& options,
MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
Status MultiSegmentSegmenter::Initialize(
EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams) {
Status status =
Segmenter::Initialize(encryptor_source, clear_lead_in_seconds, streams);
if (!status.ok())
return status;
DCHECK(ftyp());
DCHECK(moov());
// Generate the output file with init segment.
File* file = File::Open(options().output_file_name.c_str(), "w");
if (file == NULL) {
return Status(error::FILE_FAILURE,
"Cannot open file for write " + options().output_file_name);
}
scoped_ptr<BufferWriter> buffer(new BufferWriter);
ftyp()->Write(buffer.get());
moov()->Write(buffer.get());
status = buffer->WriteToFile(file);
if (!file->Close()) {
LOG(WARNING) << "Failed to close the file properly: "
<< options().output_file_name;
}
return status;
}
bool MultiSegmentSegmenter::GetInitRange(size_t* offset, size_t* size) {
DLOG(INFO) << "MultiSegmentSegmenter outputs init segment: "
<< options().output_file_name;
@ -69,11 +41,31 @@ bool MultiSegmentSegmenter::GetIndexRange(size_t* offset, size_t* size) {
return false;
}
Status MultiSegmentSegmenter::FinalizeSegment() {
Status status = Segmenter::FinalizeSegment();
if (!status.ok())
return status;
Status MultiSegmentSegmenter::DoInitialize() {
DCHECK(ftyp());
DCHECK(moov());
// Generate the output file with init segment.
File* file = File::Open(options().output_file_name.c_str(), "w");
if (file == NULL) {
return Status(error::FILE_FAILURE,
"Cannot open file for write " + options().output_file_name);
}
scoped_ptr<BufferWriter> buffer(new BufferWriter);
ftyp()->Write(buffer.get());
moov()->Write(buffer.get());
Status status = buffer->WriteToFile(file);
if (!file->Close()) {
LOG(WARNING) << "Failed to close the file properly: "
<< options().output_file_name;
}
return status;
}
Status MultiSegmentSegmenter::DoFinalize() {
return Status::OK;
}
Status MultiSegmentSegmenter::DoFinalizeSegment() {
DCHECK(sidx());
// earliest_presentation_time is the earliest presentation time of any
// access unit in the reference stream in the first subsegment.

View File

@ -36,18 +36,16 @@ class MultiSegmentSegmenter : public Segmenter {
/// @name Segmenter implementation overrides.
/// @{
virtual Status Initialize(EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams) OVERRIDE;
virtual bool GetInitRange(size_t* offset, size_t* size) OVERRIDE;
virtual bool GetIndexRange(size_t* offset, size_t* size) OVERRIDE;
/// @}
protected:
virtual Status FinalizeSegment() OVERRIDE;
private:
// Segmenter implementation overrides.
virtual Status DoInitialize() OVERRIDE;
virtual Status DoFinalize() OVERRIDE;
virtual Status DoFinalizeSegment() OVERRIDE;
// Write segment to file.
Status WriteSegment();

View File

@ -9,6 +9,7 @@
#include <algorithm>
#include "base/stl_util.h"
#include "media/base/aes_encryptor.h"
#include "media/base/buffer_writer.h"
#include "media/base/encryptor_source.h"
#include "media/base/media_sample.h"
@ -18,14 +19,79 @@
#include "media/formats/mp4/box_definitions.h"
#include "media/formats/mp4/fragmenter.h"
namespace media {
namespace mp4 {
namespace {
// Generate 64bit IV by default.
const size_t kDefaultIvSize = 8u;
// The version of cenc implemented here. CENC 4.
const int kCencSchemeVersion = 0x00010000;
uint64 Rescale(uint64 time_in_old_scale, uint32 old_scale, uint32 new_scale) {
return static_cast<double>(time_in_old_scale) / old_scale * new_scale;
}
} // namespace
namespace media {
namespace mp4 {
scoped_ptr<AesCtrEncryptor> CreateEncryptor(
const EncryptionKey& encryption_key) {
scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor());
const bool initialized =
encryption_key.iv.empty()
? encryptor->InitializeWithRandomIv(encryption_key.key,
kDefaultIvSize)
: encryptor->InitializeWithIv(encryption_key.key, encryption_key.iv);
if (!initialized) {
LOG(ERROR) << "Failed to the initialize encryptor.";
return scoped_ptr<AesCtrEncryptor>();
}
return encryptor.Pass();
}
void GenerateSinf(const EncryptionKey& encryption_key,
FourCC old_type,
ProtectionSchemeInfo* sinf) {
sinf->format.format = old_type;
sinf->type.type = FOURCC_CENC;
sinf->type.version = kCencSchemeVersion;
sinf->info.track_encryption.is_encrypted = true;
sinf->info.track_encryption.default_iv_size =
encryption_key.iv.empty() ? kDefaultIvSize : encryption_key.iv.size();
sinf->info.track_encryption.default_kid = encryption_key.key_id;
}
void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
double clear_lead_in_seconds,
SampleDescription* description) {
DCHECK(description);
if (description->type == kVideo) {
DCHECK_EQ(1u, description->video_entries.size());
// Add a second entry for clear content if needed.
if (clear_lead_in_seconds > 0)
description->video_entries.push_back(description->video_entries[0]);
// Convert the first entry to an encrypted entry.
VideoSampleEntry& entry = description->video_entries[0];
GenerateSinf(encryption_key, entry.format, &entry.sinf);
entry.format = FOURCC_ENCV;
} else {
DCHECK_EQ(kAudio, description->type);
DCHECK_EQ(1u, description->audio_entries.size());
// Add a second entry for clear content if needed.
if (clear_lead_in_seconds > 0)
description->audio_entries.push_back(description->audio_entries[0]);
// Convert the first entry to an encrypted entry.
AudioSampleEntry& entry = description->audio_entries[0];
GenerateSinf(encryption_key, entry.format, &entry.sinf);
entry.format = FOURCC_ENCA;
}
}
} // namespace
Segmenter::Segmenter(const MuxerOptions& options,
scoped_ptr<FileType> ftyp,
@ -41,9 +107,10 @@ Segmenter::Segmenter(const MuxerOptions& options,
Segmenter::~Segmenter() { STLDeleteElements(&fragmenters_); }
Status Segmenter::Initialize(EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams) {
Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
EncryptorSource* encryptor_source,
EncryptorSource::TrackType track_type,
double clear_lead_in_seconds) {
DCHECK_LT(0u, streams.size());
moof_->header.sequence_number = 0;
@ -64,7 +131,30 @@ Status Segmenter::Initialize(EncryptorSource* encryptor_source,
}
scoped_ptr<AesCtrEncryptor> encryptor;
if (encryptor_source) {
encryptor = encryptor_source->CreateEncryptor();
SampleDescription& description =
moov_->tracks[i].media.information.sample_table.description;
DCHECK(track_type == EncryptorSource::TRACK_TYPE_SD ||
track_type == EncryptorSource::TRACK_TYPE_HD);
EncryptionKey encryption_key;
Status status = encryptor_source->GetKey(
description.type == kAudio ? EncryptorSource::TRACK_TYPE_AUDIO
: track_type,
&encryption_key);
if (!status.ok())
return status;
GenerateEncryptedSampleEntry(
encryption_key, clear_lead_in_seconds, &description);
// We need one and only one pssh box.
if (moov_->pssh.empty()) {
moov_->pssh.resize(1);
moov_->pssh[0].raw_box = encryption_key.pssh;
}
encryptor = CreateEncryptor(encryption_key);
if (!encryptor)
return Status(error::MUXER_FAILURE, "Failed to create the encryptor.");
}
@ -84,7 +174,7 @@ Status Segmenter::Initialize(EncryptorSource* encryptor_source,
// Use the reference stream's time scale as movie time scale.
moov_->header.timescale = sidx_->timescale;
InitializeFragments();
return Status::OK;
return DoInitialize();
}
Status Segmenter::Finalize() {
@ -110,7 +200,7 @@ Status Segmenter::Finalize() {
moov_->header.duration = track->header.duration;
}
return Status::OK;
return DoFinalize();
}
Status Segmenter::AddSample(const MediaStream* stream,
@ -191,7 +281,7 @@ void Segmenter::InitializeSegment() {
Status Segmenter::FinalizeSegment() {
segment_initialized_ = false;
return Status::OK;
return DoFinalizeSegment();
}
uint32 Segmenter::GetReferenceStreamId() {

View File

@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "media/base/encryptor_source.h"
#include "media/base/status.h"
namespace media {
@ -47,17 +48,30 @@ class Segmenter {
/// Initialize the segmenter.
/// Calling other public methods of this class without this method returning
/// Status::OK, results in an undefined behavior.
/// @param encryptor_source can be NULL.
/// @return Status::OK on success.
virtual Status Initialize(EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams);
/// Status::OK results in an undefined behavior.
/// @param encryptor_source points to the key source which contains
/// the encryption keys. It can be NULL to indicate that no encryption
/// is required.
/// @param track_type indicates whether SD key or HD key should be used to
/// encrypt the video content.
/// @param clear_time specifies clear lead duration in seconds.
/// @return OK on success, an error status otherwise.
Status Initialize(const std::vector<MediaStream*>& streams,
EncryptorSource* encryptor_source,
EncryptorSource::TrackType track_type,
double clear_lead_in_seconds);
virtual Status Finalize();
/// Finalize the segmenter.
/// @return OK on success, an error status otherwise.
Status Finalize();
virtual Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample);
/// Add sample to the indicated stream.
/// @param stream points to the stream to which the sample belongs. It cannot
/// be NULL.
/// @param sample points to the sample to be added.
/// @return OK on success, an error status otherwise.
Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample);
/// @return true if there is an initialization range, while setting @a offset
/// and @a size; or false if initialization range does not apply.
@ -73,11 +87,6 @@ class Segmenter {
double GetDuration() const;
protected:
void InitializeSegment();
virtual Status FinalizeSegment();
uint32 GetReferenceStreamId();
const MuxerOptions& options() const { return options_; }
FileType* ftyp() { return ftyp_.get(); }
Movie* moov() { return moov_.get(); }
@ -85,6 +94,14 @@ class Segmenter {
SegmentIndex* sidx() { return sidx_.get(); }
private:
virtual Status DoInitialize() = 0;
virtual Status DoFinalize() = 0;
virtual Status DoFinalizeSegment() = 0;
void InitializeSegment();
Status FinalizeSegment();
uint32 GetReferenceStreamId();
void InitializeFragments();
Status FinalizeFragment(Fragmenter* fragment);

View File

@ -21,27 +21,30 @@ SingleSegmentSegmenter::SingleSegmentSegmenter(const MuxerOptions& options,
: Segmenter(options, ftyp.Pass(), moov.Pass()) {}
SingleSegmentSegmenter::~SingleSegmentSegmenter() {}
Status SingleSegmentSegmenter::Initialize(
EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams) {
Status status =
Segmenter::Initialize(encryptor_source, clear_lead_in_seconds, streams);
if (!status.ok())
return status;
temp_file_.reset(File::Open(options().temp_file_name.c_str(), "w"));
if (temp_file_ == NULL) {
return Status(error::FILE_FAILURE,
"Cannot open file to write " + options().temp_file_name);
}
return Status::OK;
bool SingleSegmentSegmenter::GetInitRange(size_t* offset, size_t* size) {
// In Finalize, ftyp and moov gets written first so offset must be 0.
*offset = 0;
*size = ftyp()->ComputeSize() + moov()->ComputeSize();
return true;
}
Status SingleSegmentSegmenter::Finalize() {
Status status = Segmenter::Finalize();
if (!status.ok())
return status;
bool SingleSegmentSegmenter::GetIndexRange(size_t* offset, size_t* size) {
// Index range is right after init range so the offset must be the size of
// ftyp and moov.
*offset = ftyp()->ComputeSize() + moov()->ComputeSize();
*size = vod_sidx_->ComputeSize();
return true;
}
Status SingleSegmentSegmenter::DoInitialize() {
temp_file_.reset(File::Open(options().temp_file_name.c_str(), "w"));
return temp_file_
? Status::OK
: Status(error::FILE_FAILURE,
"Cannot open file to write " + options().temp_file_name);
}
Status SingleSegmentSegmenter::DoFinalize() {
DCHECK(temp_file_);
DCHECK(ftyp());
DCHECK(moov());
@ -65,7 +68,7 @@ Status SingleSegmentSegmenter::Finalize() {
ftyp()->Write(buffer.get());
moov()->Write(buffer.get());
vod_sidx_->Write(buffer.get());
status = buffer->WriteToFile(file.get());
Status status = buffer->WriteToFile(file.get());
if (!status.ok())
return status;
@ -94,26 +97,7 @@ Status SingleSegmentSegmenter::Finalize() {
return Status::OK;
}
bool SingleSegmentSegmenter::GetInitRange(size_t* offset, size_t* size) {
// In Finalize, ftyp and moov gets written first so offset must be 0.
*offset = 0;
*size = ftyp()->ComputeSize() + moov()->ComputeSize();
return true;
}
bool SingleSegmentSegmenter::GetIndexRange(size_t* offset, size_t* size) {
// Index range is right after init range so the offset must be the size of
// ftyp and moov.
*offset = ftyp()->ComputeSize() + moov()->ComputeSize();
*size = vod_sidx_->ComputeSize();
return true;
}
Status SingleSegmentSegmenter::FinalizeSegment() {
Status status = Segmenter::FinalizeSegment();
if (!status.ok())
return status;
Status SingleSegmentSegmenter::DoFinalizeSegment() {
DCHECK(sidx());
DCHECK(fragment_buffer());
// sidx() contains pre-generated segment references with one reference per

View File

@ -33,19 +33,16 @@ class SingleSegmentSegmenter : public Segmenter {
/// @name Segmenter implementation overrides.
/// @{
virtual Status Initialize(EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams) OVERRIDE;
virtual Status Finalize() OVERRIDE;
virtual bool GetInitRange(size_t* offset, size_t* size) OVERRIDE;
virtual bool GetIndexRange(size_t* offset, size_t* size) OVERRIDE;
/// @}
protected:
virtual Status FinalizeSegment() OVERRIDE;
private:
// Segmenter implementation overrides.
virtual Status DoInitialize() OVERRIDE;
virtual Status DoFinalize() OVERRIDE;
virtual Status DoFinalizeSegment() OVERRIDE;
scoped_ptr<SegmentIndex> vod_sidx_;
scoped_ptr<File, FileCloser> temp_file_;

View File

@ -9,7 +9,7 @@
#include "base/strings/stringprintf.h"
#include "base/time/clock.h"
#include "media/base/demuxer.h"
#include "media/base/fixed_encryptor_source.h"
#include "media/base/encryptor_source.h"
#include "media/base/media_stream.h"
#include "media/base/muxer.h"
#include "media/base/status_test_util.h"
@ -148,8 +148,9 @@ void PackagerTestBasic::Remux(const std::string& input,
Demuxer demuxer(GetFullPath(input), decryptor_source_);
ASSERT_OK(demuxer.Initialize());
FixedEncryptorSource encryptor_source(kKeyIdHex, kKeyHex, kPsshHex);
ASSERT_OK(encryptor_source.Initialize());
scoped_ptr<EncryptorSource> encryptor_source(
EncryptorSource::CreateFromHexStrings(kKeyIdHex, kKeyHex, kPsshHex, ""));
DCHECK(encryptor_source);
scoped_ptr<Muxer> muxer_video;
if (!video_output.empty()) {
@ -159,8 +160,11 @@ void PackagerTestBasic::Remux(const std::string& input,
muxer_video->AddStream(FindFirstVideoStream(demuxer.streams()));
if (enable_encryption)
muxer_video->SetEncryptorSource(&encryptor_source, kClearLeadInSeconds);
if (enable_encryption) {
muxer_video->SetEncryptorSource(encryptor_source.get(),
EncryptorSource::TRACK_TYPE_SD,
kClearLeadInSeconds);
}
}
scoped_ptr<Muxer> muxer_audio;
@ -171,8 +175,11 @@ void PackagerTestBasic::Remux(const std::string& input,
muxer_audio->AddStream(FindFirstAudioStream(demuxer.streams()));
if (enable_encryption)
muxer_video->SetEncryptorSource(&encryptor_source, kClearLeadInSeconds);
if (enable_encryption) {
muxer_audio->SetEncryptorSource(encryptor_source.get(),
EncryptorSource::TRACK_TYPE_SD,
kClearLeadInSeconds);
}
}
// Start remuxing process.