This source file includes following definitions.
- gf_oci_event_new
- gf_oci_event_del
- gf_oci_event_set_start_time
- gf_oci_event_set_duration
- OCI_IsOCIDesc
- gf_oci_event_add_desc
- gf_oci_event_get_id
- gf_oci_event_get_start_time
- gf_oci_event_get_duration
- gf_oci_event_get_desc_count
- gf_oci_event_get_desc
- gf_oci_event_rem_desc
- gf_oci_codec_new
- gf_oci_codec_del
- gf_oci_codec_add_event
- WriteSevenBitLength
- gf_oci_codec_encode
- gf_oci_codec_decode
- gf_oci_codec_get_event
#include <gpac/internal/odf_dev.h>
#ifndef GPAC_MINIMAL_ODF
GF_Err gf_odf_write_descriptor_list(GF_BitStream *bs, GF_List *descList);
GF_Err gf_odf_size_descriptor_list(GF_List *descList, u32 *outSize);
GF_Err gf_odf_delete_descriptor(GF_Descriptor *desc);
GF_Err gf_odf_parse_descriptor(GF_BitStream *bs, GF_Descriptor **desc, u32 *desc_size);
s32 gf_odf_size_field_size(u32 size_desc);
#define OCI_MAX_EVENT_SIZE 1<<28 - 1
#define MAX_OCIEVENT_ID 0x7FFF
struct __tag_oci_event
{
u16 EventID;
u8 AbsoluteTimeFlag;
char StartingTime[4];
char duration[4];
GF_List *OCIDescriptors;
};
struct __tag_oci_codec
{
GF_List *OCIEvents;
u8 Version;
u8 Mode;
};
GF_EXPORT
OCIEvent *gf_oci_event_new(u16 EventID)
{
OCIEvent *tmp;
if (EventID > MAX_OCIEVENT_ID) return NULL;
tmp = (OCIEvent *)gf_malloc(sizeof(OCIEvent));
if (!tmp) return NULL;
memset(tmp, 0, sizeof(OCIEvent));
tmp->EventID = EventID;
tmp->OCIDescriptors = gf_list_new();
return tmp;
}
GF_EXPORT
void gf_oci_event_del(OCIEvent *event)
{
GF_Descriptor *desc;
if (!event) return;
while (gf_list_count(event->OCIDescriptors)) {
desc = (GF_Descriptor *)gf_list_get(event->OCIDescriptors, 0);
gf_list_rem(event->OCIDescriptors, 0);
gf_odf_delete_descriptor(desc);
}
gf_list_del(event->OCIDescriptors);
gf_free(event);
}
GF_EXPORT
GF_Err gf_oci_event_set_start_time(OCIEvent *event, u8 Hours, u8 Minutes, u8 Seconds, u8 HundredSeconds, u8 IsAbsoluteTime)
{
if (!event || (Hours >= 100) || (Minutes >= 100) || (Seconds >= 100) || (HundredSeconds >= 100) )
return GF_BAD_PARAM;
event->AbsoluteTimeFlag = IsAbsoluteTime;
event->StartingTime[0] = Hours;
event->StartingTime[1] = Minutes;
event->StartingTime[2] = Seconds;
event->StartingTime[3] = HundredSeconds;
return GF_OK;
}
GF_EXPORT
GF_Err gf_oci_event_set_duration(OCIEvent *event, u8 Hours, u8 Minutes, u8 Seconds, u8 HundredSeconds)
{
if (!event || (Hours >= 100) || (Minutes >= 100) || (Seconds >= 100) || (HundredSeconds >= 100) )
return GF_BAD_PARAM;
event->duration[0] = Hours;
event->duration[1] = Minutes;
event->duration[2] = Seconds;
event->duration[3] = HundredSeconds;
return GF_OK;
}
u8 OCI_IsOCIDesc(GF_Descriptor *oci_desc)
{
if (oci_desc->tag < GF_ODF_OCI_BEGIN_TAG) return 0;
if (oci_desc->tag > GF_ODF_OCI_END_TAG) return 0;
return 1;
}
GF_EXPORT
GF_Err gf_oci_event_add_desc(OCIEvent *event, GF_Descriptor *oci_desc)
{
if (!event || !oci_desc) return GF_BAD_PARAM;
if (!OCI_IsOCIDesc(oci_desc)) return GF_ODF_INVALID_DESCRIPTOR;
gf_list_add(event->OCIDescriptors, oci_desc);
return GF_OK;
}
GF_EXPORT
GF_Err gf_oci_event_get_id(OCIEvent *event, u16 *ID)
{
if (!event || !ID) return GF_BAD_PARAM;
*ID = event->EventID;
return GF_OK;
}
GF_EXPORT
GF_Err gf_oci_event_get_start_time(OCIEvent *event, u8 *Hours, u8 *Minutes, u8 *Seconds, u8 *HundredSeconds, u8 *IsAbsoluteTime)
{
if (!event || !Hours || !Minutes || !Seconds || !HundredSeconds || !IsAbsoluteTime)
return GF_BAD_PARAM;
*IsAbsoluteTime = event->AbsoluteTimeFlag;
*Hours = event->StartingTime[0];
*Minutes = event->StartingTime[1];
*Seconds = event->StartingTime[2];
*HundredSeconds = event->StartingTime[3];
return GF_OK;
}
GF_EXPORT
GF_Err gf_oci_event_get_duration(OCIEvent *event, u8 *Hours, u8 *Minutes, u8 *Seconds, u8 *HundredSeconds)
{
if (!event || !Hours || !Minutes || !Seconds || !HundredSeconds)
return GF_BAD_PARAM;
*Hours = event->duration[0];
*Minutes = event->duration[1];
*Seconds = event->duration[2];
*HundredSeconds = event->duration[3];
return GF_OK;
}
GF_EXPORT
u32 gf_oci_event_get_desc_count(OCIEvent *event)
{
if (!event) return 0;
return gf_list_count(event->OCIDescriptors);
}
GF_EXPORT
GF_Descriptor *gf_oci_event_get_desc(OCIEvent *event, u32 DescIndex)
{
if (!event || DescIndex >= gf_list_count(event->OCIDescriptors) ) return NULL;
return (GF_Descriptor *) gf_list_get(event->OCIDescriptors, DescIndex);
}
GF_EXPORT
GF_Err gf_oci_event_rem_desc(OCIEvent *event, u32 DescIndex)
{
if (!event || DescIndex >= gf_list_count(event->OCIDescriptors) ) return GF_BAD_PARAM;
return gf_list_rem(event->OCIDescriptors, DescIndex);
}
GF_EXPORT
OCICodec *gf_oci_codec_new(u8 IsEncoder, u8 Version)
{
OCICodec *tmp;
if (Version != 0x01) return NULL;
tmp = (OCICodec *)gf_malloc(sizeof(OCICodec));
if (!tmp) return NULL;
tmp->Mode = IsEncoder ? 1 : 0;
tmp->Version = 0x01;
tmp->OCIEvents = gf_list_new();
return tmp;
}
GF_EXPORT
void gf_oci_codec_del(OCICodec *codec)
{
OCIEvent *ev;
if (!codec) return;
while (gf_list_count(codec->OCIEvents)) {
ev = (OCIEvent *)gf_list_get(codec->OCIEvents, 0);
gf_oci_event_del(ev);
gf_list_rem(codec->OCIEvents, 0);
}
gf_list_del(codec->OCIEvents);
gf_free(codec);
}
GF_EXPORT
GF_Err gf_oci_codec_add_event(OCICodec *codec, OCIEvent *event)
{
if (!codec || !codec->Mode || !event) return GF_BAD_PARAM;
return gf_list_add(codec->OCIEvents, event);
}
GF_Err WriteSevenBitLength(GF_BitStream *bs, u32 size)
{
u32 length;
unsigned char vals[4];
if (!bs || !size) return GF_BAD_PARAM;
length = size;
vals[3] = (unsigned char) (length & 0x7f);
length >>= 7;
vals[2] = (unsigned char) ((length & 0x7f) | 0x80);
length >>= 7;
vals[1] = (unsigned char) ((length & 0x7f) | 0x80);
length >>= 7;
vals[0] = (unsigned char) ((length & 0x7f) | 0x80);
if (size < 0x00000080) {
gf_bs_write_int(bs, vals[3], 8);
} else if (size < 0x00004000) {
gf_bs_write_int(bs, vals[2], 8);
gf_bs_write_int(bs, vals[3], 8);
} else if (size < 0x00200000) {
gf_bs_write_int(bs, vals[1], 8);
gf_bs_write_int(bs, vals[2], 8);
gf_bs_write_int(bs, vals[3], 8);
} else if (size < 0x10000000) {
gf_bs_write_int(bs, vals[0], 8);
gf_bs_write_int(bs, vals[1], 8);
gf_bs_write_int(bs, vals[2], 8);
gf_bs_write_int(bs, vals[3], 8);
} else {
return GF_ODF_INVALID_DESCRIPTOR;
}
return GF_OK;
}
GF_EXPORT
GF_Err gf_oci_codec_encode(OCICodec *codec, char **outAU, u32 *au_length)
{
GF_BitStream *bs;
u32 i, size, desc_size;
GF_Err e;
OCIEvent *ev;
if (!codec || !codec->Mode || *outAU) return GF_BAD_PARAM;
bs = NULL;
size = 0;
i=0;
while ((ev = (OCIEvent *)gf_list_enum(codec->OCIEvents, &i))) {
size += 10;
e = gf_odf_size_descriptor_list(codec->OCIEvents, &desc_size);
if (e) goto err_exit;
size += desc_size;
}
bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
e = WriteSevenBitLength(bs, size);
if (e) goto err_exit;
while (gf_list_count(codec->OCIEvents)) {
ev = (OCIEvent *)gf_list_get(codec->OCIEvents, 0);
gf_list_rem(codec->OCIEvents, 0);
gf_bs_write_int(bs, ev->EventID, 15);
gf_bs_write_int(bs, ev->AbsoluteTimeFlag, 1);
gf_bs_write_data(bs, ev->StartingTime, 4);
gf_bs_write_data(bs, ev->duration, 4);
e = gf_odf_write_descriptor_list(bs, ev->OCIDescriptors);
gf_oci_event_del(ev);
if (e) goto err_exit;
gf_bs_align(bs);
}
gf_bs_get_content(bs, outAU, au_length);
gf_bs_del(bs);
return GF_OK;
err_exit:
if (bs) gf_bs_del(bs);
while (gf_list_count(codec->OCIEvents)) {
ev = (OCIEvent *)gf_list_get(codec->OCIEvents, 0);
gf_list_rem(codec->OCIEvents, 0);
gf_oci_event_del(ev);
}
return e;
}
GF_EXPORT
GF_Err gf_oci_codec_decode(OCICodec *codec, char *au, u32 au_length)
{
OCIEvent *ev;
GF_BitStream *bs;
u32 size, hdrS, desc_size, tot_size, tmp_size, val;
GF_Descriptor *tmp;
GF_Err e;
if (!codec || codec->Mode || !au) return GF_BAD_PARAM;
bs = gf_bs_new(au, au_length, GF_BITSTREAM_READ);
ev = 0;
tot_size = 0;
while (tot_size < au_length) {
ev = gf_oci_event_new(0);
if (!ev) {
e = GF_OUT_OF_MEM;
goto err_exit;
}
gf_bs_read_int(bs, 8);
size = 0;
hdrS = 0;
do {
val = gf_bs_read_int(bs, 8);
hdrS += 1;
size <<= 7;
size |= val & 0x7F;
} while ( val & 0x80 );
ev->EventID = gf_bs_read_int(bs, 15);
ev->AbsoluteTimeFlag = gf_bs_read_int(bs, 1);
gf_bs_read_data(bs, ev->StartingTime, 4);
gf_bs_read_data(bs, ev->duration, 4);
desc_size = 0;
while (desc_size < size - 10) {
e = gf_odf_parse_descriptor(bs, &tmp, &tmp_size);
if (e || !tmp) goto err_exit;
if (!OCI_IsOCIDesc(tmp)) {
gf_odf_delete_descriptor(tmp);
e = GF_ODF_INVALID_DESCRIPTOR;
goto err_exit;
}
gf_list_add(ev->OCIDescriptors, tmp);
desc_size += tmp_size + gf_odf_size_field_size(tmp_size);
}
if (desc_size != size - 10) {
e = GF_CORRUPTED_DATA;
goto err_exit;
}
gf_list_add(codec->OCIEvents, ev);
size += 1;
tot_size += size + hdrS;
ev = NULL;
}
if (tot_size != au_length) {
e = GF_CORRUPTED_DATA;
goto err_exit;
}
gf_bs_del(bs);
return GF_OK;
err_exit:
gf_bs_del(bs);
if (ev) gf_oci_event_del(ev);
while (gf_list_count(codec->OCIEvents)) {
ev = (OCIEvent *)gf_list_get(codec->OCIEvents, 0);
gf_list_rem(codec->OCIEvents, 0);
gf_oci_event_del(ev);
}
return e;
}
GF_EXPORT
OCIEvent *gf_oci_codec_get_event(OCICodec *codec)
{
OCIEvent *ev;
if (!codec ||codec->Mode) return NULL;
ev = (OCIEvent *)gf_list_get(codec->OCIEvents, 0);
gf_list_rem(codec->OCIEvents, 0);
return ev;
}
#endif