mp4file.cpp
来自「faac-1.25.rar音频编解码器demo」· C++ 代码 · 共 2,476 行 · 第 1/5 页
CPP
2,476 行
m_pRootAtom->BeginWrite();
}
void MP4File::FinishWrite()
{
// for all tracks, flush chunking buffers
for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
ASSERT(m_pTracks[i]);
m_pTracks[i]->FinishWrite();
}
// ask root atom to write
m_pRootAtom->FinishWrite();
// check if file shrunk, e.g. we deleted a track
if (GetSize() < m_orgFileSize) {
// just use a free atom to mark unused space
// MP4Optimize() should be used to clean up this space
MP4Atom* pFreeAtom = MP4Atom::CreateAtom("free");
ASSERT(pFreeAtom);
pFreeAtom->SetFile(this);
int64_t size = m_orgFileSize - (m_fileSize + 8);
if (size < 0) size = 0;
pFreeAtom->SetSize(size);
pFreeAtom->Write();
delete pFreeAtom;
}
}
MP4Duration MP4File::UpdateDuration(MP4Duration duration)
{
MP4Duration currentDuration = GetDuration();
if (duration > currentDuration) {
SetDuration(duration);
return duration;
}
return currentDuration;
}
void MP4File::Dump(FILE* pDumpFile, bool dumpImplicits)
{
if (pDumpFile == NULL) {
pDumpFile = stdout;
}
fprintf(pDumpFile, "Dumping %s meta-information...\n", m_fileName);
m_pRootAtom->Dump(pDumpFile, 0, dumpImplicits);
}
void MP4File::Close()
{
if (m_mode == 'w') {
SetIntegerProperty("moov.mvhd.modificationTime",
MP4GetAbsTimestamp());
FinishWrite();
}
fclose(m_pFile);
m_pFile = NULL;
}
const char* MP4File::TempFileName()
{
// there are so many attempts in libc to get this right
// that for portablity reasons, it's best just to roll our own
#ifndef _WIN32
static char tempFileName[64];
u_int32_t i;
for (i = getpid(); i < 0xFFFFFFFF; i++) {
sprintf(tempFileName, "./tmp%u.mp4", i);
if (access(tempFileName, F_OK) != 0) {
break;
}
}
if (i == 0xFFFFFFFF) {
throw new MP4Error("can't create temporary file", "TempFileName");
}
#else
static char tempFileName[MAX_PATH + 3];
GetTempFileName(".", // dir. for temp. files
"mp4", // temp. filename prefix
0, // create unique name
tempFileName); // buffer for name
#endif
return tempFileName;
}
void MP4File::Rename(const char* oldFileName, const char* newFileName)
{
int rc;
#ifdef _WIN32
rc = remove(newFileName);
if (rc == 0) {
rc = rename(oldFileName, newFileName);
}
#else
rc = rename(oldFileName, newFileName);
#endif
if (rc != 0) {
throw new MP4Error(errno, "can't overwrite existing file", "Rename");
}
}
void MP4File::ProtectWriteOperation(char* where)
{
if (m_mode == 'r') {
throw new MP4Error("operation not permitted in read mode", where);
}
}
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, bool shallHaveIods)
{
MP4DescriptorProperty* pDescriptorProperty = NULL;
m_pRootAtom->FindProperty("moov.iods.esIds",
(MP4Property**)&pDescriptorProperty);
if (shallHaveIods) {
ASSERT(pDescriptorProperty);
} else {
if (!pDescriptorProperty) {
return;
}
}
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)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?