This source file includes following definitions.
- Media_RewriteODFrame
- Media_ParseODFrame
- Media_FindOD_ID
- gf_isom_find_od_for_track
#include <gpac/internal/isomedia_dev.h>
#ifndef GPAC_DISABLE_ISOM
GF_Err Media_RewriteODFrame(GF_MediaBox *mdia, GF_ISOSample *sample)
{
GF_Err e;
GF_ODCodec *ODdecode;
GF_ODCodec *ODencode;
GF_ODCom *com;
GF_ESDUpdate *esdU, *esdU2;
GF_ESDRemove *esdR, *esdR2;
GF_ODUpdate *odU, *odU2;
GF_ObjectDescriptor *od;
GF_IsomObjectDescriptor *isom_od;
GF_ESD *esd;
GF_ES_ID_Ref *ref;
GF_Descriptor *desc;
GF_TrackReferenceTypeBox *mpod;
u32 i, j, skipped;
if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;
mpod = NULL;
e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
if (e) return e;
if (!mpod) return GF_OK;
ODdecode = gf_odf_codec_new();
if (!ODdecode) return GF_OUT_OF_MEM;
ODencode = gf_odf_codec_new();
if (!ODencode) {
gf_odf_codec_del(ODdecode);
return GF_OUT_OF_MEM;
}
e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
if (e) goto err_exit;
e = gf_odf_codec_decode(ODdecode);
if (e) goto err_exit;
while (1) {
com = gf_odf_codec_get_com(ODdecode);
if (!com) break;
switch (com->tag) {
case GF_ODF_OD_UPDATE_TAG:
odU = (GF_ODUpdate *) com;
odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
i=0;
while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
switch (desc->tag) {
case GF_ODF_OD_TAG:
case GF_ODF_ISOM_OD_TAG:
case GF_ODF_ISOM_IOD_TAG:
break;
default:
return GF_ISOM_INVALID_FILE;
}
e = gf_odf_desc_copy(desc, (GF_Descriptor **)&isom_od);
if (e) goto err_exit;
if (desc->tag == GF_ODF_ISOM_IOD_TAG) {
od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_InitialObjectDescriptor));
} else {
od = (GF_ObjectDescriptor *) gf_malloc(sizeof(GF_ObjectDescriptor));
}
if (!od) {
e = GF_OUT_OF_MEM;
goto err_exit;
}
od->ESDescriptors = gf_list_new();
od->objectDescriptorID = isom_od->objectDescriptorID;
od->tag = GF_ODF_OD_TAG;
od->URLString = isom_od->URLString;
isom_od->URLString = NULL;
od->extensionDescriptors = isom_od->extensionDescriptors;
isom_od->extensionDescriptors = NULL;
od->IPMP_Descriptors = isom_od->IPMP_Descriptors;
isom_od->IPMP_Descriptors = NULL;
od->OCIDescriptors = isom_od->OCIDescriptors;
isom_od->OCIDescriptors = NULL;
if (isom_od->tag == GF_ODF_ISOM_IOD_TAG) {
((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel;
((GF_InitialObjectDescriptor *)od)->inlineProfileFlag = ((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag;
((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel;
((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel;
((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel;
((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel = ((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel;
((GF_InitialObjectDescriptor *)od)->IPMPToolList = ((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList;
((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = NULL;
}
j=0;
while ((ref = (GF_ES_ID_Ref*)gf_list_enum(isom_od->ES_ID_RefDescriptors, &j))) {
if (!mpod->trackIDs || gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue;
e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd);
if (!e) e = gf_odf_desc_add_desc((GF_Descriptor *) od, (GF_Descriptor *) esd);
if (e) {
gf_odf_desc_del((GF_Descriptor *)od);
gf_odf_com_del((GF_ODCom **)&odU2);
gf_odf_desc_del((GF_Descriptor *)isom_od);
gf_odf_com_del((GF_ODCom **)&odU);
goto err_exit;
}
}
gf_odf_desc_del((GF_Descriptor *)isom_od);
gf_list_add(odU2->objectDescriptors, od);
}
gf_odf_com_del((GF_ODCom **)&odU);
gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
break;
case GF_ODF_ESD_UPDATE_TAG:
esdU = (GF_ESDUpdate *) com;
esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
esdU2->ODID = esdU->ODID;
i=0;
while ((ref = (GF_ES_ID_Ref*)gf_list_enum(esdU->ESDescriptors, &i))) {
if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1]) == NULL) continue;
e = GetESDForTime(mdia->mediaTrack->moov, mpod->trackIDs[ref->trackRef - 1], sample->DTS, &esd);
if (e) goto err_exit;
gf_list_add(esdU2->ESDescriptors, esd);
}
gf_odf_com_del((GF_ODCom **)&esdU);
gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
break;
case GF_ODF_ESD_REMOVE_REF_TAG:
esdR = (GF_ESDRemove *) com;
esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
esdR2->ODID = esdR->ODID;
esdR2->NbESDs = esdR->NbESDs;
esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
if (!esdR2->ES_ID) {
e = GF_OUT_OF_MEM;
goto err_exit;
}
skipped = 0;
for (i = 0; i < esdR->NbESDs; i++) {
if (gf_isom_get_track_from_id(mdia->mediaTrack->moov, mpod->trackIDs[esdR->ES_ID[i] - 1]) == NULL) {
skipped ++;
} else {
esdR2->ES_ID[i - skipped] = mpod->trackIDs[esdR->ES_ID[i] - 1];
}
}
if (skipped && (skipped != esdR2->NbESDs) ) {
esdR2->NbESDs -= skipped;
esdR2->ES_ID = (unsigned short*)gf_realloc(esdR2->ES_ID, sizeof(u32) * esdR2->NbESDs);
}
gf_odf_com_del((GF_ODCom **)&esdR);
gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
break;
default:
e = gf_odf_codec_add_com(ODencode, com);
if (e) goto err_exit;
}
}
e = gf_odf_codec_encode(ODencode, 1);
if (e) goto err_exit;
gf_free(sample->data);
sample->data = NULL;
sample->dataLength = 0;
e = gf_odf_codec_get_au(ODencode, &sample->data, &sample->dataLength);
err_exit:
gf_odf_codec_del(ODdecode);
gf_odf_codec_del(ODencode);
return e;
}
GF_Err Media_ParseODFrame(GF_MediaBox *mdia, const GF_ISOSample *sample, GF_ISOSample **od_samp)
{
GF_TrackReferenceBox *tref;
GF_TrackReferenceTypeBox *mpod;
GF_Err e;
GF_ODCom *com;
GF_ODCodec *ODencode;
GF_ODCodec *ODdecode;
u32 i, j;
GF_ESDUpdate *esdU, *esdU2;
GF_ESDRemove *esdR, *esdR2;
GF_ODUpdate *odU, *odU2;
GF_ObjectDescriptor *od;
GF_IsomObjectDescriptor *isom_od;
GF_ESD *esd;
GF_ES_ID_Ref *ref;
GF_Descriptor *desc;
*od_samp = NULL;
if (!mdia || !sample || !sample->data || !sample->dataLength) return GF_BAD_PARAM;
tref = mdia->mediaTrack->References;
if (!tref) {
tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF);
e = trak_AddBox((GF_Box*)mdia->mediaTrack, (GF_Box *) tref);
if (e) return e;
}
e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
if (e) return e;
if (!mpod) {
mpod = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
mpod->reference_type = GF_ISOM_BOX_TYPE_MPOD;
e = tref_AddBox((GF_Box*)tref, (GF_Box *)mpod);
if (e) return e;
}
ODencode = gf_odf_codec_new();
if (!ODencode) return GF_OUT_OF_MEM;
ODdecode = gf_odf_codec_new();
if (!ODdecode) return GF_OUT_OF_MEM;
e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
if (e) goto err_exit;
e = gf_odf_codec_decode(ODdecode);
if (e) goto err_exit;
while (1) {
com = gf_odf_codec_get_com(ODdecode);
if (!com) break;
switch (com->tag) {
case GF_ODF_OD_UPDATE_TAG:
odU = (GF_ODUpdate *) com;
odU2 = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
i=0;
while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
switch (desc->tag) {
case GF_ODF_OD_TAG:
case GF_ODF_IOD_TAG:
break;
default:
e = GF_ODF_INVALID_DESCRIPTOR;
goto err_exit;
}
e = gf_odf_desc_copy(desc, (GF_Descriptor **)&od);
if (e) goto err_exit;
if (desc->tag == GF_ODF_OD_TAG) {
isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomObjectDescriptor));
isom_od->tag = GF_ODF_ISOM_OD_TAG;
} else {
isom_od = (GF_IsomObjectDescriptor *) gf_malloc(sizeof(GF_IsomInitialObjectDescriptor));
isom_od->tag = GF_ODF_ISOM_IOD_TAG;
((GF_IsomInitialObjectDescriptor *)isom_od)->inlineProfileFlag = ((GF_InitialObjectDescriptor *)od)->inlineProfileFlag;
((GF_IsomInitialObjectDescriptor *)isom_od)->graphics_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->graphics_profileAndLevel;
((GF_IsomInitialObjectDescriptor *)isom_od)->audio_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->audio_profileAndLevel;
((GF_IsomInitialObjectDescriptor *)isom_od)->OD_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->OD_profileAndLevel;
((GF_IsomInitialObjectDescriptor *)isom_od)->scene_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->scene_profileAndLevel;
((GF_IsomInitialObjectDescriptor *)isom_od)->visual_profileAndLevel = ((GF_InitialObjectDescriptor *)od)->visual_profileAndLevel;
((GF_IsomInitialObjectDescriptor *)isom_od)->IPMPToolList = ((GF_InitialObjectDescriptor *)od)->IPMPToolList;
((GF_InitialObjectDescriptor *)od)->IPMPToolList = NULL;
}
isom_od->ES_ID_RefDescriptors = gf_list_new();
isom_od->ES_ID_IncDescriptors = NULL;
isom_od->extensionDescriptors = od->extensionDescriptors;
od->extensionDescriptors = NULL;
isom_od->IPMP_Descriptors = od->IPMP_Descriptors;
od->IPMP_Descriptors = NULL;
isom_od->OCIDescriptors = od->OCIDescriptors;
od->OCIDescriptors = NULL;
isom_od->URLString = od->URLString;
od->URLString = NULL;
isom_od->objectDescriptorID = od->objectDescriptorID;
j=0;
while ((esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &j))) {
ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
if (e) goto err_exit;
e = gf_odf_desc_add_desc((GF_Descriptor *)isom_od, (GF_Descriptor *)ref);
if (e) goto err_exit;
}
gf_odf_desc_del((GF_Descriptor *)od);
gf_list_add(odU2->objectDescriptors, isom_od);
}
gf_odf_com_del((GF_ODCom **)&odU);
gf_odf_codec_add_com(ODencode, (GF_ODCom *)odU2);
break;
case GF_ODF_ESD_UPDATE_TAG:
esdU = (GF_ESDUpdate *) com;
esdU2 = (GF_ESDUpdate *) gf_odf_com_new(GF_ODF_ESD_UPDATE_TAG);
esdU2->ODID = esdU->ODID;
i=0;
while ((esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &i))) {
ref = (GF_ES_ID_Ref *) gf_odf_desc_new(GF_ODF_ESD_REF_TAG);
e = reftype_AddRefTrack(mpod, esd->ESID, &ref->trackRef);
if (e) goto err_exit;
e = gf_list_add(esdU2->ESDescriptors, ref);
if (e) goto err_exit;
}
gf_odf_com_del((GF_ODCom **)&esdU);
gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdU2);
break;
case GF_ODF_ESD_REMOVE_TAG:
esdR = (GF_ESDRemove *) com;
esdR2 = (GF_ESDRemove *) gf_odf_com_new(GF_ODF_ESD_REMOVE_TAG);
esdR2->tag = GF_ODF_ESD_REMOVE_REF_TAG;
esdR2->ODID = esdR->ODID;
esdR2->NbESDs = esdR->NbESDs;
if (esdR->NbESDs) {
esdR2->ES_ID = (unsigned short*)gf_malloc(sizeof(u32) * esdR->NbESDs);
if (!esdR2->ES_ID) {
e = GF_OUT_OF_MEM;
goto err_exit;
}
for (i = 0; i < esdR->NbESDs; i++) {
e = reftype_AddRefTrack(mpod, esdR->ES_ID[i], &esdR2->ES_ID[i]);
if (e) goto err_exit;
}
}
gf_odf_com_del(&com);
gf_odf_codec_add_com(ODencode, (GF_ODCom *)esdR2);
break;
default:
e = gf_odf_codec_add_com(ODencode, com);
if (e) goto err_exit;
}
}
e = gf_odf_codec_encode(ODencode, 1);
if (e) goto err_exit;
*od_samp = gf_isom_sample_new();
(*od_samp)->CTS_Offset = sample->CTS_Offset;
(*od_samp)->DTS = sample->DTS;
(*od_samp)->IsRAP = sample->IsRAP;
e = gf_odf_codec_get_au(ODencode, & (*od_samp)->data, & (*od_samp)->dataLength);
if (e) {
gf_isom_sample_del(od_samp);
*od_samp = NULL;
}
err_exit:
gf_odf_codec_del(ODencode);
gf_odf_codec_del(ODdecode);
return e;
}
static u32 Media_FindOD_ID(GF_MediaBox *mdia, GF_ISOSample *sample, u32 track_id)
{
GF_Err e;
GF_ODCodec *ODdecode;
GF_ODCom *com;
u32 the_od_id;
GF_ODUpdate *odU;
GF_ESD *esd;
GF_Descriptor *desc;
GF_TrackReferenceTypeBox *mpod;
u32 i, j;
if (!mdia || !sample || !sample->data || !sample->dataLength) return 0;
mpod = NULL;
e = Track_FindRef(mdia->mediaTrack, GF_ISOM_BOX_TYPE_MPOD, &mpod);
if (e) return 0;
if (!mpod) return 0;
the_od_id = 0;
ODdecode = gf_odf_codec_new();
if (!ODdecode) return 0;
e = gf_odf_codec_set_au(ODdecode, sample->data, sample->dataLength);
if (e) goto err_exit;
e = gf_odf_codec_decode(ODdecode);
if (e) goto err_exit;
while (1) {
GF_List *esd_list = NULL;
com = gf_odf_codec_get_com(ODdecode);
if (!com) break;
if (com->tag != GF_ODF_OD_UPDATE_TAG) continue;
odU = (GF_ODUpdate *) com;
i=0;
while ((desc = (GF_Descriptor*)gf_list_enum(odU->objectDescriptors, &i))) {
switch (desc->tag) {
case GF_ODF_OD_TAG:
case GF_ODF_IOD_TAG:
esd_list = ((GF_ObjectDescriptor *)desc)->ESDescriptors;
break;
default:
continue;
}
j=0;
while ((esd = (GF_ESD*)gf_list_enum( esd_list, &j))) {
if (esd->ESID==track_id) {
the_od_id = ((GF_IsomObjectDescriptor*)desc)->objectDescriptorID;
break;
}
}
if (the_od_id) break;
}
gf_odf_com_del((GF_ODCom **)&odU);
if (the_od_id) break;
}
err_exit:
gf_odf_codec_del(ODdecode);
if (e) return 0;
return the_od_id;
}
GF_EXPORT
u32 gf_isom_find_od_for_track(GF_ISOFile *file, u32 track)
{
u32 i, j, di, the_od_id;
GF_TrackBox *od_tk;
GF_TrackBox *tk = gf_isom_get_track_from_file(file, track);
if (!tk) return 0;
i=0;
while ( (od_tk = (GF_TrackBox*)gf_list_enum(file->moov->trackList, &i))) {
if (od_tk->Media->handler->handlerType != GF_ISOM_MEDIA_OD) continue;
for (j=0; j<od_tk->Media->information->sampleTable->SampleSize->sampleCount; j++) {
GF_ISOSample *samp = gf_isom_get_sample(file, i, j+1, &di);
the_od_id = Media_FindOD_ID(od_tk->Media, samp, tk->Header->trackID);
gf_isom_sample_del(&samp);
if (the_od_id) return the_od_id;
}
}
return 0;
}
#endif