📄 umc_mp4_parser.cpp
字号:
memset(moov->trak[moov->total_tracks], 0, sizeof(T_trak_data));
moov->total_tracks++;
} else {
return 0;
}
}
else
{
return 0;
}
return moov->trak[moov->total_tracks - 1];
}
// MOOV Box
// The metadata for a presentation is stored in the single Movie Box which occurs at the top-level of a file.
//
Status MP4Splitter::Read_moov(DataReader *dr, T_moov *moov, T_atom_mp4 *atom)
{
Status ret;
T_atom_mp4 current_atom;
moov->total_tracks = 0;
do
{
ret = Read_Atom(dr, ¤t_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(¤t_atom, "mvhd"))
{
ret = Read_mvhd(dr, &(moov->mvhd));
}
else if (Compare_Atom(¤t_atom, "iods"))
{
ret = Read_iods(dr, &(moov->iods));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, ¤t_atom);
}
else if (Compare_Atom(¤t_atom, "mvex"))
{
ret = Read_mvex(dr, &moov->mvex, ¤t_atom);
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, ¤t_atom);
}
/*else if ( Compare_Atom(¤t_atom, "clip") )
{
Atom_Skip(dr, ¤t_atom);
}*/
else if (Compare_Atom(¤t_atom, "trak"))
{
T_trak_data *trak = Add_trak(moov);
if (trak == 0)
{
return UMC_ERR_FAILED;
}
ret = Read_trak(dr, trak, ¤t_atom);
}
else
{
ret = Atom_Skip(dr, ¤t_atom);
}
} while ((dr->GetPosition() < atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
// MVHD Box
// This box defines overall information which is media-independent, and relevant to the entire presentation
// considered as a whole.
//
Status MP4Splitter::Read_mvhd(DataReader *dr, T_mvhd_data *mvhd)
{
Status ret = UMC_OK;
unsigned int temp;
dr->Get8u(&mvhd->version);
mvhd->flags = Get_24(dr);
if ( mvhd->version )
{
dr->Get64uSwap(&mvhd->creation_time);
dr->Get64uSwap(&mvhd->modification_time);
dr->Get32uSwap(&mvhd->time_scale);
dr->Get64uSwap(&mvhd->duration);
}
else
{
dr->Get32uSwap(&temp);
mvhd->creation_time = temp;
dr->Get32uSwap(&temp);
mvhd->modification_time = temp;
dr->Get32uSwap(&mvhd->time_scale);
dr->Get32uSwap(&temp);
mvhd->duration = temp;
}
dr->MovePosition((9 + 6) * 4 + 10 + 2 + 4); // RESERVED
dr->Get32uSwap(&mvhd->next_track_id);
return ret;
}
Status MP4Splitter::Read_iods(DataReader *dr, T_iods_data *iods)
{
Status ret = UMC_OK;
unsigned char tag;
dr->Get8u(&iods->version);
iods->flags = Get_24(dr );
dr->Get8u(&tag);
//**** Get_mp4_descr_length(dr); // skip length
Read_mp4_descr_length(dr); // skip length
// skip ODID, ODProfile, sceneProfile
dr->Get16uSwap(&iods->objectDescriptorID); // ODID (16 bit ?)
dr->Get8u(&iods->OD_profileAndLevel); // ODProfile
dr->Get8u(&iods->scene_profileAndLevel); // sceneProfile
dr->Get8u(&iods->audioProfileId);
dr->Get8u(&iods->videoProfileId);
dr->Get8u(&iods->graphics_profileAndLevel);
return ret;
}
// TRAK Box
// This is a container box for a single track of a presentation. A presentation consists of one or more tracks.
// Each track is independent of the other tracks in the presentation and carries its own temporal and spatial
// information. Each track will contain its associated Media Box.
//
Status MP4Splitter::Read_trak(DataReader *dr, T_trak_data *trak, T_atom_mp4 *trak_atom)
{
Status ret;
T_atom_mp4 leaf_atom;
trak->tref.dpnd.idTrak = 0;
do
{
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "tkhd"))
{
ret = Read_tkhd(dr, &(trak->tkhd));
}
else if (Compare_Atom(&leaf_atom, "mdia"))
{
ret = Read_mdia(dr, &(trak->mdia), &leaf_atom);
}
else if ( Compare_Atom(&leaf_atom, "tref") )
{
ret = Read_tref(dr, &(trak->tref), &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
} while ((dr->GetPosition() < trak_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
// TREF Box
// This box provides a reference from the containing track to another track in the presentation. These references
// are typed.
//
Status MP4Splitter::Read_tref(DataReader *dr, T_tref_data *tref, T_atom_mp4 *atom)
{
Status ret;
T_atom_mp4 leaf_atom;
do
{
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "dpnd"))
{
ret = Read_dpnd(dr, &(tref->dpnd));
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
} while ((dr->GetPosition() < atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
Status MP4Splitter::Read_dpnd(DataReader *dr, T_dpnd_data *dpnd)
{
dr->Get32uSwap(&dpnd->idTrak);
return UMC_OK;
}
// TKHD Box
// This box specifies the characteristics of a single track.
//
Status MP4Splitter::Read_tkhd(DataReader *dr, T_tkhd_data *tkhd)
{
Status ret = UMC_OK;
unsigned int temp;
dr->Get8u(&tkhd->version);
tkhd->flags = Get_24(dr);
if ( tkhd->version )
{
dr->Get64uSwap(&tkhd->creation_time);
dr->Get64uSwap(&tkhd->modification_time);
dr->Get32uSwap(&tkhd->track_id);
dr->MovePosition(4); //RESERVED
dr->Get64uSwap(&tkhd->duration);
}
else
{
dr->Get32uSwap(&temp);
tkhd->creation_time = temp;
dr->Get32uSwap(&temp);
tkhd->modification_time = temp;
dr->Get32uSwap(&tkhd->track_id);
dr->MovePosition(4); //RESERVED
dr->Get32uSwap(&temp);
tkhd->duration = temp;
}
dr->MovePosition(16 + 9 * 4); //RESERVED
dr->Get32uSwap(&temp);
tkhd->track_width = (float)(temp >> 16);
dr->Get32uSwap(&temp);
tkhd->track_height = (float)(temp >> 16);
return ret;
}
// MDIA
// The media declaration container contains all the objects that declare information about the media data within a
// track.
//
Status MP4Splitter::Read_mdia(DataReader *dr, T_mdia_data *mdia, T_atom_mp4 *trak_atom)
{
Status ret;
T_atom_mp4 leaf_atom;
do
{
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "mdhd"))
{
ret = Read_mdhd(dr, &(mdia->mdhd));
}
else if (Compare_Atom(&leaf_atom, "hdlr"))
{
ret = Read_hdlr(dr, &(mdia->hdlr));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, &leaf_atom);
}
else if (Compare_Atom(&leaf_atom, "minf"))
{
ret = Read_minf(dr, &(mdia->minf), &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
} while ((dr->GetPosition() < trak_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
// HDLR Box
// This box within a Media Box declares the process by which the media-data in the track is presented, and thus,
// the nature of the media in a track. For example, a video track would be handled by a video handler.
//
Status MP4Splitter::Read_hdlr(DataReader *dr, T_hdlr_data *hdlr)
{
Status ret = UMC_OK;
unsigned int len;
dr->Get8u(&hdlr->version);
hdlr->flags = Get_24(dr);
dr->MovePosition(4); // RESERVED
len = 4;
dr->GetData(hdlr->component_type, (Ipp32u*) &len);
dr->MovePosition(12); // RESERVED
return ret;
}
// MDHD Box
// The media header declares overall information that is media-independent, and relevant to characteristics of
// the media in a track.
//
Status MP4Splitter::Read_mdhd(DataReader *dr, T_mdhd_data *mdhd)
{
Status ret = UMC_OK;
unsigned int temp;
dr->Get8u(&mdhd->version);
mdhd->flags = Get_24(dr);
if ( mdhd->version )
{
dr->Get64uSwap(&mdhd->creation_time);
dr->Get64uSwap(&mdhd->modification_time);
dr->Get32uSwap(&mdhd->time_scale);
dr->Get64uSwap(&mdhd->duration);
}
else
{
dr->Get32uSwap(&temp);
mdhd->creation_time = temp;
dr->Get32uSwap(&temp);
mdhd->modification_time = temp;
dr->Get32uSwap(&mdhd->time_scale);
dr->Get32uSwap(&temp);
mdhd->duration = temp;
}
dr->Get16uSwap(&mdhd->language);
dr->Get16uSwap(&mdhd->quality); // RESERVED
return ret;
}
// MINF Box
// This box contains all the objects that declare characteristic information of the media in the track.
//
Status MP4Splitter::Read_minf(DataReader *dr, T_minf_data *minf, T_atom_mp4 *parent_atom)
{
Status ret;
T_atom_mp4 leaf_atom;
do
{
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "vmhd"))
{
minf->is_video = 1;
ret = Read_vmhd(dr, &(minf->vmhd));
}
else if (Compare_Atom(&leaf_atom, "smhd"))
{
minf->is_audio = 1;
ret = Read_smhd(dr, &(minf->smhd));
}
else if (Compare_Atom(&leaf_atom, "hmhd"))
{
minf->is_hint = 1;
ret = Read_hmhd(dr, &(minf->hmhd));
}
else if (Compare_Atom(&leaf_atom, "dinf"))
{
ret = Read_dinf(dr, &(minf->dinf), &leaf_atom);
}
else if (Compare_Atom(&leaf_atom, "stbl"))
{
ret = Read_stbl(dr, minf, &(minf->stbl), &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
} while ( (dr->GetPosition() < parent_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
// HMHD Box
// The hint media header contains general information, independent of the protocol, for hint tracks.
//
Status MP4Splitter::Read_hmhd(DataReader *dr, T_hmhd_data *hmhd)
{
Status ret = UMC_OK;
dr->Get8u(&hmhd->version);
hmhd->flags = Get_24(dr);
dr->Get16uSwap(&hmhd->maxPDUsize);
dr->Get16uSwap(&hmhd->avgPDUsize);
dr->Get32uSwap(&hmhd->maxbitrate);
dr->Get32uSwap(&hmhd->avgbitrate);
dr->Get32uSwap(&hmhd->slidingavgbitrate);
return ret;
}
// VMHD Box
// The video media header contains general presentation information, independent of the coding, for video
// media.
//
Status MP4Splitter::Read_vmhd(DataReader *dr, T_vmhd_data *vmhd)
{
Status ret = UMC_OK;
dr->Get8u(&vmhd->version);
vmhd->flags = Get_24(dr);
dr->MovePosition(8); // RESERVED
return ret;
}
// SMHD Box
// The sound media header contains general presentation information, independent of the coding, for audio
// media. This header is used for all tracks containing audio.
//
Status MP4Splitter::Read_smhd(DataReader *dr, T_smhd_data *smhd)
{
Status ret = UMC_OK;
dr->Get8u(&smhd->version);
smhd->flags = Get_24(dr);
dr->MovePosition(4); // RESERVED
return ret;
}
// STBL Box
// The sample table contains all the time and data indexing of the media samples in a track. Using the tables
// here, it is possible to locate samples in time, determine their type (e.g. I-frame or not), and determine their
// size, container, and offset into that container.
//
Status MP4Splitter::Read_stbl(DataReader *dr, T_minf_data *minf, T_stbl_data *stbl, T_atom_mp4 *parent_atom)
{
Status ret;
T_atom_mp4 leaf_atom;
do
{
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "stsd"))
{
ret = Read_stsd(dr, minf, &(stbl->stsd));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -