mirror of
https://github.com/axiomatic-systems/Bento4.git
synced 2026-01-19 00:05:12 +08:00
394 lines
13 KiB
C++
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;
|
|
}
|
|
}
|