📄 mp4file.cpp
字号:
pTrack = new MP4RtpHintTrack(this, pTrakAtom);
} else {
pTrack = new MP4Track(this, pTrakAtom);
}
m_pTracks.Add(pTrack);
}
catch (MP4Error* e) {
VERBOSE_ERROR(m_verbosity, e->Print());
delete e;
}
// remember when we encounter the OD track
if (pTrack && !strcmp(pTrack->GetType(), MP4_OD_TRACK_TYPE)) {
if (m_odTrackId == MP4_INVALID_TRACK_ID) {
m_odTrackId = pTrackIdProperty->GetValue();
} else {
VERBOSE_READ(GetVerbosity(),
printf("Warning: multiple OD tracks present\n"));
}
}
} else {
m_trakIds.Add(0);
}
trackIndex++;
}
}
void MP4File::CacheProperties()
{
FindIntegerProperty("moov.mvhd.modificationTime",
(MP4Property**)&m_pModificationProperty);
FindIntegerProperty("moov.mvhd.timeScale",
(MP4Property**)&m_pTimeScaleProperty);
FindIntegerProperty("moov.mvhd.duration",
(MP4Property**)&m_pDurationProperty);
}
void MP4File::BeginWrite()
{
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);
pFreeAtom->SetSize((u_int64_t)MAX((int64_t)m_orgFileSize - ((int64_t)m_fileSize + 8), 0));
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();
}
#ifndef USE_FILE_CALLBACKS
fclose(m_pFile);
m_pFile = NULL;
#else
m_MP4fclose(m_userData);
#endif
}
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
remove(oldFileName);
#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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -