This source file includes following definitions.
- isor_emulate_chapters
- isor_emulate_iod
- isor_declare_objects
- QueryInterfaces
- LoadInterface
- ShutdownInterface
#include "isom_in.h"
#include <gpac/iso639.h>
#ifndef GPAC_DISABLE_ISOM
void isor_emulate_chapters(GF_ISOFile *file, GF_InitialObjectDescriptor *iod)
{
GF_Segment *prev_seg;
u64 prev_start;
u64 start;
u32 i, count;
if (!iod || gf_list_count(iod->OCIDescriptors)) return;
count = gf_isom_get_chapter_count(file, 0);
if (!count) return;
prev_seg = NULL;
start = prev_start = 0;
for (i=0; i<count; i++) {
const char *name;
GF_Segment *seg;
gf_isom_get_chapter(file, 0, i+1, &start, &name);
seg = (GF_Segment *) gf_odf_desc_new(GF_ODF_SEGMENT_TAG);
seg->startTime = (Double) (s64) start;
seg->startTime /= 1000;
seg->SegmentName = gf_strdup(name);
gf_list_add(iod->OCIDescriptors, seg);
if (prev_seg) {
prev_seg->Duration = (Double) (s64) (start - prev_start);
prev_seg->Duration /= 1000;
} else if (start) {
prev_seg = (GF_Segment *) gf_odf_desc_new(GF_ODF_SEGMENT_TAG);
prev_seg->startTime = 0;
prev_seg->Duration = (Double) (s64) (start);
prev_seg->Duration /= 1000;
gf_list_insert(iod->OCIDescriptors, prev_seg, 0);
}
prev_seg = seg;
prev_start = start;
}
if (prev_seg) {
start = 1000*gf_isom_get_duration(file);
start /= gf_isom_get_timescale(file);
if (start>prev_start) {
prev_seg->Duration = (Double) (s64) (start - prev_start);
prev_seg->Duration /= 1000;
}
}
}
GF_Descriptor *isor_emulate_iod(ISOMReader *read)
{
GF_InitialObjectDescriptor *fake_iod = (GF_InitialObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
isor_emulate_chapters(read->mov, fake_iod);
read->no_service_desc = GF_TRUE;
return (GF_Descriptor *)fake_iod;
}
void isor_declare_objects(ISOMReader *read)
{
GF_ObjectDescriptor *od;
GF_ESD *esd;
const char *tag;
u32 i, count, ocr_es_id, tlen, base_track, j, track_id;
Bool highest_stream;
ocr_es_id = 0;
count = gf_isom_get_track_count(read->mov);
for (i=0; i<count; i++) {
u32 m_subtype;
if (!gf_isom_is_track_enabled(read->mov, i+1))
continue;
switch (gf_isom_get_media_type(read->mov, i+1)) {
case GF_ISOM_MEDIA_AUDIO:
case GF_ISOM_MEDIA_VISUAL:
case GF_ISOM_MEDIA_TEXT:
case GF_ISOM_MEDIA_SUBT:
case GF_ISOM_MEDIA_SUBPIC:
break;
case GF_ISOM_MEDIA_SCENE:
case GF_ISOM_MEDIA_OD:
if (read->no_service_desc) continue;
break;
default:
continue;
}
m_subtype = gf_isom_get_media_subtype(read->mov, i+1, 1);
switch (m_subtype) {
case GF_ISOM_SUBTYPE_HVT1:
continue;
default:
break;
}
highest_stream = GF_TRUE;
track_id = gf_isom_get_track_id(read->mov, i+1);
if (read->play_only_track_id && (read->play_only_track_id != track_id)) continue;
for (j = 0; j < count; j++) {
if (gf_isom_has_track_reference(read->mov, j+1, GF_ISOM_REF_SCAL, track_id) > 0) {
highest_stream = GF_FALSE;
break;
}
}
for (j = 0; j < count; j++) {
if (gf_isom_has_track_reference(read->mov, j+1, GF_ISOM_REF_BASE, track_id) > 0) {
highest_stream = GF_FALSE;
break;
}
}
if ((gf_isom_get_media_type(read->mov, i+1) == GF_ISOM_MEDIA_VISUAL) && !highest_stream)
continue;
esd = gf_media_map_esd(read->mov, i+1);
if (esd) {
GF_ESD *base_esd=NULL;
Bool external_base=GF_FALSE;
gf_isom_get_reference(read->mov, i+1, GF_ISOM_REF_BASE, 1, &base_track);
if (base_track) {
u32 base_subtype=0;
switch (m_subtype) {
case GF_ISOM_SUBTYPE_LHV1:
case GF_ISOM_SUBTYPE_LHE1:
base_subtype = gf_isom_get_media_subtype(read->mov, base_track, 1);
switch (base_subtype) {
case GF_ISOM_SUBTYPE_HVC1:
case GF_ISOM_SUBTYPE_HEV1:
case GF_ISOM_SUBTYPE_HVC2:
case GF_ISOM_SUBTYPE_HEV2:
break;
default:
external_base=GF_TRUE;
break;
}
}
if (external_base) {
base_esd = gf_media_map_esd(read->mov, base_track);
if (base_esd) esd->dependsOnESID = base_esd->ESID;
esd->has_scalable_layers = GF_TRUE;
} else {
esd->dependsOnESID=0;
switch (gf_isom_get_hevc_lhvc_type(read->mov, i+1, 1)) {
case GF_ISOM_HEVCTYPE_HEVC_LHVC:
case GF_ISOM_HEVCTYPE_LHVC_ONLY:
esd->has_scalable_layers = GF_TRUE;
break;
case GF_ISOM_HEVCTYPE_HEVC_ONLY:
esd->has_scalable_layers = GF_FALSE;
if (gf_isom_get_reference_count(read->mov, i+1, GF_ISOM_REF_SCAL)<=0) {
base_esd = gf_media_map_esd(read->mov, base_track);
if (base_esd) esd->dependsOnESID = base_esd->ESID;
}
break;
}
}
} else {
switch (gf_isom_get_hevc_lhvc_type(read->mov, i+1, 1)) {
case GF_ISOM_HEVCTYPE_HEVC_LHVC:
case GF_ISOM_HEVCTYPE_LHVC_ONLY:
esd->has_scalable_layers = GF_TRUE;
break;
}
}
if (!esd->langDesc) {
esd->langDesc = (GF_Language *) gf_odf_desc_new(GF_ODF_LANG_TAG);
gf_isom_get_media_language(read->mov, i+1, &esd->langDesc->full_lang_code);
}
od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
od->service_ifce = read->input;
od->objectDescriptorID = 0;
if (base_esd) {
if (!ocr_es_id) ocr_es_id = base_esd->ESID;
base_esd->OCRESID = ocr_es_id;
gf_list_add(od->ESDescriptors, base_esd);
}
if (!ocr_es_id) ocr_es_id = esd->ESID;
esd->OCRESID = ocr_es_id;
gf_list_add(od->ESDescriptors, esd);
if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
send_proxy_command(read, GF_FALSE, GF_TRUE, GF_OK, (GF_Descriptor*)od, NULL);
} else {
gf_service_declare_media(read->service, (GF_Descriptor*)od, GF_TRUE);
}
}
}
if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_COVER_ART, &tag, &tlen)==GF_OK) {
const char *cdir = gf_modules_get_option((GF_BaseInterface *)gf_service_get_interface(read->service), "General", "CacheDirectory");
if (cdir) {
char szName[GF_MAX_PATH];
const char *sep;
FILE *t;
sep = strrchr(gf_isom_get_filename(read->mov), '\\');
if (!sep) sep = strrchr(gf_isom_get_filename(read->mov), '/');
if (!sep) sep = gf_isom_get_filename(read->mov);
if ((cdir[strlen(cdir)-1] != '\\') && (cdir[strlen(cdir)-1] != '/')) {
sprintf(szName, "%s/%s_cover.%s", cdir, sep, (tlen & 0x80000000) ? "png" : "jpg");
} else {
sprintf(szName, "%s%s_cover.%s", cdir, sep, (tlen & 0x80000000) ? "png" : "jpg");
}
t = gf_fopen(szName, "wb");
if (t) {
Bool isom_contains_video = GF_FALSE;
assert(!(tlen & 0x80000000));
gf_fwrite(tag, tlen & 0x7FFFFFFF, 1, t);
gf_fclose(t);
for (i=0; i<gf_isom_get_track_count(read->mov); i++) {
if (!gf_isom_is_track_enabled(read->mov, i+1))
continue;
if (gf_isom_get_media_type(read->mov, i+1) == GF_ISOM_MEDIA_VISUAL) {
isom_contains_video = GF_TRUE;
break;
}
}
if (!isom_contains_video) {
od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
od->service_ifce = read->input;
od->objectDescriptorID = GF_MEDIA_EXTERNAL_ID;
od->URLString = gf_strdup(szName);
if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
send_proxy_command(read, GF_FALSE, GF_TRUE, GF_OK, (GF_Descriptor*)od, NULL);
} else {
gf_service_declare_media(read->service, (GF_Descriptor*)od, GF_TRUE);
}
}
}
}
}
if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
send_proxy_command(read, GF_FALSE, GF_TRUE, GF_OK, NULL, NULL);
} else {
gf_service_declare_media(read->service, NULL, GF_FALSE);
}
}
#endif
GPAC_MODULE_EXPORT
const u32 *QueryInterfaces()
{
static u32 si [] = {
#ifndef GPAC_DISABLE_ISOM
GF_NET_CLIENT_INTERFACE,
#endif
#ifndef GPAC_DISABLE_ISOM_WRITE
GF_STREAMING_MEDIA_CACHE,
#endif
0
};
return si;
}
GPAC_MODULE_EXPORT
GF_BaseInterface *LoadInterface(u32 InterfaceType)
{
#ifndef GPAC_DISABLE_ISOM
if (InterfaceType == GF_NET_CLIENT_INTERFACE)
return (GF_BaseInterface *)isor_client_load();
#endif
#ifndef GPAC_DISABLE_ISOM_WRITE
if (InterfaceType == GF_STREAMING_MEDIA_CACHE)
return (GF_BaseInterface *)isow_load_cache();
#endif
return NULL;
}
GPAC_MODULE_EXPORT
void ShutdownInterface(GF_BaseInterface *ifce)
{
switch (ifce->InterfaceType) {
#ifndef GPAC_DISABLE_ISOM
case GF_NET_CLIENT_INTERFACE:
isor_client_del(ifce);
break;
#endif
#ifndef GPAC_DISABLE_ISOM_WRITE
case GF_STREAMING_MEDIA_CACHE:
isow_delete_cache(ifce);
break;
#endif
}
}
GPAC_MODULE_STATIC_DECLARATION( isom )