Pass sample duration to MPD
- Get the first sample duration in Segmenter. - Pass the value all the way to Representation thru MuxerListener. Change-Id: I76fd970f8140d359863363dc347958f680cca5ae
This commit is contained in:
parent
fcaac3de33
commit
d685edef62
|
@ -64,6 +64,11 @@ void MpdNotifyMuxerListener::OnMediaStart(
|
|||
}
|
||||
}
|
||||
|
||||
void MpdNotifyMuxerListener::OnSampleDurationReady(
|
||||
uint32_t sample_duration) {
|
||||
mpd_notifier_->NotifySampleDuration(notification_id_, sample_duration);
|
||||
}
|
||||
|
||||
void MpdNotifyMuxerListener::OnMediaEnd(bool has_init_range,
|
||||
uint64_t init_range_start,
|
||||
uint64_t init_range_end,
|
||||
|
|
|
@ -41,7 +41,7 @@ class MpdNotifyMuxerListener : public MuxerListener {
|
|||
uint32_t time_scale,
|
||||
ContainerType container_type,
|
||||
bool is_encrypted) OVERRIDE;
|
||||
|
||||
virtual void OnSampleDurationReady(uint32_t sample_duration) OVERRIDE;
|
||||
virtual void OnMediaEnd(bool has_init_range,
|
||||
uint64_t init_range_start,
|
||||
uint64_t init_range_end,
|
||||
|
@ -50,7 +50,6 @@ class MpdNotifyMuxerListener : public MuxerListener {
|
|||
uint64_t index_range_end,
|
||||
float duration_seconds,
|
||||
uint64_t file_size) OVERRIDE;
|
||||
|
||||
virtual void OnNewSegment(uint64_t start_time,
|
||||
uint64_t duration,
|
||||
uint64_t segment_file_size) OVERRIDE;
|
||||
|
|
|
@ -19,6 +19,10 @@ namespace media {
|
|||
class StreamInfo;
|
||||
struct MuxerOptions;
|
||||
|
||||
/// MuxerListener is an event handler that can be registered to a muxer.
|
||||
/// A MuxerListener cannot be shared amongst muxer instances, in other words,
|
||||
/// every muxer instance either owns a unique MuxerListener instance.
|
||||
/// This also assumes that there is one media stream per muxer.
|
||||
class MuxerListener {
|
||||
public:
|
||||
enum ContainerType {
|
||||
|
@ -41,6 +45,10 @@ class MuxerListener {
|
|||
ContainerType container_type,
|
||||
bool is_encrypted) = 0;
|
||||
|
||||
/// Called when the average sample duration of the media is determined.
|
||||
/// @param sample_duration in timescale of the media.
|
||||
virtual void OnSampleDurationReady(uint32_t sample_duration) = 0;
|
||||
|
||||
// Called when all files are written out and the muxer object does not output
|
||||
// any more files.
|
||||
// Note: This event might not be very interesting to MPEG DASH Live profile.
|
||||
|
|
|
@ -55,6 +55,14 @@ void VodMediaInfoDumpMuxerListener::OnMediaStart(
|
|||
}
|
||||
}
|
||||
|
||||
void VodMediaInfoDumpMuxerListener::OnSampleDurationReady(
|
||||
uint32_t sample_duration) {
|
||||
// Assume one VideoInfo.
|
||||
if (media_info_->video_info_size() > 0) {
|
||||
media_info_->mutable_video_info(0)->set_frame_duration(sample_duration);
|
||||
}
|
||||
}
|
||||
|
||||
void VodMediaInfoDumpMuxerListener::OnMediaEnd(bool has_init_range,
|
||||
uint64_t init_range_start,
|
||||
uint64_t init_range_end,
|
||||
|
|
|
@ -41,7 +41,7 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
|
|||
uint32_t time_scale,
|
||||
ContainerType container_type,
|
||||
bool is_encrypted) OVERRIDE;
|
||||
|
||||
virtual void OnSampleDurationReady(uint32_t sample_duration) OVERRIDE;
|
||||
virtual void OnMediaEnd(bool has_init_range,
|
||||
uint64_t init_range_start,
|
||||
uint64_t init_range_end,
|
||||
|
@ -50,7 +50,6 @@ class VodMediaInfoDumpMuxerListener : public MuxerListener {
|
|||
uint64_t index_range_end,
|
||||
float duration_seconds,
|
||||
uint64_t file_size) OVERRIDE;
|
||||
|
||||
virtual void OnNewSegment(uint64_t start_time,
|
||||
uint64_t duration,
|
||||
uint64_t segment_file_size) OVERRIDE;
|
||||
|
|
|
@ -185,6 +185,7 @@ Status MultiSegmentSegmenter::WriteSegment() {
|
|||
|
||||
UpdateProgress(segment_duration);
|
||||
if (muxer_listener()) {
|
||||
muxer_listener()->OnSampleDurationReady(sample_duration());
|
||||
muxer_listener()->OnNewSegment(
|
||||
sidx()->earliest_presentation_time, segment_duration, segment_size);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,8 @@ Segmenter::Segmenter(const MuxerOptions& options,
|
|||
muxer_listener_(NULL),
|
||||
progress_listener_(NULL),
|
||||
progress_target_(0),
|
||||
accumulated_progress_(0) {
|
||||
accumulated_progress_(0),
|
||||
sample_duration_(0u) {
|
||||
}
|
||||
|
||||
Segmenter::~Segmenter() { STLDeleteElements(&fragmenters_); }
|
||||
|
@ -295,6 +296,8 @@ Status Segmenter::AddSample(const MediaStream* stream,
|
|||
if (!status.ok())
|
||||
return status;
|
||||
|
||||
if (sample_duration_ == 0)
|
||||
sample_duration_ = sample->duration();
|
||||
moov_->tracks[stream_id].media.header.duration += sample->duration();
|
||||
segment_durations_[stream_id] += sample->duration();
|
||||
return Status::OK;
|
||||
|
|
|
@ -96,6 +96,10 @@ class Segmenter {
|
|||
/// @return The total length, in seconds, of segmented media files.
|
||||
double GetDuration() const;
|
||||
|
||||
/// @return The sample duration in the timescale of the media.
|
||||
/// Returns 0 if no samples are added yet.
|
||||
uint32_t sample_duration() const { return sample_duration_; }
|
||||
|
||||
protected:
|
||||
/// Update segmentation progress using ProgressListener.
|
||||
void UpdateProgress(uint64_t progress);
|
||||
|
@ -140,6 +144,7 @@ class Segmenter {
|
|||
ProgressListener* progress_listener_;
|
||||
uint64_t progress_target_;
|
||||
uint64_t accumulated_progress_;
|
||||
uint32_t sample_duration_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Segmenter);
|
||||
};
|
||||
|
|
|
@ -225,6 +225,7 @@ Status SingleSegmentSegmenter::DoFinalizeSegment() {
|
|||
|
||||
UpdateProgress(vod_ref.subsegment_duration);
|
||||
if (muxer_listener()) {
|
||||
muxer_listener()->OnSampleDurationReady(sample_duration());
|
||||
muxer_listener()->OnNewSegment(vod_ref.earliest_presentation_time,
|
||||
vod_ref.subsegment_duration, segment_size);
|
||||
}
|
||||
|
|
|
@ -666,6 +666,12 @@ void Representation::AddNewSegment(uint64_t start_time,
|
|||
DCHECK_GE(segment_infos_.size(), 1u);
|
||||
}
|
||||
|
||||
void Representation::SetSampleDuration(uint32_t sample_duration) {
|
||||
// Assume single video info.
|
||||
if (media_info_.video_info_size() > 0)
|
||||
media_info_.mutable_video_info(0)->set_frame_duration(sample_duration);
|
||||
}
|
||||
|
||||
// Uses info in |media_info_| and |content_protection_elements_| to create a
|
||||
// "Representation" node.
|
||||
// MPD schema has strict ordering. The following must be done in order.
|
||||
|
|
|
@ -233,6 +233,13 @@ class Representation {
|
|||
/// @param size of the segment in bytes.
|
||||
void AddNewSegment(uint64_t start_time, uint64_t duration, uint64_t size);
|
||||
|
||||
/// Set the sample duration of this Representation.
|
||||
/// In most cases, the sample duration is not available right away. This
|
||||
/// allows setting the sample duration after the Representation has been
|
||||
/// initialized.
|
||||
/// @param sample_duration is the duration of a sample.
|
||||
void SetSampleDuration(uint32_t sample_duration);
|
||||
|
||||
/// @return Copy of <Representation>.
|
||||
xml::ScopedXmlPtr<xmlNode>::type GetXml();
|
||||
|
||||
|
@ -247,6 +254,7 @@ class Representation {
|
|||
FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, InvalidMediaInfo);
|
||||
FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, CheckVideoInfoReflectedInXml);
|
||||
FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, CheckRepresentationId);
|
||||
FRIEND_TEST_ALL_PREFIXES(CommonMpdBuilderTest, SetSampleDuration);
|
||||
|
||||
/// @param media_info is a MediaInfo containing information on the media.
|
||||
/// @a media_info.bandwidth is required for 'static' profile. If @a
|
||||
|
|
|
@ -399,6 +399,22 @@ TEST_F(CommonMpdBuilderTest, CheckRepresentationId) {
|
|||
ASSERT_NO_FATAL_FAILURE(CheckIdEqual(kRepresentationId, &representation));
|
||||
}
|
||||
|
||||
// TODO(rkuroiwa): Better way to test this is to use GetXml(). Check that
|
||||
// frameRate is set once the patch that adds frameRate attribute lands.
|
||||
// For now, check that media_info_ owned by Representation has
|
||||
// frame_duration = sample_duration.
|
||||
TEST_F(CommonMpdBuilderTest, SetSampleDuration) {
|
||||
const MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
const uint32_t kRepresentationId = 1;
|
||||
|
||||
Representation representation(
|
||||
video_media_info, MpdOptions(), kRepresentationId);
|
||||
EXPECT_TRUE(representation.Init());
|
||||
representation.SetSampleDuration(2u);
|
||||
EXPECT_EQ(2u,
|
||||
representation.media_info_.video_info(0).frame_duration());
|
||||
}
|
||||
|
||||
// Add one video check the output.
|
||||
TEST_F(StaticMpdBuilderTest, Video) {
|
||||
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
|
|
|
@ -46,6 +46,16 @@ class MpdNotifier {
|
|||
virtual bool NotifyNewContainer(const MediaInfo& media_info,
|
||||
uint32_t* container_id) = 0;
|
||||
|
||||
/// Change the sample duration of container with @a container_id.
|
||||
/// @param container_id Container ID obtained from calling
|
||||
/// NotifyNewContainer().
|
||||
/// @param sample_duration is the duration of a sample in timescale of the
|
||||
/// media.
|
||||
/// @return true on success, false otherwise. This may fail if the container
|
||||
/// specified by @a container_id does not exist.
|
||||
virtual bool NotifySampleDuration(uint32_t container_id,
|
||||
uint32_t sample_duration) = 0;
|
||||
|
||||
/// Notifies MpdBuilder that there is a new segment ready. Used only for live
|
||||
/// profile.
|
||||
/// @param container_id Container ID obtained from calling
|
||||
|
|
|
@ -74,6 +74,18 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SimpleMpdNotifier::NotifySampleDuration(uint32_t container_id,
|
||||
uint32_t sample_duration) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
RepresentationMap::iterator it = representation_map_.find(container_id);
|
||||
if (it == representation_map_.end()) {
|
||||
LOG(ERROR) << "Unexpected container_id: " << container_id;
|
||||
return false;
|
||||
}
|
||||
it->second->SetSampleDuration(sample_duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleMpdNotifier::NotifyNewSegment(uint32_t container_id,
|
||||
uint64_t start_time,
|
||||
uint64_t duration,
|
||||
|
|
|
@ -38,6 +38,8 @@ class SimpleMpdNotifier : public MpdNotifier {
|
|||
virtual bool Init() OVERRIDE;
|
||||
virtual bool NotifyNewContainer(const MediaInfo& media_info,
|
||||
uint32_t* id) OVERRIDE;
|
||||
virtual bool NotifySampleDuration(uint32_t container_id,
|
||||
uint32_t sample_duration) OVERRIDE;
|
||||
virtual bool NotifyNewSegment(uint32_t id,
|
||||
uint64_t start_time,
|
||||
uint64_t duration,
|
||||
|
|
Loading…
Reference in New Issue