2014-02-14 23:21:05 +00:00
|
|
|
// Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// 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
|
2013-11-22 21:24:25 +00:00
|
|
|
|
|
|
|
#ifndef MEDIA_MP4_BOX_BUFFER_H_
|
|
|
|
#define MEDIA_MP4_BOX_BUFFER_H_
|
|
|
|
|
|
|
|
#include "base/compiler_specific.h"
|
|
|
|
#include "media/base/buffer_writer.h"
|
|
|
|
#include "media/mp4/box.h"
|
|
|
|
#include "media/mp4/box_reader.h"
|
|
|
|
|
|
|
|
namespace media {
|
|
|
|
namespace mp4 {
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// 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.
|
2013-11-22 21:24:25 +00:00
|
|
|
class BoxBuffer {
|
|
|
|
public:
|
2014-01-23 22:34:39 +00:00
|
|
|
/// Create a reader version of the BoxBuffer.
|
|
|
|
/// @param reader should not be NULL.
|
2013-11-22 21:24:25 +00:00
|
|
|
explicit BoxBuffer(BoxReader* reader) : reader_(reader), writer_(NULL) {
|
|
|
|
DCHECK(reader);
|
|
|
|
}
|
2014-01-23 22:34:39 +00:00
|
|
|
/// Create a writer version of the BoxBuffer.
|
|
|
|
/// @param writer should not be NULL.
|
2013-11-22 21:24:25 +00:00
|
|
|
explicit BoxBuffer(BufferWriter* writer) : reader_(NULL), writer_(writer) {
|
|
|
|
DCHECK(writer);
|
|
|
|
}
|
|
|
|
~BoxBuffer() {}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @return true for reader, false for writer.
|
2013-11-22 21:24:25 +00:00
|
|
|
bool Reading() const { return reader_ != NULL; }
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @return Current read/write position. In read mode, this is the current
|
|
|
|
/// read position. In write mode, it is the same as Size().
|
2013-11-22 21:24:25 +00:00
|
|
|
size_t Pos() const {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->pos();
|
|
|
|
return writer_->Size();
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @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.
|
2013-11-22 21:24:25 +00:00
|
|
|
size_t Size() const {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->size();
|
|
|
|
return writer_->Size();
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @name Read/write integers of various sizes and signedness.
|
|
|
|
/// @{
|
2013-11-22 21:24:25 +00:00
|
|
|
bool ReadWriteUInt8(uint8* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read1(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteUInt16(uint16* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read2(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteUInt32(uint32* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read4(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteUInt64(uint64* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read8(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteInt16(int16* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read2s(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteInt32(int32* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read4s(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteInt64(int64* v) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->Read8s(v);
|
|
|
|
writer_->AppendInt(*v);
|
|
|
|
return true;
|
|
|
|
}
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @}
|
2013-11-22 21:24:25 +00:00
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// 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.
|
2013-11-22 21:24:25 +00:00
|
|
|
bool ReadWriteUInt64NBytes(uint64* v, size_t num_bytes) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->ReadNBytesInto8(v, num_bytes);
|
|
|
|
writer_->AppendNBytes(*v, num_bytes);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteInt64NBytes(int64* v, size_t num_bytes) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->ReadNBytesInto8s(v, num_bytes);
|
|
|
|
writer_->AppendNBytes(*v, num_bytes);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteVector(std::vector<uint8>* vector, size_t count) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->ReadToVector(vector, count);
|
|
|
|
DCHECK_EQ(vector->size(), count);
|
|
|
|
writer_->AppendVector(*vector);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool ReadWriteFourCC(FourCC* fourcc) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->ReadFourCC(fourcc);
|
|
|
|
writer_->AppendInt(static_cast<uint32>(*fourcc));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// Prepare child boxes for reading/writing.
|
|
|
|
/// @return true on success, false otherwise.
|
2013-11-22 21:24:25 +00:00
|
|
|
bool PrepareChildren() {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->ScanChildren();
|
|
|
|
// NOP in write mode.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// Read/write child box.
|
|
|
|
/// @return true on success, false otherwise.
|
2013-11-22 21:24:25 +00:00
|
|
|
bool ReadWriteChild(Box* box) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->ReadChild(box);
|
|
|
|
// The box is mandatory, i.e. the box size should not be 0.
|
|
|
|
DCHECK_NE(0, box->atom_size);
|
|
|
|
CHECK(box->ReadWrite(this));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// Read/write child box if exists.
|
|
|
|
/// @return true on success, false otherwise.
|
2013-11-22 21:24:25 +00:00
|
|
|
bool TryReadWriteChild(Box* box) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->TryReadChild(box);
|
|
|
|
// The box is optional, i.e. it can be skipped if the box size is 0.
|
|
|
|
if (box->atom_size != 0)
|
|
|
|
CHECK(box->ReadWrite(this));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @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.
|
2013-11-22 21:24:25 +00:00
|
|
|
bool IgnoreBytes(size_t num_bytes) {
|
|
|
|
if (reader_)
|
|
|
|
return reader_->SkipBytes(num_bytes);
|
|
|
|
std::vector<uint8> vector(num_bytes, 0);
|
|
|
|
writer_->AppendVector(vector);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @return A pointer to the inner reader object.
|
2013-11-22 21:24:25 +00:00
|
|
|
BoxReader* reader() { return reader_; }
|
2014-01-23 22:34:39 +00:00
|
|
|
/// @return A pointer to the inner writer object.
|
2013-11-22 21:24:25 +00:00
|
|
|
BufferWriter* writer() { return writer_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
BoxReader* reader_;
|
|
|
|
BufferWriter* writer_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(BoxBuffer);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mp4
|
|
|
|
} // namespace media
|
|
|
|
|
|
|
|
#endif // MEDIA_MP4_BOX_BUFFER_H_
|