📄 mp4file.cpp
字号:
}
MP4Track* MP4File::GetTrack(MP4TrackId trackId)
{
return m_pTracks[FindTrackIndex(trackId)];
}
MP4Atom* MP4File::FindAtom(const char* name)
{
MP4Atom* pAtom = NULL;
if (!name || !strcmp(name, "")) {
pAtom = m_pRootAtom;
} else {
pAtom = m_pRootAtom->FindAtom(name);
}
return pAtom;
}
MP4Atom* MP4File::AddChildAtom(
const char* parentName,
const char* childName)
{
return AddChildAtom(FindAtom(parentName), childName);
}
MP4Atom* MP4File::AddChildAtom(
MP4Atom* pParentAtom,
const char* childName)
{
return InsertChildAtom(pParentAtom, childName,
pParentAtom->GetNumberOfChildAtoms());
}
MP4Atom* MP4File::InsertChildAtom(
const char* parentName,
const char* childName,
u_int32_t index)
{
return InsertChildAtom(FindAtom(parentName), childName, index);
}
MP4Atom* MP4File::InsertChildAtom(
MP4Atom* pParentAtom,
const char* childName,
u_int32_t index)
{
MP4Atom* pChildAtom = MP4Atom::CreateAtom(childName);
ASSERT(pParentAtom);
pParentAtom->InsertChildAtom(pChildAtom, index);
pChildAtom->Generate();
return pChildAtom;
}
MP4Atom* MP4File::AddDescendantAtoms(
const char* ancestorName,
const char* descendantNames)
{
return AddDescendantAtoms(FindAtom(ancestorName), descendantNames);
}
MP4Atom* MP4File::AddDescendantAtoms(
MP4Atom* pAncestorAtom, const char* descendantNames)
{
ASSERT(pAncestorAtom);
MP4Atom* pParentAtom = pAncestorAtom;
MP4Atom* pChildAtom = NULL;
while (true) {
char* childName = MP4NameFirst(descendantNames);
if (childName == NULL) {
break;
}
descendantNames = MP4NameAfterFirst(descendantNames);
pChildAtom = pParentAtom->FindChildAtom(childName);
if (pChildAtom == NULL) {
pChildAtom = AddChildAtom(pParentAtom, childName);
}
pParentAtom = pChildAtom;
MP4Free(childName);
}
return pChildAtom;
}
bool MP4File::FindProperty(const char* name,
MP4Property** ppProperty, u_int32_t* pIndex)
{
if (pIndex) {
*pIndex = 0; // set the default answer for index
}
return m_pRootAtom->FindProperty(name, ppProperty, pIndex);
}
void MP4File::FindIntegerProperty(const char* name,
MP4Property** ppProperty, u_int32_t* pIndex)
{
if (!FindProperty(name, ppProperty, pIndex)) {
throw new MP4Error("no such property - %s", "MP4File::FindIntegerProperty", name);
}
switch ((*ppProperty)->GetType()) {
case Integer8Property:
case Integer16Property:
case Integer24Property:
case Integer32Property:
case Integer64Property:
break;
default:
throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindIntegerProperty", name, (*ppProperty)->GetType());
}
}
u_int64_t MP4File::GetIntegerProperty(const char* name)
{
MP4Property* pProperty;
u_int32_t index;
FindIntegerProperty(name, &pProperty, &index);
return ((MP4IntegerProperty*)pProperty)->GetValue(index);
}
void MP4File::SetIntegerProperty(const char* name, u_int64_t value)
{
ProtectWriteOperation("SetIntegerProperty");
MP4Property* pProperty = NULL;
u_int32_t index = 0;
FindIntegerProperty(name, &pProperty, &index);
((MP4IntegerProperty*)pProperty)->SetValue(value, index);
}
void MP4File::FindFloatProperty(const char* name,
MP4Property** ppProperty, u_int32_t* pIndex)
{
if (!FindProperty(name, ppProperty, pIndex)) {
throw new MP4Error("no such property - %s", "MP4File::FindFloatProperty", name);
}
if ((*ppProperty)->GetType() != Float32Property) {
throw new MP4Error("type mismatch - property %s type %d",
"MP4File::FindFloatProperty",
name,
(*ppProperty)->GetType());
}
}
float MP4File::GetFloatProperty(const char* name)
{
MP4Property* pProperty;
u_int32_t index;
FindFloatProperty(name, &pProperty, &index);
return ((MP4Float32Property*)pProperty)->GetValue(index);
}
void MP4File::SetFloatProperty(const char* name, float value)
{
ProtectWriteOperation("SetFloatProperty");
MP4Property* pProperty;
u_int32_t index;
FindFloatProperty(name, &pProperty, &index);
((MP4Float32Property*)pProperty)->SetValue(value, index);
}
void MP4File::FindStringProperty(const char* name,
MP4Property** ppProperty, u_int32_t* pIndex)
{
if (!FindProperty(name, ppProperty, pIndex)) {
throw new MP4Error("no such property - %s", "MP4File::FindStringProperty", name);
}
if ((*ppProperty)->GetType() != StringProperty) {
throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindStringProperty",
name, (*ppProperty)->GetType());
}
}
const char* MP4File::GetStringProperty(const char* name)
{
MP4Property* pProperty;
u_int32_t index;
FindStringProperty(name, &pProperty, &index);
return ((MP4StringProperty*)pProperty)->GetValue(index);
}
void MP4File::SetStringProperty(const char* name, const char* value)
{
ProtectWriteOperation("SetStringProperty");
MP4Property* pProperty;
u_int32_t index;
FindStringProperty(name, &pProperty, &index);
((MP4StringProperty*)pProperty)->SetValue(value, index);
}
void MP4File::FindBytesProperty(const char* name,
MP4Property** ppProperty, u_int32_t* pIndex)
{
if (!FindProperty(name, ppProperty, pIndex)) {
throw new MP4Error("no such property %s", "MP4File::FindBytesProperty", name);
}
if ((*ppProperty)->GetType() != BytesProperty) {
throw new MP4Error("type mismatch - property %s - type %d", "MP4File::FindBytesProperty", name, (*ppProperty)->GetType());
}
}
void MP4File::GetBytesProperty(const char* name,
u_int8_t** ppValue, u_int32_t* pValueSize)
{
MP4Property* pProperty;
u_int32_t index;
FindBytesProperty(name, &pProperty, &index);
((MP4BytesProperty*)pProperty)->GetValue(ppValue, pValueSize, index);
}
void MP4File::SetBytesProperty(const char* name,
const u_int8_t* pValue, u_int32_t valueSize)
{
ProtectWriteOperation("SetBytesProperty");
MP4Property* pProperty;
u_int32_t index;
FindBytesProperty(name, &pProperty, &index);
((MP4BytesProperty*)pProperty)->SetValue(pValue, valueSize, index);
}
// track functions
MP4TrackId MP4File::AddTrack(const char* type, u_int32_t timeScale)
{
ProtectWriteOperation("AddTrack");
// create and add new trak atom
MP4Atom* pTrakAtom = AddChildAtom("moov", "trak");
// allocate a new track id
MP4TrackId trackId = AllocTrackId();
m_trakIds.Add(trackId);
// set track id
MP4Integer32Property* pInteger32Property = NULL;
pTrakAtom->FindProperty(
"trak.tkhd.trackId", (MP4Property**)&pInteger32Property);
ASSERT(pInteger32Property);
pInteger32Property->SetValue(trackId);
// set track type
const char* normType = MP4Track::NormalizeTrackType(type);
// sanity check for user defined types
if (strlen(normType) > 4) {
VERBOSE_WARNING(m_verbosity,
printf("AddTrack: type truncated to four characters\n"));
// StringProperty::SetValue() will do the actual truncation
}
MP4StringProperty* pStringProperty = NULL;
pTrakAtom->FindProperty(
"trak.mdia.hdlr.handlerType", (MP4Property**)&pStringProperty);
ASSERT(pStringProperty);
pStringProperty->SetValue(normType);
// set track time scale
pInteger32Property = NULL;
pTrakAtom->FindProperty(
"trak.mdia.mdhd.timeScale", (MP4Property**)&pInteger32Property);
ASSERT(pInteger32Property);
pInteger32Property->SetValue(timeScale ? timeScale : 1000);
// now have enough to create MP4Track object
MP4Track* pTrack = NULL;
if (!strcmp(normType, MP4_HINT_TRACK_TYPE)) {
pTrack = new MP4RtpHintTrack(this, pTrakAtom);
} else {
pTrack = new MP4Track(this, pTrakAtom);
}
m_pTracks.Add(pTrack);
// mark non-hint tracks as enabled
if (strcmp(normType, MP4_HINT_TRACK_TYPE)) {
SetTrackIntegerProperty(trackId, "tkhd.flags", 1);
}
// mark track as contained in this file
// LATER will provide option for external data references
AddDataReference(trackId, NULL);
return trackId;
}
void MP4File::AddTrackToIod(MP4TrackId trackId)
{
MP4DescriptorProperty* pDescriptorProperty = NULL;
m_pRootAtom->FindProperty("moov.iods.esIds",
(MP4Property**)&pDescriptorProperty);
ASSERT(pDescriptorProperty);
MP4Descriptor* pDescriptor =
pDescriptorProperty->AddDescriptor(MP4ESIDIncDescrTag);
ASSERT(pDescriptor);
MP4Integer32Property* pIdProperty = NULL;
pDescriptor->FindProperty("id",
(MP4Property**)&pIdProperty);
ASSERT(pIdProperty);
pIdProperty->SetValue(trackId);
}
void MP4File::RemoveTrackFromIod(MP4TrackId trackId)
{
MP4DescriptorProperty* pDescriptorProperty = NULL;
m_pRootAtom->FindProperty("moov.iods.esIds",
(MP4Property**)&pDescriptorProperty);
ASSERT(pDescriptorProperty);
for (u_int32_t i = 0; i < pDescriptorProperty->GetCount(); i++) {
static char name[32];
snprintf(name, sizeof(name), "esIds[%u].id", i);
MP4Integer32Property* pIdProperty = NULL;
pDescriptorProperty->FindProperty(name,
(MP4Property**)&pIdProperty);
ASSERT(pIdProperty);
if (pIdProperty->GetValue() == trackId) {
pDescriptorProperty->DeleteDescriptor(i);
break;
}
}
}
void MP4File::AddTrackToOd(MP4TrackId trackId)
{
if (!m_odTrackId) {
return;
}
AddTrackReference(MakeTrackName(m_odTrackId, "tref.mpod"), trackId);
}
void MP4File::RemoveTrackFromOd(MP4TrackId trackId)
{
if (!m_odTrackId) {
return;
}
RemoveTrackReference(MakeTrackName(m_odTrackId, "tref.mpod"), trackId);
}
void MP4File::GetTrackReferenceProperties(const char* trefName,
MP4Property** ppCountProperty, MP4Property** ppTrackIdProperty)
{
char propName[1024];
snprintf(propName, sizeof(propName), "%s.%s", trefName, "entryCount");
m_pRootAtom->FindProperty(propName, ppCountProperty);
ASSERT(*ppCountProperty);
snprintf(propName, sizeof(propName), "%s.%s", trefName, "entries.trackId");
m_pRootAtom->FindProperty(propName, ppTrackIdProperty);
ASSERT(*ppTrackIdProperty);
}
void MP4File::AddTrackReference(const char* trefName, MP4TrackId refTrackId)
{
MP4Integer32Property* pCountProperty = NULL;
MP4Integer32Property* pTrackIdProperty = NULL;
GetTrackReferenceProperties(trefName,
(MP4Property**)&pCountProperty,
(MP4Property**)&pTrackIdProperty);
pTrackIdProperty->AddValue(refTrackId);
pCountProperty->IncrementValue();
}
u_int32_t MP4File::FindTrackReference(const char* trefName,
MP4TrackId refTrackId)
{
MP4Integer32Property* pCountProperty = NULL;
MP4Integer32Property* pTrackIdProperty = NULL;
GetTrackReferenceProperties(trefName,
(MP4Property**)&pCountProperty,
(MP4Property**)&pTrackIdProperty);
for (u_int32_t i = 0; i < pCountProperty->GetValue(); i++) {
if (refTrackId == pTrackIdProperty->GetValue(i)) {
return i + 1; // N.B. 1 not 0 based index
}
}
return 0;
}
void MP4File::RemoveTrackReference(const char* trefName, MP4TrackId refTrackId)
{
MP4Integer32Property* pCountProperty = NULL;
MP4Integer32Property* pTrackIdProperty = NULL;
GetTrackReferenceProperties(trefName,
(MP4Property**)&pCountProperty,
(MP4Property**)&pTrackIdProperty);
for (u_int32_t i = 0; i < pCountProperty->GetValue(); i++) {
if (refTrackId == pTrackIdProperty->GetValue(i)) {
pTrackIdProperty->DeleteValue(i);
pCountProperty->IncrementValue(-1);
}
}
}
void MP4File::AddDataReference(MP4TrackId trackId, const char* url)
{
MP4Atom* pDrefAtom =
FindAtom(MakeTrackName(trackId, "mdia.minf.dinf.dref"));
ASSERT(pDrefAtom);
MP4Integer32Property* pCountProperty = NULL;
pDrefAtom->FindProperty("dref.entryCount",
(MP4Property**)&pCountProperty);
ASSERT(pCountProperty);
pCountProperty->IncrementValue();
MP4Atom* pUrlAtom = AddChildAtom(pDrefAtom, "url ");
if (url && url[0] != '\0') {
pUrlAtom->SetFlags(pUrlAtom->GetFlags() & 0xFFFFFE);
MP4StringProperty* pUrlProperty = NULL;
pUrlAtom->FindProperty("url .location",
(MP4Property**)&pUrlProperty);
ASSERT(pUrlProperty);
pUrlProperty->SetValue(url);
} else {
pUrlAtom->SetFlags(pUrlAtom->GetFlags() | 1);
}
}
MP4TrackId MP4File::AddSystemsTrack(const char* type)
{
const char* normType = MP4Track::NormalizeTrackType(type);
// TBD if user type, fix name to four chars, and warn
MP4TrackId trackId = AddTrack(type, MP4_MSECS_TIME_SCALE);
InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0);
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4s");
// stsd is a unique beast in that it has a count of the number
// of child atoms that needs to be incremented after we add the mp4s atom
MP4Integer32Property* pStsdCountProperty;
FindIntegerProperty(
MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
(MP4Property**)&pStsdCountProperty);
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4s.esds.ESID", trackId);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId",
MP4SystemsV1ObjectType);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.streamType",
ConvertTrackTypeToStreamType(normType));
return trackId;
}
MP4TrackId MP4File::AddODTrack()
{
// until a demonstrated need emerges
// we limit ourselves to one object description track
if (m_odTrackId != MP4_INVALID_TRACK_ID) {
throw new MP4Error("object description track already exists",
"AddObjectDescriptionTrack");
}
m_odTrackId = AddSystemsTrack(MP4_OD_TRACK_TYPE);
AddTrackToIod(m_odTrackId);
AddDescendantAtoms(MakeTrackName(m_odTrackId, NULL), "tref.mpod");
return m_odTrackId;
}
MP4TrackId MP4File::AddSceneTrack()
{
MP4TrackId trackId = AddSystemsTrack(MP4_SCENE_TRACK_TYPE);
AddTrackToIod(trackId);
AddTrackToOd(trackId);
return trackId;
}
MP4TrackId MP4File::AddAudioTrack(
u_int32_t timeScale,
MP4Duration sampleDuration,
u_int8_t audioType)
{
MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale);
AddTrackToOd(trackId);
SetTrackFloatProperty(trackId, "tkhd.volume", 1.0);
InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4a");
// stsd is a unique beast in that it has a count of the number
// of child atoms that needs to be incremented after we add the mp4a atom
MP4Integer32Property* pStsdCountProperty;
FindIntegerProperty(
MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
(MP4Property**)&pStsdCountProperty);
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4a.timeScale", timeScale);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4a.esds.ESID", trackId);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId",
audioType);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.streamType",
MP4AudioStreamType);
m_pTracks[FindTrackIndex(trackId)]->
SetFixedSampleDuration(sampleDuration);
return trackId;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -