mp4file.cpp
来自「faac-1.25.rar音频编解码器demo」· C++ 代码 · 共 2,476 行 · 第 1/5 页
CPP
2,476 行
return trackId;
}
MP4TrackId MP4File::AddVideoTrack(
u_int32_t timeScale,
MP4Duration sampleDuration,
u_int16_t width,
u_int16_t height,
u_int8_t videoType)
{
MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
AddTrackToOd(trackId);
SetTrackFloatProperty(trackId, "tkhd.width", width);
SetTrackFloatProperty(trackId, "tkhd.height", height);
InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4v");
// 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 mp4v atom
MP4Integer32Property* pStsdCountProperty;
FindIntegerProperty(
MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
(MP4Property**)&pStsdCountProperty);
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4v.width", width);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4v.height", height);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4v.esds.ESID",
#if 0
// note - for a file, these values need to
// be 0 - wmay - 04/16/2003
trackId
#else
0
#endif
);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId",
videoType);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.streamType",
MP4VisualStreamType);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsz.sampleSize", sampleDuration);
m_pTracks[FindTrackIndex(trackId)]->
SetFixedSampleDuration(sampleDuration);
return trackId;
}
MP4TrackId MP4File::AddEncVideoTrack(u_int32_t timeScale,
MP4Duration sampleDuration,
u_int16_t width,
u_int16_t height,
u_int8_t videoType,
u_int32_t scheme_type,
u_int16_t scheme_version,
u_int8_t key_ind_len,
u_int8_t iv_len,
bool selective_enc,
char *kms_uri
)
{
u_int32_t original_fmt = 0;
MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
AddTrackToOd(trackId);
SetTrackFloatProperty(trackId, "tkhd.width", width);
SetTrackFloatProperty(trackId, "tkhd.height", height);
InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "encv");
// 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 encv atom
MP4Integer32Property* pStsdCountProperty;
FindIntegerProperty(
MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
(MP4Property**)&pStsdCountProperty);
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.width", width);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.height", height);
/* set all the ismacryp-specific values */
// original format is mp4v
original_fmt = ('m'<<24 | 'p'<<16 | '4'<<8 | 'v');
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.frma.data-format",
original_fmt);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.schm.scheme_type",
scheme_type);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.schm.scheme_version",
scheme_version);
SetTrackStringProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.schi.iKMS.kms_URI",
kms_uri);
if (kms_uri != NULL) {
free(kms_uri);
}
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.selective-encryption",
selective_enc);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.key-indicator-length",
key_ind_len);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.IV-length",
iv_len);
/* end ismacryp */
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.esds.ESID",
#if 0
// note - for a file, these values need to
// be 0 - wmay - 04/16/2003
trackId
#else
0
#endif
);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.esds.decConfigDescr.objectTypeId",
videoType);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.encv.esds.decConfigDescr.streamType",
MP4VisualStreamType);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsz.sampleSize", sampleDuration);
m_pTracks[FindTrackIndex(trackId)]->
SetFixedSampleDuration(sampleDuration);
return trackId;
}
void MP4File::SetH263Vendor(
MP4TrackId trackId,
u_int32_t vendor)
{
MP4Atom* d263Atom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"));
if (d263Atom == NULL)
return;
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.vendor",
vendor);
d263Atom->Rewrite();
}
void MP4File::SetH263DecoderVersion(
MP4TrackId trackId,
u_int8_t decoderVersion)
{
MP4Atom* d263Atom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"));
if (d263Atom == NULL) {
return;
}
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.decoderVersion",
decoderVersion);
d263Atom->Rewrite();
}
void MP4File::SetH263Bitrates(
MP4TrackId trackId,
u_int32_t avgBitrate,
u_int32_t maxBitrate)
{
MP4Atom* bitrAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263.bitr"));
if (bitrAtom == NULL) {
VERBOSE_ERROR(m_verbosity, WARNING("Could not find bitr atom!"));
return;
}
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.bitr.avgBitrate",
avgBitrate);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.bitr.maxBitrate",
maxBitrate);
bitrAtom->Rewrite();
}
MP4TrackId MP4File::AddH263VideoTrack(
u_int32_t timeScale,
MP4Duration sampleDuration,
u_int16_t width,
u_int16_t height,
u_int8_t h263Level,
u_int8_t h263Profile,
u_int32_t avgBitrate,
u_int32_t maxBitrate)
{
MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
AddTrackToOd(trackId);
SetTrackFloatProperty(trackId, "tkhd.width", width);
SetTrackFloatProperty(trackId, "tkhd.height", height);
InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "s263");
// 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 mp4v atom
MP4Integer32Property* pStsdCountProperty;
FindIntegerProperty(
MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
(MP4Property**)&pStsdCountProperty);
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.width", width);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.height", height);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.h263Level", h263Level);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.h263Profile", h263Profile);
// Add the bitr atom
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"),
"bitr");
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.bitr.avgBitrate", avgBitrate);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.s263.d263.bitr.maxBitrate", maxBitrate);
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsz.sampleSize", sampleDuration);
m_pTracks[FindTrackIndex(trackId)]->
SetFixedSampleDuration(sampleDuration);
return trackId;
}
MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId)
{
// validate reference track id
FindTrackIndex(refTrackId);
MP4TrackId trackId =
AddTrack(MP4_HINT_TRACK_TYPE, GetTrackTimeScale(refTrackId));
InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "hmhd", 0);
AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "rtp ");
// 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 rtp atom
MP4Integer32Property* pStsdCountProperty;
FindIntegerProperty(
MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
(MP4Property**)&pStsdCountProperty);
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.rtp .tims.timeScale",
GetTrackTimeScale(trackId));
AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint");
AddTrackReference(MakeTrackName(trackId, "tref.hint"), refTrackId);
AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp ");
AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf");
return trackId;
}
void MP4File::DeleteTrack(MP4TrackId trackId)
{
ProtectWriteOperation("MP4DeleteTrack");
u_int32_t trakIndex = FindTrakAtomIndex(trackId);
u_int16_t trackIndex = FindTrackIndex(trackId);
MP4Track* pTrack = m_pTracks[trackIndex];
MP4Atom* pTrakAtom = pTrack->GetTrakAtom();
ASSERT(pTrakAtom);
MP4Atom* pMoovAtom = FindAtom("moov");
ASSERT(pMoovAtom);
RemoveTrackFromIod(trackId, ShallHaveIods());
RemoveTrackFromOd(trackId);
if (trackId == m_odTrackId) {
m_odTrackId = 0;
}
pMoovAtom->DeleteChildAtom(pTrakAtom);
m_trakIds.Delete(trakIndex);
m_pTracks.Delete(trackIndex);
delete pTrack;
delete pTrakAtom;
}
u_int32_t MP4File::GetNumberOfTracks(const char* type, u_int8_t subType)
{
if (type == NULL) {
return m_pTracks.Size();
}
u_int32_t typeSeen = 0;
const char* normType = MP4Track::NormalizeTrackType(type);
for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
if (!strcmp(normType, m_pTracks[i]->GetType())) {
if (subType) {
if (normType == MP4_AUDIO_TRACK_TYPE) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
} else if (normType == MP4_VIDEO_TRACK_TYPE) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
}
// else unknown subtype, ignore it
}
typeSeen++;
}
}
return typeSeen;
}
MP4TrackId MP4File::AllocTrackId()
{
MP4TrackId trackId =
GetIntegerProperty("moov.mvhd.nextTrackId");
if (trackId <= 0xFFFF) {
// check that nextTrackid is correct
try {
FindTrackIndex(trackId);
// ERROR, this trackId is in use
}
catch (MP4Error* e) {
// OK, this trackId is not in use, proceed
delete e;
SetIntegerProperty("moov.mvhd.nextTrackId", trackId + 1);
return trackId;
}
}
// we need to search for a track id
for (trackId = 1; trackId <= 0xFFFF; trackId++) {
try {
FindTrackIndex(trackId);
// KEEP LOOKING, this trackId is in use
}
catch (MP4Error* e) {
// OK, this trackId is not in use, proceed
delete e;
return trackId;
}
}
// extreme case where mp4 file has 2^16 tracks in it
throw new MP4Error("too many existing tracks", "AddTrack");
return MP4_INVALID_TRACK_ID; // to keep MSVC happy
}
MP4TrackId MP4File::FindTrackId(u_int16_t trackIndex,
const char* type, u_int8_t subType)
{
if (type == NULL) {
return m_pTracks[trackIndex]->GetId();
}
u_int32_t typeSeen = 0;
const char* normType = MP4Track::NormalizeTrackType(type);
for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
if (!strcmp(normType, m_pTracks[i]->GetType())) {
if (subType) {
if (normType == MP4_AUDIO_TRACK_TYPE) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
} else if (normType == MP4_VIDEO_TRACK_TYPE) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
}
// else unknown subtype, ignore it
}
if (trackIndex == typeSeen) {
return m_pTracks[i]->GetId();
}
typeSeen++;
}
}
throw new MP4Error("Track index doesn't exist - track %d type %s",
"FindTrackId",
trackIndex, type);
return MP4_INVALID_TRACK_ID; // satisfy MS compiler
}
u_int16_t MP4File::FindTrackIndex(MP4TrackId trackId)
{
for (u_int32_t i = 0; i < m_pTracks.Size() && i <= 0xFFFF; i++) {
if (m_pTracks[i]->GetId() == trackId) {
return (u_int16_t)i;
}
}
throw new MP4Error("Track id %d doesn't exist", "FindTrackIndex", trackId);
return (u_int16_t)-1; // satisfy MS compiler
}
u_int16_t MP4File::FindTrakAtomIndex(MP4TrackId trackId)
{
if (trackId) {
for (u_int32_t i = 0; i < m_trakIds.Size(); i++) {
if (m_trakIds[i] == trackId) {
return i;
}
}
}
throw new MP4Error("Track id %d doesn't exist", "FindTrakAtomIndex",
trackId);
return (u_int16_t)-1; // satisfy MS compiler
}
u_int32_t MP4File::GetSampleSize(MP4TrackId trackId, MP4SampleId sampleId)
{
return m_pTracks[FindTrackIndex(trackId)]->GetSampleSize(sampleId);
}
u_int32_t MP4File::GetTrackMaxSampleSize(MP4TrackId trackId)
{
return m_pTracks[FindTrackIndex(trackId)]->GetMaxSampleSize();
}
MP4SampleId MP4File::GetSampleIdFromTime(MP4TrackId trackId,
MP4Timestamp when, bool wantSyncSample)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?