Files
Bento4/Source/C++/Core/Ap4TrakAtom.cpp
2015-05-22 11:38:06 -07:00

394 lines
13 KiB
C++

/*****************************************************************
|
| AP4 - trak Atoms
|
| Copyright 2002-2008 Axiomatic Systems, LLC
|
|
| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
|
| Unless you have obtained Bento4 under a difference license,
| this version of Bento4 is Bento4|GPL.
| Bento4|GPL is free software; you can redistribute it and/or modify
| it under the terms of the GNU General Public License as published by
| the Free Software Foundation; either version 2, or (at your option)
| any later version.
|
| Bento4|GPL is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with Bento4|GPL; see the file COPYING. If not, write to the
| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
| 02111-1307, USA.
|
****************************************************************/
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include "Ap4TrakAtom.h"
#include "Ap4MdhdAtom.h"
#include "Ap4TkhdAtom.h"
#include "Ap4HdlrAtom.h"
#include "Ap4VmhdAtom.h"
#include "Ap4SmhdAtom.h"
#include "Ap4HmhdAtom.h"
#include "Ap4NmhdAtom.h"
#include "Ap4SthdAtom.h"
#include "Ap4DrefAtom.h"
#include "Ap4UrlAtom.h"
#include "Ap4StcoAtom.h"
#include "Ap4Co64Atom.h"
#include "Ap4AtomFactory.h"
#include "Ap4SampleTable.h"
#include "Ap4Utils.h"
/*----------------------------------------------------------------------
| dynamic cast support
+---------------------------------------------------------------------*/
AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_TrakAtom)
/*----------------------------------------------------------------------
| AP4_TrakAtom::AP4_TrakAtom
+---------------------------------------------------------------------*/
AP4_TrakAtom::AP4_TrakAtom(AP4_SampleTable* sample_table,
AP4_Atom::Type hdlr_type,
const char* hdlr_name,
AP4_UI32 track_id,
AP4_UI32 creation_time,
AP4_UI32 modification_time,
AP4_UI64 track_duration,
AP4_UI32 media_time_scale,
AP4_UI64 media_duration,
AP4_UI16 volume,
const char* language,
AP4_UI32 width,
AP4_UI32 height,
AP4_UI16 layer,
AP4_UI16 alternate_group,
const AP4_SI32* matrix) :
AP4_ContainerAtom(AP4_ATOM_TYPE_TRAK)
{
AP4_Result result;
// create a tkhd atom
m_TkhdAtom = new AP4_TkhdAtom(creation_time,
modification_time,
track_id,
track_duration,
volume,
width,
height,
layer,
alternate_group,
matrix);
// create an edts
// create a mdia atom
AP4_ContainerAtom* mdia = new AP4_ContainerAtom(AP4_ATOM_TYPE_MDIA);
// create a hdlr atom for the mdia atom
AP4_HdlrAtom* hdlr = new AP4_HdlrAtom(hdlr_type, hdlr_name);
// create a minf atom
AP4_ContainerAtom* minf = new AP4_ContainerAtom(AP4_ATOM_TYPE_MINF);
// create a media header atom for minf (vmhd, smhd, hmhd or nmhd)
AP4_Atom* minf_header;
switch (hdlr_type) {
case AP4_HANDLER_TYPE_VIDE:
minf_header = new AP4_VmhdAtom(0, 0, 0, 0);
break;
case AP4_HANDLER_TYPE_SOUN:
minf_header = new AP4_SmhdAtom(0);
break;
case AP4_HANDLER_TYPE_SUBT:
minf_header = new AP4_SthdAtom();
break;
default:
minf_header = new AP4_NmhdAtom();
break;
}
// create a dinf atom for minf
AP4_ContainerAtom* dinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_DINF);
// create a url atom as a ref for dref
AP4_Atom* url = new AP4_UrlAtom(); // local ref
// create a dref atom for dinf
AP4_DrefAtom* dref = new AP4_DrefAtom(&url, 1);
// create a stbl atom for minf
AP4_ContainerAtom* stbl;
result = sample_table->GenerateStblAtom(stbl);
if (AP4_FAILED(result)) stbl = NULL;
// populate the dinf atom
dinf->AddChild(dref);
// populate the minf atom
minf->AddChild(minf_header);
minf->AddChild(dinf);
if (stbl) minf->AddChild(stbl);
// create a mdhd atom for the mdia atom
m_MdhdAtom = new AP4_MdhdAtom(creation_time,
modification_time,
media_time_scale,
media_duration,
language);
// populate the mdia atom
mdia->AddChild(m_MdhdAtom);
mdia->AddChild(hdlr);
mdia->AddChild(minf);
// attach the children
AddChild(m_TkhdAtom);
AddChild(mdia);
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::AP4_TrakAtom
+---------------------------------------------------------------------*/
AP4_TrakAtom::AP4_TrakAtom(AP4_UI32 size,
AP4_ByteStream& stream,
AP4_AtomFactory& atom_factory) :
AP4_ContainerAtom(AP4_ATOM_TYPE_TRAK, size, false, stream, atom_factory)
{
m_TkhdAtom = AP4_DYNAMIC_CAST(AP4_TkhdAtom, FindChild("tkhd"));
m_MdhdAtom = AP4_DYNAMIC_CAST(AP4_MdhdAtom, FindChild("mdia/mdhd"));
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetId
+---------------------------------------------------------------------*/
AP4_UI32
AP4_TrakAtom::GetId()
{
return m_TkhdAtom?m_TkhdAtom->GetTrackId():0;
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetId
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetId(AP4_UI32 id)
{
if (m_TkhdAtom) {
m_TkhdAtom->SetTrackId(id);
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetMediaTimeScale
+---------------------------------------------------------------------*/
AP4_UI32
AP4_TrakAtom::GetMediaTimeScale()
{
return m_MdhdAtom?m_MdhdAtom->GetTimeScale():0;
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetMediaTimeScale
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetMediaTimeScale(AP4_UI32 timescale)
{
if (m_MdhdAtom) {
m_MdhdAtom->SetTimeScale(timescale);
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetDuration
+---------------------------------------------------------------------*/
AP4_UI64
AP4_TrakAtom::GetDuration()
{
return m_TkhdAtom?m_TkhdAtom->GetDuration():0;
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetDuration
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetDuration(AP4_UI64 duration)
{
if (m_TkhdAtom) {
m_TkhdAtom->SetDuration(duration);
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetMediaDuration
+---------------------------------------------------------------------*/
AP4_UI64
AP4_TrakAtom::GetMediaDuration()
{
return m_MdhdAtom?m_MdhdAtom->GetDuration():0;
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetMediaDuration
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetMediaDuration(AP4_UI32 duration)
{
if (m_MdhdAtom) {
m_MdhdAtom->SetDuration(duration);
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetWidth
+---------------------------------------------------------------------*/
AP4_UI32
AP4_TrakAtom::GetWidth()
{
return m_TkhdAtom?m_TkhdAtom->GetWidth():0;
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetWidth
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetWidth(AP4_UI32 width)
{
if (m_TkhdAtom) {
m_TkhdAtom->SetWidth(width);
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetHeight
+---------------------------------------------------------------------*/
AP4_UI32
AP4_TrakAtom::GetHeight()
{
return m_TkhdAtom?m_TkhdAtom->GetHeight():0;
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetHeight
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetHeight(AP4_UI32 height)
{
if (m_TkhdAtom) {
m_TkhdAtom->SetHeight(height);
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::AdjustChunkOffsets
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::AdjustChunkOffsets(AP4_SI64 delta)
{
AP4_Atom* atom;
if ((atom = FindChild("mdia/minf/stbl/stco")) != NULL) {
AP4_StcoAtom* stco = AP4_DYNAMIC_CAST(AP4_StcoAtom, atom);
return stco->AdjustChunkOffsets((int)delta);
} else if ((atom = FindChild("mdia/minf/stbl/co64")) != NULL) {
AP4_Co64Atom* co64 = AP4_DYNAMIC_CAST(AP4_Co64Atom, atom);
return co64->AdjustChunkOffsets(delta);
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::GetChunkOffsets
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::GetChunkOffsets(AP4_Array<AP4_UI64>& chunk_offsets)
{
AP4_Atom* atom;
if ((atom = FindChild("mdia/minf/stbl/stco")) != NULL) {
AP4_StcoAtom* stco = AP4_DYNAMIC_CAST(AP4_StcoAtom, atom);
if (stco == NULL) return AP4_ERROR_INTERNAL;
AP4_Cardinal stco_chunk_count = stco->GetChunkCount();
const AP4_UI32* stco_chunk_offsets = stco->GetChunkOffsets();
chunk_offsets.SetItemCount(stco_chunk_count);
for (unsigned int i=0; i<stco_chunk_count; i++) {
chunk_offsets[i] = stco_chunk_offsets[i];
}
return AP4_SUCCESS;
} else if ((atom = FindChild("mdia/minf/stbl/co64")) != NULL) {
AP4_Co64Atom* co64 = AP4_DYNAMIC_CAST(AP4_Co64Atom, atom);
if (co64 == NULL) return AP4_ERROR_INTERNAL;
AP4_Cardinal co64_chunk_count = co64->GetChunkCount();
const AP4_UI64* co64_chunk_offsets = co64->GetChunkOffsets();
chunk_offsets.SetItemCount(co64_chunk_count);
for (unsigned int i=0; i<co64_chunk_count; i++) {
chunk_offsets[i] = co64_chunk_offsets[i];
}
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}
/*----------------------------------------------------------------------
| AP4_TrakAtom::SetChunkOffsets
+---------------------------------------------------------------------*/
AP4_Result
AP4_TrakAtom::SetChunkOffsets(const AP4_Array<AP4_UI64>& chunk_offsets)
{
AP4_Atom* atom;
if ((atom = FindChild("mdia/minf/stbl/stco")) != NULL) {
AP4_StcoAtom* stco = AP4_DYNAMIC_CAST(AP4_StcoAtom, atom);
if (stco == NULL) return AP4_ERROR_INTERNAL;
AP4_Cardinal stco_chunk_count = stco->GetChunkCount();
AP4_UI32* stco_chunk_offsets = stco->GetChunkOffsets();
if (stco_chunk_count > chunk_offsets.ItemCount()) {
return AP4_ERROR_OUT_OF_RANGE;
}
for (unsigned int i=0; i<stco_chunk_count; i++) {
stco_chunk_offsets[i] = (AP4_UI32)chunk_offsets[i];
}
return AP4_SUCCESS;
} else if ((atom = FindChild("mdia/minf/stbl/co64")) != NULL) {
AP4_Co64Atom* co64 = AP4_DYNAMIC_CAST(AP4_Co64Atom, atom);
if (co64 == NULL) return AP4_ERROR_INTERNAL;
AP4_Cardinal co64_chunk_count = co64->GetChunkCount();
AP4_UI64* co64_chunk_offsets = co64->GetChunkOffsets();
if (co64_chunk_count > chunk_offsets.ItemCount()) {
return AP4_ERROR_OUT_OF_RANGE;
}
for (unsigned int i=0; i<co64_chunk_count; i++) {
co64_chunk_offsets[i] = chunk_offsets[i];
}
return AP4_SUCCESS;
} else {
return AP4_ERROR_INVALID_STATE;
}
}