Adding AddLastFrame to Segment

Adding AddLastFrame function to the Segment muxer so that the duration
of the Segment can be accurately calculated given the last Block's duration.
We now provide an AddLastFrame function which will take duration of that block
as a parameter. When this function is used to add the last frame, the duration
of it is taken into account when computing the Segment's duration.

Change-Id: I3e1456299fefa1a4dd6d845c47292951d1ce3ad0
This commit is contained in:
Vignesh Venkatasubramanian 2013-10-21 12:29:57 -07:00
parent 25025a5471
commit 4134f6e04e
2 changed files with 102 additions and 9 deletions

View File

@ -115,15 +115,20 @@ bool ChunkedCopy(mkvparser::IMkvReader* source,
// Frame Class
Frame::Frame()
: frame_(NULL),
: add_id_(0),
additional_(NULL),
additional_length_(0),
duration_(0),
frame_(NULL),
is_key_(false),
length_(0),
track_number_(0),
timestamp_(0),
is_key_(false) {
timestamp_(0) {
}
Frame::~Frame() {
delete [] frame_;
delete [] additional_;
}
bool Frame::Init(const uint8* frame, uint64 length) {
@ -140,6 +145,22 @@ bool Frame::Init(const uint8* frame, uint64 length) {
return true;
}
bool Frame::AddAdditionalData(const uint8* additional, uint64 length,
uint64 add_id) {
uint8* const data =
new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
if (!data)
return false;
delete [] additional_;
additional_ = data;
additional_length_ = length;
add_id_ = add_id;
memcpy(additional_, additional, static_cast<size_t>(additional_length_));
return true;
}
///////////////////////////////////////////////////////////////
//
// CuePoint Class
@ -2140,7 +2161,8 @@ bool Segment::Finalize() {
}
const double duration =
static_cast<double>(last_timestamp_) / segment_info_.timecode_scale();
(static_cast<double>(last_timestamp_) + last_block_duration_) /
segment_info_.timecode_scale();
segment_info_.set_duration(duration);
if (!segment_info_.Finalize(writer_header_))
return false;
@ -2456,6 +2478,34 @@ bool Segment::AddMetadata(const uint8* frame,
return true;
}
bool Segment::AddGenericFrame(const Frame* frame) {
last_block_duration_ = frame->duration();
if (!tracks_.TrackIsAudio(frame->track_number()) &&
!tracks_.TrackIsVideo(frame->track_number()) &&
frame->duration() > 0) {
return AddMetadata(frame->frame(),
frame->length(),
frame->track_number(),
frame->timestamp(),
frame->duration());
} else if (frame->additional() && frame->additional_length() > 0) {
return AddFrameWithAdditional(frame->frame(),
frame->length(),
frame->additional(),
frame->additional_length(),
frame->add_id(),
frame->track_number(),
frame->timestamp(),
frame->is_key());
} else {
return AddFrame(frame->frame(),
frame->length(),
frame->track_number(),
frame->timestamp(),
frame->is_key());
}
}
void Segment::OutputCues(bool output_cues) {
output_cues_ = output_cues;
}

View File

@ -73,19 +73,43 @@ class Frame {
// Copies |frame| data into |frame_|. Returns true on success.
bool Init(const uint8* frame, uint64 length);
// Copies |additional| data into |additional_|. Returns true on success.
bool AddAdditionalData(const uint8* additional, uint64 length,
uint64 add_id);
uint64 add_id() const { return add_id_; }
const uint8* additional() const { return additional_; }
uint64 additional_length() const { return additional_length_; }
void set_duration(uint64 duration) { duration_ = duration; }
uint64 duration() const { return duration_; }
const uint8* frame() const { return frame_; }
void set_is_key(bool key) { is_key_ = key; }
bool is_key() const { return is_key_; }
uint64 length() const { return length_; }
void set_track_number(uint64 track_number) { track_number_ = track_number; }
uint64 track_number() const { return track_number_; }
void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; }
uint64 timestamp() const { return timestamp_; }
void set_is_key(bool key) { is_key_ = key; }
bool is_key() const { return is_key_; }
private:
// Id of the Additional data.
uint64 add_id_;
// Pointer to additional data. Owned by this class.
uint8* additional_;
// Length of the additional data.
uint64 additional_length_;
// Duration of the frame in nanoseconds.
uint64 duration_;
// Pointer to the data. Owned by this class.
uint8* frame_;
// Flag telling if the data should set the key flag of a block.
bool is_key_;
// Length of the data.
uint64 length_;
@ -94,9 +118,6 @@ class Frame {
// Timestamp of the data in nanoseconds.
uint64 timestamp_;
// Flag telling if the data should set the key flag of a block.
bool is_key_;
};
///////////////////////////////////////////////////////////////
@ -998,6 +1019,19 @@ class Segment {
uint64 timestamp_ns,
uint64 duration_ns);
// Writes a frame with additional data to the output medium; returns true on
// success.
// Inputs:
// frame: Pointer to the data.
// length: Length of the data.
// additional: Pointer to additional data.
// additional_length: Length of additional data.
// add_id: Additional ID which identifies the type of additional data.
// track_number: Track to add the data to. Value returned by Add track
// functions.
// timestamp: Absolute timestamp of the frame, expressed in nanosecond
// units.
// is_key: Flag telling whether or not this frame is a key frame.
bool AddFrameWithAdditional(const uint8* frame,
uint64 length,
const uint8* additional,
@ -1007,6 +1041,12 @@ class Segment {
uint64 timestamp,
bool is_key);
// Writes a Frame to the output medium. Chooses the correct way of writing
// the frame (Block vs SimpleBlock) based on the parameters passed.
// Inputs:
// frame: frame object
bool AddGenericFrame(const Frame* frame);
// Adds a video track to the segment. Returns the number of the track on
// success, 0 on error. |number| is the number to use for the video track.
// |number| must be >= 0. If |number| == 0 then the muxer will decide on
@ -1222,6 +1262,9 @@ class Segment {
// Flag telling if the segment's header has been written.
bool header_written_;
// Duration of the last block in nanoseconds.
uint64 last_block_duration_;
// Last timestamp in nanoseconds added to a cluster.
uint64 last_timestamp_;