📄 umc_mp4_parser.cpp
字号:
ret = Read_esds(dr, &(table->esds));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
}
return ret;
} // int Read_stsd_drms(UMC::DataReader *dr, T_stsd_table_data *table, T_atom_mp4 *parent_atom)
// STSD_HINT
// For hint tracks, the sample description contains appropriate declarative data for the streaming protocol being
// used, and the format of the hint track. The definition of the sample description is specific to the protocol.
//
Status MP4Splitter::Read_stsd_hint(DataReader *dr, T_stsd_table_data *table, T_atom_mp4 *parent_atom)
{
Status ret = UMC_OK;
//dr->MovePosition(16); // RESERVED
while ((dr->GetPosition() < parent_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK))
{
T_atom_mp4 leaf_atom;
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if ( Compare_Atom(&leaf_atom, "esds") )
{
ret = Read_esds(dr, &(table->esds));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
}
return ret;
}
// STSD_VIDEO
// For video tracks, a VisualSampleEntry is used.
//
Status MP4Splitter::Read_stsd_video(DataReader *dr, T_stsd_table_data *table, T_atom_mp4 *parent_atom)
{
Status ret = UMC_OK;
dr->MovePosition(2 + 2 + 3*4);
table->width = 0;
table->height = 0;
dr->Get16uSwap(&table->width);
dr->Get16uSwap(&table->height);
dr->Get32uSwap(&table->dpi_horizontal);
dr->Get32uSwap(&table->dpi_vertical);
dr->MovePosition(4 + 2 + 32 + 2 + 2);
while ((dr->GetPosition() < parent_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK))
{
T_atom_mp4 leaf_atom;
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "esds"))
{
ret = Read_esds(dr, &(table->esds));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
}
return ret;
//return 0;
}
Status MP4Splitter::Read_h263_video(DataReader *dr, T_stsd_table_data *table, T_atom_mp4 *parent_atom)
{
dr->MovePosition(16);
table->width = 0;
table->height = 0;
dr->Get16uSwap(&table->width);
dr->Get16uSwap(&table->height);
dr->MovePosition(39);
dr->MovePosition(8);
return UMC_OK;
}
void MP4Splitter::SetH264FrameIntraSize(Ipp8u* decoderConfig)
{
Ipp8u *p = decoderConfig;
p += 4;
m_nH264FrameIntraSize = *p;
m_nH264FrameIntraSize <<= 6;
m_nH264FrameIntraSize >>= 6; // remove reserved bits
m_nH264FrameIntraSize++;
return;
};
Ipp32s MP4Splitter::Read_h264_video(DataReader *dr, T_stsd_table_data *table, T_atom_mp4 *parent_atom)
{
Status ret = UMC_OK;
dr->MovePosition(16);
table->width = 0;
table->height = 0;
dr->Get16uSwap(&table->width);
dr->Get16uSwap(&table->height);
dr->MovePosition(50);
while ((dr->GetPosition() < parent_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK))
{
T_atom_mp4 leaf_atom;
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "avcC"))
{
Ipp32u temp;
table->avcC.decoderConfigLen = (Ipp32s)(leaf_atom.size - 8);
table->avcC.decoderConfig = (Ipp8u*)(ippsMalloc_8u(table->avcC.decoderConfigLen));
// Check memory allocation
if (NULL == table->avcC.decoderConfig && table->avcC.decoderConfigLen > 0)
{
return UMC_ERR_FAILED;
}
// Zeroed allocated table
memset(table->avcC.decoderConfig, 0, table->avcC.decoderConfigLen);
temp = table->avcC.decoderConfigLen;
dr->GetData(table->avcC.decoderConfig, (Ipp32u*) &temp);
if (temp > 4)
SetH264FrameIntraSize(table->avcC.decoderConfig);
//***** SetH264FrameIntraSize(table->avcC.decoderConfig, m_nH264FrameIntraSize);
ret = Atom_Skip(dr, &leaf_atom);
}
else if (Compare_Atom(&leaf_atom, "btrt"))
{
dr->Get32uSwap((Ipp32u*)&table->esds.bufferSizeDB);
dr->Get32uSwap(&table->esds.maxBitrate);
dr->Get32uSwap(&table->esds.avgBitrate);
ret = Atom_Skip(dr, &leaf_atom);
}
else if ( Compare_Atom(&leaf_atom, "m4ds") )
{
ret = Atom_Skip(dr, &leaf_atom);
}
}
return ret;
}
Status MP4Splitter::Read_stsd_audio(DataReader *dr, T_stsd_table_data *table, T_atom_mp4 *parent_atom)
{
Status ret = UMC_OK;
dr->MovePosition(8); // RESERVED
dr->Get16uSwap(&table->channels);
dr->Get16uSwap(&table->sample_size);
dr->MovePosition(4); // RESERVED
dr->Get32uSwap(&table->sample_rate);
table->sample_rate = table->sample_rate >> 16;
while ((dr->GetPosition() < parent_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK))
{
T_atom_mp4 leaf_atom;
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(&leaf_atom, "esds"))
{
ret = Read_esds(dr, &(table->esds));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, &leaf_atom);
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
}
}
return ret;
}
Status MP4Splitter::Read_esds(DataReader *dr, T_esds_data *esds)
{
unsigned char tag;
unsigned char temp2 = 0;
int len;
unsigned int temp;
dr->Get8u(&esds->version);
esds->flags = Get_24(dr);
esds->decoderConfigLen = 0;
/* get and verify ES_DescrTag */
dr->Get8u(&tag);
if ( tag == 0x03 )
{
len = Read_mp4_descr_length(dr);
dr->Get16uSwap(&esds->es_ID);
dr->Get8u(&temp2);
esds->streamDependenceFlag = temp2 & (1 << 7) ? 1 : 0;
esds->urlflag = temp2 & (1 << 6) ? 1 : 0;
esds->ocrflag = temp2 & (1 << 5) ? 1 : 0;
esds->streamPriority = temp2 & 0x1f;
len -= 3;
while ( len > 0 )
{
dr->Get8u(&tag);
len -= 1;
switch ( tag )
{
case 0x04: // verify DecoderConfigDescrTag
{
Read_mp4_descr_length(dr);
dr->Get8u(&esds->objectTypeID);
dr->Get8u(&esds->streamType); // 3 - video, 4 - graphic, 5 - audio
esds->bufferSizeDB = Get_24(dr);
dr->Get32uSwap(&esds->maxBitrate);
dr->Get32uSwap(&esds->avgBitrate);
len -= 17;
if (0 == len) break;
dr->Get8u(&tag);
if ( tag == 0x05 )
{
esds->decoderConfigLen = Read_mp4_descr_length(dr);
if ( esds->decoderConfigLen )
{
esds->decoderConfig = (Ipp8u*)(ippsMalloc_8u(esds->decoderConfigLen));
// Check memory allocation
if (NULL == esds->decoderConfig) {
return UMC_OK;
}
// Zeroed allocated table
memset(esds->decoderConfig, 0, esds->decoderConfigLen);
esds->start = dr->GetPosition();
temp = esds->decoderConfigLen;
dr->GetData(esds->decoderConfig, (Ipp32u*) &temp);
len -= 4 + temp;
}
else
{
esds->decoderConfigLen = 0;
len -= 4;
}
}
break;
}
case 0x06: // verify DecSpecificInfoTag
{
temp = Read_mp4_descr_length(dr);
dr->MovePosition(temp); // skip SL tag
len -= 4 + temp;
break;
}
} // switch tag
} // while
} // if (tag)
else
{
return UMC_OK;
}
return UMC_OK;
}
// DINF Box
// The data information box contains objects that declare the location of the media information in a track.
//
Status MP4Splitter::Read_dinf(DataReader *dr, T_dinf_data *dinf, T_atom_mp4 *dinf_atom)
{
Status ret;
T_atom_mp4 leaf_atom;
do
{
ret = Read_Atom(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
if(Compare_Atom(&leaf_atom, "dref"))
{
ret = Read_dref(dr, &(dinf->dref));
UMC_CHECK_STATUS(ret)
}
else
{
ret = Atom_Skip(dr, &leaf_atom);
UMC_CHECK_STATUS(ret)
}
} while ((dr->GetPosition() < dinf_atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
// DREF Box
// The data reference object contains a table of data references (normally URLs) that declare the location(s) of
// the media data used within the presentation.
//
Status MP4Splitter::Read_dref(DataReader *dr, T_dref_data *dref)
{
Status ret = UMC_OK;
unsigned int i;
dr->Get8u(&dref->version);
dref->flags = Get_24(dr);
dr->Get32uSwap(&dref->total_entries);
dref->table = (T_dref_table_data*)ippsMalloc_8u(sizeof(T_dref_table_data) * dref->total_entries);
// Check memory allocation
if (NULL == dref->table) {
return ret;
}
// Zeroed allocated table
memset(dref->table, 0, sizeof(T_dref_table_data) * dref->total_entries);
for ( i = 0; i < dref->total_entries; i++ )
{
ret = Read_dref_table(dr, &(dref->table[i]));
UMC_CHECK_STATUS(ret)
}
return ret;
}
Status MP4Splitter::Read_dref_table(DataReader *dr, T_dref_table_data *table)
{
Status ret = UMC_OK;
unsigned int len;
dr->Get32uSwap(&table->size);
len = 4;
dr->GetData(table->type, (Ipp32u*) &len);
dr->Get8u(&table->version);
table->flags = Get_24(dr);
table->data_reference = (char*)ippsMalloc_8u(table->size);
// Check memory allocation
if (NULL == table->data_reference) {
return ret;
}
// Zeroed allocated table
memset(table->data_reference, 0, table->size);
len = table->size - 12;
if ( table->size > 12 )
{
dr->GetData(table->data_reference, (Ipp32u*) &len);
}
table->data_reference[table->size - 12] = 0;
return ret;
}
Status MP4Splitter::Read_mvex(DataReader *dr, T_mvex_data *mvex, T_atom_mp4 *atom)
{
Status ret;
T_atom_mp4 current_atom;
mvex->total_tracks = 0;
do
{
ret = Read_Atom(dr, ¤t_atom);
UMC_CHECK_STATUS(ret)
if (Compare_Atom(¤t_atom, "trex"))
{
mvex->trex[mvex->total_tracks] = (T_trex_data*) (ippsMalloc_8u(sizeof(T_trex_data)));
ret = Read_trex(dr, (mvex->trex[mvex->total_tracks]));
UMC_CHECK_STATUS(ret)
ret = Atom_Skip(dr, ¤t_atom);
mvex->total_tracks++;
}
} while((dr->GetPosition() < atom->end) && (dr->GetPosition() != 0) && (ret == UMC_OK));
return ret;
}
Status MP4Splitter::Read_trex(DataReader *dr, T_trex_data *trex)
{
dr->Get8u(&trex->version);
trex->flags = Get_24(dr);
dr->Get32uSwap(&trex->track_ID);
dr->Get32uSwap(&trex->default_sample_description_index);
dr->Get32uSwap(&trex->default_sample_duration);
dr->Get32uSwap(&trex->default_sample_size);
dr->Get32uSwap(&trex->default_sample_flags);
return UMC_OK;
}
Status MP4Splitter::Read_mfhd(DataReader *dr, T_mfhd *mfhd)
{
dr->Get8u(&mfhd->version);
mfhd->flags = Get_24(dr);
dr->Get32uSwap(&mfhd->sequence_number);
return UMC_OK;
}
} // namespace UMC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -