MuxerOptions and MuxerListener change for HLS

- Add hls_name and hls_group_id fields to MuxerOptions. This is used to
  pass the NAME and GROUP-ID values for EXT-X-MEDIA tag to
  MuxerListener.
- Change MuxerListener::OnEncryptionInfoReady() to take an
  initialization vector.
- Change MuxerListener::OnNewSegment() to take segment name.
- Reworded and formatted MuxerListener comments to Doxygen style.

Issue #85

Change-Id: Iea06e68552a56ae180177ffd6ca315a7cf39456c
This commit is contained in:
Rintaro Kuroiwa 2016-03-28 01:23:20 -07:00
parent 16ba8da295
commit 300c23104e
14 changed files with 122 additions and 67 deletions

View File

@ -60,6 +60,17 @@ struct MuxerOptions {
/// Optional. /// Optional.
std::string segment_template; std::string segment_template;
/// name of the output stream. This is not (necessarily) the same as @a
/// output_file_name. For HLS this is used as the NAME attribute for
/// EXT-X-MEDIA.
/// Required for audio when outputting HLS.
std::string hls_name;
/// The group ID for the output stream.
/// For HLS this is used as the GROUP-ID attribute for EXT-X-MEDIA.
/// Required for audio when outputting HLS.
std::string hls_group_id;
/// Specify temporary directory for intermediate files. /// Specify temporary directory for intermediate files.
std::string temp_dir; std::string temp_dir;

View File

@ -31,6 +31,7 @@ MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {}
void MpdNotifyMuxerListener::OnEncryptionInfoReady( void MpdNotifyMuxerListener::OnEncryptionInfoReady(
bool is_initial_encryption_info, bool is_initial_encryption_info,
const std::vector<uint8_t>& key_id, const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& iv,
const std::vector<ProtectionSystemSpecificInfo>& key_system_info) { const std::vector<ProtectionSystemSpecificInfo>& key_system_info) {
if (is_initial_encryption_info) { if (is_initial_encryption_info) {
LOG_IF(WARNING, is_encrypted_) LOG_IF(WARNING, is_encrypted_)
@ -142,7 +143,8 @@ void MpdNotifyMuxerListener::OnMediaEnd(bool has_init_range,
mpd_notifier_->Flush(); mpd_notifier_->Flush();
} }
void MpdNotifyMuxerListener::OnNewSegment(uint64_t start_time, void MpdNotifyMuxerListener::OnNewSegment(const std::string& file_name,
uint64_t start_time,
uint64_t duration, uint64_t duration,
uint64_t segment_file_size) { uint64_t segment_file_size) {
if (mpd_notifier_->dash_profile() == kLiveProfile) { if (mpd_notifier_->dash_profile() == kLiveProfile) {

View File

@ -35,6 +35,7 @@ class MpdNotifyMuxerListener : public MuxerListener {
/// @{ /// @{
void OnEncryptionInfoReady(bool is_initial_encryption_info, void OnEncryptionInfoReady(bool is_initial_encryption_info,
const std::vector<uint8_t>& key_id, const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& iv,
const std::vector<ProtectionSystemSpecificInfo>& const std::vector<ProtectionSystemSpecificInfo>&
key_system_info) override; key_system_info) override;
void OnMediaStart(const MuxerOptions& muxer_options, void OnMediaStart(const MuxerOptions& muxer_options,
@ -50,7 +51,8 @@ class MpdNotifyMuxerListener : public MuxerListener {
uint64_t index_range_end, uint64_t index_range_end,
float duration_seconds, float duration_seconds,
uint64_t file_size) override; uint64_t file_size) override;
void OnNewSegment(uint64_t start_time, void OnNewSegment(const std::string& file_name,
uint64_t start_time,
uint64_t duration, uint64_t duration,
uint64_t segment_file_size) override; uint64_t segment_file_size) override;
/// @} /// @}

View File

@ -55,6 +55,11 @@ void SetDefaultLiveMuxerOptionsValues(media::MuxerOptions* muxer_options) {
muxer_options->temp_dir.clear(); muxer_options->temp_dir.clear();
} }
const uint8_t kBogusIv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x67, 0x83, 0xC3, 0x66, 0xEE, 0xAB, 0xB2, 0xF1,
};
} // namespace } // namespace
namespace media { namespace media {
@ -161,8 +166,10 @@ TEST_F(MpdNotifyMuxerListenerTest, VodEncryptedContent) {
"}\n"; "}\n";
EXPECT_CALL(*notifier_, NotifyNewContainer(_, _)).Times(0); EXPECT_CALL(*notifier_, NotifyNewContainer(_, _)).Times(0);
listener_->OnEncryptionInfoReady(kInitialEncryptionInfo,
default_key_id, GetDefaultKeySystemInfo()); std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, default_key_id, iv,
GetDefaultKeySystemInfo());
listener_->OnMediaStart(muxer_options, *video_stream_info, listener_->OnMediaStart(muxer_options, *video_stream_info,
kDefaultReferenceTimeScale, kDefaultReferenceTimeScale,
@ -245,8 +252,8 @@ TEST_F(MpdNotifyMuxerListenerTest, VodOnNewSegment) {
listener_->OnMediaStart(muxer_options, *video_stream_info, listener_->OnMediaStart(muxer_options, *video_stream_info,
kDefaultReferenceTimeScale, kDefaultReferenceTimeScale,
MuxerListener::kContainerMp4); MuxerListener::kContainerMp4);
listener_->OnNewSegment(kStartTime1, kDuration1, kSegmentFileSize1); listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
listener_->OnNewSegment(kStartTime2, kDuration2, kSegmentFileSize2); listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
::testing::Mock::VerifyAndClearExpectations(notifier_.get()); ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
InSequence s; InSequence s;
@ -312,13 +319,14 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2)); NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
EXPECT_CALL(*notifier_, Flush()); EXPECT_CALL(*notifier_, Flush());
listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
default_key_id, GetDefaultKeySystemInfo()); listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, default_key_id, iv,
GetDefaultKeySystemInfo());
listener_->OnMediaStart(muxer_options, *video_stream_info, listener_->OnMediaStart(muxer_options, *video_stream_info,
kDefaultReferenceTimeScale, kDefaultReferenceTimeScale,
MuxerListener::kContainerMp4); MuxerListener::kContainerMp4);
listener_->OnNewSegment(kStartTime1, kDuration1, kSegmentFileSize1); listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
listener_->OnNewSegment(kStartTime2, kDuration2, kSegmentFileSize2); listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
::testing::Mock::VerifyAndClearExpectations(notifier_.get()); ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
EXPECT_CALL(*notifier_, Flush()).Times(0); EXPECT_CALL(*notifier_, Flush()).Times(0);
@ -374,16 +382,17 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2)); NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
EXPECT_CALL(*notifier_, Flush()); EXPECT_CALL(*notifier_, Flush());
listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, default_key_id, std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, default_key_id, iv,
std::vector<ProtectionSystemSpecificInfo>()); std::vector<ProtectionSystemSpecificInfo>());
listener_->OnMediaStart(muxer_options, *video_stream_info, listener_->OnMediaStart(muxer_options, *video_stream_info,
kDefaultReferenceTimeScale, kDefaultReferenceTimeScale,
MuxerListener::kContainerMp4); MuxerListener::kContainerMp4);
listener_->OnEncryptionInfoReady(kNonInitialEncryptionInfo, listener_->OnEncryptionInfoReady(kNonInitialEncryptionInfo,
std::vector<uint8_t>(), std::vector<uint8_t>(), iv,
GetDefaultKeySystemInfo()); GetDefaultKeySystemInfo());
listener_->OnNewSegment(kStartTime1, kDuration1, kSegmentFileSize1); listener_->OnNewSegment("", kStartTime1, kDuration1, kSegmentFileSize1);
listener_->OnNewSegment(kStartTime2, kDuration2, kSegmentFileSize2); listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
::testing::Mock::VerifyAndClearExpectations(notifier_.get()); ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
EXPECT_CALL(*notifier_, Flush()).Times(0); EXPECT_CALL(*notifier_, Flush()).Times(0);

View File

@ -6,8 +6,6 @@
// //
// Event handler for events fired by Muxer. // Event handler for events fired by Muxer.
// TODO(rkuroiwa): Document using doxygen style comments.
#ifndef MEDIA_EVENT_MUXER_LISTENER_H_ #ifndef MEDIA_EVENT_MUXER_LISTENER_H_
#define MEDIA_EVENT_MUXER_LISTENER_H_ #define MEDIA_EVENT_MUXER_LISTENER_H_
@ -38,31 +36,37 @@ class MuxerListener {
virtual ~MuxerListener() {}; virtual ~MuxerListener() {};
// Called when the media's encryption information is ready. This should be /// Called when the media's encryption information is ready. This should be
// called before OnMediaStart(), if the media is encrypted. /// called before OnMediaStart(), if the media is encrypted.
// All the parameters may be empty just to notify that the media is encrypted. /// All the parameters may be empty just to notify that the media is
// |is_initial_encryption_info| is true if this is the first encryption info /// encrypted.
// for the media. /// For ISO BMFF (MP4) media:
// In general, this flag should always be true for non-key-rotated media and /// If @a is_initial_encryption_info is true then @a key_id is the default_KID
// should be called only once. /// in 'tenc' box.
// |key_id| is the key ID for the media. /// If @a is_initial_encryption_info is false then @a key_id is the new key ID
// The format should be a vector of uint8_t, i.e. not (necessarily) human /// for the for the next crypto period.
// readable hex string. /// @param is_initial_encryption_info is true if this is the first encryption
// For ISO BMFF (MP4) media: /// info for the media. In general, this flag should always be true for
// If |is_initial_encryption_info| is true then |key_id| is the default_KID in /// non-key-rotated media and should be called only once.
// 'tenc' box. /// @param key_id is the key ID for the media. The format should be a vector
// If |is_initial_encryption_info| is false then |key_id| is the new key ID /// of uint8_t, i.e. not (necessarily) human readable hex string.
// for the for the next crypto period. /// @param iv is the initialization vector. For most cases this should be 16
/// bytes, but whether the input is accepted is up to the
/// implementation.
virtual void OnEncryptionInfoReady( virtual void OnEncryptionInfoReady(
bool is_initial_encryption_info, bool is_initial_encryption_info,
const std::vector<uint8_t>& key_id, const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& iv,
const std::vector<ProtectionSystemSpecificInfo>& key_system_info) = 0; const std::vector<ProtectionSystemSpecificInfo>& key_system_info) = 0;
// Called when muxing starts. /// Called when muxing starts.
// For MPEG DASH Live profile, the initialization segment information is /// For MPEG DASH Live profile, the initialization segment information is
// available from StreamInfo. /// available from StreamInfo.
// |time_scale| is a reference time scale that overrides the time scale /// @param muxer_options is the options for Muxer.
// specified in |stream_info|. /// @param stream_info is the information of this media.
/// @param time_scale is a reference time scale that overrides the time scale
/// specified in @a stream_info.
/// @param container_type is the container of this media.
virtual void OnMediaStart(const MuxerOptions& muxer_options, virtual void OnMediaStart(const MuxerOptions& muxer_options,
const StreamInfo& stream_info, const StreamInfo& stream_info,
uint32_t time_scale, uint32_t time_scale,
@ -72,16 +76,21 @@ class MuxerListener {
/// @param sample_duration in timescale of the media. /// @param sample_duration in timescale of the media.
virtual void OnSampleDurationReady(uint32_t sample_duration) = 0; virtual void OnSampleDurationReady(uint32_t sample_duration) = 0;
// Called when all files are written out and the muxer object does not output /// Called when all files are written out and the muxer object does not output
// any more files. /// any more files.
// Note: This event might not be very interesting to MPEG DASH Live profile. /// Note: This event might not be very interesting to MPEG DASH Live profile.
// |init_range_{start,end}| is the byte range of initialization segment, in /// @param has_init_range is true if @a init_range_start and @a init_range_end
// the media file. If |has_init_range| is false, these values are ignored. /// actually define an initialization range of a segment. The range is
// |index_range_{start,end}| is the byte range of segment index, in the media /// inclusive for both start and end.
// file. If |has_index_range| is false, these values are ignored. /// @param init_range_start is the start of the initialization range.
// Both ranges are inclusive. /// @param init_range_end is the end of the initialization range.
// Media length of |duration_seconds|. /// @param has_index_range is true if @a index_range_start and @a
// |file_size| of the media in bytes. /// index_range_end actually define an index range of a segment. The
/// range is inclusive for both start and end.
/// @param index_range_start is the start of the index range.
/// @param index_range_end is the end of the index range.
/// @param duration_seconds is the length of the media in seconds.
/// @param file_size is the size of the file in bytes.
virtual void OnMediaEnd(bool has_init_range, virtual void OnMediaEnd(bool has_init_range,
uint64_t init_range_start, uint64_t init_range_start,
uint64_t init_range_end, uint64_t init_range_end,
@ -91,12 +100,19 @@ class MuxerListener {
float duration_seconds, float duration_seconds,
uint64_t file_size) = 0; uint64_t file_size) = 0;
// Called when a segment has been muxed and the file has been written. /// Called when a segment has been muxed and the file has been written.
// Note: For video on demand (VOD), this would be for subsegments. /// Note: For some implementations, this is used to signal new subsegments.
// |start_time| and |duration| are relative to time scale specified /// For example, for generating video on demand (VOD) MPD manifest, this is
// OnMediaStart(). /// called to signal subsegments.
// |segment_file_size| in bytes. /// @param segment_name is the name of the new segment. Note that some
virtual void OnNewSegment(uint64_t start_time, /// implementations may not require this, e.g. if this is a subsegment.
/// @param start_time is the start time of the segment, relative to the
/// timescale specified by MediaInfo passed to OnMediaStart().
/// @param duration is the duration of the segment, relative to the timescale
/// specified by MediaInfo passed to OnMediaStart().
/// @param segment_file_size is the segment size in bytes.
virtual void OnNewSegment(const std::string& segment_name,
uint64_t start_time,
uint64_t duration, uint64_t duration,
uint64_t segment_file_size) = 0; uint64_t segment_file_size) = 0;

View File

@ -28,6 +28,7 @@ VodMediaInfoDumpMuxerListener::~VodMediaInfoDumpMuxerListener() {}
void VodMediaInfoDumpMuxerListener::OnEncryptionInfoReady( void VodMediaInfoDumpMuxerListener::OnEncryptionInfoReady(
bool is_initial_encryption_info, bool is_initial_encryption_info,
const std::vector<uint8_t>& default_key_id, const std::vector<uint8_t>& default_key_id,
const std::vector<uint8_t>& iv,
const std::vector<ProtectionSystemSpecificInfo>& key_system_info) { const std::vector<ProtectionSystemSpecificInfo>& key_system_info) {
LOG_IF(WARNING, !is_initial_encryption_info) LOG_IF(WARNING, !is_initial_encryption_info)
<< "Updating (non initial) encryption info is not supported by " << "Updating (non initial) encryption info is not supported by "
@ -91,10 +92,10 @@ void VodMediaInfoDumpMuxerListener::OnMediaEnd(bool has_init_range,
WriteMediaInfoToFile(*media_info_, output_file_name_); WriteMediaInfoToFile(*media_info_, output_file_name_);
} }
void VodMediaInfoDumpMuxerListener::OnNewSegment(uint64_t start_time, void VodMediaInfoDumpMuxerListener::OnNewSegment(const std::string& file_name,
uint64_t start_time,
uint64_t duration, uint64_t duration,
uint64_t segment_file_size) { uint64_t segment_file_size) {}
}
// static // static
bool VodMediaInfoDumpMuxerListener::WriteMediaInfoToFile( bool VodMediaInfoDumpMuxerListener::WriteMediaInfoToFile(

View File

@ -34,6 +34,7 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
/// @{ /// @{
void OnEncryptionInfoReady(bool is_initial_encryption_info, void OnEncryptionInfoReady(bool is_initial_encryption_info,
const std::vector<uint8_t>& default_key_id, const std::vector<uint8_t>& default_key_id,
const std::vector<uint8_t>& iv,
const std::vector<ProtectionSystemSpecificInfo>& const std::vector<ProtectionSystemSpecificInfo>&
key_system_info) override; key_system_info) override;
void OnMediaStart(const MuxerOptions& muxer_options, void OnMediaStart(const MuxerOptions& muxer_options,
@ -49,7 +50,8 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
uint64_t index_range_end, uint64_t index_range_end,
float duration_seconds, float duration_seconds,
uint64_t file_size) override; uint64_t file_size) override;
void OnNewSegment(uint64_t start_time, void OnNewSegment(const std::string& file_name,
uint64_t start_time,
uint64_t duration, uint64_t duration,
uint64_t segment_file_size) override; uint64_t segment_file_size) override;
/// @} /// @}

View File

@ -25,6 +25,11 @@ const uint8_t kBogusDefaultKeyId[] = {0x5f, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x6c, 0x74, 0x5f, 0x6b, 0x65, 0x79,
0x5f, 0x69, 0x64, 0x5f}; 0x5f, 0x69, 0x64, 0x5f};
const uint8_t kBogusIv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x67, 0x83, 0xC3, 0x66, 0xEE, 0xAB, 0xB2, 0xF1,
};
const bool kInitialEncryptionInfo = true; const bool kInitialEncryptionInfo = true;
} // namespace } // namespace
@ -76,9 +81,10 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test {
std::vector<uint8_t> bogus_default_key_id( std::vector<uint8_t> bogus_default_key_id(
kBogusDefaultKeyId, kBogusDefaultKeyId,
kBogusDefaultKeyId + arraysize(kBogusDefaultKeyId)); kBogusDefaultKeyId + arraysize(kBogusDefaultKeyId));
std::vector<uint8_t> bogus_iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, listener_->OnEncryptionInfoReady(kInitialEncryptionInfo,
bogus_default_key_id, bogus_default_key_id, bogus_iv,
GetDefaultKeySystemInfo()); GetDefaultKeySystemInfo());
} }
listener_->OnMediaStart(muxer_options, stream_info, kReferenceTimeScale, listener_->OnMediaStart(muxer_options, stream_info, kReferenceTimeScale,

View File

@ -81,6 +81,7 @@ Status KeyRotationFragmenter::PrepareFragmentForEncryption(
if (muxer_listener_) { if (muxer_listener_) {
muxer_listener_->OnEncryptionInfoReady(!kInitialEncryptionInfo, muxer_listener_->OnEncryptionInfoReady(!kInitialEncryptionInfo,
encryption_key()->key_id, encryption_key()->key_id,
encryption_key()->iv,
encryption_key()->key_system_info); encryption_key()->key_system_info);
} }

View File

@ -148,11 +148,10 @@ Status MultiSegmentSegmenter::WriteSegment() {
"Cannot open file for append " + options().output_file_name); "Cannot open file for append " + options().output_file_name);
} }
} else { } else {
file = File::Open(GetSegmentName(options().segment_template, file_name = GetSegmentName(options().segment_template,
sidx()->earliest_presentation_time, sidx()->earliest_presentation_time,
num_segments_++, num_segments_++, options().bandwidth);
options().bandwidth).c_str(), file = File::Open(file_name.c_str(), "w");
"w");
if (file == NULL) { if (file == NULL) {
return Status(error::FILE_FAILURE, return Status(error::FILE_FAILURE,
"Cannot open file for write " + file_name); "Cannot open file for write " + file_name);
@ -186,8 +185,9 @@ Status MultiSegmentSegmenter::WriteSegment() {
UpdateProgress(segment_duration); UpdateProgress(segment_duration);
if (muxer_listener()) { if (muxer_listener()) {
muxer_listener()->OnSampleDurationReady(sample_duration()); muxer_listener()->OnSampleDurationReady(sample_duration());
muxer_listener()->OnNewSegment( muxer_listener()->OnNewSegment(file_name,
sidx()->earliest_presentation_time, segment_duration, segment_size); sidx()->earliest_presentation_time,
segment_duration, segment_size);
} }
return Status::OK; return Status::OK;

View File

@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include "packager/base/logging.h"
#include "packager/base/stl_util.h" #include "packager/base/stl_util.h"
#include "packager/media/base/aes_cryptor.h" #include "packager/media/base/aes_cryptor.h"
#include "packager/media/base/buffer_writer.h" #include "packager/media/base/buffer_writer.h"
@ -214,7 +215,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
local_protection_scheme, &description); local_protection_scheme, &description);
if (muxer_listener_) { if (muxer_listener_) {
muxer_listener_->OnEncryptionInfoReady( muxer_listener_->OnEncryptionInfoReady(
kInitialEncryptionInfo, encryption_key.key_id, kInitialEncryptionInfo, encryption_key.key_id, encryption_key.iv,
encryption_key.key_system_info); encryption_key.key_system_info);
} }
@ -252,6 +253,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
if (muxer_listener_) { if (muxer_listener_) {
muxer_listener_->OnEncryptionInfoReady(kInitialEncryptionInfo, muxer_listener_->OnEncryptionInfoReady(kInitialEncryptionInfo,
encryption_key->key_id, encryption_key->key_id,
encryption_key->iv,
encryption_key->key_system_info); encryption_key->key_system_info);
} }
} }

View File

@ -226,7 +226,8 @@ Status SingleSegmentSegmenter::DoFinalizeSegment() {
UpdateProgress(vod_ref.subsegment_duration); UpdateProgress(vod_ref.subsegment_duration);
if (muxer_listener()) { if (muxer_listener()) {
muxer_listener()->OnSampleDurationReady(sample_duration()); muxer_listener()->OnSampleDurationReady(sample_duration());
muxer_listener()->OnNewSegment(vod_ref.earliest_presentation_time, muxer_listener()->OnNewSegment(options().output_file_name,
vod_ref.earliest_presentation_time,
vod_ref.subsegment_duration, segment_size); vod_ref.subsegment_duration, segment_size);
} }
return Status::OK; return Status::OK;

View File

@ -120,6 +120,7 @@ Status Encryptor::CreateEncryptor(MuxerListener* muxer_listener,
const bool kInitialEncryptionInfo = true; const bool kInitialEncryptionInfo = true;
muxer_listener->OnEncryptionInfoReady(kInitialEncryptionInfo, muxer_listener->OnEncryptionInfoReady(kInitialEncryptionInfo,
encryption_key->key_id, encryption_key->key_id,
encryptor->iv(),
encryption_key->key_system_info); encryption_key->key_system_info);
} }

View File

@ -50,7 +50,8 @@ Status MultiSegmentSegmenter::FinalizeSegment() {
const uint64_t start_timescale = FromWebMTimecode(start_webm_timecode); const uint64_t start_timescale = FromWebMTimecode(start_webm_timecode);
const uint64_t length = static_cast<uint64_t>( const uint64_t length = static_cast<uint64_t>(
cluster_length_sec() * info()->time_scale()); cluster_length_sec() * info()->time_scale());
muxer_listener()->OnNewSegment(start_timescale, length, size); muxer_listener()->OnNewSegment(writer_->file()->file_name(),
start_timescale, length, size);
} }
VLOG(1) << "WEBM file '" << writer_->file()->file_name() << "' finalized."; VLOG(1) << "WEBM file '" << writer_->file()->file_name() << "' finalized.";