First draft doxygen documentation for media/mp4.

Change-Id: I13a28245168724a237a4653e298d6b835c24f17b
This commit is contained in:
Kongqun Yang 2014-01-23 14:34:39 -08:00
parent 6046cde3d8
commit cca3767c25
17 changed files with 298 additions and 237 deletions

View File

@ -15,50 +15,56 @@ class BitReader;
namespace mp4 {
// This class parses the AAC information from decoder specific information
// embedded in the esds box in an ISO BMFF file.
// Please refer to ISO 14496 Part 3 Table 1.13 - Syntax of AudioSpecificConfig
// for more details.
/// This class parses the AAC information from decoder specific information
/// embedded in the @b esds box in an ISO BMFF file.
/// Please refer to ISO 14496 Part 3 Table 1.13 - Syntax of AudioSpecificConfig
/// for more details.
class AACAudioSpecificConfig {
public:
AACAudioSpecificConfig();
~AACAudioSpecificConfig();
// Parse the AAC config from the raw binary data embedded in esds box.
// The function will parse the data and get the ElementaryStreamDescriptor,
// then it will parse the ElementaryStreamDescriptor to get audio stream
// configurations.
/// Parse the AAC config from decoder specific information embedded in an @b
/// esds box. The function will parse the data and get the
/// ElementaryStreamDescriptor, then it will parse the
/// ElementaryStreamDescriptor to get audio stream configurations.
/// @param data contains decoder specific information from an @b esds box.
/// @return true if successful, false otherwise.
bool Parse(const std::vector<uint8>& data);
// Get the output sample rate for the AAC stream.
// |sbr_in_mimetype| should be set to true if the SBR mode is
// signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter).
/// @param sbr_in_mimetype indicates whether SBR mode is specified in the
/// mimetype, i.e. codecs parameter contains mp4a.40.5.
/// @return Output sample rate for the AAC stream.
uint32 GetOutputSamplesPerSecond(bool sbr_in_mimetype) const;
// Get number of channels for the AAC stream.
// |sbr_in_mimetype| should be set to true if the SBR mode is
// signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter).
/// @param sbr_in_mimetype indicates whether SBR mode is specified in the
/// mimetype, i.e. codecs parameter contains mp4a.40.5.
/// @return Number of channels for the AAC stream.
uint8 GetNumChannels(bool sbr_in_mimetype) const;
// This function converts a raw AAC frame into an AAC frame with an ADTS
// header. On success, the function returns true and stores the converted data
// in the buffer. The function returns false on failure and leaves the buffer
// unchanged.
/// Convert a raw AAC frame into an AAC frame with an ADTS header.
/// @param[in,out] buffer contains the raw AAC frame on input, and the
/// converted frame on output if successful; it is untouched
/// on failure.
/// @return true on success, false otherwise.
bool ConvertToADTS(std::vector<uint8>* buffer) const;
/// @return The audio object type for this AAC config.
uint8 audio_object_type() const {
return audio_object_type_;
}
/// @return The sampling frequency for this AAC config.
uint32 frequency() const {
return frequency_;
}
/// @return Number of channels for this AAC config.
uint8 num_channels() const {
return num_channels_;
}
// Size in bytes of the ADTS header added by ConvertEsdsToADTS().
/// Size in bytes of the ADTS header added by ConvertEsdsToADTS().
static const size_t kADTSHeaderSize = 7;
private:

View File

@ -20,32 +20,39 @@ namespace mp4 {
class BoxBuffer;
class BoxReader;
// Defines Box and FullBox, the two base ISO BMFF box objects as defined in
// ISO 14496-12:2012 ISO BMFF section 4.2. All ISO BMFF compatible boxes
// inherits either Box or FullBox.
/// Defines the base ISO BMFF box objects as defined in ISO 14496-12:2012
/// ISO BMFF section 4.2. All ISO BMFF compatible boxes inherit from either
/// Box or FullBox.
struct Box {
public:
Box();
virtual ~Box();
/// Parse the mp4 box.
/// @param reader points to a BoxReader object which parses the box.
bool Parse(BoxReader* reader);
// Write the box to buffer.
// The function calls ComputeSize internally to compute box size.
/// Write the box to buffer.
/// This function calls ComputeSize internally to compute box size.
/// @param writer points to a BufferWriter object which wraps the buffer for
/// writing.
void Write(BufferWriter* writer);
// Computer box size.
// The calculated size will be saved in |atom_size| for consumption later.
/// Compute the size of this box.
/// The calculated size will be saved in |atom_size| for later consumption.
virtual uint32 ComputeSize() = 0;
virtual FourCC BoxType() const = 0;
protected:
friend class BoxBuffer;
// Read or write the mp4 box through BoxBuffer.
/// Read/write the mp4 box from/to BoxBuffer.
virtual bool ReadWrite(BoxBuffer* buffer);
// We don't support 64-bit atom size. 32-bit should be large enough for our
// current needs.
/// We don't support 64-bit atom sizes. 32-bit should be large enough for our
/// current needs.
uint32 atom_size;
};
/// Defines FullBox, the other base ISO BMFF box objects as defined in
/// ISO 14496-12:2012 ISO BMFF section 4.2. All ISO BMFF compatible boxes
/// inherit from either Box or FullBox.
struct FullBox : Box {
public:
FullBox();

View File

@ -15,45 +15,47 @@
namespace media {
namespace mp4 {
// Defines a wrapper for mp4 box reading/writing, which is symmetric in most
// cases, i.e. we can use one single routine for the reading and writing.
// BoxBuffer wraps either BoxReader for reading or BufferWriter for writing.
// Thus it is capable of doing either reading or writing, but not both.
/// Class for MP4 box I/O. Box I/O is symmetric and exclusive, so we can define
/// a single method to do either reading or writing box objects.
/// BoxBuffer wraps either BoxReader for reading or BufferWriter for writing.
/// Thus it is capable of doing either reading or writing, but not both.
class BoxBuffer {
public:
// Creates a "reader" version of the BoxBuffer.
// Caller retains |reader| ownership. |reader| should not be NULL.
/// Create a reader version of the BoxBuffer.
/// @param reader should not be NULL.
explicit BoxBuffer(BoxReader* reader) : reader_(reader), writer_(NULL) {
DCHECK(reader);
}
// Creates a "writer" version of the BoxBuffer.
// Caller retains |writer| ownership. |writer| should not be NULL.
/// Create a writer version of the BoxBuffer.
/// @param writer should not be NULL.
explicit BoxBuffer(BufferWriter* writer) : reader_(NULL), writer_(writer) {
DCHECK(writer);
}
~BoxBuffer() {}
// Reading or writing?
/// @return true for reader, false for writer.
bool Reading() const { return reader_ != NULL; }
// Returns current read/write position. In read mode, this is the current
// read position. In write mode, it is the same as Size().
/// @return Current read/write position. In read mode, this is the current
/// read position. In write mode, it is the same as Size().
size_t Pos() const {
if (reader_)
return reader_->pos();
return writer_->Size();
}
// Returns total buffer size.In read mode, it includes data that has already
// been read or skipped, and will not change. In write mode, it includes all
// data that has been written, and will change as data is written.
/// @return Total buffer size. In read mode, it includes data that has already
/// been read or skipped, and will not change. In write mode, it
/// includes all data that has been written, and will change as more
/// data is written.
size_t Size() const {
if (reader_)
return reader_->size();
return writer_->Size();
}
// Read/write integers of various size and unsigned/signed.
/// @name Read/write integers of various sizes and signedness.
/// @{
bool ReadWriteUInt8(uint8* v) {
if (reader_)
return reader_->Read1(v);
@ -96,9 +98,11 @@ class BoxBuffer {
writer_->AppendInt(*v);
return true;
}
/// @}
// Read/write the least significant |num_bytes| of |v| from/to buffer.
// |num_bytes| should not be larger than sizeof(v), i.e. 8.
/// Read/write the least significant |num_bytes| of |v| from/to the buffer.
/// @param num_bytes should not be larger than sizeof(v), i.e. 8.
/// @return true on success, false otherwise.
bool ReadWriteUInt64NBytes(uint64* v, size_t num_bytes) {
if (reader_)
return reader_->ReadNBytesInto8(v, num_bytes);
@ -125,7 +129,8 @@ class BoxBuffer {
return true;
}
// Prepare child boxes for read/write.
/// Prepare child boxes for reading/writing.
/// @return true on success, false otherwise.
bool PrepareChildren() {
if (reader_)
return reader_->ScanChildren();
@ -133,7 +138,8 @@ class BoxBuffer {
return true;
}
// Read/write child box.
/// Read/write child box.
/// @return true on success, false otherwise.
bool ReadWriteChild(Box* box) {
if (reader_)
return reader_->ReadChild(box);
@ -143,7 +149,8 @@ class BoxBuffer {
return true;
}
// Read/write child box if exist.
/// Read/write child box if exists.
/// @return true on success, false otherwise.
bool TryReadWriteChild(Box* box) {
if (reader_)
return reader_->TryReadChild(box);
@ -153,7 +160,9 @@ class BoxBuffer {
return true;
}
// Skip |num_bytes| in read mode, otherwise fill with |num_bytes| of '\0'.
/// @param num_bytes specifies number of bytes to skip in read mode or number
/// of bytes to be padded with zero in write mode.
/// @return true on success, false otherwise.
bool IgnoreBytes(size_t num_bytes) {
if (reader_)
return reader_->SkipBytes(num_bytes);
@ -162,7 +171,9 @@ class BoxBuffer {
return true;
}
/// @return A pointer to the inner reader object.
BoxReader* reader() { return reader_; }
/// @return A pointer to the inner writer object.
BufferWriter* writer() { return writer_; }
private:

View File

@ -19,63 +19,74 @@ namespace mp4 {
class Box;
/// Class for reading MP4 boxes.
class BoxReader : public BufferReader {
public:
~BoxReader();
// Create a BoxReader from a buffer. Note that this function may return NULL
// if an intact, complete box was not available in the buffer. If |*err| is
// set, there was a stream-level error when creating the box; otherwise, NULL
// values are only expected when insufficient data is available.
//
// |buf| is retained but not owned, and must outlive the BoxReader instance.
/// Create a BoxReader from a buffer.
/// @param buf is retained but not owned, and must outlive the BoxReader
/// instance.
/// @param buf_size indicates the size of the input buffer.
/// @param[out] err is set to true if there was a stream-level error when
/// reading the box.
/// @return New box reader if successful, NULL otherwise.
static BoxReader* ReadTopLevelBox(const uint8* buf,
const int buf_size,
bool* err);
// Read the box header from the current buffer. This function returns true if
// there is enough data to read the header and the header is sane; that is, it
// does not check to ensure the entire box is in the buffer before returning
// true. The semantics of |*err| are the same as above.
//
// |buf| is not retained.
/// Read the box header from the current buffer.
/// @param buf is not retained.
/// @param buf_size indicates the size of the input buffer.
/// @param[out] type is filled with the fourcc of the box on success.
/// @param[out] box_size is filled with the size of the box on success.
/// @param[out] err is set to true if there was a stream-level error when
/// reading the box.
/// @return true if there is enough data to read the header and the header is
/// sane, which does not imply that the entire box is in the buffer.
static bool StartTopLevelBox(const uint8* buf,
const int buf_size,
FourCC* type,
int* box_size,
bool* err) WARN_UNUSED_RESULT;
// Returns true if |type| is recognized to be a top-level box, false
// otherwise. This returns true for some boxes which we do not parse.
// Helpful in debugging misaligned appends.
/// @return true if @a type is recognized to be the fourcc of a top-level box,
/// false otherwise. This returns true for some boxes which we do not
/// parse.
/// This method is helpful for debugging misaligned appends.
static bool IsValidTopLevelBox(const FourCC& type);
// Scan through all boxes within the current box, starting at the current
// buffer position. Must be called before any of the *Child functions work.
/// Scan through all boxes within the current box, starting at the current
/// buffer position. Must be called before any of the @b *Child functions
/// work.
/// @return true on success, false otherwise.
bool ScanChildren() WARN_UNUSED_RESULT;
// Return true if child with type |child.BoxType()| exists.
/// @return true if child with type @a child.BoxType() exists.
bool ChildExist(Box* child) WARN_UNUSED_RESULT;
// Read exactly one child box from the set of children. The type of the child
// will be determined by the BoxType() method of |child|.
/// Read exactly one child box from the set of children. The type of the
/// child will be determined by the BoxType() of @a child.
/// @return true on success, false otherwise.
bool ReadChild(Box* child) WARN_UNUSED_RESULT;
// Read one child if available. Returns false on error, true on successful
// read or on child absent.
/// Read one child if available.
/// @return false on error, true on successful read or on child absent.
bool TryReadChild(Box* child) WARN_UNUSED_RESULT;
// Read at least one child. False means error or no such child present.
/// Read at least one child.
/// @return false on error or no child of type <T> present.
template <typename T>
bool ReadChildren(std::vector<T>* children) WARN_UNUSED_RESULT;
// Read any number of children. False means error.
/// Read any number of children.
/// @return false on error.
template <typename T>
bool TryReadChildren(std::vector<T>* children) WARN_UNUSED_RESULT;
// Read all children, regardless of FourCC. This is used from exactly one box,
// corresponding to a rather significant inconsistency in the BMFF spec.
// Note that this method is mutually exclusive with ScanChildren().
/// Read all children. It expects all children to be of type T.
/// Note that this method is mutually exclusive with ScanChildren().
/// @return true on success, false otherwise.
template <typename T>
bool ReadAllChildren(std::vector<T>* children) WARN_UNUSED_RESULT;

View File

@ -3,10 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Implements a wrapper around Sample to Chunk Box (STSC) to iterate through
// the compressed table by sample/chunk. This class also provides a convenient
// function to query total number of samples from start_chunk to end_chunk.
#ifndef MEDIA_MP4_CHUNK_INFO_ITERATOR_H_
#define MEDIA_MP4_CHUNK_INFO_ITERATOR_H_
@ -18,38 +14,42 @@
namespace media {
namespace mp4 {
/// Sample to chunk box (STSC) iterator used to iterate through the compressed
/// table by sample/chunk. This class also provides a convenient function to
/// query total number of samples from start_chunk to end_chunk.
class ChunkInfoIterator {
public:
/// Create ChunkInfoIterator from sample to chunk box.
explicit ChunkInfoIterator(const SampleToChunk& sample_to_chunk);
~ChunkInfoIterator();
// Advance the properties to refer to the next chunk. Return status
// indicating whether the chunk is still valid.
/// Advance to the next chunk.
/// @return true if not past the last chunk, false otherwise.
bool AdvanceChunk();
// Advance the properties to refer to the next sample. Return status
// indicating whether the sample is still valid.
/// Advance to the next sample.
/// @return true if not past the last sample, false otherwise.
bool AdvanceSample();
// Return whether the current chunk is valid.
/// @return true if not past the last chunk/sample, false otherwise.
bool IsValid() const;
// Return current chunk.
/// @return Current chunk.
uint32 current_chunk() const { return current_chunk_; }
// Return samples per chunk for current chunk.
/// @return Samples per chunk for current chunk.
uint32 samples_per_chunk() const { return iterator_->samples_per_chunk; }
// Return sample description index for current chunk.
/// @return Sample description index for current chunk.
uint32 sample_description_index() const {
return iterator_->sample_description_index;
}
// Return number of samples from start_chunk to end_chunk, both 1-based,
// inclusive.
/// @return Number of samples from start_chunk to end_chunk, both 1-based,
/// inclusive.
uint32 NumSamples(uint32 start_chunk, uint32 end_chunk) const;
// Return the last first_chunk in chunk_info_table.
/// @return The last first_chunk in chunk_info_table.
uint32 LastFirstChunk() const {
return chunk_info_table_.empty() ? 0
: chunk_info_table_.back().first_chunk;

View File

@ -3,11 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Implements a wrapper around Composition Time to Sample Box (CTTS) to iterate
// through the compressed table. This class also provides convenient functions
// to query total number of samples and the composition offset for a particular
// sample.
#ifndef MEDIA_MP4_COMPOSITION_OFFSET_ITERATOR_H_
#define MEDIA_MP4_COMPOSITION_OFFSET_ITERATOR_H_
@ -19,26 +14,31 @@
namespace media {
namespace mp4 {
/// Composition time to sample box (CTTS) iterator used to iterate through the
/// compressed table. This class also provides convenient functions to query
/// total number of samples and the composition offset for a particular sample.
class CompositionOffsetIterator {
public:
/// Create CompositionOffsetIterator from composition time to sample box.
explicit CompositionOffsetIterator(
const CompositionTimeToSample& composition_time_to_sample);
~CompositionOffsetIterator();
// Advance the properties to refer to the next sample. Return status
// indicating whether the sample is still valid.
/// Advance the iterator to the next sample.
/// @return true if not past the last sample, false otherwise.
bool AdvanceSample();
// Return whether the current sample is valid.
/// @return true if the iterator is still valid, false if past the last
/// sample.
bool IsValid() const;
// Return sample offset for current sample.
/// @return Sample offset for current sample.
uint32 sample_offset() const { return iterator_->sample_offset; }
// Return sample offset @ sample, 1-based.
/// @return Sample offset @a sample, 1-based.
uint32 SampleOffset(uint32 sample) const;
// Return total number of samples.
/// @return Total number of samples.
uint32 NumSamples() const;
private:

View File

@ -3,11 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Implements a wrapper around Decoding Time to Sample Box (STTS) to iterate
// through the compressed table. This class also provides convenient functions
// to query total number of samples and the duration from start_sample to
// end_sample.
#ifndef MEDIA_MP4_DECODING_TIME_ITERATOR_H_
#define MEDIA_MP4_DECODING_TIME_ITERATOR_H_
@ -19,26 +14,31 @@
namespace media {
namespace mp4 {
/// Decoding time to sample box (STTS) iterator used to iterate through the
/// compressed table. This class also provides convenient functions to query
/// total number of samples and the duration from start_sample to end_sample.
class DecodingTimeIterator {
public:
/// Create DecodingTimeIterator from decoding time to sample box.
explicit DecodingTimeIterator(
const DecodingTimeToSample& decoding_time_to_sample);
~DecodingTimeIterator();
// Advance the properties to refer to the next sample. Return status
// indicating whether the sample is still valid.
/// Advance to the next sample.
/// @return true if not past the last sample, false otherwise.
bool AdvanceSample();
// Return whether the current sample is valid.
/// @return true if the iterator is still valid, false if past the last
/// sample.
bool IsValid() const;
// Return sample delta for current sample.
/// @return Sample delta for current sample.
uint32 sample_delta() const { return iterator_->sample_delta; }
// Return duration from start_sample to end_sample, both 1-based, inclusive.
/// @return Duration from start_sample to end_sample, both 1-based, inclusive.
uint64 Duration(uint32 start_sample, uint32 end_sample) const;
// Return total number of samples in the table.
/// @return Total number of samples in the table.
uint32 NumSamples() const;
private:

View File

@ -25,9 +25,9 @@ enum ObjectType {
kEAC3 = 0xa6 // Dolby Digital Plus
};
// This class parse object type and decoder specific information from an
// elementary stream descriptor, which is usually contained in an esds box.
// Please refer to ISO 14496 Part 1 7.2.6.5 for more details.
/// This class parses object type and decoder specific information from an
/// elementary stream descriptor, which is usually contained in an esds
/// box. Please refer to ISO 14496 Part 1 7.2.6.5 for more details.
class ESDescriptor {
public:
ESDescriptor();
@ -51,7 +51,7 @@ class ESDescriptor {
decoder_specific_info_ = decoder_specific_info;
}
// Check if the stream is AAC.
/// @return true if the stream is AAC.
bool IsAAC() const {
return object_type_ == kISO_14496_3 || object_type_ == kISO_13818_7_AAC_LC;
}

View File

@ -3,10 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// MP4Fragmenter is responsible for the generation of MP4 fragments, i.e. traf
// and the corresponding mdat. The samples are also encrypted if encryption is
// requested.
#ifndef MEDIA_MP4_MP4_FRAGMENTER_H_
#define MEDIA_MP4_MP4_FRAGMENTER_H_
@ -28,13 +24,20 @@ namespace mp4 {
class SegmentReference;
class TrackFragment;
/// MP4Fragmenter is responsible for the generation of MP4 fragments, i.e. traf
/// box and corresponding mdat box. The samples are also encrypted if encryption
/// is requested.
class MP4Fragmenter {
public:
// Caller retains the ownership of |traf| and transfers ownership of
// |encryptor|. |clear_time| specifies clear time in the current track
// timescale. |nalu_length_size| specifies NAL unit length size, for
// subsample encryption. |normalize_presentation_timestamp| defines whether
// PTS should be normalized to start from zero.
/// @param traf points to a TrackFragment box.
/// @param encryptor handles encryption of the samples. It can be NULL, which
/// indicates no encryption is required.
/// @param clear_time specifies clear lead duration in units of the current
/// track's timescale.
/// @param nalu_length_size NAL unit length size, in bytes, for subsample
/// encryption.
/// @param normalize_presentation_timestamp defines whether PTS should be
/// normalized to start from zero.
MP4Fragmenter(TrackFragment* traf,
scoped_ptr<AesCtrEncryptor> encryptor,
int64 clear_time,
@ -42,15 +45,16 @@ class MP4Fragmenter {
bool normalize_presentation_timestamp);
~MP4Fragmenter();
/// Add a sample to the fragmenter.
virtual Status AddSample(scoped_refptr<MediaSample> sample);
// Initialize the fragment with default data.
/// Initialize the fragment with default data.
void InitializeFragment();
// Finalize and optimize the fragment.
/// Finalize and optimize the fragment.
void FinalizeFragment();
// Fill in |reference| with current fragment information.
/// Fill @a reference with current fragment information.
void GenerateSegmentReference(SegmentReference* reference);
uint64 fragment_duration() const { return fragment_duration_; }

View File

@ -3,20 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Segmenter for MP4 live, main and simple profiles. The generated media file
// could contain one to many segments with segment duration defined by
// |MuxerOptions.segment_duration|. A segment could contain one to many
// subsegments defined by |num_subsegments_per_sidx|. A subsegment could
// contain one to many fragments with fragment duration defined by
// |MuxerOptions.fragment_duration|. The actual segment or fragment duration
// may not match the defined duration exactly but in a best effort basic, i.e.
// the segmenter tries to end segment/fragment at the first sample with
// overall segment/fragment duration not smaller than defined duration and
// yet meet SAP requirements. The generated segments are written into files
// defined by |MuxerOptions.segment_template| if it is defined; otherwise,
// the segments are appended to the main output file defined by
// |MuxerOptions.output_file_name|.
#ifndef MEDIA_MP4_MP4_GENERAL_SEGMENTER_H_
#define MEDIA_MP4_MP4_GENERAL_SEGMENTER_H_
@ -28,21 +14,35 @@ namespace mp4 {
struct SegmentType;
/// Segmenter for MP4 live, main and simple profiles. The generated media file
/// can contain one or many segments with segment duration defined by @b
/// MuxerOptions.segment_duration. A segment can contain one or many
/// subsegments defined by @b num_subsegments_per_sidx. A subsegment can
/// contain one or many fragments with fragment duration defined by @b
/// MuxerOptions.fragment_duration. The actual segment or fragment duration
/// may not match the requested duration exactly, but will be approximated.
/// That is, the segmenter tries to end segment/fragment at the first sample
/// with overall segment/fragment duration not smaller than defined duration
/// and yet meet SAP requirements. The generated segments are written to files
/// defined by @b MuxerOptions.segment_template if specified; otherwise,
/// the segments are appended to the main output file specified by @b
/// MuxerOptions.output_file_name.
class MP4GeneralSegmenter : public MP4Segmenter {
public:
// Caller transfers the ownership of |ftyp| and |moov| to this class.
MP4GeneralSegmenter(const MuxerOptions& options,
scoped_ptr<FileType> ftyp,
scoped_ptr<Movie> moov);
virtual ~MP4GeneralSegmenter();
// MP4Segmenter implementations.
/// @name MP4Segmenter 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;

View File

@ -30,10 +30,13 @@ class MP4MediaParser : public MediaParser {
MP4MediaParser();
virtual ~MP4MediaParser();
/// @name MediaParser implementation overrides.
/// @{
virtual void Init(const InitCB& init_cb,
const NewSampleCB& new_sample_cb,
const NeedKeyCB& need_key_cb) OVERRIDE;
virtual bool Parse(const uint8* buf, int size) OVERRIDE;
/// @}
private:
enum State {

View File

@ -3,8 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Implements MP4 Muxer.
#ifndef MEDIA_MP4_MP4_MUXER_H_
#define MEDIA_MP4_MP4_MUXER_H_
@ -28,16 +26,21 @@ struct ProtectionSchemeInfo;
struct ProtectionSystemSpecificHeader;
struct Track;
/// Implements MP4 Muxer for ISO-BMFF. Please refer to ISO/IEC 14496-12: ISO
/// base media file format for details.
class MP4Muxer : public Muxer {
public:
/// Create a MP4Muxer object from MuxerOptions.
explicit MP4Muxer(const MuxerOptions& options);
virtual ~MP4Muxer();
// Muxer implementations.
/// @name Muxer implementation overrides.
/// @{
virtual Status Initialize() OVERRIDE;
virtual Status Finalize() OVERRIDE;
virtual Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample) OVERRIDE;
/// @}
private:
// Generate Audio/Video Track atom.

View File

@ -3,13 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// This class defines the MP4 Segmenter which is responsible for organizing
// MP4 fragments into segments/subsegments and package into a MP4 file.
// Inherited by MP4GeneralSegmenter and MP4VODSegmenter. MP4VODSegmenter defines
// the segmenter for DASH Video-On-Demand with a single segment for each media
// presentation while MP4GeneralSegmenter handles all other cases including
// DASH live profile.
#ifndef MEDIA_MP4_MP4_SEGMENTER_H_
#define MEDIA_MP4_MP4_SEGMENTER_H_
@ -39,18 +32,24 @@ struct Movie;
struct MovieFragment;
struct SegmentIndex;
/// This class defines the MP4 Segmenter which is responsible for organizing
/// MP4 fragments into segments/subsegments and package them into a MP4 file.
/// Inherited by MP4GeneralSegmenter and MP4VODSegmenter. MP4VODSegmenter
/// defines the segmenter for DASH Video-On-Demand with a single segment for
/// each media presentation while MP4GeneralSegmenter handles all other cases
/// including DASH live profile.
class MP4Segmenter {
public:
// Caller transfers the ownership of |ftyp| and |moov| to this class.
MP4Segmenter(const MuxerOptions& options,
scoped_ptr<FileType> ftyp,
scoped_ptr<Movie> moov);
virtual ~MP4Segmenter();
// Initialize the segmenter. Caller retains the ownership of
// |encryptor_source|. |encryptor_source| can be NULL.
// Calling other public methods of this class without this method returning
// Status::OK, results in an undefined behavior.
/// 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);
@ -60,19 +59,17 @@ class MP4Segmenter {
virtual Status AddSample(const MediaStream* stream,
scoped_refptr<MediaSample> sample);
// Returns false if it does not apply.
// If it has an initialization byte range this returns true and set |offset|
// and |size|, otherwise returns false.
/// @return true if there is an initialization range, while setting @a offset
/// and @a size; or false if initialization range does not apply.
virtual bool GetInitRange(size_t* offset, size_t* size) = 0;
// Returns false if it does not apply.
// If it has an index byte range this returns true and set |offset| and
// |size|, otherwise returns false.
/// @return true if there is an index byte range, while setting @a offset
/// and @a size; or false if index byte range does not apply.
virtual bool GetIndexRange(size_t* offset, size_t* size) = 0;
uint32 GetReferenceTimeScale() const;
// Returns the total length, in seconds, of segmented media files.
/// @return The total length, in seconds, of segmented media files.
double GetDuration() const;
protected:

View File

@ -3,18 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Segmenter for MP4 Dash Video-On-Demand profile. A single MP4 file with a
// single segment is created, i.e. with only one SIDX box. The generated media
// file could contain one to many subsegments with subsegment duration
// defined by|MuxerOptions.segment_duration|. A subsegment could contain one
// to many fragments with fragment duration defined by
// |MuxerOptions.fragment_duration|. The actual subsegment or fragment duration
// may not match the defined duration exactly but in a best effort basic, i.e.
// the segmenter tries to end subsegment/fragment at the first sample with
// overall subsegment/fragment duration not smaller than defined duration and
// yet meet SAP requirements. VOD segmenter ignores
// |MuxerOptions.num_subsegments_per_sidx|.
#ifndef MEDIA_MP4_MP4_VOD_SEGMENTER_H_
#define MEDIA_MP4_MP4_VOD_SEGMENTER_H_
@ -25,15 +13,26 @@
namespace media {
namespace mp4 {
/// Segmenter for MP4 Dash Video-On-Demand profile. A single MP4 file with a
/// single segment is created, i.e. with only one SIDX box. The generated media
/// file can contain one or many subsegments with subsegment duration
/// defined by @b MuxerOptions.segment_duration. A subsegment can contain one
/// or many fragments with fragment duration defined by @b
/// MuxerOptions.fragment_duration. The actual subsegment or fragment duration
/// may not match the requested duration exactly, but will be approximated. That
/// is, the segmenter tries to end subsegment/fragment at the first sample with
/// overall subsegment/fragment duration not smaller than defined duration and
/// yet meet SAP requirements. VOD segmenter ignores @b
/// MuxerOptions.num_subsegments_per_sidx.
class MP4VODSegmenter : public MP4Segmenter {
public:
// Caller transfers the ownership of |ftyp| and |moov| to this class.
MP4VODSegmenter(const MuxerOptions& options,
scoped_ptr<FileType> ftyp,
scoped_ptr<Movie> moov);
virtual ~MP4VODSegmenter();
// MP4Segmenter implementations.
/// @name MP4Segmenter implementation overrides.
/// @{
virtual Status Initialize(EncryptorSource* encryptor_source,
double clear_lead_in_seconds,
const std::vector<MediaStream*>& streams) OVERRIDE;
@ -41,6 +40,7 @@ class MP4VODSegmenter : public MP4Segmenter {
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;

View File

@ -10,42 +10,46 @@
namespace media {
// A wrapper around a ByteQueue which maintains a notion of a
// monotonically-increasing offset. All buffer access is done by passing these
// offsets into this class, going some way towards preventing the proliferation
// of many different meanings of "offset", "head", etc.
/// Wrapper around ByteQueue, which encapsulates the notion of a
/// monotonically-increasing byte offset. All buffer access is done by passing
/// these offsets into this class, reducing the proliferation of many different
/// meanings of "offset", "head", etc.
class OffsetByteQueue {
public:
OffsetByteQueue();
~OffsetByteQueue();
// These work like their underlying ByteQueue counterparts.
/// @name These work like their underlying ByteQueue counterparts.
/// @{
void Reset();
void Push(const uint8* buf, int size);
void Peek(const uint8** buf, int* size);
void Pop(int count);
/// @}
// Sets |buf| to point at the first buffered byte corresponding to |offset|,
// and |size| to the number of bytes available starting from that offset.
//
// It is an error if the offset is before the current head. It's not an error
// if the current offset is beyond tail(), but you will of course get back
// a null |buf| and a |size| of zero.
/// Set @a buf to point at the first buffered byte corresponding to @a offset,
/// and @a size to the number of bytes available starting from that offset.
///
/// It is an error if the offset is before the current head. It's not an error
/// if the current offset is beyond tail(), but you will of course get back
/// a null @a buf and a @a size of zero.
void PeekAt(int64 offset, const uint8** buf, int* size);
// Marks the bytes up to (but not including) |max_offset| as ready for
// deletion. This is relatively inexpensive, but will not necessarily reduce
// the resident buffer size right away (or ever).
//
// Returns true if the full range of bytes were successfully trimmed,
// including the case where |max_offset| is less than the current head.
// Returns false if |max_offset| > tail() (although all bytes currently
// buffered are still cleared).
/// Mark the bytes up to (but not including) @a max_offset as ready for
/// deletion. This is relatively inexpensive, but will not necessarily reduce
/// the resident buffer size right away (or ever).
///
/// @return true if the full range of bytes were successfully trimmed,
/// including the case where @a max_offset is less than the current
/// head.
/// @return false if @a max_offset > tail() (although all bytes currently
/// buffered are still cleared).
bool Trim(int64 max_offset);
// The head and tail positions, in terms of the file's absolute offsets.
// tail() is an exclusive bound.
/// @return The head position, in terms of the file's absolute offset.
int64 head() { return head_; }
/// @return The tail position (exclusive), in terms of the file's absolute
/// offset.
int64 tail() { return head_ + size_; }
private:

View File

@ -3,9 +3,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//
// Implements a wrapper around Sync Sample Box (STSS) to iterate through the
// compressed table.
#ifndef MEDIA_MP4_SYNC_SAMPLE_ITERATOR_H_
#define MEDIA_MP4_SYNC_SAMPLE_ITERATOR_H_
@ -17,20 +14,22 @@
namespace media {
namespace mp4 {
// Sample to Chunk Box (STSS) Iterator.
/// Sync sample box (STSS) iterator used to iterate through the entries within
/// the compressed table.
class SyncSampleIterator {
public:
/// Create a new SyncSampleIterator from sync sample box.
explicit SyncSampleIterator(const SyncSample& sync_sample);
~SyncSampleIterator();
// Advance the properties to refer to the next sample. Return status
// indicating whether the sample is still valid.
/// Advance to the next sample.
/// @return true if not past the last sample, false otherwise.
bool AdvanceSample();
// Return whether the current sample is a sync sample.
/// @return true if the current sample is a sync sample, false otherwise.
bool IsSyncSample() const;
// Return whether sample (1-based) is a sync sample.
/// @return true if @a sample (1-based) is a sync sample, false otherwise.
bool IsSyncSample(uint32 sample) const;
private:

View File

@ -22,66 +22,82 @@ struct TrackRunInfo;
class TrackRunIterator {
public:
// Create a new TrackRunIterator. A reference to |moov| will be retained for
// the lifetime of this object.
/// Create a new TrackRunIterator from movie box.
/// @param moov should not be NULL.
explicit TrackRunIterator(const Movie* moov);
~TrackRunIterator();
// For non-fragmented mp4, moov contains all the chunks information; This
// function sets up the iterator to handle all the chunks.
// For fragmented mp4, chunk and sample information are generally contained
// in moof. This function is a no-op in this case. Init(moof) will be called
// later after parsing moof.
/// For non-fragmented mp4, moov contains all the chunk information; This
/// function sets up the iterator to access all the chunks.
/// For fragmented mp4, chunk and sample information are generally contained
/// in moof. This function is a no-op in this case. Init(moof) will be called
/// later after parsing moof.
/// @return true on success, false otherwise.
bool Init();
// Sets up the iterator to handle all the runs from the current fragment.
/// Set up the iterator to handle all the runs from the current fragment.
/// @return true on success, false otherwise.
bool Init(const MovieFragment& moof);
// Returns true if the properties of the current run or sample are valid.
/// @return true if the iterator points to a valid run, false if past the
/// last run.
bool IsRunValid() const;
/// @return true if the iterator points to a valid sample, false if past the
/// last sample.
bool IsSampleValid() const;
// Advance the properties to refer to the next run or sample. Requires that
// the current sample be valid.
/// Advance iterator to the next run. Require that the iterator point to a
/// valid run.
void AdvanceRun();
/// Advance iterator to the next sample. Require that the iterator point to a
/// valid sample.
void AdvanceSample();
// Returns true if this track run has auxiliary information and has not yet
// been cached. Only valid if IsRunValid().
/// @return true if this track run has auxiliary information and has not yet
/// been cached. Only valid if IsRunValid().
bool AuxInfoNeedsToBeCached();
// Caches the CENC data from the given buffer. |buf| must be a buffer starting
// at the offset given by cenc_offset(), with a |size| of at least
// cenc_size(). Returns true on success, false on error.
/// Caches the CENC data from the given buffer.
/// @param buf must be a buffer starting at the offset given by cenc_offset().
/// @param size must be at least cenc_size().
/// @return true on success, false on error.
bool CacheAuxInfo(const uint8* buf, int size);
// Returns the maximum buffer location at which no data earlier in the stream
// will be required in order to read the current or any subsequent sample. You
// may clear all data up to this offset before reading the current sample
// safely. Result is in the same units as offset() (for Media Source this is
// in bytes past the the head of the MOOF box).
/// @return the maximum buffer location at which no data earlier in the
/// stream will be required in order to read the current or any
/// subsequent sample. You may clear all data up to this offset
/// before reading the current sample safely. Result is in the same
/// units as offset() (for Media Source this is in bytes past the
/// head of the MOOF box).
int64 GetMaxClearOffset();
// Property of the current run. Only valid if IsRunValid().
/// @name Properties of the current run. Only valid if IsRunValid().
/// @{
uint32 track_id() const;
int64 aux_info_offset() const;
int aux_info_size() const;
bool is_encrypted() const;
bool is_audio() const;
// Only one is valid, based on the value of is_audio().
/// @}
/// @name Only one is valid, based on the value of is_audio().
/// @{
const AudioSampleEntry& audio_description() const;
const VideoSampleEntry& video_description() const;
/// @}
// Properties of the current sample. Only valid if IsSampleValid().
/// @name Properties of the current sample. Only valid if IsSampleValid().
/// @{
int64 sample_offset() const;
int sample_size() const;
int64 dts() const;
int64 cts() const;
int64 duration() const;
bool is_keyframe() const;
/// @}
// Only call when is_encrypted() is true and AuxInfoNeedsToBeCached() is
// false. Result is owned by caller.
/// Only call when is_encrypted() is true and AuxInfoNeedsToBeCached() is
/// false. Result is owned by caller.
scoped_ptr<DecryptConfig> GetDecryptConfig();
private: