Imported Upstream version 0.5.0+svn4281~dfsg1
authorAlessio Treglia <alessio@debian.org>
Wed, 16 Jan 2013 16:08:33 +0000 (16:08 +0000)
committerAlessio Treglia <alessio@debian.org>
Wed, 16 Jan 2013 16:08:33 +0000 (16:08 +0000)
103 files changed:
README
applications/mp42ts/main.c
applications/mp4box/filedump.c
applications/mp4box/fileimport.c
applications/mp4box/main.c
applications/mp4client/main.c
applications/ts2hds/f4m.c
applications/ts2hds/f4v.c
applications/ts2hds/main.c
bin/smartphone 2003 (armv4)/release/install/gpac.inf
configure
doc/configuration.html
include/gpac/avparse.h
include/gpac/configuration.h
include/gpac/constants.h
include/gpac/dash.h
include/gpac/download.h
include/gpac/internal/compositor_dev.h
include/gpac/internal/isomedia_dev.h
include/gpac/internal/media_dev.h
include/gpac/internal/mpd.h
include/gpac/internal/smjs_api.h
include/gpac/isomedia.h
include/gpac/media_tools.h
include/gpac/modules/service.h
include/gpac/mpeg4_odf.h
include/gpac/mpegts.h
include/gpac/setup.h
include/gpac/tools.h
modules/ffmpeg_in/ffmpeg_decode.c
modules/ffmpeg_in/ffmpeg_in.h
modules/freenect/freenect.c
modules/gpac_js/gpac_js.c
modules/isom_in/isom_in.h
modules/isom_in/load.c
modules/isom_in/read.c
modules/isom_in/read_ch.c
modules/mp3_in/mp3_in.c
modules/mpd_in/mpd_in.c
modules/mpegts_in/mpegts_in.c
modules/opensvc_dec/opensvc_dec.c
modules/platinum/GPACPlatinum.cpp
modules/platinum/GPACPlatinum.h
modules/platinum/GenericDevice.cpp
modules/widgetman/widget.c
modules/widgetman/widgetman.c
src/Makefile
src/compositor/audio_mixer.c
src/compositor/compositor.c
src/compositor/compositor_2d.c
src/compositor/texturing.c
src/export.cpp
src/ietf/rtp_streamer.c
src/isomedia/avc_ext.c
src/isomedia/box_code_adobe.c
src/isomedia/box_code_base.c
src/isomedia/box_dump.c
src/isomedia/box_funcs.c
src/isomedia/data_map.c
src/isomedia/drm_sample.c
src/isomedia/isom_intern.c
src/isomedia/isom_read.c
src/isomedia/isom_write.c
src/isomedia/media.c
src/isomedia/movie_fragments.c
src/isomedia/stbl_write.c
src/isomedia/track.c
src/media_tools/av_parsers.c
src/media_tools/dash_client.c
src/media_tools/dash_segmenter.c
src/media_tools/filestreamer.c
src/media_tools/isom_hinter.c
src/media_tools/isom_tools.c
src/media_tools/m2ts_mux.c
src/media_tools/m3u8.c
src/media_tools/media_export.c
src/media_tools/media_import.c
src/media_tools/mpd.c
src/media_tools/mpegts.c
src/media_tools/text_import.c
src/odf/descriptors.c
src/scene_manager/loader_bt.c
src/scene_manager/loader_xmt.c
src/scene_manager/scene_engine.c
src/scene_manager/swf_parse.c
src/scenegraph/dom_smjs.c
src/scenegraph/svg_smjs.c
src/scenegraph/vrml_smjs.c
src/terminal/decoder.c
src/terminal/media_manager.c
src/terminal/media_memory.c
src/terminal/network_service.c
src/terminal/object_manager.c
src/terminal/scene.c
src/utils/base_encoding.c
src/utils/cache.c
src/utils/configfile.c
src/utils/downloader.c
src/utils/error.c
src/utils/os_divers.c
src/utils/os_thread.c
src/utils/sha1.c
src/utils/xml_parser.c

diff --git a/README b/README
index ab1c8cd719a2e32058081824685d71e650e69ec1..ccb6ea66b34996ea14655066e750703d99163971 100644 (file)
--- a/README
+++ b/README
@@ -7,7 +7,7 @@ mozilla SpiderMonkey javascript engine.
 GPAC currently supports local playback, http progressive download, Adaptive HTTP Streaming (MPEG-DASH, HLS), RTP/RTSP streaming over UDP (unicast or multicast) or TCP and TS demuxing (from file, IP or DVB4Linux).
 GPAC also features MP4Box, a multimedia swiss-army knife for the prompt.
 
-For compilation and installation instruction, check INSTALL file
+For compilation and installation instruction, check INSTALLME file
 
 For GPAC configuration instruction, check gpac/doc/configuration.html or gpac/doc/man/gpac.1 (man gpac when installed)
 
index 0eedc2565eb562173fcaa5080a106b47b2f02562..ee6f3cd2758e7aa3b5ad8908829437badd665b22 100644 (file)
@@ -36,6 +36,8 @@
 #include <gpac/scene_engine.h>
 #endif
 
+#define USE_ISOBMF_REWRITE
+
 
 #ifdef GPAC_DISABLE_ISOM
 
@@ -137,13 +139,16 @@ typedef struct
        u32 image_repeat_ms, nb_repeat_last;
        void *dsi;
        u32 dsi_size;
-       u32 nalu_size;
+
        void *dsi_and_rap;
        Bool loop;
        Bool is_repeat;
        u64 ts_offset;
        M2TSProgram *prog;
-       char nalu_delim[6];
+
+#ifndef USE_ISOBMF_REWRITE
+       u32 nalu_size;
+#endif
 } GF_ESIMP4;
 
 typedef struct
@@ -215,6 +220,7 @@ static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param)
                        pck.flags |= GF_ESI_DATA_HAS_DTS;
                }
 
+#ifndef USE_ISOBMF_REWRITE
                if (priv->nalu_size) {
                        Bool nalu_delim_sent = 0;
                        u32 remain = priv->sample->dataLength;
@@ -271,7 +277,10 @@ static GF_Err mp4_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param)
                                ptr += size;
                        }
 
-               } else {
+               } else 
+#endif //USE_ISOBMF_REWRITE
+               
+               {
 
                        if (priv->sample->IsRAP && priv->dsi && priv->dsi_size) {
                                pck.data = priv->dsi;
@@ -375,14 +384,21 @@ static void fill_isom_es_ifce(M2TSProgram *prog, GF_ESInterface *ifce, GF_ISOFil
                        priv->dsi_size = dcd->decoderSpecificInfo->dataLength;
                        memcpy(priv->dsi, dcd->decoderSpecificInfo->data, dcd->decoderSpecificInfo->dataLength);
                        break;
+               case GPAC_OTI_VIDEO_HEVC:
+                       gf_isom_set_nalu_extract_mode(mp4, track_num, GF_ISOM_NALU_EXTRACT_LAYER_ONLY | GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG | GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG);
+                       break;
                case GPAC_OTI_VIDEO_AVC:
                {
-#ifndef GPAC_DISABLE_AV_PARSERS
+#ifdef USE_ISOBMF_REWRITE
+                       gf_isom_set_nalu_extract_mode(mp4, track_num, GF_ISOM_NALU_EXTRACT_LAYER_ONLY | GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG | GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG);
+
+#elif !defined(GPAC_DISABLE_AV_PARSERS)
                        GF_AVCConfigSlot *slc;
                        u32 i;
                        GF_BitStream *bs;
                        GF_AVCConfig *avccfg = gf_isom_avc_config_get(mp4, track_num, 1);
                        priv->nalu_size = avccfg->nal_unit_size;
+
                        bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
                        for (i=0; i<gf_list_count(avccfg->sequenceParameterSets);i++) {
                                slc = gf_list_get(avccfg->sequenceParameterSets, i);
@@ -398,9 +414,7 @@ static void fill_isom_es_ifce(M2TSProgram *prog, GF_ESInterface *ifce, GF_ISOFil
                        gf_bs_del(bs);
                        gf_odf_avc_cfg_del(avccfg);
 #endif
-                       priv->nalu_delim[3] = 1;
-                       priv->nalu_delim[4] = 0; /*this will be nal header*/
-                       priv->nalu_delim[5] = 0xF0 /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
+
                }
                        break;
                }
index 147426e889c256957c768558793e6884f5c466d9..285deca6a3cb64ede1d144dda5c86e736be5fc5c 100644 (file)
@@ -873,13 +873,51 @@ void dump_file_timestamps(GF_ISOFile *file, char *inName)
 }
 
 
-static void dump_nalu_type_name(FILE *dump, char *ptr, Bool is_svc)
+static void dump_nalu(FILE *dump, char *ptr, Bool is_svc, Bool is_hevc)
 {
-       u8 type = ptr[0] & 0x1F;
+       u8 type;
        u8 dependency_id, quality_id, temporal_id;
        u8 track_ref_index;
-       u32 data_offset;
+       u32 data_offset, sps_id, pps_id;
        
+       if (is_hevc) {
+               type = (ptr[0]  & 0x7E) >> 1;
+               fprintf(dump, "code=\"%d\" type=\"", type);
+               switch (type) {
+               case GF_HEVC_NALU_SLICE_TRAIL_N: fputs("TRAIL_N slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_TRAIL_R: fputs("TRAIL_R slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_TSA_N: fputs("TSA_N slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_TSA_R: fputs("TSA_R slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_STSA_N: fputs("STSA_N slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_STSA_R: fputs("STSA_R slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_RADL_N: fputs("RADL_N slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_RADL_R: fputs("RADL_R slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_RASL_N: fputs("RASL_N slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_RASL_R: fputs("RASL_R slice segment", dump); break;
+               case GF_HEVC_NALU_SLICE_BLA_W_LP: fputs("Broken link access slice (W LP)", dump); break;
+               case GF_HEVC_NALU_SLICE_BLA_W_DLP: fputs("Broken link access slice (W DLP)", dump); break;
+               case GF_HEVC_NALU_SLICE_BLA_N_LP: fputs("Broken link access slice (N LP)", dump); break;
+               case GF_HEVC_NALU_SLICE_IDR_W_DLP: fputs("IDR slice (W DLP)", dump); break;
+               case GF_HEVC_NALU_SLICE_IDR_N_LP: fputs("IDR slice (N LP)", dump); break;
+               case GF_HEVC_NALU_SLICE_CRA: fputs("CRA slice", dump); break;
+
+               case GF_HEVC_NALU_VID_PARAM: fputs("Video Parameter Set", dump); break;
+               case GF_HEVC_NALU_SEQ_PARAM: fputs("Sequence Parameter Set", dump); break;
+               case GF_HEVC_NALU_PIC_PARAM: fputs("Picture Parameter Set", dump); break;
+               case GF_HEVC_NALU_ACCESS_UNIT: fputs("AU Delimiter", dump); break;
+               case GF_HEVC_NALU_END_OF_SEQ: fputs("End of Sequence", dump); break;
+               case GF_HEVC_NALU_END_OF_STREAM: fputs("End of Stream", dump); break;
+               case GF_HEVC_NALU_FILLER_DATA: fputs("Filler Data", dump); break;
+               case GF_HEVC_NALU_SEI_PREFIX: fputs("SEI Prefix", dump); break;
+               case GF_HEVC_NALU_SEI_SUFFIX: fputs("SEI Suffix", dump); break;
+               default:
+                       fputs("UNKNOWN", dump); break;
+               }
+               fputs("\"", dump);
+               return;
+       } 
+       
+       type = ptr[0] & 0x1F;
        fprintf(dump, "code=\"%d\" type=\"", type);
        switch (type) {
        case GF_AVC_NALU_NON_IDR_SLICE: fputs("Non IDR slice", dump); break;
@@ -888,15 +926,27 @@ static void dump_nalu_type_name(FILE *dump, char *ptr, Bool is_svc)
        case GF_AVC_NALU_DP_C_SLICE: fputs("DP Type C slice", dump); break;
        case GF_AVC_NALU_IDR_SLICE: fputs("IDR slice", dump); break;
        case GF_AVC_NALU_SEI: fputs("SEI Message", dump); break;
-       case GF_AVC_NALU_SEQ_PARAM: fputs("SequenceParameterSet", dump); break;
-       case GF_AVC_NALU_PIC_PARAM: fputs("PictureParameterSet", dump); break;
+       case GF_AVC_NALU_SEQ_PARAM: 
+               fputs("SequenceParameterSet", dump); 
+               gf_avc_get_sps_info(ptr, strlen(ptr), &sps_id, NULL, NULL, NULL, NULL);
+               fprintf(dump, "\" sps_id=\"%d", sps_id);
+               break;
+       case GF_AVC_NALU_PIC_PARAM: 
+               fputs("PictureParameterSet", dump);
+               gf_avc_get_pps_info(ptr+1, strlen(ptr)-1, &pps_id, &sps_id);
+               fprintf(dump, "\" pps_id=\"%d\" sps_id=\"%d", pps_id, sps_id);
+               break;
        case GF_AVC_NALU_ACCESS_UNIT: fputs("AccessUnit delimiter", dump); break;
        case GF_AVC_NALU_END_OF_SEQ: fputs("EndOfSequence", dump); break;
        case GF_AVC_NALU_END_OF_STREAM: fputs("EndOfStream", dump); break;
        case GF_AVC_NALU_FILLER_DATA: fputs("Filler data", dump); break;
        case GF_AVC_NALU_SEQ_PARAM_EXT: fputs("SequenceParameterSetExtension", dump); break;
        case GF_AVC_NALU_SVC_PREFIX_NALU: fputs("SVCPrefix", dump); break;
-       case GF_AVC_NALU_SVC_SUBSEQ_PARAM: fputs("SVCSubsequenceParameterSet", dump); break;
+       case GF_AVC_NALU_SVC_SUBSEQ_PARAM: 
+               fputs("SVCSubsequenceParameterSet", dump); 
+               gf_avc_get_sps_info(ptr, strlen(ptr), &sps_id, NULL, NULL, NULL, NULL);
+               fprintf(dump, "\" sps_id=\"%d", sps_id);
+               break;
        case GF_AVC_NALU_SLICE_AUX: fputs("Auxiliary Slice", dump); break;
 
        case GF_AVC_NALU_SVC_SLICE: 
@@ -922,10 +972,13 @@ static void dump_nalu_type_name(FILE *dump, char *ptr, Bool is_svc)
 
 void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName)
 {
-       u32 i, count, track, nalh_size;
+       u32 i, count, track, nalh_size, timescale, cur_extract_mode;
+       Bool is_hevc = 0;
        FILE *dump;
+       s32 countRef;
 #ifndef GPAC_DISABLE_AV_PARSERS
        GF_AVCConfig *avccfg, *svccfg;
+       GF_HEVCConfig *hevccfg;
        GF_AVCConfigSlot *slc;
 #endif
 
@@ -941,20 +994,25 @@ void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName)
 
        count = gf_isom_get_sample_count(file, track);
 
-       fprintf(dump, "<NALUTrack trackID=\"%d\" SampleCount=\"%d\">\n", trackID, count);
+       timescale = gf_isom_get_media_timescale(file, track);
+
+       cur_extract_mode = gf_isom_get_nalu_extract_mode(file, track);
+
+       fprintf(dump, "<NALUTrack trackID=\"%d\" SampleCount=\"%d\" TimeScale=\"%d\">\n", trackID, count, timescale);
 
 #ifndef GPAC_DISABLE_AV_PARSERS
        avccfg = gf_isom_avc_config_get(file, track, 1);
        svccfg = gf_isom_svc_config_get(file, track, 1);
+       hevccfg = gf_isom_hevc_config_get(file, track, 1);
        fprintf(dump, " <NALUConfig>\n");
 
 #define DUMP_ARRAY(arr, name)\
        if (arr) {\
                for (i=0; i<gf_list_count(arr); i++) {\
                        slc = gf_list_get(arr, i);\
-                       fprintf(dump, "  <%s number=\"%d\" ", name, i+1);\
-                       dump_nalu_type_name(dump, slc->data , svccfg ? 1 : 0);\
-                       fprintf(dump, ">\n");\
+                       fprintf(dump, "  <%s number=\"%d\" size=\"%d\"", name, i+1, slc->size);\
+                       dump_nalu(dump, slc->data , svccfg ? 1 : 0, is_hevc);\
+                       fprintf(dump, "/>\n");\
                }\
        }\
 
@@ -972,10 +1030,42 @@ void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName)
                DUMP_ARRAY(svccfg->sequenceParameterSets, "SVCSPSArray")
                DUMP_ARRAY(svccfg->pictureParameterSets, "SVCPPSArray")
        }
+       if (hevccfg) {
+               nalh_size = hevccfg->nal_unit_size;
+               is_hevc = 1;
+               for (i=0; i<gf_list_count(hevccfg->param_array); i++) {
+                       GF_HEVCParamArray *ar = gf_list_get(hevccfg->param_array, i);
+                       if (ar->type==GF_HEVC_NALU_SEQ_PARAM) {
+                               DUMP_ARRAY(ar->nalus, "HEVCSPSArray")
+                       } else if (ar->type==GF_HEVC_NALU_PIC_PARAM) {
+                               DUMP_ARRAY(ar->nalus, "HEVCPPSArray")
+                       } else if (ar->type==GF_HEVC_NALU_VID_PARAM) {
+                               DUMP_ARRAY(ar->nalus, "HEVCVPSArray")
+                       } else { 
+                               DUMP_ARRAY(ar->nalus, "HEVCUnknownPSArray")
+                       }
+               }
+       }
 #endif
        fprintf(dump, " </NALUConfig>\n");
 
+       /*for testing dependency*/
+       countRef = gf_isom_get_reference_count(file, track, GF_ISOM_REF_SCAL);
+       if (countRef > 0)
+       {
+               u32 refTrackID;
+               fprintf(dump, " <SCALReferences>\n");
+               for (i = 1; i <= (u32) countRef; i++)
+               {
+                       gf_isom_get_reference_ID(file, track, GF_ISOM_REF_SCAL, i, &refTrackID);
+                       fprintf(dump, "  <SCALReference number=\"%d\" refTrackID=\"%d\"/>\n", i, refTrackID);
+               }
+                       
+               fprintf(dump, " </SCALReferences>\n");
+       }
+
        fprintf(dump, " <NALUSamples>\n");
+       gf_isom_set_nalu_extract_mode(file, track, GF_ISOM_NALU_EXTRACT_INSPECT);
        for (i=0; i<count; i++) {
                u64 dts, cts;
                u32 size, nal_size, idx;
@@ -1004,7 +1094,7 @@ void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName)
                                break;
                        } else {
                                fprintf(dump, "   <NALU number=\"%d\" size=\"%d\" ", idx, nal_size);
-                               dump_nalu_type_name(dump, ptr, svccfg ? 1 : 0);
+                               dump_nalu(dump, ptr, svccfg ? 1 : 0, is_hevc);
                                fprintf(dump, "/>\n");
                        }
                        idx++;
@@ -1021,6 +1111,9 @@ void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName)
        fprintf(dump, "</NALUTrack>\n");
 
        if (inName) fclose(dump);
+       if (avccfg) gf_odf_avc_cfg_del(avccfg);
+       if (svccfg) gf_odf_avc_cfg_del(svccfg);
+       gf_isom_set_nalu_extract_mode(file, track, cur_extract_mode);
 }
 
 #ifndef GPAC_DISABLE_ISOM_DUMP
@@ -1300,8 +1393,12 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump)
                || (msub_type==GF_ISOM_SUBTYPE_MPEG4_CRYP) 
                || (msub_type==GF_ISOM_SUBTYPE_AVC_H264)
                || (msub_type==GF_ISOM_SUBTYPE_AVC2_H264)
+               || (msub_type==GF_ISOM_SUBTYPE_AVC3_H264)
+               || (msub_type==GF_ISOM_SUBTYPE_AVC4_H264)
                || (msub_type==GF_ISOM_SUBTYPE_SVC_H264)
                || (msub_type==GF_ISOM_SUBTYPE_LSR1)
+               || (msub_type==GF_ISOM_SUBTYPE_HVC1)
+               || (msub_type==GF_ISOM_SUBTYPE_HEV1)
        )  {
                esd = gf_isom_get_esd(file, trackNum, 1);
                if (!esd) {
@@ -1369,7 +1466,7 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump)
                                                        }
                                                }
                                                if (avccfg->chroma_bit_depth) {
-                                                       fprintf(stderr, "\tChroma format %d - Luma bit depth %d - chroma bot depth %d\n", avccfg->chroma_format, avccfg->luma_bit_depth, avccfg->chroma_bit_depth);
+                                                       fprintf(stderr, "\tChroma format %d - Luma bit depth %d - chroma bit depth %d\n", avccfg->chroma_format, avccfg->luma_bit_depth, avccfg->chroma_bit_depth);
                                                }
                                                gf_odf_avc_cfg_del(avccfg);
                                        }
@@ -1392,7 +1489,42 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump)
                                                gf_odf_avc_cfg_del(svccfg);
                                        }
 #endif /*GPAC_DISABLE_AV_PARSERS*/
+
+                               } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_HEVC) {
+#ifndef GPAC_DISABLE_AV_PARSERS
+                                       GF_HEVCConfig *hevccfg;
+#endif
+
+                                       gf_isom_get_visual_info(file, trackNum, 1, &w, &h);
+                                       if (full_dump) fprintf(stderr, "\t");
+                                       fprintf(stderr, "HEVC Video - Visual Size %d x %d\n", w, h);
+#ifndef GPAC_DISABLE_AV_PARSERS
+                                       hevccfg = gf_isom_hevc_config_get(file, trackNum, 1);
+                                       if (!hevccfg ) {
+                                               fprintf(stderr, "\n\n\tNon-compliant HEVC track: hvcC not found in sample description\n");
+                                       } else {
+                                               u32 k;
+                                               fprintf(stderr, "\tHEVC Info: Profile IDC %d - Level IDC %d - Chroma Format %d\n", hevccfg->profile_idc, hevccfg->level_idc, hevccfg->chromaFormat);
+                                               fprintf(stderr, "\tNAL Unit length bits: %d - profile compatibility 0x%08X\n", 8*hevccfg->nal_unit_size, hevccfg->profile_compatibility_indications);
+                                               fprintf(stderr, "\tParameter Sets: ");
+                                               for (k=0; k<gf_list_count(hevccfg->param_array); k++) {
+                                                       GF_HEVCParamArray *ar=gf_list_get(hevccfg->param_array, k);
+                                                       if (ar->type==GF_HEVC_NALU_SEQ_PARAM) {
+                                                               fprintf(stderr, "%d SPS ", gf_list_count(ar->nalus));
+                                                       }
+                                                       else if (ar->type==GF_HEVC_NALU_PIC_PARAM) {
+                                                               fprintf(stderr, "%d PPS ", gf_list_count(ar->nalus));
+                                                       }
+                                                       if (ar->type==GF_HEVC_NALU_VID_PARAM) {
+                                                               fprintf(stderr, "%d VPS ", gf_list_count(ar->nalus));
+                                                       }
+                                               }
+                                               fprintf(stderr, "\n\tBit Depth luma %d - Chroma %d - %d temporal layers\n", hevccfg->luma_bit_depth, hevccfg->chroma_bit_depth, hevccfg->numTemporalLayers);
+                                               gf_odf_hevc_cfg_del(hevccfg);
+                                       }
+#endif /*GPAC_DISABLE_AV_PARSERS*/
                                } 
+
                                /*OGG media*/
                                else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_MEDIA_OGG) {
                                        char *szName;
@@ -1444,7 +1576,8 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump)
                                        if (full_dump) fprintf(stderr, "\t");
                                        if (e) fprintf(stderr, "Corrupted AAC Config\n");
                                        else {
-                                               fprintf(stderr, "MPEG-%d Audio %s - %d Channel(s) - SampleRate %d", is_mp2 ? 2 : 4, gf_m4a_object_type_name(a_cfg.base_object_type), a_cfg.nb_chan, a_cfg.base_sr);
+                                               fprintf(stderr, "%s - %d Channel(s) - SampleRate %d", gf_m4a_object_type_name(a_cfg.base_object_type), a_cfg.nb_chan, a_cfg.base_sr);
+                                               if (is_mp2) fprintf(stderr, " (MPEG-2 Signaling)"); 
                                                if (a_cfg.has_sbr) fprintf(stderr, " - SBR SampleRate %d", a_cfg.sbr_sr);
                                                if (a_cfg.has_ps) fprintf(stderr, " - PS");
                                                fprintf(stderr, "\n");
@@ -1946,7 +2079,7 @@ void DumpMovieInfo(GF_ISOFile *file)
                                fprintf(stderr, "\tTempo (BPM): %d\n", tag[1]);
                        }
                }
-               if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACKNUMBER, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tTrackNumber: %d / %d\n", tag[3], tag[5]);
+               if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACKNUMBER, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tTrackNumber: %d / %d\n", (0xff00 & (tag[2]<<8)) | (0xff & tag[3]), (0xff00 & (tag[4]<<8)) | (0xff & tag[5]));
                if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_TRACK, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tTrack: %s\n", tag);
                if (gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_GROUP, &tag, &tag_len)==GF_OK) fprintf(stderr, "\tGroup: %s\n", tag);
 
index e1976a8ee0864533eb3e27681a66b949e2b7d512..d364d372febd2d14555cab1eb14afc6fa9833506 100644 (file)
@@ -41,6 +41,7 @@
 #ifndef GPAC_DISABLE_VRML
 #include <gpac/nodes_mpeg4.h>
 #endif
+#include <gpac/network.h>
 
 #ifndef GPAC_DISABLE_ISOM_WRITE
 
@@ -155,6 +156,27 @@ void convert_file_info(char *inName, u32 trackID)
        if (!found && trackID) fprintf(stderr, "Cannot find track %d in file\n", trackID);
 }
 
+static void set_chapter_track(GF_ISOFile *file, u32 track, u32 chapter_ref_trak)
+{
+       u64 ref_duration, chap_duration;
+       Double scale;
+
+       gf_isom_set_track_reference(file, chapter_ref_trak, GF_4CC('c','h','a','p'), gf_isom_get_track_id(file, track) );
+       gf_isom_set_track_enabled(file, track, 0);
+
+       ref_duration = gf_isom_get_media_duration(file, chapter_ref_trak);
+       chap_duration = gf_isom_get_media_duration(file, track);
+       scale = (Double) (s64) gf_isom_get_media_timescale(file, track);
+       scale /= gf_isom_get_media_timescale(file, chapter_ref_trak);
+       ref_duration = (u64) (ref_duration * scale);
+
+       if (chap_duration < ref_duration) {
+               chap_duration -= gf_isom_get_sample_duration(file, track, gf_isom_get_sample_count(file, track));
+               chap_duration = ref_duration - chap_duration;
+               gf_isom_set_last_sample_duration(file, track, (u32) chap_duration);
+       }
+}
+
 GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample)
 {
        u32 track_id, i, timescale, track, stype, profile, level, new_timescale, rescale, svc_mode;
@@ -425,7 +447,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
        import.video_fps = force_fps;
        import.frames_per_sample = frames_per_sample;
        import.flags = import_flags;
-
+       
        if (!import.nb_tracks) {
                u32 count, o_count;
                o_count = gf_isom_get_track_count(import.dest);
@@ -458,13 +480,12 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                        if (handler_name) gf_isom_set_handler_name(import.dest, i+1, handler_name);
                        else if (!keep_handler) {
                                char szHName[1024];
-                               char *fName = strrchr(inName, '/');
-                               if (!fName) fName = strrchr(inName, '\\');
+                               const char *fName = gf_url_get_resource_name((const  char *)inName);
+                               fName = strchr(fName, '.');
+                               if (fName) fName += 1;
+                               else fName = "?";
 
-                               if (!fName) fName = inName;
-                               else fName = fName+1;
-
-                               sprintf(szHName, "%s - Imported with GPAC %s", fName, GPAC_FULL_VERSION);
+                               sprintf(szHName, "*%s@GPAC%s", fName, GPAC_FULL_VERSION);
                                gf_isom_set_handler_name(import.dest, i+1, szHName);
                        }
                        if (handler) gf_isom_set_media_type(import.dest, i+1, handler);
@@ -480,8 +501,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                                gf_isom_set_media_subtype(import.dest, i+1, 1, stype);
 
                        if (is_chap && chap_ref) {
-                               gf_isom_set_track_reference(import.dest, chap_ref, GF_4CC('c','h','a','p'), gf_isom_get_track_id(import.dest, i+1) );
-                               gf_isom_set_track_enabled(import.dest, i+1, 0);
+                               set_chapter_track(import.dest, i+1, chap_ref);
                        }
 
                        if (profile || level) 
@@ -492,8 +512,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
 
                        gf_isom_set_composition_offset_mode(import.dest, i+1, negative_cts_offset);
 
-                       /*when importing SVC we ALWAYS have AVC+SVC single track mode*/
-                       if (gf_isom_get_avc_svc_type(import.dest, i+1, 1)==GF_ISOM_AVCTYPE_AVC_SVC)
+                       if (gf_isom_get_avc_svc_type(import.dest, i+1, 1)>=GF_ISOM_AVCTYPE_AVC_SVC)
                                check_track_for_svc = i+1;
                }
        } else {
@@ -547,13 +566,12 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                        if (handler_name) gf_isom_set_handler_name(import.dest, track, handler_name);
                        else if (!keep_handler) {
                                char szHName[1024];
-                               char *fName = strrchr(inName, '/');
-                               if (!fName) fName = strrchr(inName, '\\');
-
-                               if (!fName) fName = inName;
-                               else fName = fName+1;
+                               const char *fName = gf_url_get_resource_name((const  char *)inName);
+                               fName = strchr(fName, '.');
+                               if (fName) fName += 1;
+                               else fName = "?";
 
-                               sprintf(szHName, "%s - Imported with GPAC %s", fName, GPAC_FULL_VERSION);
+                               sprintf(szHName, "%s@GPAC%s", fName, GPAC_FULL_VERSION);
                                gf_isom_set_handler_name(import.dest, track, szHName);
                        }
                        if (handler) gf_isom_set_media_type(import.dest, track, handler);
@@ -569,8 +587,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                                gf_isom_set_media_subtype(import.dest, track, 1, stype);
 
                        if (is_chap && chap_ref) {
-                               gf_isom_set_track_reference(import.dest, chap_ref, GF_4CC('c','h','a','p'), gf_isom_get_track_id(import.dest, i+1) );
-                               gf_isom_set_track_enabled(import.dest, track, 0);
+                               set_chapter_track(import.dest, track, chap_ref);
                        }
 
                        if (profile || level) 
@@ -618,8 +635,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                        
                        gf_isom_set_composition_offset_mode(import.dest, track, negative_cts_offset);
 
-                       /*when importing SVC we ALWAYS have AVC+SVC single track mode*/
-                       if (gf_isom_get_avc_svc_type(import.dest, track, 1)==GF_ISOM_AVCTYPE_AVC_SVC)
+                       if (gf_isom_get_avc_svc_type(import.dest, track, 1)>=GF_ISOM_AVCTYPE_AVC_SVC)
                                check_track_for_svc = track;
                }
                if (track_id) fprintf(stderr, "WARNING: Track ID %d not found in file\n", track_id);
@@ -635,6 +651,16 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc
                }
        }
 
+       /*force to rewrite all dependencies*/
+       for (i = 1; i <= gf_isom_get_track_count(import.dest); i++)
+       {
+               e = gf_isom_rewrite_track_dependencies(import.dest, i);
+               if (e) {
+                       fprintf(stderr, "Warning: track ID %d has references to a track not imported\n", gf_isom_get_track_id(import.dest, i));
+                       e = GF_OK;
+               }
+       }
+
        if (check_track_for_svc) {
                if (svc_mode) {
                        e = gf_media_split_svc(import.dest, check_track_for_svc, (svc_mode==2) ? 1 : 0);
@@ -1359,8 +1385,10 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
        for (i=0; i<nb_tracks; i++) {
                u64 last_DTS, dest_track_dur_before_cat;
                u32 nb_edits = 0;
+               Bool skip_lang_test = 1;
                Bool use_ts_dur = 1;
                Bool merge_edits = 0;
+               Bool new_track = 0;
                mtype = gf_isom_get_media_type(orig, i+1);
                switch (mtype) {
                case GF_ISOM_MEDIA_HINT:
@@ -1384,8 +1412,56 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                }
 
                dst_tk = 0;
-               tk_id = gf_isom_get_track_id(orig, i+1);
+               /*if we had a temporary import of the file, check if the original track ID matches the dst one. If so, skip all language detection code*/
+               tk_id = gf_isom_get_track_original_id(orig, i+1);
+               if (!tk_id) {
+                       tk_id = gf_isom_get_track_id(orig, i+1);
+                       skip_lang_test = 0;
+               }
                dst_tk = gf_isom_get_track_by_id(dest, tk_id);
+
+
+               if (dst_tk) {
+                       if (mtype != gf_isom_get_media_type(dest, dst_tk))
+                               dst_tk = 0;
+                       else if (gf_isom_get_media_subtype(dest, dst_tk, 1) != gf_isom_get_media_subtype(orig, i+1, 1))
+                               dst_tk = 0;
+               }
+
+               if (!dst_tk) {
+                       for (j=0; j<gf_isom_get_track_count(dest); j++) {
+                               if (mtype != gf_isom_get_media_type(dest, j+1)) continue;
+                               if (gf_isom_is_same_sample_description(orig, i+1, 0, dest, j+1, 0)) {
+                                       if (mtype==GF_ISOM_MEDIA_VISUAL) {
+                                               u32 w, h, ow, oh;
+                                               gf_isom_get_visual_info(orig, i+1, 1, &ow, &oh);
+                                               gf_isom_get_visual_info(dest, j+1, 1, &w, &h);
+                                               if ((ow==w) && (oh==h)) {
+                                                       dst_tk = j+1;
+                                                       break;
+                                               }
+                                       }
+                                       /*check language code*/
+                                       else if (!skip_lang_test && (mtype==GF_ISOM_MEDIA_AUDIO)) {
+                                               u32 lang_src, lang_dst;
+                                               char lang[4];
+                                               lang[3]=0;
+                                               gf_isom_get_media_language(orig, i+1, lang);
+                                               lang_src = GF_4CC(lang[0], lang[1], lang[2], lang[3]);
+                                               gf_isom_get_media_language(dest, j+1, lang);
+                                               lang_dst = GF_4CC(lang[0], lang[1], lang[2], lang[3]);
+                                               if (lang_dst==lang_src) {
+                                                       dst_tk = j+1;
+                                                       break;
+                                               }
+                                       } else {
+                                               dst_tk = j+1;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
                if (dst_tk) {
                        u32 stype = gf_isom_get_media_subtype(dest, dst_tk, 1);
                        /*we MUST have the same codec*/
@@ -1407,7 +1483,7 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                        }
 
                        /*merge AVC config if possible*/
-                       if (!dst_tk && ((stype == GF_ISOM_SUBTYPE_AVC_H264) || (stype == GF_ISOM_SUBTYPE_AVC2_H264))  ) {
+                       if (!dst_tk && ((stype == GF_ISOM_SUBTYPE_AVC_H264) || (stype == GF_ISOM_SUBTYPE_AVC2_H264) || (stype == GF_ISOM_SUBTYPE_AVC3_H264) || (stype == GF_ISOM_SUBTYPE_AVC4_H264))  ) {
                                GF_AVCConfig *avc_src, *avc_dst;
                                dst_tk = gf_isom_get_track_by_id(dest, tk_id);
                                
@@ -1481,45 +1557,13 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                        }
                }
 
-               if (!dst_tk) {
-                       for (j=0; j<gf_isom_get_track_count(dest); j++) {
-                               if (mtype != gf_isom_get_media_type(dest, j+1)) continue;
-                               if (gf_isom_is_same_sample_description(orig, i+1, 0, dest, j+1, 0)) {
-                                       if (mtype==GF_ISOM_MEDIA_VISUAL) {
-                                               u32 w, h, ow, oh;
-                                               gf_isom_get_visual_info(orig, i+1, 1, &ow, &oh);
-                                               gf_isom_get_visual_info(dest, j+1, 1, &w, &h);
-                                               if ((ow==w) && (oh==h)) {
-                                                       dst_tk = j+1;
-                                                       break;
-                                               }
-                                       }
-                                       /*check language code*/
-                                       else if (mtype==GF_ISOM_MEDIA_AUDIO) {
-                                               u32 lang_src, lang_dst;
-                                               char lang[4];
-                                               lang[3]=0;
-                                               gf_isom_get_media_language(orig, i+1, lang);
-                                               lang_src = GF_4CC(lang[0], lang[1], lang[2], lang[3]);
-                                               gf_isom_get_media_language(dest, j+1, lang);
-                                               lang_dst = GF_4CC(lang[0], lang[1], lang[2], lang[3]);
-                                               if (lang_dst==lang_src) {
-                                                       dst_tk = j+1;
-                                                       break;
-                                               }
-                                       } else {
-                                               dst_tk = j+1;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               /*looks like a new file*/
+               /*looks like a new track*/
                if (!dst_tk) {
                        fprintf(stderr, "No suitable destination track found - creating new one (type %s)\n", gf_4cc_to_str(mtype));
                        e = gf_isom_clone_track(orig, i+1, dest, 1, &dst_tk);
                        if (e) goto err_exit;
                        gf_isom_clone_pl_indications(orig, dest);
+                       new_track = 1;
 
                        if (align_timelines) {
                                u32 max_timescale = 0;
@@ -1584,7 +1628,7 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                        u32 di;
                        samp = gf_isom_get_sample(orig, i+1, j+1, &di);
                        last_DTS = samp->DTS;
-                       samp->DTS =  (u64) (ts_scale * samp->DTS + insert_dts);
+                       samp->DTS =  (u64) (ts_scale * samp->DTS + (new_track ? 0 : insert_dts));
                        samp->CTS_Offset =  (u32) (samp->CTS_Offset * ts_scale);
 
                        if (gf_isom_is_self_contained(orig, i+1, di)) {
@@ -1607,7 +1651,18 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou
                        gf_isom_set_last_sample_duration(dest, dst_tk, (u32) insert_dts);
                }
 
-               if (merge_edits) {
+               if (new_track && insert_dts) {
+                       u64 media_dur = gf_isom_get_media_duration(orig, i+1);
+                       /*convert from media time to track time*/
+                       Double rescale = (Float) gf_isom_get_timescale(dest);
+                       rescale /= (Float) gf_isom_get_media_timescale(dest, dst_tk);
+                       /*convert from orig to dst time scale*/
+                       rescale *= ts_scale;
+
+                       gf_isom_set_edit_segment(dest, dst_tk, 0, (u64) (s64) (insert_dts*rescale), 0, GF_ISOM_EDIT_EMPTY);
+                       gf_isom_set_edit_segment(dest, dst_tk, (u64) (s64) (insert_dts*rescale), (u64) (s64) (media_dur*rescale), 0, GF_ISOM_EDIT_NORMAL);
+               }
+               else if (merge_edits) {
                        /*convert from media time to track time*/
                        Double rescale = (Float) gf_isom_get_timescale(dest);
                        rescale /= (Float) gf_isom_get_media_timescale(dest, dst_tk);
index 2051753a97cfa3b15e3e7c2e10c9600faeafdb05..3418979e85189b696dfbff0434b74d1c02c06890 100644 (file)
@@ -213,6 +213,7 @@ void PrintGeneralUsage()
                        "                       * Note 1: some tracks may be removed in the process\n"
                        "                       * Note 2: always on for *.3gp *.3g2 *.3gpp\n"
                        " -ipod                rewrites the file for iPod\n"
+                       " -psp                 rewrites the file for PSP devices\n" 
                        " -brand ABCD[:v]      sets major brand of file, with optional version\n"
                        " -ab ABCD             adds given brand to file's alternate brand list\n"
                        " -rb ABCD             removes given brand from file's alternate brand list\n"
@@ -271,14 +272,21 @@ void PrintDASHUsage()
                        "                       Note: for onDemand profile, sets duration of a subsegment\n"
                        " -frag time_in_ms     Specifies a fragment duration of time_in_ms.\n"
                        "                       * Note: By default, this is the DASH duration\n"
-                       " -out filename        specifies output file name\n"
-                       "                       * Note: By default input (MP4,3GP) file is overwritten\n"
+                       " -out filename        specifies output MPD file name.\n"
                        " -tmp dirname         specifies directory for temporary file creation\n"
                        "                       * Note: Default temp dir is OS-dependent\n"
                        " -profile NAME   specifies the target DASH profile: \"onDemand\", \"live\", \"main\", \"simple\", \"full\"\n"
                        "                       * This will set default option values to ensure conformance to the desired profile\n"
                        "                       * Default profile is \"full\" in static mode, \"live\" in dynamic mode\n"
                        "\n"
+                       "Input media files to dash can use the following modifiers\n"
+                       " \":id=NAME\"         sets the representation ID to NAME\n"
+                       " \":period=NAME\"     sets the representation's period to NAME. Multiple periods may be used\n"
+                       "                       period appear in the MPD in the same order as specified with this option\n"
+                       " \":bandwidth=VALUE\" sets the representation's bandwidth to a given value\n"
+                       " \":role=VALUE\"      sets the role of this representation (cf DASH spec).\n"
+                       "                       media with different roles belong to different adaptation sets.\n"
+                       "\n"
                        " -rap                 segments begin with random access points\n"
                        "                       Note: segment duration may not be exactly what asked by\n"
                        "                       \"-dash\" since encoded video data is not modified\n"
@@ -312,7 +320,7 @@ void PrintDASHUsage()
                        " -daisy-chain         uses daisy-chain SIDX instead of hierarchical. Ignored if frags/sidx is 0.\n"
                        " -single-segment      uses a single segment for the whole file (OnDemand profile). \n"
                        " -single-file         uses a single file for the whole file (default). \n"
-                       " -bs-switching MODE   sets bitstream switching to \"yes\" (default), \"no\" or \"single\" to test with single input.\n" 
+                       " -bs-switching MODE   sets bitstream switching to \"yes\" (default), \"merge\", \"no\" or \"single\" to test with single input.\n" 
                        " -dash-ts-prog N      program_number to be considered in case of an MPTS input file.\n"
                        "\n");
 }
@@ -563,6 +571,7 @@ void PrintExtractUsage()
                        " -saf                 remux file to SAF multiplex\n"
                        " -dvbhdemux           demux DVB-H file into IP Datagrams\n"
                        "                       * Note: can be used when encoding scene descriptions\n"
+                       " -raw-layer ID        same as -raw but skips SVC/MVC extractors when extracting\n" 
                        " -diod                extracts file IOD in raw format when supported\n" 
                        "\n");
 }
@@ -1292,6 +1301,7 @@ GF_DashSegmenterInput *set_dash_input(GF_DashSegmenterInput *dash_inputs, char *
                        if (!strnicmp(opts, "id=", 3)) strncpy(di->representationID, opts+3, 99);
                        else if (!strnicmp(opts, "period=", 7)) strncpy(di->periodID, opts+7, 99);
                        else if (!strnicmp(opts, "bandwidth=", 10)) di->bandwidth = atoi(opts+10);
+                       else if (!strnicmp(opts, "role=", 5)) strncpy(di->role, opts+5, 99);
                        
                        if (!sep) break;
                        sep[0] = ':';
@@ -1321,9 +1331,10 @@ int mp4boxMain(int argc, char **argv)
        s32 subsegs_per_sidx;
        u32 *brand_add = NULL;
        u32 *brand_rem = NULL;
-       u32 i, stat_level, hint_flags, info_track_id, import_flags, nb_add, nb_cat, ismaCrypt, agg_samples, nb_sdp_ex, max_ptime, raw_sample_num, split_size, nb_meta_act, nb_track_act, rtp_rate, major_brand, nb_alt_brand_add, nb_alt_brand_rem, old_interleave, car_dur, minor_version, conv_type, nb_tsel_acts, program_number, bitstream_switching_mode, dump_nal, time_shift_depth;
+       GF_DashSwitchingMode bitstream_switching_mode = GF_DASH_BSMODE_INBAND;
+       u32 i, stat_level, hint_flags, info_track_id, import_flags, nb_add, nb_cat, ismaCrypt, agg_samples, nb_sdp_ex, max_ptime, raw_sample_num, split_size, nb_meta_act, nb_track_act, rtp_rate, major_brand, nb_alt_brand_add, nb_alt_brand_rem, old_interleave, car_dur, minor_version, conv_type, nb_tsel_acts, program_number, dump_nal, time_shift_depth, dash_dynamic;
        Bool HintIt, needSave, FullInter, Frag, HintInter, dump_std, dump_rtp, dump_mode, regular_iod, trackID, remove_sys_tracks, remove_hint, force_new, remove_root_od, import_subtitle, dump_chap;
-       Bool print_sdp, print_info, open_edit, track_dump_type, dump_isom, dump_cr, force_ocr, encode, do_log, do_flat, dump_srt, dump_ttxt, dump_timestamps, do_saf, dump_m2ts, dump_cart, do_hash, verbose, force_cat, align_cat, pack_wgt, single_group, dash_dynamic, dash_live;
+       Bool print_sdp, print_info, open_edit, track_dump_type, dump_isom, dump_cr, force_ocr, encode, do_log, do_flat, dump_srt, dump_ttxt, dump_timestamps, do_saf, dump_m2ts, dump_cart, do_hash, verbose, force_cat, align_cat, pack_wgt, single_group, dash_live;
        char *inName, *outName, *arg, *mediaSource, *tmpdir, *input_ctx, *output_ctx, *drm_file, *avi2raw, *cprt, *chap_file, *pes_dump, *itunes_tags, *pack_file, *raw_cat, *seg_name, *dash_ctx_file;
 
        char **mpd_base_urls = NULL;
@@ -1379,8 +1390,8 @@ int mp4boxMain(int argc, char **argv)
        dump_nal = 0;
        FullInter = HintInter = encode = do_log = old_interleave = do_saf = do_hash = verbose = 0;
        dump_mode = Frag = force_ocr = remove_sys_tracks = agg_samples = remove_hint = keep_sys_tracks = remove_root_od = single_group = 0;
-       conv_type = HintIt = needSave = print_sdp = print_info = regular_iod = dump_std = open_edit = dump_isom = dump_rtp = dump_cr = dump_chap = dump_srt = dump_ttxt = force_new = dump_timestamps = dump_m2ts = dump_cart = import_subtitle = force_cat = pack_wgt = dash_dynamic = dash_live = 0;
-       bitstream_switching_mode = 1;
+       conv_type = HintIt = needSave = print_sdp = print_info = regular_iod = dump_std = open_edit = dump_isom = dump_rtp = dump_cr = dump_chap = dump_srt = dump_ttxt = force_new = dump_timestamps = dump_m2ts = dump_cart = import_subtitle = force_cat = pack_wgt = dash_live = 0;
+       dash_dynamic = 0;
        /*align cat is the new default behaviour for -cat*/
        align_cat = 1;
        subsegs_per_sidx = 0;
@@ -1468,6 +1479,12 @@ int mp4boxMain(int argc, char **argv)
                        trackID = atoi(argv[i+1]);
                        i++;
                }
+               else if (!stricmp(arg, "-raw-layer")) {
+                       CHECK_NEXT_ARG
+                               track_dump_type = GF_EXPORT_NATIVE | GF_EXPORT_SVC_LAYER;
+                       trackID = atoi(argv[i+1]);
+                       i++;
+               }
                else if (!stricmp(arg, "-qcp")) {
                        CHECK_NEXT_ARG
                        track_dump_type = GF_EXPORT_NATIVE | GF_EXPORT_USE_QCP;
@@ -1623,6 +1640,7 @@ int mp4boxMain(int argc, char **argv)
                else if (!stricmp(arg, "-isma")) { conv_type = GF_ISOM_CONV_TYPE_ISMA; open_edit = 1; }
                else if (!stricmp(arg, "-3gp")) { conv_type = GF_ISOM_CONV_TYPE_3GPP; open_edit = 1; }
                else if (!stricmp(arg, "-ipod")) { conv_type = GF_ISOM_CONV_TYPE_IPOD; open_edit = 1; }
+               else if (!stricmp(arg, "-psp")) { conv_type = GF_ISOM_CONV_TYPE_PSP; open_edit = 1; }
                else if (!stricmp(arg, "-ismax")) { conv_type = GF_ISOM_CONV_TYPE_ISMA_EX; open_edit = 1; }
 
                else if (!stricmp(arg, "-no-sys") || !stricmp(arg, "-nosys")) { remove_sys_tracks = 1; open_edit = 1; }
@@ -1685,14 +1703,16 @@ int mp4boxMain(int argc, char **argv)
                        i++;
                } else if (!stricmp(arg, "-bs-switching")) {
                        CHECK_NEXT_ARG
-                       if (!stricmp(argv[i+1], "no") || !stricmp(argv[i+1], "off")) bitstream_switching_mode = 0;
-                       else if (!stricmp(argv[i+1], "single"))  bitstream_switching_mode = 2;
-                       else bitstream_switching_mode = 1;
+                       if (!stricmp(argv[i+1], "no") || !stricmp(argv[i+1], "off")) bitstream_switching_mode = GF_DASH_BSMODE_NONE;
+                       else if (!stricmp(argv[i+1], "merge"))  bitstream_switching_mode = GF_DASH_BSMODE_MERGED;
+                       else if (!stricmp(argv[i+1], "single"))  bitstream_switching_mode = GF_DASH_BSMODE_SINGLE;
+                       else if (!stricmp(argv[i+1], "single_merge"))  bitstream_switching_mode = GF_DASH_BSMODE_SINGLE_MERGED;
+                       else bitstream_switching_mode = GF_DASH_BSMODE_INBAND;
                        i++;
                }
                else if (!stricmp(arg, "-dynamic")) { dash_dynamic = 1; }
-               else if (!strnicmp(arg, "-dash-live", 10)) {
-                       dash_dynamic = 1;
+               else if (!strnicmp(arg, "-dash-live", 10) || !strnicmp(arg, "-ddbg-live", 10)) {
+                       dash_dynamic = !strnicmp(arg, "-ddbg-live", 10) ? 2 : 1;
                        dash_live = 1;
                        if (arg[10]=='=') {
                                dash_ctx_file = arg+11;
@@ -1876,7 +1896,8 @@ int mp4boxMain(int argc, char **argv)
                        tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1));
 
                        tracks[nb_track_act].act_type = 4;
-                       strcpy(szTK, argv[i+1]);
+                       assert(strlen(argv[i+1])+1 <= sizeof(szTK));
+                       strncpy(szTK, argv[i+1], sizeof(szTK));
                        ext = strchr(szTK, '=');
                        if (!ext) {
                                fprintf(stderr, "Bad format for track par - expecting ID=PAR_NUM:PAR_DEN got %s\n", argv[i+1]);
@@ -1885,7 +1906,13 @@ int mp4boxMain(int argc, char **argv)
                        if (!stricmp(ext+1, "none")) {
                                tracks[nb_track_act].par_num = tracks[nb_track_act].par_den = -1;
                        } else {
-                               sscanf(ext+1, "%d:%d", &tracks[nb_track_act].par_num, &tracks[nb_track_act].par_den);
+                               sscanf(ext+1, "%d", &tracks[nb_track_act].par_num);
+                               ext = strchr(ext+1, ':');
+                               if (!ext) {
+                                       fprintf(stderr, "Bad format for track par - expecting ID=PAR_NUM:PAR_DEN got %s\n", argv[i+1]);
+                                       MP4BOX_EXIT_WITH_CODE(1);
+                               }
+                               sscanf(ext+1, "%d", &tracks[nb_track_act].par_den);
                        }
                        ext[0] = 0;
                        tracks[nb_track_act].trackID = atoi(szTK);
@@ -2542,11 +2569,30 @@ int mp4boxMain(int argc, char **argv)
                }
                for (i=0; i<(u32) argc; i++) {
                        if (!strcmp(argv[i], "-add")) {
-                               e = import_file(file, argv[i+1], import_flags, import_fps, agg_samples);
+                               char *src = argv[i+1];
+
+                               e = import_file(file, src, import_flags, import_fps, agg_samples);
                                if (e) {
-                                       fprintf(stderr, "Error importing %s: %s\n", argv[i+1], gf_error_to_string(e));
-                                       gf_isom_delete(file);
-                                       MP4BOX_EXIT_WITH_CODE(1);
+                                       while (src) {
+                                               char *sep = strchr(src, '+');
+                                               if (sep) sep[0] = 0;
+
+                                               e = import_file(file, src, import_flags, import_fps, agg_samples);
+
+                                               if (sep) {
+                                                       sep[0] = '+';
+                                                       src = sep+1;
+                                               } else {
+                                                       src= NULL;
+                                               }
+                                               if (e)
+                                                       break;
+                                       }
+                                       if (e) {
+                                               fprintf(stderr, "Error importing %s: %s\n", argv[i+1], gf_error_to_string(e));
+                                               gf_isom_delete(file);
+                                               MP4BOX_EXIT_WITH_CODE(1);
+                                       }
                                }
                                i++;
                        }
@@ -2706,14 +2752,19 @@ int mp4boxMain(int argc, char **argv)
                                        char c = (char) gf_prompt_get_char(); 
                                        if (c=='q') break;
                                }
-                               fprintf(stderr, "sleep for %d ms\n", sleep_for);
-                               gf_sleep(sleep_for);
+                               if (sleep_for) {
+                                       if (dash_dynamic != 2) {
+                                               fprintf(stderr, "sleep for %d ms\n", sleep_for);
+                                               gf_sleep(sleep_for);
+                                       }
+                               }
                        } else {
                                break;
                        }
                }
 
                if (dash_ctx) gf_cfg_del(dash_ctx);
+               if (e) fprintf(stderr, "Error DASHing file: %s\n", gf_error_to_string(e));
 
                gf_sys_close();
                MP4BOX_EXIT_WITH_CODE( (e!=GF_OK) ? 1 : 0 );
@@ -3172,6 +3223,8 @@ int mp4boxMain(int argc, char **argv)
                                        switch (gf_isom_get_media_subtype(file, i+1, 1)) {
                                        case GF_ISOM_SUBTYPE_AVC_H264:
                                        case GF_ISOM_SUBTYPE_AVC2_H264:
+                                       case GF_ISOM_SUBTYPE_AVC3_H264:
+                                       case GF_ISOM_SUBTYPE_AVC4_H264:
                                                fprintf(stderr, "Forcing AVC/H264 SAR to 1:1...\n");
                                                gf_media_change_par(file, i+1, 1, 1);
                                                break;
@@ -3405,8 +3458,8 @@ int mp4boxMain(int argc, char **argv)
                                n = t = 0;
                                memset(_t, 0, sizeof(char)*8);
                                tlen = (itag==GF_ISOM_ITUNE_DISK) ? 6 : 8;
-                               if (sscanf(val, "%u/%u", &n, &t) == 2) { _t[3]=n; _t[5]=t;}
-                               else if (sscanf(val, "%u", &n) == 1) { _t[3]=n;}
+                               if (sscanf(val, "%u/%u", &n, &t) == 2) { _t[3]=n; _t[2]=n>>8; _t[5]=t; _t[4]=t>>8; }
+                               else if (sscanf(val, "%u", &n) == 1) { _t[3]=n; _t[2]=n>>8;}
                                else tlen = 0;
                                if (tlen) gf_isom_apple_set_tag(file, itag, _t, tlen);
                        }
index caa330b4ab1b0889515d35aaf071d94c108185df..7fcd4591d709a5b86b26d4acc67b57837af8e0cb 100644 (file)
@@ -1155,7 +1155,13 @@ int main (int argc, char **argv)
 
        fprintf(stderr, "Loading modules\n");
        str = gf_cfg_get_key(cfg_file, "General", "ModulesDirectory");
-       assert( str );
+       if (! str ) {
+               fprintf(stderr, "Mmodule directory not found - check the configuration file exit and the \"ModulesDirectory\" key is set\n");
+               gf_cfg_del(cfg_file);
+               gf_sys_close();
+               if (logfile) fclose(logfile);
+               return 1;
+       }
 
        user.modules = gf_modules_new((const unsigned char *) str, cfg_file);
        if (user.modules) i = gf_modules_get_count(user.modules);
index b09aa498e12447df3887a0b9845a787694335843..92b31b662013a7ee323e48400717a169c12b501a 100644 (file)
@@ -29,7 +29,7 @@
 \r
 #include <gpac/base_coding.h>\r
 \r
-#define ADOBE_INLINED_BOOTSTRAP\r
+//#define ADOBE_INLINED_BOOTSTRAP\r
 \r
 struct __tag_adobe_stream\r
 {\r
@@ -47,6 +47,20 @@ struct __tag_adobe_multirate
        GF_List *streams;\r
 };\r
 \r
+static GF_Err adobe_gen_stream_manifest(AdobeStream *as) \r
+{ \r
+       fprintf(as->f, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); \r
+       fprintf(as->f, "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n"); \r
+       fprintf(as->f, "<id>%s</id>\n", as->id); \r
+       if (as->base_url) \r
+               fprintf(as->f, "<baseURL>%s</baseURL>\n", as->base_url); \r
+       fprintf(as->f, "<bootstrapInfo profile=\"named\" id=\"boot_%s_%d\" url=\"%s_%d.bootstrap\"/>\n", as->id, as->bitrate, as->id, as->bitrate); \r
+       fprintf(as->f, "<media url=\"%s_%u_\" bitrate=\"%u\" bootstrapInfoId=\"boot_%s_%d\"/>\n", as->id, as->bitrate, as->bitrate, as->id, as->bitrate); \r
+       fprintf(as->f, "</manifest>\n"); \r
+\r
+       return GF_OK; \r
+}\r
+\r
 AdobeMultirate *adobe_alloc_multirate_manifest(char *id)\r
 {\r
        AdobeMultirate *am = gf_calloc(1, sizeof(AdobeMultirate));\r
@@ -70,6 +84,16 @@ AdobeMultirate *adobe_alloc_multirate_manifest(char *id)
                AdobeStream *as = gf_calloc(1, sizeof(AdobeStream));\r
                as->id = "HD";\r
                as->bitrate = 100;\r
+               sprintf(filename, "%s_%s_%d.f4m", am->id, as->id, as->bitrate); \r
+               as->f = fopen(filename, "wt"); \r
+               if (!as->f) { \r
+                       fprintf(stderr, "Couldn't create Adobe stream manifest file: %s\n", filename); \r
+                       assert(0); \r
+                       gf_list_del(am->streams); \r
+                       gf_free(as); \r
+                       gf_free(am); \r
+                       return NULL; \r
+               } \r
                gf_list_add(am->streams, as);\r
        }\r
 \r
@@ -86,6 +110,8 @@ void adobe_free_multirate_manifest(AdobeMultirate *am)
        for (i=0; i<gf_list_count(am->streams); i++) {\r
                AdobeStream *as = gf_list_get(am->streams, i);\r
                assert(as);\r
+               if (as->f) \r
+                       fclose(as->f); \r
                //TODO: base_url and id may be stored as gf_strdup in the future\r
                gf_list_rem(am->streams, i);\r
                gf_free(as);\r
@@ -97,6 +123,7 @@ void adobe_free_multirate_manifest(AdobeMultirate *am)
 \r
 GF_Err adobe_gen_multirate_manifest(AdobeMultirate* am, char *bootstrap, size_t bootstrap_size)\r
 {\r
+       GF_Err e;\r
        u32 i;\r
 #ifdef ADOBE_INLINED_BOOTSTRAP\r
        char bootstrap64[GF_MAX_PATH];\r
@@ -104,7 +131,7 @@ GF_Err adobe_gen_multirate_manifest(AdobeMultirate* am, char *bootstrap, size_t
 #endif\r
 \r
        fprintf(am->f, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");\r
-       fprintf(am->f, "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n");\r
+       fprintf(am->f, "<manifest xmlns=\"http://ns.adobe.com/f4m/2.0\">\n");\r
        fprintf(am->f, "<id>%s</id>\n", am->id);\r
        fprintf(am->f, "<baseURL>%s</baseURL>\n", am->base_url);\r
     fprintf(am->f, "<streamType>live</streamType>\n");\r
@@ -123,7 +150,6 @@ GF_Err adobe_gen_multirate_manifest(AdobeMultirate* am, char *bootstrap, size_t
                }\r
                fprintf(am->f, "\n</bootstrapInfo>\n");\r
 #else\r
-               fprintf(am->f, "<bootstrapInfo profile=\"named\" id=\"boot_%s_%d\" url=\"%s_%d.bootstrap\"/>\n", as->id, as->bitrate, as->id, as->bitrate);\r
                {\r
                        char filename[GF_MAX_PATH];\r
                        FILE *bstfile;\r
@@ -133,7 +159,13 @@ GF_Err adobe_gen_multirate_manifest(AdobeMultirate* am, char *bootstrap, size_t
                        fclose(bstfile);\r
                }\r
 #endif\r
-               fprintf(am->f, "<media url=\"%s_%s_%d_\" bitrate=\"%d\" bootstrapInfoId=\"boot_%s_%d\"/>\n", am->id, as->id, as->bitrate, as->bitrate, as->id, as->bitrate);\r
+               e = adobe_gen_stream_manifest(as); \r
+               if (!e) { \r
+                       if (!am->base_url && !as->base_url) \r
+                               fprintf(stderr, "Warning: no base_url specified\n"); \r
+\r
+                       fprintf(am->f, "<media href=\"%s_%s_%d.f4m\" bitrate=\"%d\"/>\n", am->id, as->id, as->bitrate, as->bitrate); \r
+               }\r
        }\r
        fprintf(am->f, "</manifest>\n");\r
 \r
index f49284b5d4c5e8c986eb721c48d52ca79940e4e0..9a80b6518b05b15e7125514991e29ea45e99fac8 100644 (file)
@@ -61,7 +61,7 @@ GF_Err adobize_segment(GF_ISOFile *isom_file, AdobeHDSCtx *ctx)
 \r
        afra->entry_count = 1;\r
        ae->time = init_seg_time;\r
-       ae->offset = 31663;\r
+       ae->offset = 3999;\r
        gf_list_add(afra->local_access_entries, ae);\r
 \r
        afra->global_entries = 0;\r
@@ -101,7 +101,7 @@ GF_Err adobize_segment(GF_ISOFile *isom_file, AdobeHDSCtx *ctx)
                asrt->flags = 0;\r
                asrt->segment_run_entry_count = 1;\r
                {\r
-                       asre->first_segment = 1;\r
+                       asre->first_segment = ctx->segnum;\r
                        asre->fragment_per_segment = 1;\r
                }\r
                e = gf_list_add(asrt->segment_run_entry_table, asre);\r
@@ -124,7 +124,7 @@ GF_Err adobize_segment(GF_ISOFile *isom_file, AdobeHDSCtx *ctx)
                afrt->type = GF_4CC('a', 'f', 'r', 't');\r
                afrt->version = 0;\r
                afrt->flags = 0;\r
-               afrt->timescale = 1000;\r
+               afrt->timescale = gf_isom_get_timescale(isom_file);\r
                afrt->fragment_run_entry_count = 1;\r
                {\r
                        afre->first_fragment = 1;\r
index 0e98a52ddd838fe158bd30d25acaeb44adff776b..09fc32b099aadcbe2ef02e742215d832c6c861e2 100644 (file)
@@ -141,8 +141,7 @@ int main(int argc, char **argv)
        e = GF_OK;\r
        memset(&ctx, 0, sizeof(ctx));\r
        \r
-       ctx.multirate_manifest = adobe_alloc_multirate_manifest(output);\r
-       ctx.curr_time = 6000;\r
+       ctx.curr_time = 0;\r
        ctx.segnum = 1;\r
 \r
        /*********************************************/\r
@@ -153,6 +152,8 @@ int main(int argc, char **argv)
                goto exit;\r
        }\r
 \r
+       ctx.multirate_manifest = adobe_alloc_multirate_manifest(output);\r
+\r
 #if 0 /*'moov' conversion tests*/\r
        {\r
                char metamoov64[GF_MAX_PATH];\r
index 0bce1e0f2c38c9439d105c88912b839a8717d5b2..870c6ea671c64b9b27330a95f2fb75de31e36b48 100644 (file)
@@ -46,12 +46,7 @@ js32.dll = 1
 gm_aac_in.dll = 1
 gm_bifs_dec.dll = 1
 gm_ctx_load.dll = 1
-gm_dummy_in.dll = 1
-gm_ffmpeg_in.dll = 1
-avcodec-52.dll = 1
-avformat-52.dll = 1
-avutil-50.dll = 1
-swscale-0.dll = 1
+gm_dummy_in.dll = 1 
 gm_ft_font.dll = 1
 gm_gapi.dll = 1
 gm_gpac_js.dll = 1
@@ -71,7 +66,12 @@ gm_wav_out.dll = 1
 gm_widgetman.dll = 1
 gm_xvid_dec.dll = 1
 gm_ogg.dll = 1
-
+;commenting out ffmpeg since we no longer have a recent version (and no one uses smartphone 2003 anymore ...)
+;gm_ffmpeg_in.dll = 1
+;avcodec-52.dll = 1
+;avformat-52.dll = 1
+;avutil-50.dll = 1
+;swscale-0.dll = 1
 
 ;==================================================
 
index e3220ac75d66bc2b229496062b0f130711e2211e..a5ca4e144a48b480ac6f482fbed1b8063a68ffed 100755 (executable)
--- a/configure
+++ b/configure
@@ -18,13 +18,7 @@ fi
 
 
 #remember the ./configure command line
-for v in "$@"; do
-    r="${v#*=}"
-    l="${v%$r}"
-    test "$r" = "${r#* }" || r="'$r'"
-    GPAC_CONFIGURATION="${GPAC_CONFIGURATION# } ${l}${r}"
-done
-
+GPAC_CONFIGURATION="$@"
 
 TMPC="${TMPDIR1}/gpac-conf-${RANDOM}-$$-${RANDOM}.c"
 TMPH="${TMPDIR1}/gpac-conf-${RANDOM}-$$-${RANDOM}.h"
@@ -150,6 +144,7 @@ disable_isoff_write="no"
 disable_isoff_frag="no"
 disable_isoff_hint="no"
 disable_isoff_frag="no"
+disable_isoff_hds="no"
 disable_streaming="no"
 disable_player="no"
 disable_scenegraph="no"
@@ -283,6 +278,7 @@ Configuration options for libgpac - all options can be enabled with --enable-opt
   --disable-isoff-write    disable ISO File Format edit/write
   --disable-isoff-hint     disable ISO File Format hinting
   --disable-isoff-frag     disable fragments in ISO File Format
+  --disable-isoff-hds      disable HDS support in ISO File Format
   --disable-streaming      disable RTP/RTSP/SDP
   --disable-dvbx           disable DVB-specific tools (MPE, FEC, DSM-CC)
   --disable-vobsub         disable VobSub support
@@ -294,7 +290,7 @@ Configuration options for libgpac - all options can be enabled with --enable-opt
 Extra libraries configuration. You can turn a libray off or force using the local version in gpac/extra_lib/
   --use-js=OPT             force SpiderMonkey ECMAScript OPT=[no,local]
   --use-ft=OPT             force FreeType OPT=[no,local]
-  --use-zlib=OPT           force ZLIB OPT=[no,local]
+  --use-zlib=OPT           force ZLIB OPT=[no,system,local]
   --use-jpeg=OPT           force JPEG OPT=[no,local]
   --use-png=OPT            force PNG OPT=[no,local]
   --use-faad=OPT           force FAAD OPT=[no,local]
@@ -653,7 +649,7 @@ if test "$cross_prefix" = "" ; then
       has_zlib="system"
   fi
 fi
-if test "$has_zlib" = "no" ; then
+if test "$has_zlib" = "force-no" ; then
   if $cc -o $TMPO $TMPC -I"$local_inc/zlib" -L$local_lib -lz 2> /dev/null  ; then
     has_zlib="local"
   fi
@@ -869,6 +865,8 @@ int main( void ) { jsval *vp; JSObject *obj = JS_NewObjectForConstructor(c, vp);
 EOF
                        if $cc -o $TMPO $TMPC $js_flags $LDFLAGS $js_lib 2> /dev/null  ; then
                            js_flags="-DUSE_FFDEV_12 $js_flags"
+                       elif grep JSMutableHandleValue $js_inc/jsapi.h > /dev/null 2>&1 ; then
+                               js_flags="-DUSE_FFDEV_17 $js_flags"
                        elif ! grep JS_ConstructObject $js_inc/jsapi.h > /dev/null 2>&1 ; then
                                js_flags="-DUSE_FFDEV_16 $js_flags"
                        elif grep JSHandleObject $js_inc/jsapi.h > /dev/null 2>&1 ; then
@@ -1713,8 +1711,13 @@ for opt do
                         echo 
                     fi
                 fi
+                               has_zlib=$tmp_has_zlib
+                       elif test "$tmp_has_zlib" = "no" ; then
+                               echo 
+                               echo "WARNING!! : you have forced not to use ZLIB. This will disable some core functionalities of GPAC."
+                               echo 
+                               has_zlib="force-no"
             fi
-            has_png=$tmp_has_png
             ;;
         --use-ogg=*) has_ogg=${opt#--use-ogg=}
             ;;
@@ -1729,7 +1732,7 @@ for opt do
         --enable-pulseaudio=*) has_pulseaudio="yes"
             ;;
 
-        --disable-all) has_pulseaudio="no"; has_alsa="no"; disable_core_tools="yes"; disable_3d="yes"; disable_svg="yes"; disable_vrml="yes"; disable_od="yes"; disable_bifs="yes"; disable_bifs_enc="yes"; disable_laser="yes"; disable_seng="yes"; disable_qtvr="yes";  disable_avi="yes"; disable_ogg="yes"; disable_m2ps="yes"; disable_m2ts="yes"; disable_m2ts_mux="yes"; disable_parsers="yes"; disable_import="yes"; disable_export="yes"; disable_swf="yes"; disable_scene_stats="yes"; disable_scene_dump="yes"; disable_scene_encode="yes"; disable_loader_isoff="yes"; disable_od_dump="yes"; disable_od_parse="yes"; disable_isom_dump="yes"; disable_mcrypt="yes"; disable_isoff="yes"; disable_isoff_write="yes"; disable_isoff_hint="yes"; disable_isoff_frag="yes"; disable_streaming="yes"; disable_x3d="yes"; disable_loader_bt="yes"; disable_loader_xmt="yes"; has_dvb4linux="no"; disable_player="yes"; disable_vobsub="yes"; disable_scenegraph="yes"; disable_dvbx="yes"; disable_ttxt="yes"; disable_saf="yes"; disable_smgr="yes"; disable_mpd="yes"; disable_dash="yes"
+        --disable-all) has_pulseaudio="no"; has_alsa="no"; disable_core_tools="yes"; disable_3d="yes"; disable_svg="yes"; disable_vrml="yes"; disable_od="yes"; disable_bifs="yes"; disable_bifs_enc="yes"; disable_laser="yes"; disable_seng="yes"; disable_qtvr="yes";  disable_avi="yes"; disable_ogg="yes"; disable_m2ps="yes"; disable_m2ts="yes"; disable_m2ts_mux="yes"; disable_parsers="yes"; disable_import="yes"; disable_export="yes"; disable_swf="yes"; disable_scene_stats="yes"; disable_scene_dump="yes"; disable_scene_encode="yes"; disable_loader_isoff="yes"; disable_od_dump="yes"; disable_od_parse="yes"; disable_isom_dump="yes"; disable_mcrypt="yes"; disable_isoff="yes"; disable_isoff_write="yes"; disable_isoff_hint="yes"; disable_isoff_frag="yes"; disable_streaming="yes"; disable_x3d="yes"; disable_loader_bt="yes"; disable_loader_xmt="yes"; has_dvb4linux="no"; disable_player="yes"; disable_vobsub="yes"; disable_scenegraph="yes"; disable_dvbx="yes"; disable_ttxt="yes"; disable_saf="yes"; disable_smgr="yes"; disable_mpd="yes"; disable_dash="yes"; disable_isoff_hds = "yes"
             ;;
 
         --disable-3d) disable_3d="yes"
@@ -1866,6 +1869,10 @@ for opt do
             ;;
         --enable-isoff-frag) disable_isoff_frag="no"
             ;;
+        --disable-isoff-hds) disable_isoff_hds="yes"
+            ;;
+        --enable-isoff-hds) disable_isoff_hds="no"
+            ;;
         --disable-streaming) disable_streaming="yes"
             ;;
         --enable-streaming) disable_streaming="no"
@@ -2405,6 +2412,11 @@ if test "$disable_isoff_frag" = "yes" ; then
     echo "ISO File Format fragments disabled"
     echo "#define GPAC_DISABLE_ISOM_FRAGMENTS" >> $TMPH
 fi
+if test "$disable_isoff_hds" = "yes" ; then
+    echo "ISO File Format Adobe HDS disabled"
+    echo "#define GPAC_DISABLE_ISOM_ADOBE" >> $TMPH
+fi
+
 if test "$disable_streaming" = "yes" ; then
     echo "RTP/RTSP/SDP streaming disabled"
     echo "#define GPAC_DISABLE_STREAMING" >> $TMPH
@@ -2692,6 +2704,9 @@ else
     echo "#define GPAC_HAS_SPIDERMONKEY" >> $TMPH
 fi
 echo "CONFIG_ZLIB=$has_zlib" >> config.mak
+if test "$has_zlib" = "no" ; then
+    echo "#define GPAC_DISABLE_ZLIB" >> $TMPH
+fi
 echo "CONFIG_FT=$has_ft" >> config.mak
 
 echo "CONFIG_JPEG=$has_jpeg" >> config.mak
@@ -2765,6 +2780,7 @@ echo "DISABLE_CORE_TOOLS=$disable_core_tools" >> config.mak
 echo "DISABLE_OD_DUMP=$disable_od_dump" >> config.mak
 echo "DISABLE_OD_PARSE=$disable_od_parse" >> config.mak
 echo "MINIMAL_OD=$disable_od" >> config.mak
+echo "DISABLE_ISOM_ADOBE=$disable_isoff_hds" >> config.mak
 
 if test "$disable_parsers" = "yes" ; then
     disable_m2ts_mux="yes"
index 1062bafc414c681975933268d163e75f4b55d034..1eae4e46d41b5db2ef6ba7605ebc170d5013e33b 100644 (file)
@@ -10,7 +10,7 @@
 <br/>\r
 <b><span style="Font-Size: 24pt">GPAC Configuration file documentation<br/>Version 0.5.0</span></b>\r
 <br/>\r
-<b><span style="Font-Size: 18pt">Last Modified $LastChangedDate: 2012-11-15 18:57:26 +0000 (Thu, 15 Nov 2012) $</span></b>\r
+<b><span style="Font-Size: 18pt">Last Modified $LastChangedDate: 2012-12-06 19:08:32 +0000 (Thu, 06 Dec 2012) $</span></b>\r
 </p>\r
 \r
 <br/><br/>\r
@@ -728,9 +728,12 @@ For debug purposes, instructs the player to switch representation every N segmen
 <b>DisableSwitching</b> [value: <i>yes, no</i>]\r
 <p style="text-indent: 5%">\r
 Disables automatic adaptation logic. Default is no</p>\r
-<b>KeepFiles</b> [value: <i>yes, no</i>]\r
+<b>MemoryStorage</b> [value: <i>yes, no</i>]\r
+<p style="text-indent: 5%">\r
+Files are only stored in memory and destroyed after playback, no disk IO is used. Default is no</p>\r
+<b>UseMaxResolution</b> [value: <i>yes, no</i>]\r
 <p style="text-indent: 5%">\r
-Forces files to be kept on disk. Default is no</p>\r
+Forces the player to set the output video resolution to the max resolution available instead of resizing the window. Default is yes</p>\r
 <b>StartRepresentation</b> [value: <i>minBandwidth, maxBandwidth, minQuality, maxQuality</i>]\r
 <p style="text-indent: 5%">\r
 Instructs the DASH client to start playing the indicated representation before doing any switching. Default is minBandwidth.</p>\r
index 3bd79e6edb003464c040069566368c694cb8294f..c8b4f29d27f03ae27db8527046b45df88c265052 100644 (file)
@@ -220,6 +220,7 @@ u32 gf_ac3_get_channels(u32 acmod);
 u32 gf_ac3_get_bitrate(u32 brcode);
 
 GF_Err gf_avc_get_sps_info(char *sps, u32 sps_size, u32 *sps_id, u32 *width, u32 *height, s32 *par_n, s32 *par_d);
+GF_Err gf_avc_get_pps_info(char *pps, u32 pps_size, u32 *pps_id, u32 *sps_id);
 const char *gf_avc_get_profile_name(u8 video_prof);
 
 #endif /*GPAC_DISABLE_AV_PARSERS*/
index 320d5520aa51f1037c6caf6af3b3475727311943..ae829b5c2e9e7dcaa181eea5b3f36194658faa29 100644 (file)
@@ -58,6 +58,9 @@
 #define MOZILLA_1_8_BRANCH
 #endif
 
+/*zlib enabled*/
+//#define GPAC_DISABLE_ZLIB
+
 /*libjpeg enabled*/
 #define GPAC_HAS_JPEG
 
index eab19e1656206f1d8f6a788ecf72dc64b8b933b0..21409cbb7453fb9bdceef1bd8705fffb8cde799a 100644 (file)
@@ -268,6 +268,8 @@ enum
        GPAC_OTI_VIDEO_AVC = 0x21,
        /*!OTI for AVC Parameter sets streams*/
        GPAC_OTI_VIDEO_AVC_PS = 0x22,
+       /*!OTI for HEVC video */
+       GPAC_OTI_VIDEO_HEVC = 0x23,
        /*!OTI for MPEG-4 AAC streams*/
     GPAC_OTI_AUDIO_AAC_MPEG4 = 0x40,
 
@@ -563,6 +565,40 @@ enum
 #define GF_AVC_TYPE2_SI 9
 
 
+
+/*HEVC NAL unit types*/
+enum {
+       GF_HEVC_NALU_SLICE_TRAIL_N = 0,
+       GF_HEVC_NALU_SLICE_TRAIL_R = 1,
+       GF_HEVC_NALU_SLICE_TSA_N = 2,
+       GF_HEVC_NALU_SLICE_TSA_R = 3,
+       GF_HEVC_NALU_SLICE_STSA_N = 4,
+       GF_HEVC_NALU_SLICE_STSA_R = 5,
+       GF_HEVC_NALU_SLICE_RADL_N = 6,
+       GF_HEVC_NALU_SLICE_RADL_R = 7,
+       GF_HEVC_NALU_SLICE_RASL_N = 8,
+       GF_HEVC_NALU_SLICE_RASL_R = 9,
+
+       GF_HEVC_NALU_SLICE_BLA_W_LP = 16,
+       GF_HEVC_NALU_SLICE_BLA_W_DLP = 17,
+       GF_HEVC_NALU_SLICE_BLA_N_LP = 18,
+
+       GF_HEVC_NALU_SLICE_IDR_W_DLP = 19,
+       GF_HEVC_NALU_SLICE_IDR_N_LP = 20,
+       GF_HEVC_NALU_SLICE_CRA = 21,
+
+       GF_HEVC_NALU_VID_PARAM = 32,
+       GF_HEVC_NALU_SEQ_PARAM = 33,
+       GF_HEVC_NALU_PIC_PARAM = 34,
+       GF_HEVC_NALU_ACCESS_UNIT = 35,
+       GF_HEVC_NALU_END_OF_SEQ = 36,
+       GF_HEVC_NALU_END_OF_STREAM = 37,
+       GF_HEVC_NALU_FILLER_DATA = 38,
+       GF_HEVC_NALU_SEI_PREFIX = 39,
+       GF_HEVC_NALU_SEI_SUFFIX = 40,
+};
+
+
 /*rate sizes - note that these sizes INCLUDE the rate_type header byte*/
 static const unsigned int GF_QCELP_RATE_TO_SIZE [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};
 static const unsigned int GF_QCELP_RATE_TO_SIZE_NB = 7;
index 2f865cf8b3ab3dae058363c73a003afb49f36611..828ea7d64117c88ff8ef4bd3944b02ecaa0cd313 100644 (file)
@@ -83,7 +83,7 @@ struct _gf_dash_io
        /*resetup the file session with a new resource to get - this allows persistent connection usage with HTTP servers*/\r
        GF_Err (*setup_from_url)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, const char *url);\r
        /*set download range for the file session*/\r
-       GF_Err (*set_range)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, u64 start_range, u64 end_range);\r
+       GF_Err (*set_range)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, u64 start_range, u64 end_range, Bool discontinue_cache);\r
        /*initialize the file session - all the headers shall be fetched before returning*/\r
        GF_Err (*init)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session);\r
        /*download the content - synchronous call: all the file shall be fetched before returning*/\r
@@ -142,7 +142,7 @@ const char *gf_dash_get_url(GF_DashClient *dash);
 void gf_dash_get_info(GF_DashClient *dash, const char **title, const char **source);\r
 \r
 /*switches quality up or down*/\r
-void gf_dash_switch_quality(GF_DashClient *dash, Bool switch_up);\r
+void gf_dash_switch_quality(GF_DashClient *dash, Bool switch_up, Bool force_immediate_switch);\r
 \r
 /*indicates whether the DASH client is running or not. For the moment, the DASH client is always run by an internal thread*/\r
 Bool gf_dash_is_running(GF_DashClient *dash);\r
@@ -174,11 +174,13 @@ const char *gf_dash_group_get_segment_mime(GF_DashClient *dash, u32 idx);
 const char *gf_dash_group_get_segment_init_url(GF_DashClient *dash, u32 idx, u64 *start_range, u64 *end_range);\r
 \r
 /*returns the URL and byte range of the next media resource to play in this group. \r
-If switching occured and no bitstream switching is possible, also set the url and byte range of the media file required to intialize the playback\r
+If switching occured, sets switching_index to the new representation index.\r
+If no bitstream switching is possible, also set the url and byte range of the media file required to intialize \r
+the playback of the next segment\r
 original_url is optional and may be used to het the URI of the segment\r
 */\r
 GF_Err gf_dash_group_get_next_segment_location(GF_DashClient *dash, u32 idx, const char **url, u64 *start_range, u64 *end_range, \r
-                                                                                       const char **switching_url, u64 *switching_start_range, u64 *switching_end_range, \r
+                                                                                       s32 *switching_index, const char **switching_url, u64 *switching_start_range, u64 *switching_end_range, \r
                                                                                        const char **original_url);\r
 /*discards the first media resource in the queue of this group*/\r
 void gf_dash_group_discard_segment(GF_DashClient *dash, u32 idx);\r
@@ -209,6 +211,8 @@ void gf_dash_seek(GF_DashClient *dash, Double start_range);
 Double gf_dash_get_playback_start_range(GF_DashClient *dash);\r
 /*when seeking, this flag is set when the seek is outside of the previously playing segment.*/\r
 Bool gf_dash_group_segment_switch_forced(GF_DashClient *dash, u32 idx);\r
+/*get video info for this group if video*/\r
+GF_Err gf_dash_group_get_video_info(GF_DashClient *dash, u32 idx, u32 *max_width, u32 *max_height);\r
 \r
 /*returns the start_time of the first segment in the queue (usually the one being played)*/\r
 Double gf_dash_group_current_segment_start_time(GF_DashClient *dash, u32 idx);\r
@@ -216,6 +220,9 @@ Double gf_dash_group_current_segment_start_time(GF_DashClient *dash, u32 idx);
 /*allow reloading of MPD on the local file system - usefull for testing live generators*/\r
 void gf_dash_allow_local_mpd_update(GF_DashClient *dash, Bool allow_local_mpd_update);\r
 \r
+/*gets media info for representation*/\r
+GF_Err gf_dash_group_get_representation_info(GF_DashClient *dash, u32 idx, u32 representation_idx, u32 *width, u32 *height, u32 *audio_samplerate, u32 *bandwidth, const char **codecs);\r
+\r
 \r
 #endif //GPAC_DISABLE_DASH_CLIENT\r
 \r
index a28f9d21e8d1ca051ea560f91add73d11a4c6cfd..b94b95e4f2688f328968394d6f1aafbf9b87c2b9 100644 (file)
@@ -170,6 +170,9 @@ extern "C" {
         GF_NETIO_SESSION_NOT_CACHED    =       1<<1,
                /*indicates that the connection to the server should be kept once the download is successfully completed*/
         GF_NETIO_SESSION_PERSISTENT =  1<<2,
+               /*file is stored in memory, and the cache name is set to gpac://%u@%p, where %d is the size in bytes and %d is the the pointer to the memory.
+               Memory cached files are destroyed upon downloader destruction*/
+        GF_NETIO_SESSION_MEMORY_CACHE  =       1<<3,
     };
 
 
@@ -318,9 +321,10 @@ extern "C" {
      *\param sess the download session
      *\param start_range HTTP download start range in byte 
      *\param end_range HTTP download end range in byte 
+     *\param discontinue If set, forces a new cache entry if byte range are not continuous. Otherwise a single cache entry is used to reconstruct the file
      *\note this can only be used when the session is not threaded
      */
-       GF_Err gf_dm_sess_set_range(GF_DownloadSession *sess, u64 start_range, u64 end_range);
+       GF_Err gf_dm_sess_set_range(GF_DownloadSession *sess, u64 start_range, u64 end_range, Bool discontinue_cache);
     /*!
      *\brief get cache file name
      *
index afee21fed0011ba57fd4b5d76ee81a414370800d..95f7ee071aeb633db5afe8746323b6e2f2422d2a 100644 (file)
@@ -246,7 +246,7 @@ struct __tag_compositor
        /*options*/
        u32 aspect_ratio, antiAlias, texture_text_mode;
        Bool high_speed, stress_mode;
-       Bool force_opengl_2d;
+       Bool force_opengl_2d, was_opengl;
 #ifdef OPENGL_RASTER
        Bool opengl_raster;
 #endif
@@ -331,7 +331,7 @@ struct __tag_compositor
        /*screen buffer for direct access*/
        GF_VideoSurface hw_surface;
        /*output buffer is configured in video memory*/
-       Bool video_memory, request_video_memory;
+       Bool video_memory, request_video_memory, was_system_memory;
        /*indicate if overlays were prezsent in the previous frame*/
        Bool last_had_overlays;
        GF_RasterCallback raster_callbacks;
index 151cf0bee667511b1b8b6382dedadad086e53c5d..eac338027733af49a7109a7b5d47b1864994dfcb 100644 (file)
@@ -198,8 +198,13 @@ enum
        GF_ISOM_BOX_TYPE_PASP   = GF_4CC( 'p', 'a', 's', 'p' ),
        GF_ISOM_BOX_TYPE_AVC1   = GF_4CC( 'a', 'v', 'c', '1' ),
        GF_ISOM_BOX_TYPE_AVC2   = GF_4CC( 'a', 'v', 'c', '2' ),
+       GF_ISOM_BOX_TYPE_AVC3   = GF_4CC( 'a', 'v', 'c', '3' ),
+       GF_ISOM_BOX_TYPE_AVC4   = GF_4CC( 'a', 'v', 'c', '4' ),
        GF_ISOM_BOX_TYPE_SVCC   = GF_4CC( 's', 'v', 'c', 'C' ),
        GF_ISOM_BOX_TYPE_SVC1   = GF_4CC( 's', 'v', 'c', '1' ),
+       GF_ISOM_BOX_TYPE_HVCC   = GF_4CC( 'h', 'v', 'c', 'C' ),
+       GF_ISOM_BOX_TYPE_HVC1   = GF_4CC( 'h', 'v', 'c', '1' ),
+       GF_ISOM_BOX_TYPE_HEV1   = GF_4CC( 'h', 'e', 'v', '1' ),
 
        /*LASeR extension*/
        GF_ISOM_BOX_TYPE_LSRC   = GF_4CC( 'l', 's', 'r', 'C' ),
@@ -528,6 +533,13 @@ typedef struct
        char *name;
        /*private for editing*/
        Bool is_unpacked;
+       /*private for checking dependency*/
+       u32 originalFile;
+       u32 originalID;
+
+       /*private for SVC/MVC extractors resolution*/
+       s32 extractor_mode;
+       Bool has_base_layer;
 
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS
        u64 dts_at_seg_start;
@@ -788,6 +800,7 @@ typedef struct
        GF_SLConfig *slc;
 } GF_LASeRSampleEntryBox;
 
+/*rewrites avcC based on the given esd - this destroys the esd*/
 GF_Err LSR_UpdateESD(GF_LASeRSampleEntryBox *lsr, GF_ESD *esd);
 
 typedef struct
@@ -841,6 +854,12 @@ typedef struct
        GF_AVCConfig *config;
 } GF_AVCConfigurationBox;
 
+typedef struct
+{
+       GF_ISOM_BOX
+       GF_HEVCConfig *config;
+} GF_HEVCConfigurationBox;
+
 typedef struct
 {
        GF_ISOM_VISUAL_SAMPLE_ENTRY
@@ -851,6 +870,9 @@ typedef struct
        /*avc extensions - we merged with regular 'mp4v' box to handle isma E&A signaling of AVC*/
        GF_AVCConfigurationBox *avc_config;
        GF_AVCConfigurationBox *svc_config;
+       /*hevc extension*/
+       GF_HEVCConfigurationBox *hevc_config;
+
        GF_MPEG4BitRateBox *bitrate;
        /*ext descriptors*/
        GF_MPEG4ExtensionDescriptorsBox *descr;
@@ -861,6 +883,8 @@ typedef struct
 
 } GF_MPEGVisualSampleEntryBox;
 
+Bool gf_isom_is_nalu_based_entry(GF_MediaBox *mdia, GF_SampleEntryBox *_entry);
+GF_Err gf_isom_nalu_sample_rewrite(GF_MediaBox *mdia, GF_ISOSample *sample, u32 sampleNumber, GF_MPEGVisualSampleEntryBox *entry);
 
 /*this is the default visual sdst (to handle unknown media)*/
 typedef struct
@@ -2326,6 +2350,11 @@ GF_Err gf_isom_datamap_add_data(GF_DataMap *ptr, char *data, u32 dataSize);
 #define GF_ISOM_GET_FRAG_SYNC(flag) ( ! ( ( (flag) >> 16) & 0x1))
 #define GF_ISOM_GET_FRAG_DEG(flag)     (flag) & 0x7FFF
 
+#define GF_ISOM_GET_FRAG_LEAD(flag) ( (flag) >> 26) & 0x3
+#define GF_ISOM_GET_FRAG_DEPENDS(flag) ( (flag) >> 24) & 0x3
+#define GF_ISOM_GET_FRAG_DEPENDED(flag) ( (flag) >> 22) & 0x3
+#define GF_ISOM_GET_FRAG_REDUNDANT(flag) ( (flag) >> 20) & 0x3
+
 #define GF_ISOM_GET_FRAG_DEPEND_FLAGS(lead, depends, depended, redundant) ( (lead<<26) | (depends<<24) | (depended<<22) | (redundant<<20) )
 #define GF_ISOM_RESET_FRAG_DEPEND_FLAGS(flags) flags = flags & 0xFFFFF
 
@@ -2416,6 +2445,7 @@ GF_ISOFile *gf_isom_new_movie();
 GF_TrackBox *gf_isom_get_track_from_file(GF_ISOFile *the_file, u32 trackNumber);
 GF_TrackBox *gf_isom_get_track(GF_MovieBox *moov, u32 trackNumber);
 GF_TrackBox *gf_isom_get_track_from_id(GF_MovieBox *moov, u32 trackID);
+GF_TrackBox *gf_isom_get_track_from_original_id(GF_MovieBox *moov, u32 originalID, u32 originalFile);
 u32 gf_isom_get_tracknum_from_id(GF_MovieBox *moov, u32 trackID);
 /*open a movie*/
 GF_ISOFile *gf_isom_open_file(const char *fileName, u32 OpenMode, const char *tmp_dir);
@@ -2444,6 +2474,9 @@ GF_Err Media_RewriteODFrame(GF_MediaBox *mdia, GF_ISOSample *sample);
 GF_Err Media_FindDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNname, u32 *dataRefIndex);
 Bool Media_IsSelfContained(GF_MediaBox *mdia, u32 StreamDescIndex);
 
+
+GF_TrackBox *GetTrackbyID(GF_MovieBox *moov, u32 TrackID);
+
 /*check the TimeToSample for the given time and return the Sample number
 if the entry is not found, return the closest sampleNumber in prevSampleNumber and 0 in sampleNumber
 if the DTS required is after all DTSs in the list, set prevSampleNumber and SampleNumber to 0
@@ -2575,8 +2608,11 @@ GF_Err minf_AddBox(GF_Box *s, GF_Box *a);
 GF_Err mdia_AddBox(GF_Box *s, GF_Box *a);
 GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a);
 
-GF_Err AVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd);
+/*rewrites avcC based on the given esd - this destroys the esd*/
+GF_Err AVC_HEVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd);
 void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc);
+void HEVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc);
+
 GF_Err reftype_AddRefTrack(GF_TrackReferenceTypeBox *ref, u32 trackID, u16 *outRefIndex);
 
 GF_XMLBox *gf_isom_get_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool *is_binary);
@@ -3250,7 +3286,11 @@ GF_Err avcc_Size(GF_Box *s);
 
 GF_Box *avc1_New();
 GF_Box *avc2_New();
+GF_Box *avc3_New();
+GF_Box *avc4_New();
 GF_Box *svc1_New();
+GF_Box *hvc1_New();
+GF_Box *hev1_New();
 
 GF_Box *m4ds_New();
 void m4ds_del(GF_Box *s);
@@ -3846,6 +3886,13 @@ GF_Err cslg_Size(GF_Box *s);
 GF_Err cslg_Read(GF_Box *s, GF_BitStream *bs);
 GF_Err cslg_dump(GF_Box *a, FILE * trace);
 
+GF_Box *hvcc_New();
+void hvcc_del(GF_Box *);
+GF_Err hvcc_Write(GF_Box *s, GF_BitStream *bs);
+GF_Err hvcc_Size(GF_Box *s);
+GF_Err hvcc_Read(GF_Box *s, GF_BitStream *bs);
+GF_Err hvcc_dump(GF_Box *a, FILE * trace);
+
 #endif /*GPAC_DISABLE_ISOM*/
 
 #ifdef __cplusplus
index 4ff8ab12e72e21171046e9fcf1042c707b38fa53..daf53d203bbeca5c5e22f2ecdadc95e7b151b1be 100644 (file)
@@ -49,9 +49,15 @@ GF_Err gf_import_message(GF_MediaImporter *import, GF_Err e, char *format, ...);
 
 /*returns 0 if not a start code, or size of start code (3 or 4 bytes). If start code, bitstream
 is positionned AFTER start code*/
-u32 AVC_IsStartCode(GF_BitStream *bs);
+u32 gf_media_nalu_is_start_code(GF_BitStream *bs);
+
 /*returns size of chunk between current and next startcode (excluding startcode sizes), 0 if no more startcodes (eos)*/
-u32 AVC_NextStartCode(GF_BitStream *bs);
+u32 gf_media_nalu_next_start_code_bs(GF_BitStream *bs);
+
+/*return nb bytes from current data until the next start code and set the size of the next start code (3 or 4 bytes)
+returns data_len if no startcode found and sets sc_size to 0 (last nal in payload)*/
+u32 gf_media_nalu_next_start_code(u8 *data, u32 data_len, u32 *sc_size);
+
 /*returns NAL unit type - bitstream must be sync'ed!!*/
 u8 AVC_NALUType(GF_BitStream *bs);
 Bool SVC_NALUIsSlice(u8 type);
@@ -133,6 +139,7 @@ typedef struct
        u32 slice_group_count;                  /* num_slice_groups_minus1 + 1*/
        /*used to discard repeated SPSs - 0: not parsed, 1 parsed, 2 sent*/
        u32 status;
+
 } AVC_PPS;
 
 typedef struct 
@@ -205,29 +212,163 @@ typedef struct
 
 
 /*return sps ID or -1 if error*/
-s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, u32 *vui_flag_pos);
+s32 gf_media_avc_read_sps(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, u32 *vui_flag_pos);
 /*return pps ID or -1 if error*/
-s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc);
+s32 gf_media_avc_read_pps(char *pps_data, u32 pps_size, AVCState *avc);
 /*return sps ID or -1 if error*/
-s32 AVC_ReadSeqParamSetExtId(char *spse_data, u32 spse_size);
+s32 gf_media_avc_read_sps_ext(char *spse_data, u32 spse_size);
 /*is slice an IDR*/
-Bool AVC_SliceIsIDR(AVCState *avc);
+Bool gf_media_avc_slice_is_IDR(AVCState *avc);
 /*is slice containing intra MB only*/
-Bool AVC_SliceIsIntra(AVCState *avc);
+Bool gf_media_avc_slice_is_intra(AVCState *avc);
 /*parses NALU, updates avc state and returns:
        1 if NALU part of new frame
        0 if NALU part of prev frame
        -1 if bitstream error
 */
-s32 AVC_ParseNALU(GF_BitStream *bs, u32 nal_hdr, AVCState *avc);
+s32 gf_media_avc_parse_nalu(GF_BitStream *bs, u32 nal_hdr, AVCState *avc);
 /*remove SEI messages not allowed in MP4*/
 /*nota: 'buffer' remains unmodified but cannot be set const*/
-u32 AVC_ReformatSEI_NALU(char *buffer, u32 nal_size, AVCState *avc);
+u32 gf_media_avc_reformat_sei(char *buffer, u32 nal_size, AVCState *avc);
 
 #ifndef GPAC_DISABLE_ISOM
-GF_Err AVC_ChangePAR(GF_AVCConfig *avcc, s32 ar_n, s32 ar_d);
+GF_Err gf_media_avc_change_par(GF_AVCConfig *avcc, s32 ar_n, s32 ar_d);
 #endif
 
+
+
+typedef struct
+{
+       Bool profile_present_flag, level_present_flag, tier_flag;
+       u8 profile_space;
+       u8 profile_idc;
+       u32 profile_compatibility_flag;
+       u8 level_idc;
+} HEVC_SublayerPTL;
+
+typedef struct
+{
+       u8 profile_space, tier_flag, profile_idc, level_idc;
+       u32 profile_compatibility_flag;
+       
+       HEVC_SublayerPTL sub_ptl[8];
+} HEVC_ProfileTierLevel;
+
+typedef struct
+{
+       u32 num_negative_pics;
+       u32 num_positive_pics;
+       s32 delta_poc[16];
+} HEVC_ReferencePictureSets;
+
+typedef struct
+{
+       s32 id, vps_id; 
+       /*used to discard repeated SPSs - 0: not parsed, 1 parsed, 2 stored*/
+       u32 state;
+       u32 width, height;
+
+       HEVC_ProfileTierLevel ptl;
+
+       u8 chroma_format_idc;
+       Bool cw_flag ;
+       u32 cw_left, cw_right, cw_top, cw_bottom;
+       u8 bit_depth_luma;
+       u8 bit_depth_chroma;
+       u8 log2_max_pic_order_cnt_lsb;
+       Bool separate_colour_plane_flag;
+
+       u32 max_CU_width, max_CU_height, max_CU_depth;
+       u32 bitsSliceSegmentAddress;
+
+       u32 num_short_term_ref_pic_sets, num_long_term_ref_pic_sps;
+       HEVC_ReferencePictureSets rps[64];
+} HEVC_SPS;
+
+typedef struct
+{
+       s32 id; 
+       u32 sps_id; 
+       /*used to discard repeated SPSs - 0: not parsed, 1 parsed, 2 stored*/
+       u32 state;
+
+       Bool dependent_slice_segments_enabled_flag, tiles_enabled_flag, uniform_spacing_flag;
+       u32 num_extra_slice_header_bits;
+       Bool slice_segment_header_extension_present_flag, output_flag_present_flag;
+} HEVC_PPS;
+
+typedef struct
+{
+       u16 avg_bit_rate, max_bit_rate, avg_pic_rate;
+       u8 constand_pic_rate_idc;
+} HEVC_RateInfo;
+
+typedef struct
+{
+       s32 id; 
+       /*used to discard repeated SPSs - 0: not parsed, 1 parsed, 2 stored*/
+       u32 state;
+       u8 max_sub_layer;
+       HEVC_ProfileTierLevel ptl;
+
+       HEVC_SublayerPTL sub_ptl[8];
+       HEVC_RateInfo rates[8];
+
+} HEVC_VPS;
+
+typedef struct
+{
+       AVCSeiRecoveryPoint recovery_point;
+       AVCSeiPicTiming pic_timing;
+
+} HEVC_SEI;
+
+typedef struct
+{
+       u8 nal_unit_type;
+       s8 temporal_id;
+
+       u32 frame_num, poc_lsb, slice_type;
+
+       s32 redundant_pic_cnt;
+
+       s32 poc;
+       u32 poc_msb, poc_msb_prev, poc_lsb_prev, frame_num_prev;
+       s32 frame_num_offset, frame_num_offset_prev;
+
+       HEVC_SPS *sps;
+       HEVC_PPS *pps;
+} HEVCSliceInfo;
+
+typedef struct
+{
+       HEVC_SPS sps[16]; /* range allowed in the spec is 0..15 */
+       s8 sps_active_idx;      /*currently active sps; must be initalized to -1 in order to discard not yet decodable SEIs*/
+
+       HEVC_PPS pps[64];
+
+       HEVC_VPS vps[16];
+
+       HEVCSliceInfo s_info;
+       HEVC_SEI sei;
+
+       Bool is_svc;
+} HEVCState;
+
+enum
+{
+       GF_HEVC_TYPE_B = 0,
+       GF_HEVC_TYPE_P = 1,
+       GF_HEVC_TYPE_I = 2,
+};
+s32 gf_media_hevc_read_vps(char *data, u32 size, HEVCState *hevc);
+s32 gf_media_hevc_read_sps(char *data, u32 size, HEVCState *hevc);
+s32 gf_media_hevc_read_pps(char *data, u32 size, HEVCState *hevc);
+s32 gf_media_hevc_parse_nalu(GF_BitStream *bs, HEVCState *hevc, u8 *nal_unit_type, u8 *temporal_id);
+Bool gf_media_hevc_slice_is_intra(HEVCState *hevc);
+Bool gf_media_hevc_slice_is_IDR(HEVCState *hevc);
+
+
 #endif /*GPAC_DISABLE_AV_PARSERS*/
 
 typedef struct
index dfee3513e2730c1334e58cbe1973e15d7250f87e..cbb6e42f028cabe38d6bfae75b413c5a32c57602 100644 (file)
@@ -94,7 +94,7 @@ typedef struct
 #define GF_MPD_SEGMENT_BASE    \
        u32 timescale;  \
        u64 presentation_time_offset;   \
-       u32 index_range;        \
+       GF_MPD_ByteRange *index_range;  \
        Bool index_range_exact; \
        GF_MPD_URL *initialization_segment;     \
        GF_MPD_URL *representation_index;       \
@@ -124,6 +124,7 @@ typedef struct
        GF_MPD_ByteRange *media_range;
        char *index;
        GF_MPD_ByteRange *index_range;
+       u64 duration;
 } GF_MPD_SegmentURL;
 
 typedef struct 
@@ -329,6 +330,7 @@ GF_MPD *gf_mpd_new();
 void gf_mpd_del(GF_MPD *mpd);
 /*frees a GF_MPD_SegmentURL structure (type-casted to void *)*/
 void gf_mpd_segment_url_free(void *ptr);
+void gf_mpd_segment_base_free(void *ptr);
 
 typedef struct _gf_file_get GF_FileDownload;
 struct _gf_file_get
index 756347be2a9405bfe4e235a6e79f97438bf14bdf..f53bd1662315b80c72fc42aa80830993cf81442e 100644 (file)
@@ -52,6 +52,10 @@ typedef struct
 /*new APIs*/
 #if (JS_VERSION>=185)
 
+#ifdef USE_FFDEV_17
+#define USE_FFDEV_16
+#endif
+
 #ifdef USE_FFDEV_16
 #define USE_FFDEV_15
 #endif
@@ -85,6 +89,24 @@ typedef double jsdouble;
 #define JS_NewDouble(c, v)     v
 #define JS_PropertyStub_forSetter JS_StrictPropertyStub
 
+#if defined(USE_FFDEV_17)
+
+#define SMJS_DECL_FUNC_PROP_SET(func_name) JSBool func_name(JSContext *c, JSHandleObject __hobj, JSHandleId __hid, JSBool strict, JSMutableHandleValue __vp) 
+#define SMJS_FUNC_PROP_SET(func_name) SMJS_DECL_FUNC_PROP_SET(func_name) { JSObject *obj = *(__hobj._); jsid id = *(__hid._); jsval *vp = __vp._;
+#define SMJS_FUNC_PROP_SET_NOVP(func_name) SMJS_DECL_FUNC_PROP_SET(func_name) { JSObject *obj = *(__hobj._); jsid id = *(__hid._);
+
+#define SMJS_DECL_FUNC_PROP_GET(func_name) JSBool func_name(JSContext *c, JSHandleObject __hobj, JSHandleId __hid, JSMutableHandleValue __vp)
+#define SMJS_FUNC_PROP_GET(func_name) SMJS_DECL_FUNC_PROP_GET( func_name ) { JSObject *obj = *(__hobj._); jsid id = *(__hid._); jsval *vp = __vp._;
+#define SMJS_CALL_PROP_STUB() JS_PropertyStub(c, __hobj, __hid, __vp)
+#define DECL_FINALIZE(func_name) void func_name(JSFreeOp *fop, JSObject *obj) { void *c = NULL;
+
+#define SMJS_FUNCTION_SPEC(__name, __fun, __argc) JS_FS(__name, __fun, __argc, 0)
+#define SMJS_PROPERTY_SPEC(__name, __tinyid, __flags, __getter, __setter) \
+    {__name, __tinyid, __flags, JSOP_WRAPPER(__getter), JSOP_WRAPPER(__setter)}
+
+
+#else
+
 #ifdef USE_FFDEV_15
 
 #define SMJS_DECL_FUNC_PROP_SET(func_name) JSBool func_name(JSContext *c, JSHandleObject __hobj, JSHandleId __hid, JSBool strict, jsval *vp) 
@@ -105,8 +127,14 @@ typedef double jsdouble;
 
 #endif
 
+#define SMJS_FUNC_PROP_SET_NOVP        SMJS_FUNC_PROP_SET
 
 #define SMJS_FUNCTION_SPEC(__name, __fun, __argc) {__name, __fun, __argc, 0}
+#define SMJS_PROPERTY_SPEC(__name, __tinyid, __flags, __getter, __setter) \
+    {__name, __tinyid, __flags, __getter, __setter}
+
+#endif
+
 #define SMJS_FUNCTION(__name) __name(JSContext *c, uintN argc, jsval *argsvp)
 #define SMJS_FUNCTION_EXT(__name, __ext) __name(JSContext *c, uintN argc, jsval *argsvp, __ext)
 #define SMJS_ARGS      jsval *argv = JS_ARGV(c, argsvp);
@@ -178,6 +206,7 @@ typedef double jsdouble;
 
 #define SMJS_DECL_FUNC_PROP_SET(func_name) JSBool func_name(JSContext *c, JSObject *obj, jsval id, jsval *vp)
 #define SMJS_FUNC_PROP_SET(func_name) SMJS_DECL_FUNC_PROP_SET(func_name) {
+#define SMJS_FUNC_PROP_SET_NOVP        SMJS_FUNC_PROP_SET
 #define SMJS_DECL_FUNC_PROP_GET(func_name) JSBool func_name(JSContext *c, JSObject *obj, jsval id, jsval *vp) 
 #define SMJS_FUNC_PROP_GET(func_name) SMJS_DECL_FUNC_PROP_GET( func_name) { 
 #define DECL_FINALIZE(func_name) void func_name(JSContext *c, JSObject *obj) {
@@ -187,6 +216,7 @@ typedef double jsdouble;
 #define SMJS_PROP_GETTER jsval id
 #define JS_PropertyStub_forSetter JS_PropertyStub
 #define SMJS_FUNCTION_SPEC(__name, __fun, __argc) {__name, __fun, __argc, 0, 0}
+#define SMJS_PROPERTY_SPEC(__name, __tinyid, __flags, __getter, __setter) {__name, __tinyid, __flags, __getter, __setter}
 #define SMJS_FUNCTION(__name) __name(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 #define SMJS_FUNCTION_EXT(__name, __ext) __name(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, __ext)
 #define SMJS_ARGS
index 9c001f2b89b6e063032eef500e05298837227bf7..73aa5f539d71628fae892c90e795c50ed91ee17d 100644 (file)
@@ -179,7 +179,11 @@ enum
        GF_AVCConfig to MPEG-4 ESD*/
        GF_ISOM_SUBTYPE_AVC_H264                = GF_4CC( 'a', 'v', 'c', '1' ),
        GF_ISOM_SUBTYPE_AVC2_H264               = GF_4CC( 'a', 'v', 'c', '2' ),
+       GF_ISOM_SUBTYPE_AVC3_H264               = GF_4CC( 'a', 'v', 'c', '3' ),
+       GF_ISOM_SUBTYPE_AVC4_H264               = GF_4CC( 'a', 'v', 'c', '4' ),
        GF_ISOM_SUBTYPE_SVC_H264                = GF_4CC( 's', 'v', 'c', '1' ),
+       GF_ISOM_SUBTYPE_HVC1                    = GF_4CC( 'h', 'v', 'c', '1' ),
+       GF_ISOM_SUBTYPE_HEV1                    = GF_4CC( 'h', 'e', 'v', '1' ),
 
        /*3GPP(2) extension subtypes*/
        GF_ISOM_SUBTYPE_3GP_H263                = GF_4CC( 's', '2', '6', '3' ),
@@ -413,6 +417,9 @@ u32 gf_isom_get_track_id(GF_ISOFile *the_file, u32 trackNumber);
 /*return the track number of the track of specified ID, or 0 if error*/
 u32 gf_isom_get_track_by_id(GF_ISOFile *the_file, u32 trackID);
 
+/*return the original trackID of the track number n, or 0 if error*/
+u32 gf_isom_get_track_original_id(GF_ISOFile *movie, u32 trackNumber);
+
 /*gets the enable flag of a track 0: NO, 1: yes, 2: error*/
 u8 gf_isom_is_track_enabled(GF_ISOFile *the_file, u32 trackNumber);
 
@@ -625,8 +632,13 @@ return -1 if error, 0 if the reference is a NULL one, or the trackNumber
 */
 GF_Err gf_isom_get_reference(GF_ISOFile *the_file, u32 trackNumber, u32 referenceType, u32 referenceIndex, u32 *refTrack);
 
-/*Return 1 if the given track has a reference to the given TreckID of a given ReferenceType, 0 otherwise*/
-Bool gf_isom_has_track_reference(GF_ISOFile *movie, u32 trackNumber, u32 referenceType, u32 refTrackID);
+/*Return the referenced track ID for a track and a given ReferenceType and Index
+return -1 if error, 0 if the reference is a NULL one, or the trackNumber
+*/
+GF_Err gf_isom_get_reference_ID(GF_ISOFile *the_file, u32 trackNumber, u32 referenceType, u32 referenceIndex, u32 *refTrackID);
+
+/*Return referenceIndex if the given track has a reference to the given TreckID of a given ReferenceType, 0 otherwise*/
+u32 gf_isom_has_track_reference(GF_ISOFile *movie, u32 trackNumber, u32 referenceType, u32 refTrackID);
 
 u8 gf_isom_get_pl_indication(GF_ISOFile *the_file, u8 PL_Code);
 
@@ -794,6 +806,9 @@ GF_Err gf_isom_set_track_creation_time(GF_ISOFile *movie,u32 trackNumber, u64 ti
 returns error if trackID is already in used in the file*/
 GF_Err gf_isom_set_track_id(GF_ISOFile *the_file, u32 trackNumber, u32 trackID);
 
+/*force to rewrite all dependencies when trackID changes*/
+GF_Err gf_isom_rewrite_track_dependencies(GF_ISOFile *movie, u32 trackNumber);
+
 /*Add samples to a track. Use streamDescriptionIndex to specify the desired stream (if several)*/
 GF_Err gf_isom_add_sample(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, GF_ISOSample *sample);
 
@@ -1556,6 +1571,9 @@ GF_AVCConfig *gf_isom_avc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32
 /*gets uncompressed SVC config - user is responsible for deleting it*/
 GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex);
 
+/*gets uncompressed HEVC config - user is responsible for deleting it*/
+GF_HEVCConfig *gf_isom_hevc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex);
+
 typedef enum
 {
        GF_ISOM_AVCTYPE_NONE=0,
@@ -1563,8 +1581,27 @@ typedef enum
        GF_ISOM_AVCTYPE_AVC_SVC,
        GF_ISOM_AVCTYPE_SVC_ONLY,
 } GF_ISOMAVCType;
+
 u32 gf_isom_get_avc_svc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex);
 
+
+enum
+{
+       /*all extractors are rewritten*/
+       GF_ISOM_NALU_EXTRACT_DEFAULT = 0,
+       /*all extractors are skipped but NALU data from this track is kept*/
+       GF_ISOM_NALU_EXTRACT_LAYER_ONLY,
+       /*all extractors are kept (untouched sample) - used for dumping modes*/
+       GF_ISOM_NALU_EXTRACT_INSPECT,
+       /*above mode is applied and PPS/SPS/... are appended in the front of every IDR*/
+       GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG = 1<<16,
+       /*above mode is applied and all start codes are rewritten*/
+       GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG = 2<<16,
+};
+
+GF_Err gf_isom_set_nalu_extract_mode(GF_ISOFile *the_file, u32 trackNumber, u32 nalu_extract_mode);
+u32 gf_isom_get_nalu_extract_mode(GF_ISOFile *the_file, u32 trackNumber);
+
 #ifndef GPAC_DISABLE_ISOM_WRITE
 /*creates new AVC config*/
 GF_Err gf_isom_avc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex);
@@ -1576,6 +1613,16 @@ GF_Err gf_isom_svc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 Desc
 GF_Err gf_isom_svc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex);
 /*deletes SVC config*/
 GF_Err gf_isom_svc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex);
+
+/*sets avc3 entry type (inband SPS/PPS) instead of of avc1 (SPS/PPS in avcC box)*/
+GF_Err gf_isom_avc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex);
+
+
+/*creates new AVC config*/
+GF_Err gf_isom_hevc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_HEVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex);
+/*updates AVC config*/
+GF_Err gf_isom_hevc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg);
+
 #endif /*GPAC_DISABLE_ISOM_WRITE*/
 
 
index f860a7cfc8868c61d6c8dcc20e64bbda22cc7749..010f06421618717b63c08052f040e4169e5c8f67 100644 (file)
@@ -268,6 +268,7 @@ typedef struct
        char *file_name;
        char representationID[100];
        char periodID[100];
+       char role[100];
        u32 bandwidth;
 } GF_DashSegmenterInput;
 
@@ -283,13 +284,24 @@ typedef enum
        GF_DASH_PROFILE_UNKNOWN
 } GF_DashProfile;
 
+
+typedef enum
+{
+       GF_DASH_BSMODE_NONE = 0,
+       GF_DASH_BSMODE_INBAND,
+       GF_DASH_BSMODE_MERGED,
+       GF_DASH_BSMODE_SINGLE,
+       GF_DASH_BSMODE_SINGLE_MERGED,
+
+} GF_DashSwitchingMode;
+
 GF_Err gf_dasher_segment_files(const char *mpd_name, GF_DashSegmenterInput *inputs, u32 nb_inputs, GF_DashProfile profile, 
                                                           const char *mpd_title, const char *mpd_source, const char *mpd_copyright,
                                                           const char *mpd_moreInfoURL, const char **mpd_base_urls, u32 nb_mpd_base_urls, 
-                                                          Bool use_url_template, Bool single_segment, Bool single_file, Bool bitstream_switching_mode,
+                                                          Bool use_url_template, Bool single_segment, Bool single_file, GF_DashSwitchingMode bitstream_switching_mode,
                                                           Bool segments_start_with_rap, Double dash_duration_sec, char *seg_rad_name, char *seg_ext,
                                                           Double frag_duration_sec, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool fragments_start_with_rap, const char *tmp_dir,  
-                                                          GF_Config *dash_ctx, Bool dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double subduration);
+                                                          GF_Config *dash_ctx, u32 dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double subduration);
 
 /*returns time to wait until end of currently generated segments*/
 u32 gf_dasher_next_update_time(GF_Config *dash_ctx, u32 mpd_update_time);
@@ -339,6 +351,8 @@ enum
        GF_EXPORT_USE_QCP = (1<<11),
        /*indicates full NHML dump*/
        GF_EXPORT_NHML_FULL = (1<<11),
+       /**/
+       GF_EXPORT_SVC_LAYER = (1<<12),
        /*ony probes extraction format*/
        GF_EXPORT_PROBE_ONLY = (1<<30),
        /*when set by user during export, will abort*/
index 388079fb07fc5255f4d89f2ad0f37d4556b4005d..e0b0575ac12454db2114f3dc3740ff9030f75b2e 100644 (file)
@@ -94,6 +94,9 @@ typedef enum
        GF_NET_SERVICE_INFO,
        /*checks if there is an audio stream in the service - term->net only*/
        GF_NET_SERVICE_HAS_AUDIO,
+
+       /*checks if there is a forced video size  - if yes, info is stored in GF_NetComPixelAR - term->net only*/
+       GF_NET_SERVICE_HAS_FORCED_VIDEO_SIZE,
        /*instructs the service to get the migration info - term->net only*/
        GF_NET_SERVICE_MIGRATION_INFO,
 
index a31acfb87bd12b1303c6e8992464ca6c53aee366..4f0517356e069f4ed9aded8990bfbd65bb736ebd 100644 (file)
@@ -697,6 +697,9 @@ typedef struct
        GF_List *IPIDataSet;
        GF_List *IPMPDescriptorPointers;
        GF_List *extensionDescriptors;
+
+       /* 1 if this stream is referenced by type GF_ISOM_REF_BASE, 0 otherwise*/
+       Bool has_ref_base;
 } GF_ESD;
 
 
@@ -880,6 +883,36 @@ typedef struct
 } GF_AVCConfig;
 
 
+
+/*used for SPS/PPS/VPS/SEI*/
+typedef struct
+{
+       u8 type;
+       u8 array_completeness;
+       GF_List *nalus;
+} GF_HEVCParamArray;
+
+
+typedef struct 
+{
+       u8 configurationVersion;
+       u8 profile_space;
+       u8 profile_idc;
+       u8 constraint_indicator_flags;
+       u8 level_idc;
+       u32 profile_compatibility_indications;
+       u8 chromaFormat;
+       u8 luma_bit_depth;
+       u8 chroma_bit_depth;
+       u16 avgFrameRate;
+       u8 constantFrameRate;
+       u8 numTemporalLayers;
+
+       u8 nal_unit_size;
+       
+       GF_List *param_array;
+} GF_HEVCConfig;
+
 /************************************************************
                                Media Control Extensions
 ************************************************************/
@@ -1073,6 +1106,14 @@ GF_AVCConfig *gf_odf_avc_cfg_read(char *dsi, u32 dsi_size);
 /*writes GF_AVCConfig as MPEG-4 DSI*/
 GF_Err gf_odf_avc_cfg_write(GF_AVCConfig *cfg, char **outData, u32 *outSize);
 
+
+GF_HEVCConfig *gf_odf_hevc_cfg_new();
+void gf_odf_hevc_cfg_del(GF_HEVCConfig *cfg);
+GF_Err gf_odf_hevc_cfg_write_bs(GF_HEVCConfig *cfg, GF_BitStream *bs);
+GF_Err gf_odf_hevc_cfg_write(GF_HEVCConfig *cfg, char **outData, u32 *outSize);
+GF_HEVCConfig *gf_odf_hevc_cfg_read_bs(GF_BitStream *bs);
+GF_HEVCConfig *gf_odf_hevc_cfg_read(char *dsi, u32 dsi_size);
+
 /*destroy the descriptors in a list but not the list*/
 GF_Err gf_odf_desc_list_del(GF_List *descList);
 
index 6bf26acc55e506cb2671db195025b3c1ec610280..f4ef599837d70025a6788d78217c81956fc9c2f0 100644 (file)
@@ -206,6 +206,7 @@ enum
        GF_M2TS_SYSTEMS_MPEG4_SECTIONS  = 0x13,
 
        GF_M2TS_VIDEO_H264                              = 0x1B,
+       GF_M2TS_VIDEO_HEVC                              = 0x24,
 
        GF_M2TS_AUDIO_AC3                               = 0x81,
        GF_M2TS_AUDIO_DTS                               = 0x8A,
@@ -758,6 +759,8 @@ struct tag_m2ts_demux
        u32 stb_at_last_pcr;
        u32 nb_pck;
        Bool loop_demux;
+       const char *ts_data_chunk;
+       u32 ts_data_chunk_size;
 
        /* "Network" =  "MobileIP", "DefaultMCastInterface" */
        Bool MobileIPEnabled;
index cbf8d09227730e6765926dd81aeac9528cb4f663..59e2d871228364886ceff96209fddf4a742a8ba2 100644 (file)
@@ -425,6 +425,11 @@ void gf_memory_print(void); /*prints the state of current allocations*/
        
 /*safety checks on macros*/
 
+#ifdef GPAC_DISABLE_ZLIB
+# define GPAC_DISABLE_LOADER_BT
+# define GPAC_DISABLE_SWF_IMPORT
+#endif
+
 #ifdef GPAC_DISABLE_VRML
 # ifndef GPAC_DISABLE_BIFS
 # define GPAC_DISABLE_BIFS
index bd99679476bc8a023ee10502430046b64fcf2ff4..fa08ffc4fb256dbe8e0196078b0d3cc5900eaa20 100644 (file)
@@ -690,7 +690,7 @@ GF_Err gf_cleanup_dir(char* DirPathName);
  *     \param size buffer size
  *     \return computed CRC32
  */
-u32 gf_crc_32(char *data, u32 size);
+u32 gf_crc_32(const char *data, u32 size);
 
 
 /*!\brief run-time system info object
index 592cee2ff47150795ee083f331027e6c1e0324fe..af5efe4909a75a2c7fb97df8990fa58d4e522d44 100644 (file)
@@ -696,88 +696,104 @@ redecode:
        w = ctx->width;
        h = ctx->height;
 
-       if (ffd->check_h264_isma) {
-               /*for AVC bitstreams after ISMA decryption, in case (as we do) the decryption DRM tool
-               doesn't put back nalu size, do it ourselves...*/
-               if (inBuffer && !inBuffer[0] && !inBuffer[1] && !inBuffer[2] && (inBuffer[3]==0x01)) {
-                       u32 nalu_size;
-                       char *start, *end, *bufferEnd;
-
-                       start = inBuffer;
-                       end = inBuffer + 4;
-                       bufferEnd = inBuffer + inBufferLength;
-                       /* FIXME : SOUCHAY : not sure of exact behaviour, but old one was reading non-allocated memory */
-                       while ((end+3) < bufferEnd) {
-                               if (!end[0] && !end[1] && !end[2] && (end[3]==0x01)) {
-                                       nalu_size = end - start - 4;
-                                       start[0] = (nalu_size>>24)&0xFF;
-                                       start[1] = (nalu_size>>16)&0xFF;
-                                       start[2] = (nalu_size>>8)&0xFF;
-                                       start[3] = (nalu_size)&0xFF;
-                                       start = end;
-                                       end = start+4;
-                                       continue;
+       /*we have a valid frame not yet dispatched*/
+       if (ffd->had_pic) {
+               ffd->had_pic = 0;
+               gotpic = 1;
+       } else {
+               if (ffd->check_h264_isma) {
+                       /*for AVC bitstreams after ISMA decryption, in case (as we do) the decryption DRM tool
+                       doesn't put back nalu size, do it ourselves...*/
+                       if (inBuffer && !inBuffer[0] && !inBuffer[1] && !inBuffer[2] && (inBuffer[3]==0x01)) {
+                               u32 nalu_size;
+                               char *start, *end, *bufferEnd;
+
+                               start = inBuffer;
+                               end = inBuffer + 4;
+                               bufferEnd = inBuffer + inBufferLength;
+                               /* FIXME : SOUCHAY : not sure of exact behaviour, but old one was reading non-allocated memory */
+                               while ((end+3) < bufferEnd) {
+                                       if (!end[0] && !end[1] && !end[2] && (end[3]==0x01)) {
+                                               nalu_size = end - start - 4;
+                                               start[0] = (nalu_size>>24)&0xFF;
+                                               start[1] = (nalu_size>>16)&0xFF;
+                                               start[2] = (nalu_size>>8)&0xFF;
+                                               start[3] = (nalu_size)&0xFF;
+                                               start = end;
+                                               end = start+4;
+                                               continue;
+                                       }
+                                       end++;
                                }
-                               end++;
+                               nalu_size = (inBuffer+inBufferLength) - start - 4;
+                               start[0] = (nalu_size>>24)&0xFF;
+                               start[1] = (nalu_size>>16)&0xFF;
+                               start[2] = (nalu_size>>8)&0xFF;
+                               start[3] = (nalu_size)&0xFF;
+                               ffd->check_h264_isma = 2;
+                       }
+                       /*if we had ISMA E&A and lost it this is likely due to a pck loss - do NOT switch back to regular*/
+                       else if (ffd->check_h264_isma == 1) {
+                               ffd->check_h264_isma = 0;
                        }
-                       nalu_size = (inBuffer+inBufferLength) - start - 4;
-                       start[0] = (nalu_size>>24)&0xFF;
-                       start[1] = (nalu_size>>16)&0xFF;
-                       start[2] = (nalu_size>>8)&0xFF;
-                       start[3] = (nalu_size)&0xFF;
-                       ffd->check_h264_isma = 2;
-               }
-               /*if we had ISMA E&A and lost it this is likely due to a pck loss - do NOT switch back to regular*/
-               else if (ffd->check_h264_isma == 1) {
-                       ffd->check_h264_isma = 0;
                }
-       }
 
-#ifdef USE_AVCODEC2
-       if (avcodec_decode_video2(ctx, frame, &gotpic, &pkt) < 0) {
-#else
-       if (avcodec_decode_video(ctx, frame, &gotpic, inBuffer, inBufferLength) < 0) {
-#endif
-               if (!ffd->check_short_header) {
-                       return GF_NON_COMPLIANT_BITSTREAM;
-               }
+       #ifdef USE_AVCODEC2
+               if (avcodec_decode_video2(ctx, frame, &gotpic, &pkt) < 0) {
+       #else
+               if (avcodec_decode_video(ctx, frame, &gotpic, inBuffer, inBufferLength) < 0) {
+       #endif
+                       if (!ffd->check_short_header) {
+                               return GF_NON_COMPLIANT_BITSTREAM;
+                       }
 
-               /*switch to H263 (ffmpeg MPEG-4 codec doesn't understand short headers)*/
-               {
-                       u32 old_codec = (*codec)->id;
-                       ffd->check_short_header = 0;
-                       /*OK we loose the DSI stored in the codec context, but H263 doesn't need any, and if we're
-                       here this means the DSI was broken, so no big deal*/
-                       avcodec_close(ctx);
-                       *codec = avcodec_find_decoder(CODEC_ID_H263);
-                       if (! (*codec) || (avcodec_open(ctx, *codec)<0)) return GF_NON_COMPLIANT_BITSTREAM;
-#if USE_AVCODEC2
-                       if (avcodec_decode_video2(ctx, frame, &gotpic, &pkt) < 0) {
-#else
-                       if (avcodec_decode_video(ctx, frame, &gotpic, inBuffer, inBufferLength) < 0) {
-#endif
-                               /*nope, stay in MPEG-4*/
+                       /*switch to H263 (ffmpeg MPEG-4 codec doesn't understand short headers)*/
+                       {
+                               u32 old_codec = (*codec)->id;
+                               ffd->check_short_header = 0;
+                               /*OK we loose the DSI stored in the codec context, but H263 doesn't need any, and if we're
+                               here this means the DSI was broken, so no big deal*/
                                avcodec_close(ctx);
-                               *codec = avcodec_find_decoder(old_codec);
-                               assert(*codec);
-                               avcodec_open(ctx, *codec);
-                               return GF_NON_COMPLIANT_BITSTREAM;
+                               *codec = avcodec_find_decoder(CODEC_ID_H263);
+                               if (! (*codec) || (avcodec_open(ctx, *codec)<0)) return GF_NON_COMPLIANT_BITSTREAM;
+       #if USE_AVCODEC2
+                               if (avcodec_decode_video2(ctx, frame, &gotpic, &pkt) < 0) {
+       #else
+                               if (avcodec_decode_video(ctx, frame, &gotpic, inBuffer, inBufferLength) < 0) {
+       #endif
+                                       /*nope, stay in MPEG-4*/
+                                       avcodec_close(ctx);
+                                       *codec = avcodec_find_decoder(old_codec);
+                                       assert(*codec);
+                                       avcodec_open(ctx, *codec);
+                                       return GF_NON_COMPLIANT_BITSTREAM;
+                               }
                        }
                }
-       }
 
-       if (!gotpic && (!ctx->width || !ctx->height) ) {
-               ctx->width = w;
-               ctx->height = h;
-               return GF_OK;
+       /*
+               if (!gotpic && (!ctx->width || !ctx->height) ) {
+                       ctx->width = w;
+                       ctx->height = h;
+                       return GF_OK;
+               }
+       */
+               /*some streams use odd width/height frame values*/
+               if (ffd->out_pix_fmt == GF_PIXEL_YV12) {
+                       if (ctx->width%2) ctx->width++;
+                       if (ctx->height%2) ctx->height++;
+               }
        }
 
-       /*some streams use odd width/height frame values*/
-       if (ffd->out_pix_fmt == GF_PIXEL_YV12) {
-               if (ctx->width%2) ctx->width++;
-               if (ctx->height%2) ctx->height++;
+       /*we have a picture and need resize, do it*/
+       if (gotpic && ffd->needs_output_resize) {
+               ffd->needs_output_resize=0;
+               ffd->had_pic = 1;
+               *outBufferLength = ffd->out_size;
+               return GF_BUFFER_TOO_SMALL;
        }
 
+
        /*recompute outsize in case on-the-fly change*/
        if ((w != ctx->width) || (h != ctx->height)) {
                outsize = ctx->width * ctx->height * 3;
@@ -787,6 +803,17 @@ redecode:
                        ffd->yuv_size = 3 * ctx->width * ctx->height / 2;
                }
                ffd->out_size = outsize;
+
+               if (!ffd->no_par_update && ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) {
+                       ffd->previous_par = (ctx->sample_aspect_ratio.num<<16) | ctx->sample_aspect_ratio.den;
+               }
+
+               /*we didn't get any picture: wait for a picture before resizing output buffer, otherwise we will have no 
+               video in the output buffer*/
+               if (!gotpic) {
+                       ffd->needs_output_resize = 1;
+                       return GF_OK;
+               }
                *outBufferLength = ffd->out_size;
                if (ffd->check_h264_isma) {
                        inBuffer[0] = inBuffer[1] = inBuffer[2] = 0;
@@ -798,17 +825,21 @@ redecode:
                        *cached_sws = NULL;
                }
 #endif
-               if (!ffd->no_par_update && ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) {
-                       ffd->previous_par = (ctx->sample_aspect_ratio.num<<16) | ctx->sample_aspect_ratio.den;
-               }
+               ffd->had_pic = 1;
                return GF_BUFFER_TOO_SMALL;
        }
        /*check PAR in case on-the-fly change*/
        if (!ffd->no_par_update && ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) {
                u32 new_par = (ctx->sample_aspect_ratio.num<<16) | ctx->sample_aspect_ratio.den;
-               if (new_par != ffd->previous_par) {
+               if (ffd->previous_par && (new_par != ffd->previous_par)) {
                        ffd->previous_par = new_par;
+
+                       if (!gotpic) {
+                               ffd->needs_output_resize = 1;
+                               return GF_OK;
+                       }
                        *outBufferLength = ffd->out_size;
+                       ffd->had_pic = 1;
                        return GF_BUFFER_TOO_SMALL;
                }
        }
@@ -955,6 +986,9 @@ static u32 FFDEC_CanHandleStream(GF_BaseDecoder *plug, u32 StreamType, GF_ESD *e
                                GF_AVCConfig *cfg = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
                                if (!cfg) return GF_CODEC_SUPPORTED;
 
+                               if (esd->has_ref_base)
+                                       is_svc = 1;
+
                                /*decode all NALUs*/
                                count = gf_list_count(cfg->sequenceParameterSets);
                                for (i=0; i<count; i++) {
index 5f90198380154d1da172e645931e529f7c513757..f35f480bca95e1b7ba4b0cc48759280d77cf1676 100644 (file)
@@ -107,6 +107,8 @@ typedef struct
        u32 oti, st;
        u32 previous_par;
        Bool no_par_update;
+       Bool needs_output_resize;
+       Bool had_pic;
 
        Bool check_short_header;
        u32 pix_fmt;
index b8cfee7e56bba44c58aa8bb4f58e98756eb58756..4e8595ac94d1391b0d2ab23a5f8b62f0bfffb11d 100644 (file)
@@ -38,8 +38,8 @@
 #include <gpac/thread.h>
 
 
-#ifndef FREENECT_RESOLUTION_HIGH
-//#define FREENECT_MINIMAL
+#if !defined(FREENECT_DEVICE_CAMERA) && defined(FREENECT_FRAME_W)
+#define FREENECT_MINIMAL
 #endif
 
 
index 2144838c839739affeadb70b459e44d80e9821be..4004f480bb2f5cb3f338eab48b08fcc729599078 100644 (file)
@@ -849,21 +849,21 @@ static void gjs_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext
        GF_JSAPIParam par;
 
        JSPropertySpec gpacEvtClassProps[] = {
-               {"type",                         0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {"keycode",                      1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {"mouse_x",                      2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {"mouse_y",                      3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {"picked",                       4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {"wheel",                        5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {"button",                       6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-               {0, 0, 0, 0, 0}
+               SMJS_PROPERTY_SPEC("type",                       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC("keycode",                    1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC("mouse_x",                    2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC("mouse_y",                    3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC("picked",                     4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC("wheel",                      5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC("button",                     6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
        };
        JSFunctionSpec gpacEvtClassFuncs[] = {
                SMJS_FUNCTION_SPEC(0, 0, 0)
        };
 
        JSPropertySpec gpacClassProps[] = {
-               {0, 0, 0, 0, 0}
+               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
        };
        JSFunctionSpec gpacClassFuncs[] = {
                SMJS_FUNCTION_SPEC("getOption",         gpac_getOption, 3),
@@ -906,7 +906,6 @@ static void gjs_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext
 
        if (!scene) return;
 
-
        JS_SETUP_CLASS(gjs->gpacClass, "GPAC", JSCLASS_HAS_PRIVATE, gpac_getProperty, gpac_setProperty, JS_FinalizeStub);
 
        if (!gjs->gpac_obj) {
index 18945a171cbdfdbae58fc5b9287da9a5f5bccefc..226722cc4d7d3ef29e7169bcde86c7aeceeb15bf 100644 (file)
@@ -69,12 +69,15 @@ typedef struct
 
 typedef struct
 {
-       u32 track;
+       u32 track, track_id;
+       /*base track if scalable media, 0 otherwise*/
+       u32 base_track;
+       u32 next_track;
        LPNETCHANNEL channel;
        ISOMReader *owner;
        u64 duration;
 
-       Bool wait_for_segment_switch, needs_codec_update;
+       Bool wait_for_segment_switch;
        /*current sample*/
        GF_ISOSample *sample;
        GF_SLHeader current_slh;
index 02405ab54dcb756c80d901831978b2204e228a53..8fe8a9d194f63d620e5f39b94876a89ad13329ff 100644 (file)
@@ -86,7 +86,7 @@ void isor_declare_objects(ISOMReader *read)
        GF_ObjectDescriptor *od;
        GF_ESD *esd;
        const char *tag;
-       u32 i, count, ocr_es_id, tlen;
+       u32 i, count, ocr_es_id, tlen, base_track, j, track_id;
 
        ocr_es_id = 0;
 
@@ -106,8 +106,28 @@ void isor_declare_objects(ISOMReader *read)
                default:
                        continue;
                }
+               
+               /*we declare only the base track (i.e base_track == 0)*/
+               gf_isom_get_reference(read->mov, i+1, GF_ISOM_REF_BASE, 1, &base_track);
+               if (base_track)
+                       continue;
                esd = gf_media_map_esd(read->mov, i+1);
                if (esd) {
+                       esd->has_ref_base = 0;
+                       track_id = gf_isom_get_track_id(read->mov, i+1);
+                       for (j = 0; j < count; j++)
+                       {
+                               if (gf_isom_has_track_reference(read->mov, j+1, GF_ISOM_REF_BASE, track_id))
+                               {
+                                       esd->has_ref_base = 1;
+                                       break;
+                               }
+                               if (gf_isom_get_avc_svc_type(read->mov, j+1, 1)>=GF_ISOM_AVCTYPE_AVC_SVC) {
+                                       esd->has_ref_base = 1;
+                                       break;
+                               }
+                       }
+
                        od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
                        od->service_ifce = read->input;
                        od->objectDescriptorID = 0;
index 24c688a1e66ba25ea3a81a2c64aa8d414b3b931c..b73726334d98f2c1a707146290f358f09ccbf072 100644 (file)
@@ -56,6 +56,7 @@ static void isor_delete_channel(ISOMReader *reader, ISOMChannel *ch)
 static GFINLINE Bool isor_is_local(const char *url)
 {
        if (!strnicmp(url, "file://", 7)) return 1;
+       if (!strnicmp(url, "gmem://", 7)) return 1;
        if (strstr(url, "://")) return 0;
        /*the rest is local (mounted on FS)*/
        return 1;
@@ -497,7 +498,7 @@ static GF_Descriptor *ISOR_GetServiceDesc(GF_InputService *plug, u32 expect_type
 
 GF_Err ISOR_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
 {
-       u32 ESID;
+       u32 ESID, base_track, count, i;
        ISOMChannel *ch;
        GF_NetworkCommand com;
        u32 track;
@@ -561,6 +562,7 @@ GF_Err ISOR_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const ch
        ch->channel = channel;
        gf_list_add(read->channels, ch);
        ch->track = track;
+       ch->track_id = gf_isom_get_track_id(read->mov, ch->track);
        switch (gf_isom_get_media_type(ch->owner->mov, ch->track)) {
        case GF_ISOM_MEDIA_OCR:
                ch->streamType = GF_STREAM_OCR;
@@ -568,6 +570,27 @@ GF_Err ISOR_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const ch
        case GF_ISOM_MEDIA_SCENE:
                ch->streamType = GF_STREAM_SCENE;
                break;
+       case GF_ISOM_MEDIA_VISUAL:
+               count = gf_isom_get_track_count(ch->owner->mov);
+               base_track = 0;
+               for (i = 0; i < count; i++)
+               {
+                       gf_isom_get_reference(ch->owner->mov, i+1, GF_ISOM_REF_BASE, 1, &base_track);
+                       if (base_track)
+                               break;
+               }
+               ch->base_track = base_track;
+               ch->next_track = 0;
+
+               /*set track to last layer (hopefully max quality)*/
+               for (i = 0; i < count; i++) {
+                       gf_isom_get_reference(ch->owner->mov, i+1, GF_ISOM_REF_BASE, 1, &base_track);
+                       if (base_track==ch->base_track)
+                               ch->track = i+1;
+               }
+               /*in scalable mode add SPS/PPS in-band*/
+               gf_isom_set_nalu_extract_mode(ch->owner->mov, ch->track, GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);
+               break;
        }
 
        ch->has_edit_list = gf_isom_get_edit_segment_count(ch->owner->mov, ch->track) ? 1 : 0;
@@ -698,11 +721,64 @@ static u64 check_round(ISOMChannel *ch, u64 val_ts, Double val_range, Bool make_
        return val_ts;
 }
 
+/*switch channel quality. Return next channel or current channel if error*/
+static
+u32 gf_channel_switch_quality(ISOMChannel *ch, GF_ISOFile *the_file, Bool switch_up)
+{
+       u32 i, count, next_track, trackID, cur_track;
+       s32 ref_count;
+
+       cur_track = ch->next_track ? ch->next_track : ch->track;
+       count = gf_isom_get_track_count(the_file);
+       trackID = gf_isom_get_track_id(the_file, cur_track);
+       next_track = 0;
+
+       if (switch_up)
+       {
+               for (i = 0; i < count; i++)
+               {
+                       ref_count = gf_isom_get_reference_count(the_file, i+1, GF_ISOM_REF_SCAL);
+                       if (ref_count < 0)
+                               return cur_track; //error
+                       else if (ref_count == 0)
+                               continue;
+                       /*next track is the one that has the last reference of type GF_ISOM_REF_SCAL refers to this current track*/
+                       else if ((u32)ref_count == gf_isom_has_track_reference(the_file, i+1, GF_ISOM_REF_SCAL, trackID))
+                       {
+                               next_track = i+1;
+                               break;
+                       }
+               }
+               /*this is the highest quality*/ 
+               if (!next_track)
+                       return cur_track;
+       }
+       else
+       {
+               if (cur_track == ch->base_track)
+                       return cur_track;
+               ref_count = gf_isom_get_reference_count(the_file, cur_track, GF_ISOM_REF_SCAL);
+               if (ref_count < 0)
+                       return cur_track;
+               gf_isom_get_reference(the_file, cur_track, GF_ISOM_REF_SCAL, ref_count, &next_track);
+               if (!next_track)
+                       return cur_track;
+       }
+
+       /*in scalable mode add SPS/PPS in-band*/
+       gf_isom_set_nalu_extract_mode(the_file, next_track, GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);
+
+       return next_track;
+}
+
+
 GF_Err ISOR_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
 {
        Double track_dur, media_dur;
        ISOMChannel *ch;
        ISOMReader *read;
+       u32 count, i;
+
        if (!plug || !plug->priv || !com) return GF_SERVICE_ERROR;
        read = (ISOMReader *) plug->priv;
 
@@ -735,6 +811,20 @@ GF_Err ISOR_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                }
                return GF_NOT_SUPPORTED;
        }
+
+       if (com->command_type == GF_NET_SERVICE_QUALITY_SWITCH)
+       {
+               count = gf_list_count(read->channels);
+               for (i = 0; i < count; i++)
+               {
+                       ch = (ISOMChannel *)gf_list_get(read->channels, i);
+                       if (ch->base_track) {
+                               ch->next_track = gf_channel_switch_quality(ch, read->mov, com->switch_quality.up);
+                       }
+               }
+               return GF_OK;
+       }
+
        if (!com->base.on_channel) return GF_NOT_SUPPORTED;
 
        ch = isor_get_channel(read, com->base.on_channel);
@@ -818,9 +908,9 @@ GF_Err ISOR_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                        }
                        gf_odf_desc_del((GF_Descriptor *) dcd);
                }
-       }
                return GF_OK;
        }
+       }
        return GF_NOT_SUPPORTED;
 }
 
index 744a69da4ed3cdbeb3822c5e248a18672699fb59..841b3e9cc4021d65ac3eb880fb823b6ead00365d 100644 (file)
@@ -98,9 +98,24 @@ static void check_segment_switch(ISOMReader *read)
                        ch->wait_for_segment_switch = 0;
                        GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Track %d - cur sample %d - new sample count %d\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track) ));
                        if (param.url_query.next_url_init_or_switch_segment) {
-                               ch->needs_codec_update = 1;
+                               ch->track = gf_isom_get_track_by_id(read->mov, ch->track_id);
+                               if (!ch->track) {
+                                       if (gf_isom_get_track_count(read->mov)==1) {
+                                               GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Mismatch between track IDs of different representations\n"));
+                                               ch->track = 1;
+                                       } else {
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[IsoMedia] Mismatch between track IDs of different representations\n"));
+                                       }
+                               }
+
+                               /*rewrite all upcoming SPS/PPS into the samples*/
+                               gf_isom_set_nalu_extract_mode(read->mov, ch->track, GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);
+
                                /*we changed our moov structure, sample_num now starts from 0*/
                                ch->sample_num = 0;
+                       } else {
+                               /*no need to rewrite upcoming SPS/PPS into the samples*/
+                               gf_isom_set_nalu_extract_mode(read->mov, ch->track, GF_ISOM_NALU_EXTRACT_DEFAULT);
                        }
                }
        } else {
@@ -259,6 +274,12 @@ fetch_next:
                        ch->sample_num++;
                        goto fetch_next;
                }
+               if (ch->sample && ch->sample->IsRAP && ch->next_track) {
+                       ch->track = ch->next_track;
+                       ch->next_track = 0;
+                       gf_isom_sample_del(&ch->sample);
+                       goto fetch_next;
+               }
        }
        if (!ch->sample) {
                /*incomplete file - check if we're still downloading or not*/
@@ -325,62 +346,6 @@ fetch_next:
                        ch->current_slh.isma_encrypted = 0;
                }
        }
-
-       /*this is ugly we need a rearchitecture of the streaming part of GPAC to handle codec changes properly - fortunately in DASH we cannot switch codec on
-       the fly (not in the same representation)!! */
-       if (ch->sample && ch->needs_codec_update) {
-               GF_AVCConfig *avccfg, *svccfg;
-               GF_AVCConfigSlot *slc;
-               GF_BitStream *bs;
-               u32 i; 
-               ch->needs_codec_update = 0;
-
-               GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Codec configuration changed - rewriting sample\n"));
-
-               switch (gf_isom_get_media_subtype(ch->owner->mov, ch->track, 1)) {
-               case GF_ISOM_SUBTYPE_AVC_H264:
-               case GF_ISOM_SUBTYPE_AVC2_H264:
-               case GF_ISOM_SUBTYPE_SVC_H264:
-                       avccfg = gf_isom_avc_config_get(ch->owner->mov, ch->track, 1);
-                       svccfg = gf_isom_svc_config_get(ch->owner->mov, ch->track, 1);
-
-                       bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
-                       if (avccfg) {
-                               for (i=0; i<gf_list_count(avccfg->sequenceParameterSets); i++) {
-                                       slc = gf_list_get(avccfg->sequenceParameterSets, i);
-                                       gf_bs_write_int(bs, slc->size, avccfg->nal_unit_size*8);
-                                       gf_bs_write_data(bs, slc->data, slc->size);
-                               }
-                               for (i=0; i<gf_list_count(avccfg->pictureParameterSets); i++) {
-                                       slc = gf_list_get(avccfg->pictureParameterSets, i);
-                                       gf_bs_write_int(bs, slc->size, avccfg->nal_unit_size*8);
-                                       gf_bs_write_data(bs, slc->data, slc->size);
-                               }
-                               gf_odf_avc_cfg_del(avccfg);
-                       }
-                       if (svccfg) {
-                               for (i=0; i<gf_list_count(svccfg->sequenceParameterSets); i++) {
-                                       slc = gf_list_get(svccfg->sequenceParameterSets, i);
-                                       gf_bs_write_int(bs, slc->size, avccfg->nal_unit_size*8);
-                                       gf_bs_write_data(bs, slc->data, slc->size);
-                               }
-                               for (i=0; i<gf_list_count(svccfg->pictureParameterSets); i++) {
-                                       slc = gf_list_get(svccfg->pictureParameterSets, i);
-                                       gf_bs_write_int(bs, slc->size, avccfg->nal_unit_size*8);
-                                       gf_bs_write_data(bs, slc->data, slc->size);
-                               }
-                               gf_odf_avc_cfg_del(svccfg);
-                       }
-                       gf_bs_write_data(bs, ch->sample->data, ch->sample->dataLength);
-                       gf_free(ch->sample->data);
-                       ch->sample->data = 0;
-                       gf_bs_get_content(bs, &ch->sample->data, &ch->sample->dataLength);
-                       gf_bs_del(bs);
-                       break;
-               default:
-                       break;
-               }
-       }
 }
 
 void isor_reader_release_sample(ISOMChannel *ch)
index 4269701496aeb2bb780dd018473a7e7936532c34..5db68c0ff87371d5640f45eb2127ef22558f34e6 100644 (file)
@@ -131,13 +131,35 @@ static void mp3_setup_object(MP3Reader *read)
        }
 }
 
-
-static Bool MP3_ConfigureFromFile(MP3Reader *read)
+/**
+ * Returns TRUE if file is ready to be read, FALSE otherwise
+ * @param read Reader
+ * @param minSizeToRead How much bytes do we need to start reading at minimum
+ */
+static Bool MP3_ConfigureFromFile(MP3Reader *read, u32 *minSizeToRead)
 {
+       unsigned char id3v2[10];
        u32 hdr, size;
        u64 pos;
        if (!read->stream) return 0;
-
+       /* ID3VVFFFFSIZE = 13bytes
+         * ID3 string
+        * VV = Version
+         * F = Flags
+         * SIZE = 32bits size with first Most Significant bit set to 0 -> 28 bits
+        * Size starts AFTER this header, meaning we have to add 10 bytes
+        */
+       pos = fread(id3v2, sizeof(unsigned char), 10, read->stream);
+       *minSizeToRead = 0;
+       if (pos == 10){
+               /* Did we read an ID3v2 ? */
+               if (id3v2[0] == 'I' && id3v2[1] == 'D' && id3v2[2] == '3'){
+                       int sz = 10 + ((id3v2[9] & 0x7f) + ((id3v2[8] & 0x7f) << 7) + ((id3v2[7] & 0x7f) << 14) + ((id3v2[6] & 0x7f) << 21));
+                       //printf("Size of id3v2 header = %d\n", sz);
+                       *minSizeToRead = sz;
+               }
+       }
+       gf_f64_seek(read->stream, 0, SEEK_SET);
        hdr = gf_mp3_get_next_header(read->stream);
        if (!hdr) return 0;
        read->sample_rate = gf_mp3_sampling_rate(hdr);
@@ -318,14 +340,15 @@ void MP3_NetIO(void *cbk, GF_NETIO_Parameter *param)
                        read->stream = gf_f64_open((char *) szCache, "rb");
                        if (!read->stream) e = GF_SERVICE_ERROR;
                        else {
+                               u32 minSizeToRead = 0;
                                /*if full file at once (in cache) parse duration*/
                                if (e==GF_EOS) read->is_remote = 0;
                                e = GF_OK;
                                /*not enough data*/
-                               if (!MP3_ConfigureFromFile(read)) {
+                               if (!MP3_ConfigureFromFile(read, &minSizeToRead)) {
                                        gf_dm_sess_get_stats(read->dnload, NULL, NULL, NULL, &bytes_done, NULL, NULL);
                                        /*bad data - there's likely some ID3 around...*/
-                                       if (bytes_done>100*1024) {
+                                       if (bytes_done>(100*1024 + minSizeToRead)) {
                                                e = GF_CORRUPTED_DATA;
                                        } else {
                                                fclose(read->stream);
@@ -366,6 +389,7 @@ void mp3_download_file(GF_InputService *plug, char *url)
 static GF_Err MP3_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
 {
        char szURL[2048];
+       u32 minSizeToRead = 0;
        char *ext;
        GF_Err reply;
        MP3Reader *read = plug->priv;
@@ -389,7 +413,7 @@ static GF_Err MP3_ConnectService(GF_InputService *plug, GF_ClientService *serv,
        read->stream = gf_f64_open(szURL, "rb");
        if (!read->stream) {
                reply = GF_URL_ERROR;
-       } else if (!MP3_ConfigureFromFile(read)) {
+       } else if (!MP3_ConfigureFromFile(read, &minSizeToRead)) {
                fclose(read->stream);
                read->stream = NULL;
                reply = GF_NOT_SUPPORTED;
@@ -532,7 +556,8 @@ static GF_Err MP3_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                        read->done = 0;
                        /*PLAY after complete download, estimate duration*/
                        if (!read->is_remote && !read->duration) {
-                               MP3_ConfigureFromFile(read);
+                               u32 minSizeToRead = 0;
+                               MP3_ConfigureFromFile(read, &minSizeToRead);
                                if (read->duration) {
                                        GF_NetworkCommand rcfg;
                                        rcfg.base.on_channel = read->ch;
index 7c4bbe932585ac4041744fa3da038ee9757e457c..689092c27a9862fd8601442c67d025e97a44cb56 100644 (file)
@@ -44,7 +44,11 @@ typedef struct __mpd_module
 
        Bool connection_ack_sent;
        Bool in_seek;
+       Bool memory_storage;
+       Bool use_max_res, immediate_switch;
     Double previous_start_range;
+       /*max width & height in all active representations*/
+       u32 width, height;
 } GF_MPD_In;
 
 typedef struct 
@@ -165,12 +169,12 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param)
                                                        gf_dash_request_period_switch(mpdin->dash);
                                                        break;
                                                }
-                                               gf_sleep(20);
+                                               gf_sleep(30);
                                        }
                                } 
                                return GF_EOS;
                        }
-            gf_sleep(16);
+            gf_sleep(30);
         }
        
                nb_segments_cached = gf_dash_group_get_num_segments_ready(mpdin->dash, group_idx, &group_done);
@@ -186,7 +190,7 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param)
                }
 
                gf_dash_group_get_next_segment_location(mpdin->dash, group_idx, &param->url_query.next_url, &param->url_query.start_range, &param->url_query.end_range, 
-                                                               &param->url_query.next_url_init_or_switch_segment, &param->url_query.switch_start_range , &param->url_query.switch_end_range,
+                                                               NULL, &param->url_query.next_url_init_or_switch_segment, &param->url_query.switch_start_range , &param->url_query.switch_end_range,
                                                                &src_url);
 
         {
@@ -313,9 +317,11 @@ void mpdin_dash_io_delete_cache_file(GF_DASHFileIO *dashio, GF_DASHFileIOSession
 
 GF_DASHFileIOSession mpdin_dash_io_create(GF_DASHFileIO *dashio, Bool persistent, const char *url)
 {
+       GF_DownloadSession *sess;
        u32 flags = GF_NETIO_SESSION_NOT_THREADED;
        GF_MPD_In *mpdin = (GF_MPD_In *)dashio->udta;
-       GF_DownloadSession *sess;
+       if (mpdin->memory_storage)
+               flags |= GF_NETIO_SESSION_MEMORY_CACHE;
 
        if (persistent) flags |= GF_NETIO_SESSION_PERSISTENT;
        sess = gf_term_download_new(mpdin->service, url, flags, NULL, NULL);
@@ -333,9 +339,9 @@ GF_Err mpdin_dash_io_setup_from_url(GF_DASHFileIO *dashio, GF_DASHFileIOSession
 {
        return gf_dm_sess_setup_from_url((GF_DownloadSession *)session, url);
 }
-GF_Err mpdin_dash_io_set_range(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, u64 start_range, u64 end_range)
+GF_Err mpdin_dash_io_set_range(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, u64 start_range, u64 end_range, Bool discontinue_cache)
 {
-       return gf_dm_sess_set_range((GF_DownloadSession *)session, start_range, end_range);
+       return gf_dm_sess_set_range((GF_DownloadSession *)session, start_range, end_range, discontinue_cache);
 }
 GF_Err mpdin_dash_io_init(GF_DASHFileIO *dashio, GF_DASHFileIOSession session)
 {
@@ -404,8 +410,7 @@ GF_Err mpdin_dash_io_on_dash_event(GF_DASHFileIO *dashio, GF_DASHEventType dash_
 
                /*select input services if possible*/
                for (i=0; i<gf_dash_get_group_count(mpdin->dash); i++) {
-                       const char *mime, *init_segment;
-                       
+                       const char *mime, *init_segment;                        
                        if (!gf_dash_is_group_selected(mpdin->dash, i))
                                continue;
 
@@ -422,7 +427,14 @@ GF_Err mpdin_dash_io_on_dash_event(GF_DASHFileIO *dashio, GF_DASHEventType dash_
                                        GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD_IN] Unable to connect input service to %s\n", init_segment));
                                        gf_dash_group_select(mpdin->dash, i, 0);
                                } else {
+                                       u32 w, h;
                                        group->service_connected = 1;
+                                       w = h = 0;
+                                       gf_dash_group_get_video_info(mpdin->dash, i, &w, &h);
+                                       if (w && h && w>mpdin->width && h>mpdin->height) {
+                                               mpdin->width = w;
+                                               mpdin->height = h;
+                                       }
                                }
                        }
                }
@@ -521,6 +533,19 @@ GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const c
     else if (opt && !strcmp(opt, "minQuality")) first_select_mode = GF_DASH_SELECT_QUALITY_LOWEST;
     else if (opt && !strcmp(opt, "maxQuality")) first_select_mode = GF_DASH_SELECT_QUALITY_HIGHEST;
     else first_select_mode = GF_DASH_SELECT_BANDWIDTH_LOWEST;
+
+       opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "MemoryStorage");
+       if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "MemoryStorage", "no");
+       mpdin->memory_storage = (opt && !strcmp(opt, "yes")) ? 1 : 0;
+
+       opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "UseMaxResolution");
+       if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "UseMaxResolution", "yes");
+       mpdin->use_max_res = (!opt || !strcmp(opt, "yes")) ? 1 : 0;
+
+       opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "ImmediateSwitching");
+       if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "ImmediateSwitching", "no");
+       mpdin->immediate_switch = (opt && !strcmp(opt, "yes")) ? 1 : 0;
+       
        
        mpdin->in_seek = 0;
        mpdin->previous_start_range = -1;
@@ -535,7 +560,7 @@ GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const c
 
        /*dash thread starts at the end of gf_dash_open */
        e = gf_dash_open(mpdin->dash, url);
-       if (!mpdin->dash) {
+       if (e) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error - cannot initialize DASH Client for %s: %s\n", url, gf_error_to_string(e) ));
         gf_term_on_connect(mpdin->service, NULL, e);
                return GF_OK;
@@ -549,14 +574,17 @@ static GF_Descriptor *MPD_GetServiceDesc(GF_InputService *plug, u32 expect_type,
        GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv;
     GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Service Description request from terminal for %s\n", sub_url));
        for (i=0; i<gf_dash_get_group_count(mpdin->dash); i++) {
+               GF_Descriptor *desc;
                GF_MPDGroup *mudta;
                if (!gf_dash_is_group_selected(mpdin->dash, i))
                        continue;
                mudta = gf_dash_get_group_udta(mpdin->dash, i);
                if (!mudta) continue;
                if (mudta->service_descriptor_fetched) continue;
-               mudta->service_descriptor_fetched = 1;
-               return mudta->segment_ifce->GetServiceDescriptor(mudta->segment_ifce, expect_type, sub_url);
+
+               desc = mudta->segment_ifce->GetServiceDescriptor(mudta->segment_ifce, expect_type, sub_url);
+               if (desc) mudta->service_descriptor_fetched = 1;
+               return desc;
        }
        return NULL;
 }
@@ -612,8 +640,13 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
                }
         return GF_NOT_SUPPORTED;
 
+       case GF_NET_SERVICE_HAS_FORCED_VIDEO_SIZE:
+               com->par.width = mpdin->use_max_res ? mpdin->width : 0;
+               com->par.height = mpdin->use_max_res ? mpdin->height : 0;
+        return GF_OK;
+
        case GF_NET_SERVICE_QUALITY_SWITCH:
-               gf_dash_switch_quality(mpdin->dash, com->switch_quality.up);
+               gf_dash_switch_quality(mpdin->dash, com->switch_quality.up, mpdin->immediate_switch);
         return GF_OK;
        }
        /*not supported*/
index a3e84210e39c771bfffb2eecc41ddf3a819d775d..bbf866e5501bd50459ea29c839be8f9b166db3f6 100644 (file)
@@ -181,6 +181,10 @@ static GF_ObjectDescriptor *MP2TS_GetOD(M2TSIn *m2ts, GF_M2TS_PES *stream, char
                esd->decoderConfig->streamType = GF_STREAM_VISUAL;
                esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_AVC;
                break;
+       case GF_M2TS_VIDEO_HEVC:
+               esd->decoderConfig->streamType = GF_STREAM_VISUAL;
+               esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_HEVC;
+               break;
        case GF_M2TS_AUDIO_MPEG1:
                esd->decoderConfig->streamType = GF_STREAM_AUDIO;
                esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
@@ -894,6 +898,9 @@ static GF_Descriptor *M2TS_GetServiceDesc(GF_InputService *plug, u32 expect_type
                                return desc;
                        }
                }
+               /*if we expect scene, return NULL and repost a connection ack when we get the PMT*/
+               if (expect_type==GF_MEDIA_OBJECT_SCENE) 
+                       return NULL;
                if (m2ts->epg_requested) {
                        GF_ObjectDescriptor *od = M2TS_GenerateEPG_OD(m2ts);
                        m2ts->epg_requested = 0;
index 0690d0e9054e45e69ccd91ce86df15949bd9748a..191c4b6915cc152c9ac4d1edb9db61b704b3c8e8 100644 (file)
@@ -182,12 +182,15 @@ static GF_Err OSVC_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capa
        OSVCDec *ctx = (OSVCDec*) ifcg->privateStack;
        switch (capability.CapCode) {
        case GF_CODEC_MEDIA_SWITCH_QUALITY:
+
                if (capability.cap.valueInt) {
-                       // set layer up (command=1)
-                       UpdateLayer( ctx->DqIdTable, &ctx->CurrDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 1 );
+                       if (ctx->CurrDqId < ctx->MaxDqId)
+                               // set layer up (command=1)
+                               UpdateLayer( ctx->DqIdTable, &ctx->CurrDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 1 );
                } else {
-                       // set layer down (command=0)
-                       UpdateLayer( ctx->DqIdTable, &ctx->CurrDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 0 );
+                       if (ctx->CurrDqId > 0)
+                               // set layer down (command=0)
+                               UpdateLayer( ctx->DqIdTable, &ctx->CurrDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 0 );
                }
                return GF_OK;
        }
@@ -207,6 +210,7 @@ static GF_Err OSVC_ProcessData(GF_MediaDecoder *ifcg,
        OPENSVCFRAME pic;
     int Layer[4];
        OSVCDec *ctx = (OSVCDec*) ifcg->privateStack;
+       u32 curMaxDqId = ctx->MaxDqId;
 
        if (!ES_ID || (ES_ID!=ctx->ES_ID) || !ctx->codec) {
                *outBufferLength = 0;
@@ -217,25 +221,37 @@ static GF_Err OSVC_ProcessData(GF_MediaDecoder *ifcg,
                return GF_BUFFER_TOO_SMALL;
        }
 
+       ctx->MaxDqId = GetDqIdMax(inBuffer, inBufferLength, ctx->nalu_size_length, ctx->DqIdTable, ctx->nalu_size_length ? 1 : 0);
+       if(!ctx->InitParseAU){
+               if (ctx->MaxDqId == -1) {
+                       //AVC stream in a h264 file 
+                       ctx->MaxDqId = 0;
+               } else {
+                       //Firts time only, we parse the first AU to know the file configuration
+                       //does not need to ba called again ever after, unless SPS or PPS changed
+                       ParseAuPlayers(ctx->codec, inBuffer, inBufferLength, ctx->nalu_size_length, ctx->nalu_size_length ? 1 : 0);
+               }
+               ctx->InitParseAU = 1;
+       }
+/*
+       if (curMaxDqId != ctx->MaxDqId)
+       {
+               if (ctx->MaxDqId == -1)
+                       ctx->MaxDqId = 0;
+               else
+                       ParseAuPlayers(ctx->codec, inBuffer, inBufferLength, ctx->nalu_size_length, ctx->nalu_size_length ? 1 : 0);
+               ctx->CurrDqId = ctx->MaxDqId;
+       }
+//     SetCommandLayer(Layer, ctx->MaxDqId, ctx->CurrDqId, &ctx->TemporalCom, ctx->TemporalId);
+*/
+       ctx->TemporalCom = 0;
+       SetCommandLayer(Layer, ctx->MaxDqId, ctx->MaxDqId, &ctx->TemporalCom, 0);
+
        got_pic = 0;
        if (ctx->nalu_size_length) {
                u32 i, nalu_size = 0;
                u8 *ptr = inBuffer;
 
-               ctx->MaxDqId = GetDqIdMax(inBuffer, inBufferLength, ctx->nalu_size_length, ctx->DqIdTable, 1);
-               if(!ctx->InitParseAU){
-                       if (ctx->MaxDqId == -1) {
-                               //AVC stream in a h264 file 
-                               ctx->MaxDqId = 0;
-                       } else {
-                               //Firts time only, we parse the first AU to know the file configuration
-                               //does not need to ba called again ever after, unless SPS or PPS changed
-                               ParseAuPlayers(ctx->codec, inBuffer, inBufferLength, ctx->nalu_size_length, 1);
-                       }
-                       ctx->InitParseAU = 1;
-               }
-        SetCommandLayer(Layer, ctx->MaxDqId, ctx->CurrDqId, &ctx->TemporalCom, ctx->TemporalId);
-
                while (inBufferLength) {
                        for (i=0; i<ctx->nalu_size_length; i++) {
                                nalu_size = (nalu_size<<8) + ptr[i];
@@ -256,7 +272,7 @@ static GF_Err OSVC_ProcessData(GF_MediaDecoder *ifcg,
        }
        if (got_pic!=1) return GF_OK;
 
-       if ((pic.Width != ctx->width) || (pic.Height!=ctx->height)) {
+       if ((curMaxDqId != ctx->MaxDqId) || (pic.Width != ctx->width) || (pic.Height!=ctx->height)) {
                ctx->width = pic.Width;
                ctx->stride = pic.Width + 32;
                ctx->height = pic.Height;
@@ -289,6 +305,9 @@ static u32 OSVC_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, GF_ESD *esd
                        GF_AVCConfig *cfg = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
                        if (!cfg) return GF_CODEC_NOT_SUPPORTED;
 
+                       if (esd->has_ref_base)
+                               is_svc = 1;
+
                        /*decode all NALUs*/
                        count = gf_list_count(cfg->sequenceParameterSets);
                        for (i=0; i<count; i++) {
index baa6be9bf09992e7024d9afa7dbc231519d3be8f..8bc3e509cef134a2664c760c6c0359c354efe2dc 100644 (file)
@@ -541,13 +541,13 @@ static SMJS_DECL_FUNC_PROP_GET(  upnpdevice_getProperty)
        if (!prop_name) return JS_FALSE;
 
        if (!strcmp(prop_name, "Name")) {
-               *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, dev->m_device->GetFriendlyName()) );
+               VPASSIGN( STRING_TO_JSVAL( JS_NewStringCopyZ(c, dev->m_device->GetFriendlyName()) ) );
        }
        else if (!strcmp(prop_name, "UUID")) {
-               *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, dev->m_device->GetUUID()) );
+               VPASSIGN( STRING_TO_JSVAL( JS_NewStringCopyZ(c, dev->m_device->GetUUID()) ) );
        }
        else if (!strcmp(prop_name, "PresentationURL")) {
-               *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, dev->m_device->m_PresentationURL) );
+               VPASSIGN( STRING_TO_JSVAL( JS_NewStringCopyZ(c, dev->m_device->m_PresentationURL) )  );
        }
        else if (!strcmp(prop_name, "ServicesCount")) {
                u32 count = gf_list_count(dev->m_Services);
@@ -555,7 +555,7 @@ static SMJS_DECL_FUNC_PROP_GET(  upnpdevice_getProperty)
                        dev->RefreshServiceList();
                        count = gf_list_count(dev->m_Services);
                }
-               *vp = INT_TO_JSVAL(count);
+               VPASSIGN( INT_TO_JSVAL(count)  );
        }
        SMJS_FREE(c, prop_name);        
        return JS_TRUE;
@@ -663,22 +663,22 @@ static SMJS_DECL_FUNC_PROP_GET(  upnp_getProperty)
        if (!prop_name) return JS_FALSE;
 
        if (!strcmp(prop_name, "MediaRendererEnabled")) {
-               *vp = BOOLEAN_TO_JSVAL( upnp->m_pMediaRenderer ? JS_TRUE : JS_FALSE );
+               VPASSIGN( BOOLEAN_TO_JSVAL( upnp->m_pMediaRenderer ? JS_TRUE : JS_FALSE ) );
        }
        else if (!strcmp(prop_name, "MediaServerEnabled")) {
-               *vp = BOOLEAN_TO_JSVAL( upnp->m_pMediaServer ? JS_TRUE : JS_FALSE);
+               VPASSIGN( BOOLEAN_TO_JSVAL( upnp->m_pMediaServer ? JS_TRUE : JS_FALSE)  );
        }
        else if (!strcmp(prop_name, "MediaControlEnabled")) {
-               *vp = BOOLEAN_TO_JSVAL( upnp->m_pAVCtrlPoint ? JS_TRUE : JS_FALSE);
+               VPASSIGN( BOOLEAN_TO_JSVAL( upnp->m_pAVCtrlPoint ? JS_TRUE : JS_FALSE)  );
        }
        else if (!strcmp(prop_name, "MediaServersCount")) {
-               *vp = INT_TO_JSVAL( upnp->m_pAVCtrlPoint ? gf_list_count(upnp->m_pAVCtrlPoint->m_MediaServers) : 0);
+               VPASSIGN( INT_TO_JSVAL( upnp->m_pAVCtrlPoint ? gf_list_count(upnp->m_pAVCtrlPoint->m_MediaServers) : 0) );
        }
        else if (!strcmp(prop_name, "MediaRenderersCount")) {
-               *vp = INT_TO_JSVAL( upnp->m_pAVCtrlPoint ? gf_list_count(upnp->m_pAVCtrlPoint->m_MediaRenderers) : 0);
+               VPASSIGN( INT_TO_JSVAL( upnp->m_pAVCtrlPoint ? gf_list_count(upnp->m_pAVCtrlPoint->m_MediaRenderers) : 0) );
        }
        else if (!strcmp(prop_name, "DevicesCount")) {
-               *vp = INT_TO_JSVAL( upnp->m_pGenericController ? gf_list_count(upnp->m_pGenericController->m_Devices) : 0);
+               VPASSIGN( INT_TO_JSVAL( upnp->m_pGenericController ? gf_list_count(upnp->m_pGenericController->m_Devices) : 0) );
        }
        SMJS_FREE(c, prop_name);
        return JS_TRUE;
@@ -699,18 +699,18 @@ static SMJS_DECL_FUNC_PROP_SET(upnp_setProperty)
        if (!prop_name) return JS_FALSE;
 
        if (upnp->m_pMediaRenderer ) {
-               if (!strcmp(prop_name, "MovieDuration") && JSVAL_IS_DOUBLE(*vp)) {
+               if (!strcmp(prop_name, "MovieDuration") && JSVAL_IS_DOUBLE( VPGET() )) {
                        jsdouble d;
-                       JS_ValueToNumber(c, *vp, &d);
+                       JS_ValueToNumber(c, VPGET(), &d);
                        upnp->m_pMediaRenderer->SetDuration(d, 1);
                }
-               else if (!strcmp(prop_name, "MovieTime") && JSVAL_IS_DOUBLE(*vp)) {
+               else if (!strcmp(prop_name, "MovieTime") && JSVAL_IS_DOUBLE( VPGET() )) {
                        jsdouble d;
-                       JS_ValueToNumber(c, *vp, &d);
+                       JS_ValueToNumber(c, VPGET(), &d);
                        upnp->m_pMediaRenderer->SetTime(d);
                }
-               else if (!strcmp(prop_name, "MovieURL") && JSVAL_IS_STRING(*vp) ) {
-                       char *url = SMJS_CHARS(c, *vp);
+               else if (!strcmp(prop_name, "MovieURL") && JSVAL_IS_STRING( VPGET() ) ) {
+                       char *url = SMJS_CHARS(c, VPGET() );
                        if (url) upnp->m_pMediaRenderer->SetConnected(url);
                        SMJS_FREE(c, url);
                }
@@ -1454,7 +1454,7 @@ Bool GF_UPnP::LoadJS(GF_TermExtJS *param)
 {
        u32 i, count;
        JSPropertySpec upnpClassProps[] = {
-               {0, 0, 0, 0, 0}
+               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
        };
        JSFunctionSpec upnpClassFuncs[] = {
                SMJS_FUNCTION_SPEC("BindRenderer", upnp_bind_renderer, 0),
@@ -1522,7 +1522,7 @@ Bool GF_UPnP::LoadJS(GF_TermExtJS *param)
        
        /*setup JS bindings*/
        JSPropertySpec upnpDeviceClassProps[] = {
-               {0, 0, 0, 0, 0}
+               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
        };
        JSFunctionSpec upnpDeviceClassFuncs[] = {
                SMJS_FUNCTION_SPEC("FindService", upnp_device_find_service, 0),
index 74890ff7fac8912b6eb7e19de09813af6517d9b0..1264017cc0e0a9c6990fe3b29a96b54346dd2dcb 100644 (file)
@@ -141,6 +141,15 @@ public:
 
 #ifdef GPAC_HAS_SPIDERMONKEY
 SMJS_DECL_FUNC_PROP_GET( upnpservice_getProperty);
+
+#ifdef USE_FFDEV_17
+       #define VPASSIGN(__b) __vp.set( __b )
+       #define VPGET() (jsval) __vp
+#else
+       #define VPASSIGN(__b) *vp = __b
+       #define VPGET() *vp
+#endif
+
 #endif
 
 void format_time_string(char *str, Double dur);
index 33e077d056c104b931546c51f26c7c6a93370990..ee11459d6a8355a624bfbff95706f8e61ae874f2 100644 (file)
@@ -261,10 +261,10 @@ SMJS_DECL_FUNC_PROP_GET( upnpservice_getProperty)
        if (!prop_name) return JS_FALSE;
 
        if (!strcmp(prop_name, "Device")) {
-               *vp = OBJECT_TO_JSVAL(service->m_device->obj);
+               VPASSIGN( OBJECT_TO_JSVAL(service->m_device->obj) );
        }
        else if (!strcmp(prop_name, "ModifiedStateVariablesCount")) {
-               *vp = INT_TO_JSVAL(service->vars ? service->vars->GetItemCount() : 0);
+               VPASSIGN( INT_TO_JSVAL(service->vars ? service->vars->GetItemCount() : 0) );
        }
 
        SMJS_FREE(c, prop_name);
index dc62a38c73af26ccf09b490278af64ba11ad3d17..502dc22bda20fb67295d02ce1158fc1d4b5db672 100644 (file)
@@ -386,6 +386,7 @@ SMJS_FUNC_PROP_SET( widget_setProperty)
        /*avoids GCC warning*/
        if (!obj) obj = NULL;
        if (!id) id=0;
+       if (!vp) vp=0;
        return JS_TRUE;
 }
 
@@ -419,7 +420,7 @@ void widget_load(GF_WidgetManager *wm, GF_SceneGraph *scene, JSContext *c, JSObj
        } else {
 
                JSPropertySpec widgetClassProps[] = {
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec widgetClassFuncs[] = {
                        /*W3C*/
index 9e25943288d1d7dbba2a8f27fb3c899136a67efa..7f602b62fe4f1559c2d2162afcb3a2612c6e626c 100644 (file)
@@ -3497,7 +3497,7 @@ static void widgetmanager_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene,
 
        GF_JSAPIParam par;
        JSPropertySpec wmClassProps[] = {
-               {0, 0, 0, 0, 0}
+               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
        };
        JSFunctionSpec wmClassFuncs[] = {
                SMJS_FUNCTION_SPEC("initialize", wm_initialize, 0),
@@ -3545,7 +3545,7 @@ static void widgetmanager_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene,
 
        {
        JSPropertySpec wmWidgetClassProps[] = {
-               {0, 0, 0, 0, 0}
+               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
        };
        JSFunctionSpec wmWidgetClassFuncs[] = {
                SMJS_FUNCTION_SPEC("activate", wm_widget_activate, 1),
index 318b782002ec711114a1470b3f185b336a76ea4c..733ce98f5dc775dbfc45850ee64f6a3975383d81 100644 (file)
@@ -37,10 +37,13 @@ LIBGPAC_BIFS=bifs/arith_decoder.o bifs/bifs_codec.o bifs/bifs_node_tables.o bifs
 endif
 
 ## libgpac objects gathering: src/isomedia
-LIBGPAC_ISOM=isomedia/avc_ext.o isomedia/box_code_3gpp.o isomedia/box_code_adobe.o isomedia/box_code_apple.o isomedia/box_code_base.o isomedia/box_code_drm.o isomedia/box_code_meta.o isomedia/box_dump.o isomedia/box_funcs.o isomedia/data_map.o isomedia/drm_sample.o isomedia/isom_intern.o isomedia/isom_read.o isomedia/isom_store.o isomedia/isom_write.o isomedia/media.o isomedia/media_odf.o isomedia/meta.o isomedia/movie_fragments.o isomedia/sample_descs.o isomedia/stbl_read.o isomedia/stbl_write.o isomedia/track.o isomedia/tx3g.o isomedia/generic_subtitle.o 
+LIBGPAC_ISOM=isomedia/avc_ext.o isomedia/box_code_3gpp.o isomedia/box_code_apple.o isomedia/box_code_base.o isomedia/box_code_drm.o isomedia/box_code_meta.o isomedia/box_dump.o isomedia/box_funcs.o isomedia/data_map.o isomedia/drm_sample.o isomedia/isom_intern.o isomedia/isom_read.o isomedia/isom_store.o isomedia/isom_write.o isomedia/media.o isomedia/media_odf.o isomedia/meta.o isomedia/movie_fragments.o isomedia/sample_descs.o isomedia/stbl_read.o isomedia/stbl_write.o isomedia/track.o isomedia/tx3g.o isomedia/generic_subtitle.o 
 ifeq ($(DISABLE_ISOFF_HINT), no)
 LIBGPAC_ISOM+=isomedia/hint_track.o isomedia/hinting.o
 endif
+ifeq ($(DISABLE_ISOM_ADOBE), no)
+LIBGPAC_ISOM+=isomedia/box_code_adobe.o
+endif
 
 ## libgpac objects gathering: src/odf
 LIBGPAC_ODF=odf/desc_private.o odf/descriptors.o odf/odf_code.o odf/odf_codec.o odf/odf_command.o odf/qos.o odf/slc.o 
index 42010d5199e209369a3ffb9f20480cea4b67ca59..fa471a954ca2ae94d679b40882dc347ce7087c4c 100644 (file)
@@ -52,6 +52,8 @@ typedef struct
 
        Fixed speed;
        Fixed pan[6];
+
+       Bool muted;
 } MixerInput;
 
 struct __audiomix
@@ -578,6 +580,7 @@ u32 gf_mixer_get_output(GF_AudioMixer *am, void *buffer, u32 buffer_size, u32 de
                return 0;
        }
 
+       single_source->muted = single_source->src->IsMuted(single_source->src->callback);
        /*this happens if input SR cannot be mapped to output audio hardware*/
        if (single_source->src->samplerate != am->sample_rate) goto do_mix;
        /*note we don't check output cfg: if the number of channel is the same then the channel cfg is the 
@@ -590,7 +593,7 @@ single_source_mix:
 
        ptr = (char *)buffer;
        in_size = buffer_size;
-       is_muted = single_source->src->IsMuted(single_source->src->callback);
+       is_muted = single_source->muted;
 
        while (buffer_size) {
                data = single_source->src->FetchFrame(single_source->src->callback, &size, delay);
@@ -631,7 +634,8 @@ do_mix:
        single_source = NULL;
        for (i=0; i<count; i++) {
                in = (MixerInput *)gf_list_get(am->sources, i);
-               if (in->src->IsMuted(in->src->callback)) continue;
+               in->muted = in->src->IsMuted(in->src->callback);
+               if (in->muted) continue;
 
                if (in->buffer_size < nb_samples) { 
                        for (j=0; j<GF_SR_MAX_CHANNELS; j++) {
@@ -648,11 +652,16 @@ do_mix:
 
                /*if cfg unknown or changed (AudioBuffer child...) invalidate cfg settings*/
                if (!in->src->GetConfig(in->src, 0)) {
-                       nb_act_src = 0;
-                       am->must_reconfig = 1;
-                       /*if main mixer reconfig asap*/
-                       if (am->ar) gf_mixer_reconfig(am);
-                       break;
+                       if (!am->must_reconfig) {
+                               am->must_reconfig = 1;
+                               /*if main mixer reconfig asap*/
+                               if (am->ar) gf_mixer_reconfig(am);
+                       }
+                       //however keep the current mixer config and output some audio ...
+//                     nb_act_src = 0;
+//                     break;
+                       in->muted = 1;
+                       continue;
                } else if (in->speed==0) {
                        in->out_samples_to_write = 0;
                } else {
@@ -690,6 +699,10 @@ do_mix:
                /*fill*/
                for (i=0; i<count; i++) {
                        in = (MixerInput *)gf_list_get(am->sources, i);
+                       if (in->muted) {
+                               in->out_samples_to_write = 0;
+                               continue;
+                       }
                        if (in->out_samples_to_write>in->out_samples_written) {
                                gf_mixer_fetch_input(am, in, delay + 8000 * i / am->bits_per_sample / am->sample_rate / am->nb_channels);
                                if (in->out_samples_to_write>in->out_samples_written) nb_to_fill++;
@@ -698,6 +711,7 @@ do_mix:
                /*release - this is done in 2 steps in case 2 audio object use the same source...*/
                for (i=0; i<count; i++) {
                        in = (MixerInput *)gf_list_get(am->sources, i);
+                       if (in->muted) continue;
                        if (in->in_bytes_used) in->src->ReleaseFrame(in->src->callback, in->in_bytes_used-1);
                        in->in_bytes_used = 0;
                }
index 04891c8cae82a782df7ea09b2c1df219b235d28a..a327371113d83ffb43e5c47e8695d6f299795733 100644 (file)
@@ -788,7 +788,7 @@ static void gf_sc_reset(GF_Compositor *compositor)
        compositor->focus_node = NULL;
        compositor->focus_text_type = 0;
        compositor->frame_number = 0;
-       compositor->video_memory = 0;
+       compositor->video_memory = compositor->was_system_memory ? 0 : 1;
        compositor->rotation = 0;
 
        gf_list_reset(compositor->focus_ancestors);
index 9b273243f9ed43acf6d6e198c3a06ce05fe01d6c..4e6de5d02ff0f4263b66f40a8664a74f74f3e466 100644 (file)
@@ -783,6 +783,8 @@ Bool compositor_2d_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_st
 
 GF_Err compositor_2d_set_aspect_ratio(GF_Compositor *compositor)
 {
+       u32 old_vp_width, old_vp_height;
+       Bool changed = 0;
        Double ratio;
        GF_Event evt;
        GF_Err e;
@@ -793,6 +795,9 @@ GF_Err compositor_2d_set_aspect_ratio(GF_Compositor *compositor)
        compositor->vp_x = compositor->vp_y = 0;
        scaleX = scaleY = FIX_ONE;
 
+       old_vp_width = compositor->vp_width;
+       old_vp_height = compositor->vp_height;
+
        /*force complete clean*/
        compositor->traverse_state->invalidate_all = 1;
 
@@ -892,21 +897,32 @@ GF_Err compositor_2d_set_aspect_ratio(GF_Compositor *compositor)
        }
 #endif
 
+       if (compositor->was_system_memory != evt.setup.system_memory) changed = 1;
+       else if (old_vp_width != compositor->vp_width) changed=1;
+       else if (old_vp_height != compositor->vp_height) changed=1;
+       else if (compositor->was_opengl != evt.setup.opengl_mode) changed=1;
+       
 
-       GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor2D] Reconfiguring display size %d x %d - opengl %s - use %s memory\n", evt.setup.width, evt.setup.height,
-               (evt.setup.opengl_mode==2) ? "Offscreen" : (evt.setup.opengl_mode==1) ? "yes" : "no", evt.setup.system_memory ? "systems" : "video"
-               ));
+       if (changed) {
+               GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor2D] Reconfiguring display size %d x %d - opengl %s - use %s memory\n", evt.setup.width, evt.setup.height,
+                       (evt.setup.opengl_mode==2) ? "Offscreen" : (evt.setup.opengl_mode==1) ? "yes" : "no", evt.setup.system_memory ? "systems" : "video"
+                       ));
 
-       e = compositor->video_out->ProcessEvent(compositor->video_out, &evt);
-       if (e) return e;
+               e = compositor->video_out->ProcessEvent(compositor->video_out, &evt);
+               if (e) return e;
 
-       if (compositor->has_size_info) {
-               compositor->traverse_state->vp_size.x = INT2FIX(compositor->scene_width);
-               compositor->traverse_state->vp_size.y = INT2FIX(compositor->scene_height);
-       } else {
-               compositor->traverse_state->vp_size.x = INT2FIX(compositor->output_width);
-               compositor->traverse_state->vp_size.y = INT2FIX(compositor->output_height);
+               if (compositor->has_size_info) {
+                       compositor->traverse_state->vp_size.x = INT2FIX(compositor->scene_width);
+                       compositor->traverse_state->vp_size.y = INT2FIX(compositor->scene_height);
+               } else {
+                       compositor->traverse_state->vp_size.x = INT2FIX(compositor->output_width);
+                       compositor->traverse_state->vp_size.y = INT2FIX(compositor->output_height);
+               }
+               compositor->was_opengl = evt.setup.opengl_mode;
+               compositor->was_system_memory = evt.setup.system_memory;
+               
        }
+
        /*set scale factor*/
        compositor_set_ar_scale(compositor, scaleX, scaleY);
        return GF_OK;
index 9c90f2360cf20bd8f8e1470e136597c140490601..28599fad722724ddd43cd4b6769c0dcd16da0bca 100644 (file)
@@ -177,14 +177,12 @@ void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
 
        /*check init flag*/
        if (!(gf_mo_get_flags(txh->stream) & GF_MO_IS_INIT)) {
-               /*if we had a texture this means the object has changed - delete texture and force next frame 
-               composition (this will take care of OD reuse)*/
+               /*if we had a texture this means the object has changed - delete texture and resetup. Do not skip
+               texture update as this may lead to an empty rendering pass (blank frame for this object), especially in DASH*/
                if (txh->tx_io) {
                        gf_sc_texture_release(txh);
                        txh->data = NULL;
                        txh->needs_refresh = 1;
-                       gf_sc_invalidate(txh->compositor, NULL);
-                       return;
                }
                if (gf_mo_is_private_media(txh->stream)) {
                        setup_texture_object(txh, 1);
@@ -195,6 +193,7 @@ void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
 
        /*if no frame or muted don't draw*/
        if (!txh->data || !size) {
+               GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("No output frame available\n"));
                /*TODO - check if this is needed */
                if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
                        //txh->needs_refresh = 1;
index 102796855a12576e622b4a56f9a818f506b0c08c..e8b9e55fdc0f5356b6905bd245f901e2d8ae05f1 100644 (file)
 #pragma comment (linker, EXPORT_SYMBOL(gf_prompt_get_char) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_prompt_set_echo_off) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_crc_32) )
+#ifndef GPAC_DISABLE_ZLIB
 #pragma comment (linker, EXPORT_SYMBOL(gf_gz_compress_payload) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_gz_decompress_payload) )
+#endif
 
 /* Memory */
 #ifdef GPAC_MEMORY_TRACKING
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_decoder_config) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_reference_count) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_reference) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_reference_ID) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_has_track_reference) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_filename) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_brand_info) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_avc_config_get) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_svc_config_get) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_3gp_config_get) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_hevc_config_get) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_meta_item_count) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_meta_item_by_id) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_meta_item_info) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_rvc_config) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_sample_rap_roll_info) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_reset_fragment_info) )
-
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_track_original_id) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_nalu_extract_mode) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_nalu_extract_mode) )
 
 # ifndef GPAC_DISABLE_ISOM_DUMP
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_dump) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_track_creation_time) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_track_enabled) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_track_id) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_isom_rewrite_track_dependencies) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_add_sample) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_add_sample_shadow) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_isom_append_sample_data) )
 
 #ifndef GPAC_DISABLE_AV_PARSERS
 #pragma comment (linker, EXPORT_SYMBOL(gf_avc_get_sps_info) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_avc_get_pps_info) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_avc_get_profile_name) )
 #endif /*GPAC_DISABLE_AV_PARSERS*/
 
 #pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_segment_switch_forced) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_current_segment_start_time) )
 #pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_presentation_time_offset) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_video_info) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_representation_info) )
+
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_vps) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_sps) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_hevc_read_pps) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_odf_hevc_cfg_read) )
+#pragma comment (linker, EXPORT_SYMBOL(gf_odf_hevc_cfg_del) )
+
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_nalu_next_start_code) )
 
 #endif
 
index 4d638a02482ae85dcef74726016e2e27b5494af0..4324bb47f7db78167c89e7e685c48ee94af2c018 100644 (file)
@@ -342,6 +342,8 @@ GF_RTPStreamer *gf_rtp_streamer_new_extended(u32 streamType, u32 oti, u32 timeSc
                        break;
                case GF_ISOM_SUBTYPE_AVC_H264:
                case GF_ISOM_SUBTYPE_AVC2_H264:
+               case GF_ISOM_SUBTYPE_AVC3_H264:
+               case GF_ISOM_SUBTYPE_AVC4_H264:
                case GF_ISOM_SUBTYPE_SVC_H264:
                {
                        required_rate = 90000;  /* "90 kHz clock rate MUST be used"*/
index e88e74d147c3922e7c7548255212c076979a4a3e..970b83d4b7a6d9561af4daf3c6f8eefc7f10a69d 100644 (file)
 
 #ifndef GPAC_DISABLE_ISOM
 
+
+Bool gf_isom_is_nalu_based_entry(GF_MediaBox *mdia, GF_SampleEntryBox *_entry)
+{
+       GF_MPEGVisualSampleEntryBox *entry;
+       if (mdia->handler->handlerType != GF_ISOM_MEDIA_VISUAL) return 0;
+       entry = (GF_MPEGVisualSampleEntryBox*)_entry;
+       if (!entry) return 0;
+       if (entry->avc_config || entry->svc_config || entry->hevc_config) return 1;
+       return 0;
+}
+
+
+static void rewrite_nalus_list(GF_List *nalus, GF_BitStream *bs, Bool rewrite_start_codes, u32 nal_unit_size_field)
+{
+       u32 i, count = gf_list_count(nalus);
+       for (i=0; i<count; i++) {
+               GF_AVCConfigSlot *sl = gf_list_get(nalus, i);
+               if (rewrite_start_codes) gf_bs_write_u32(bs, 1);
+               else gf_bs_write_int(bs, sl->size, 8*nal_unit_size_field);
+               gf_bs_write_data(bs, sl->data, sl->size);
+       }                               
+}
+
+static void merge_nalus_list(GF_List  *src, GF_List *dst)
+{
+       u32 i, count = gf_list_count(src);
+       for (i=0; i<count; i++) {
+               void *p = gf_list_get(src, i);
+               if (p) gf_list_insert(dst, p, 0);
+       }
+}
+
+static void merge_nalus(GF_MPEGVisualSampleEntryBox *entry, GF_List *sps, GF_List *pps)
+{
+       if (entry->avc_config) {
+               merge_nalus_list(entry->avc_config->config->sequenceParameterSets, sps);
+               merge_nalus_list(entry->avc_config->config->sequenceParameterSetExtensions, sps);
+               merge_nalus_list(entry->avc_config->config->pictureParameterSets, pps);
+       }
+       if (entry->svc_config) {
+               merge_nalus_list(entry->svc_config->config->sequenceParameterSets, sps);
+               merge_nalus_list(entry->svc_config->config->pictureParameterSets, pps);
+       }
+}
+
+
+/* Rewrite mode:
+ * mode = 0: playback
+ * mode = 1: streaming
+ */
+GF_Err gf_isom_nalu_sample_rewrite(GF_MediaBox *mdia, GF_ISOSample *sample, u32 sampleNumber, GF_MPEGVisualSampleEntryBox *entry)
+{
+       Bool is_hevc = 0;
+       GF_Err e = GF_OK;
+       GF_ISOSample *ref_samp;
+       GF_BitStream *src_bs, *ref_bs, *dst_bs;
+       u64 offset;
+       u32 ref_nalu_size, data_offset, data_length, copy_size, nal_size, max_size, di, nal_unit_size_field, cur_extract_mode, extractor_mode;
+       Bool rewrite_ps, rewrite_start_codes;
+       u8 ref_track_ID, ref_track_num;
+       s8 sample_offset, nal_type;
+       u32 nal_hdr;
+       char *buffer;
+       GF_ISOFile *file = mdia->mediaTrack->moov->mov;
+
+       src_bs = ref_bs = dst_bs = NULL;
+       ref_samp = NULL;
+       buffer = NULL;
+       rewrite_ps = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG) ? 1 : 0;
+       if (! sample->IsRAP) rewrite_ps = 0;
+       rewrite_start_codes = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG) ? 1 : 0;
+       extractor_mode = mdia->mediaTrack->extractor_mode&0x0000FFFF;
+
+       if (extractor_mode == GF_ISOM_NALU_EXTRACT_INSPECT) {
+               if (!rewrite_ps && !rewrite_start_codes)
+                       return GF_OK;
+       }
+
+       if (!entry) return GF_BAD_PARAM;
+       nal_unit_size_field = 0;
+       /*if svc rewrire*/
+       if (entry->svc_config && entry->svc_config->config) nal_unit_size_field = entry->svc_config->config->nal_unit_size;
+       /*if mvc rewrire*/
+
+       /*otherwise do nothing*/
+       else if (!rewrite_ps && !rewrite_start_codes) {
+               return GF_OK;
+       }
+
+       if (!nal_unit_size_field) {
+               if (entry->avc_config) nal_unit_size_field = entry->avc_config->config->nal_unit_size;
+               else if (entry->hevc_config) {
+                       nal_unit_size_field = entry->hevc_config->config->nal_unit_size;
+                       is_hevc = 1;
+               }
+       }
+       if (!nal_unit_size_field) return GF_ISOM_INVALID_FILE;
+
+       dst_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+       src_bs = gf_bs_new(sample->data, sample->dataLength, GF_BITSTREAM_READ);
+       max_size = 4096;
+
+       /*rewrite start code with NALU delim*/
+       if (rewrite_start_codes) {
+               gf_bs_write_int(dst_bs, 1, 32);
+               if (is_hevc) {
+                       gf_bs_write_int(dst_bs, 0, 1);
+                       gf_bs_write_int(dst_bs, GF_HEVC_NALU_ACCESS_UNIT, 6);
+                       gf_bs_write_int(dst_bs, 0, 9);
+                       /*pic-type - by default we signal all slice types possible*/
+                       gf_bs_write_int(dst_bs, 2, 3);
+                       gf_bs_write_int(dst_bs, 0, 5);
+               } else {
+                       gf_bs_write_int(dst_bs, (sample->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8);
+                       gf_bs_write_int(dst_bs, 0xF0 , 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
+               }
+       }
+
+       if (rewrite_ps) {
+               if (is_hevc) {
+                       u32 i, count;
+                       count = gf_list_count(entry->hevc_config->config->param_array);
+                       for (i=0; i<count; i++) {
+                               GF_HEVCParamArray *ar = gf_list_get(entry->hevc_config->config->param_array, i);
+                               rewrite_nalus_list(ar->nalus, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                       }
+
+                       /*little optimization if we are not asked to start codes: copy over the sample*/
+                       if (!rewrite_start_codes) {
+                               gf_bs_write_data(dst_bs, sample->data, sample->dataLength);
+                               gf_free(sample->data);
+                               sample->data = NULL;
+                               gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength);
+                               gf_bs_del(src_bs);
+                               gf_bs_del(dst_bs);
+                               return GF_OK;
+                       }
+               } else {
+
+                       /*this is an SVC track: get all SPS/PPS from this track down to the base layer and rewrite them*/
+                       if (mdia->mediaTrack->has_base_layer) {
+                               u32 j;
+                               GF_List *nalu_sps = gf_list_new();
+                               GF_List *nalu_pps = gf_list_new();
+                               GF_TrackReferenceTypeBox *dpnd = NULL;
+                               Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_SCAL, &dpnd);
+
+#if 0
+                               /*get all upper layers with SCAL reference to this track*/
+                               for (j = 0; j < gf_isom_get_track_count(file); j++) {
+                                       if (gf_isom_has_track_reference(file, j+1, GF_ISOM_REF_SCAL, mdia->mediaTrack->Header->trackID)) {
+                                               u32 tkID;
+                                               GF_TrackBox *base_track;
+                                               GF_MPEGVisualSampleEntryBox *base_entry;
+                                               gf_isom_get_reference_ID(file, j+1, GF_ISOM_REF_SCAL, 1, &tkID);
+                                               
+                                               base_track = GetTrackbyID(mdia->mediaTrack->moov, tkID);
+                                               base_entry = base_track ? gf_list_get(base_track->Media->information->sampleTable->SampleDescription->other_boxes, 0) : NULL;
+                                               if (base_entry)
+                                                       merge_nalus(base_entry, nalu_sps, nalu_pps);
+                                       }
+                               }
+
+#endif
+
+                               merge_nalus(entry, nalu_sps, nalu_pps);
+                               if (dpnd) {
+                                       for (j=0; j<dpnd->trackIDCount; j++) {
+                                               GF_TrackBox *base_track = GetTrackbyID(mdia->mediaTrack->moov, dpnd->trackIDs[j]);
+                                               GF_MPEGVisualSampleEntryBox *base_entry = base_track ? gf_list_get(base_track->Media->information->sampleTable->SampleDescription->other_boxes, 0) : NULL;
+                                               if (base_entry)
+                                                       merge_nalus(base_entry, nalu_sps, nalu_pps);
+                                       }
+                               }
+
+                               //rewrite nalus
+                               rewrite_nalus_list(nalu_sps, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                               rewrite_nalus_list(nalu_pps, dst_bs, rewrite_start_codes, nal_unit_size_field);
+
+                               gf_list_del(nalu_sps);
+                               gf_list_del(nalu_pps);
+                       } else {
+
+                               if (entry->avc_config) {
+                                       rewrite_nalus_list(entry->avc_config->config->sequenceParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                                       rewrite_nalus_list(entry->avc_config->config->pictureParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                                       rewrite_nalus_list(entry->avc_config->config->sequenceParameterSetExtensions, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                               }
+
+                               /*add svc config */
+                               if (entry->svc_config) {
+                                       rewrite_nalus_list(entry->svc_config->config->sequenceParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                                       rewrite_nalus_list(entry->svc_config->config->pictureParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field);
+                               }
+
+                               /*little optimization if we are not asked to rewrite extractors or start codes: copy over the sample*/
+                               if (!entry->svc_config && !rewrite_start_codes) {
+                                       gf_bs_write_data(dst_bs, sample->data, sample->dataLength);
+                                       gf_free(sample->data);
+                                       sample->data = NULL;
+                                       gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength);
+                                       gf_bs_del(src_bs);
+                                       gf_bs_del(dst_bs);
+                                       return GF_OK;
+                               }
+                       
+                       }
+               }
+       }
+
+       buffer = (char *)gf_malloc(sizeof(char)*max_size);
+
+       while (gf_bs_available(src_bs))
+       {
+               nal_size = gf_bs_read_int(src_bs, 8*nal_unit_size_field);
+               if (nal_size>max_size) {
+                       buffer = (char*) gf_realloc(buffer, sizeof(char)*nal_size);
+                       max_size = nal_size;
+               }
+               if (is_hevc) {
+                       nal_hdr = gf_bs_read_u16(src_bs);
+                       nal_type = (nal_hdr&0x7E00) >> 9;
+               } else {
+                       nal_hdr = gf_bs_read_u8(src_bs);
+                       nal_type = nal_hdr & 0x1F;
+               } 
+
+               if (is_hevc) {
+                       /*we already wrote this stuff*/
+                       if (nal_type==GF_HEVC_NALU_ACCESS_UNIT) 
+                               continue;
+
+                       /*rewrite nal*/
+                       gf_bs_read_data(src_bs, buffer, nal_size-2);
+                       if (rewrite_start_codes) 
+                               gf_bs_write_u32(dst_bs, 1);
+                       else
+                               gf_bs_write_int(dst_bs, nal_size, 8*nal_unit_size_field);
+
+                       gf_bs_write_u16(dst_bs, nal_hdr);
+                       gf_bs_write_data(dst_bs, buffer, nal_size-2);
+
+                       continue;
+               } 
+               
+               /*we already wrote this stuff*/
+               if (nal_type==GF_AVC_NALU_ACCESS_UNIT)
+                       continue;
+
+               //extractor
+               if (nal_type == 31) {
+                       switch (extractor_mode) {
+                       case 0:
+                               gf_bs_read_int(src_bs, 24); //3 bytes of NALUHeader in extractor
+                               ref_track_ID = gf_bs_read_u8(src_bs);
+                               sample_offset = (s8) gf_bs_read_int(src_bs, 8);
+                               data_offset = gf_bs_read_u32(src_bs);
+                               data_length = gf_bs_read_u32(src_bs);
+
+                               ref_track_num = gf_isom_get_track_by_id(file, ref_track_ID);
+                               if (!ref_track_num) {
+                                       e = GF_BAD_PARAM;
+                                       goto exit;
+                               }
+                               cur_extract_mode = gf_isom_get_nalu_extract_mode(file, ref_track_num);
+                               gf_isom_set_nalu_extract_mode(file, ref_track_num, GF_ISOM_NALU_EXTRACT_INSPECT);
+                               ref_samp = gf_isom_get_sample(file, ref_track_num, sampleNumber+sample_offset, &di);
+                               if (!ref_samp) {
+                                       e = GF_IO_ERR;
+                                       goto exit;
+                               }
+                               ref_bs = gf_bs_new(ref_samp->data, ref_samp->dataLength, GF_BITSTREAM_READ);
+                               offset = 0;
+                               while (gf_bs_available(ref_bs)) {
+                                       if (gf_bs_get_position(ref_bs) < data_offset) {
+                                               ref_nalu_size = gf_bs_read_int(ref_bs, 8*nal_unit_size_field);
+                                               offset += ref_nalu_size + nal_unit_size_field;
+                                               if ((offset > data_offset) || (offset >= gf_bs_get_size(ref_bs))) {
+                                                       e = GF_BAD_PARAM;
+                                                       goto exit;
+                                               }
+
+                                               e = gf_bs_seek(ref_bs, offset);
+                                               if (e)
+                                                       goto exit;
+                                               continue;
+                                       }
+                                       ref_nalu_size = gf_bs_read_int(ref_bs, 8*nal_unit_size_field);
+                                       copy_size = data_length ? data_length : ref_nalu_size;
+                                       assert(copy_size <= ref_nalu_size);
+                                       nal_hdr = gf_bs_read_u8(ref_bs); //rewrite NAL type
+                                       if ((copy_size-1)>max_size) {
+                                               buffer = (char*)gf_realloc(buffer, sizeof(char)*(copy_size-1));
+                                               max_size = copy_size-1;
+                                       }                       
+                                       gf_bs_read_data(ref_bs, buffer, copy_size-1);
+
+                                       if (rewrite_start_codes) 
+                                               gf_bs_write_u32(dst_bs, 1);
+                                       else
+                                               gf_bs_write_int(dst_bs, copy_size, 8*nal_unit_size_field);
+
+                                       gf_bs_write_u8(dst_bs, nal_hdr);
+                                       gf_bs_write_data(dst_bs, buffer, copy_size-1);
+                               }
+
+                               gf_isom_sample_del(&ref_samp);
+                               ref_samp = NULL;
+                               gf_bs_del(ref_bs);
+                               ref_bs = NULL;
+                               gf_isom_set_nalu_extract_mode(file, ref_track_num, cur_extract_mode);
+                               break;
+                       default:
+                               //skip to end of this NALU
+                               gf_bs_skip_bytes(src_bs, nal_size-1);
+                               continue;
+                       }
+               } else {
+                       gf_bs_read_data(src_bs, buffer, nal_size-1);
+                       if (rewrite_start_codes) 
+                               gf_bs_write_u32(dst_bs, 1);
+                       else
+                               gf_bs_write_int(dst_bs, nal_size, 8*nal_unit_size_field);
+
+                       gf_bs_write_u8(dst_bs, nal_hdr);
+                       gf_bs_write_data(dst_bs, buffer, nal_size-1);
+               }
+       }
+       /*done*/
+       gf_free(sample->data);
+       sample->data = NULL;
+       gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength);
+
+exit:
+       if (ref_samp) gf_isom_sample_del(&ref_samp);
+       if (src_bs) gf_bs_del(src_bs);
+       if (ref_bs) gf_bs_del(ref_bs);
+       if (dst_bs) gf_bs_del(dst_bs);
+       if (buffer) gf_free(buffer);
+       return e;
+}
+
+GF_HEVCConfig *HEVC_DuplicateConfig(GF_HEVCConfig *cfg)
+{
+       char *data;
+       u32 data_size;
+       GF_HEVCConfig *new_cfg;
+       GF_BitStream *bs;
+       
+       if (!cfg) return NULL;
+       bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+       gf_odf_hevc_cfg_write_bs(cfg, bs);
+
+       gf_bs_get_content(bs, &data, &data_size);
+       gf_bs_del(bs);
+       bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
+
+       new_cfg = gf_odf_hevc_cfg_read_bs(bs);
+       gf_bs_del(bs);
+       gf_free(data);
+       return new_cfg;
+}
+
 static GF_AVCConfig *AVC_DuplicateConfig(GF_AVCConfig *cfg)
 {
        u32 i, count;
@@ -128,14 +491,41 @@ void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc)
                        gf_odf_avc_cfg_write(avcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
                        gf_odf_avc_cfg_del(avcc);
                }
-       } else {
+       } else if (avc->svc_config) {
                svcc = AVC_DuplicateConfig(avc->svc_config->config);
                gf_odf_avc_cfg_write(svcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
                gf_odf_avc_cfg_del(svcc);
        }
 }
 
-GF_Err AVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd)
+void HEVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *hevc)
+{
+       if (hevc->emul_esd) gf_odf_desc_del((GF_Descriptor *)hevc->emul_esd);
+       hevc->emul_esd = gf_odf_desc_esd_new(2);
+       hevc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
+       hevc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_HEVC;
+       if (hevc->bitrate) {
+               hevc->emul_esd->decoderConfig->bufferSizeDB = hevc->bitrate->bufferSizeDB;
+               hevc->emul_esd->decoderConfig->avgBitrate = hevc->bitrate->avgBitrate;
+               hevc->emul_esd->decoderConfig->maxBitrate = hevc->bitrate->maxBitrate;
+       }
+       if (hevc->descr) {
+               u32 i=0; 
+               GF_Descriptor *desc,*clone;
+               i=0;
+               while ((desc = (GF_Descriptor *)gf_list_enum(hevc->descr->descriptors, &i))) {
+                       clone = NULL;
+                       gf_odf_desc_copy(desc, &clone);
+                       if (gf_odf_desc_add_desc((GF_Descriptor *)hevc->emul_esd, clone) != GF_OK) 
+                               gf_odf_desc_del(clone);
+               }
+       }
+       if (hevc->hevc_config && hevc->hevc_config->config) {
+               gf_odf_hevc_cfg_write(hevc->hevc_config->config, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->data, &hevc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength);
+       }
+}
+
+GF_Err AVC_HEVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd)
 {
        if (!avc->bitrate) avc->bitrate = (GF_MPEG4BitRateBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_BTRT);
        if (avc->descr) gf_isom_box_del((GF_Box *) avc->descr);
@@ -178,14 +568,27 @@ GF_Err AVC_UpdateESD(GF_MPEGVisualSampleEntryBox *avc, GF_ESD *esd)
 
        /*update GF_AVCConfig*/
        if (!avc->svc_config) {
-               if (!avc->avc_config) avc->avc_config = (GF_AVCConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
-               if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
-                       if (avc->avc_config->config) gf_odf_avc_cfg_del(avc->avc_config->config);
-                       avc->avc_config->config = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
+               if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_HEVC) {
+                       if (!avc->hevc_config) avc->hevc_config = (GF_HEVCConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
+                       if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
+                               if (avc->hevc_config->config) gf_odf_hevc_cfg_del(avc->hevc_config->config);
+                               avc->hevc_config->config = gf_odf_hevc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
+                       }
+               } else {
+                       if (!avc->avc_config) avc->avc_config = (GF_AVCConfigurationBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
+                       if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
+                               if (avc->avc_config->config) gf_odf_avc_cfg_del(avc->avc_config->config);
+                               avc->avc_config->config = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
+                       }
                }
-               gf_odf_desc_del((GF_Descriptor *)esd);
+
+       }
+       gf_odf_desc_del((GF_Descriptor *)esd);
+       if (avc->hevc_config) {
+               HEVC_RewriteESDescriptor(avc);
+       } else {
+               AVC_RewriteESDescriptor(avc);
        }
-       AVC_RewriteESDescriptor(avc);
        return GF_OK;
 }
 
@@ -234,12 +637,14 @@ static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber
        e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
        if (e) return e;
        trak = gf_isom_get_track_from_file(the_file, trackNumber);
-       if (!trak || !trak->Media || !cfg || !DescriptionIndex) return GF_BAD_PARAM;
+       if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
        entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1);
        if (!entry) return GF_BAD_PARAM;
        switch (entry->type) {
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
                break;
        default:
@@ -249,6 +654,7 @@ static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber
        switch (op_type) {
        /*AVCC replacement*/
        case 0:
+               if (!cfg) return GF_BAD_PARAM;
                if (!entry->avc_config) entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
                if (entry->avc_config->config) gf_odf_avc_cfg_del(entry->avc_config->config);
                entry->avc_config->config = AVC_DuplicateConfig(cfg);
@@ -256,6 +662,7 @@ static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber
                break;
        /*SVCC replacement*/
        case 1:
+               if (!cfg) return GF_BAD_PARAM;
                if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC);
                if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config);
                entry->svc_config->config = AVC_DuplicateConfig(cfg);
@@ -263,6 +670,7 @@ static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber
                break;
        /*SVCC replacement and AVC removal*/
        case 2:
+               if (!cfg) return GF_BAD_PARAM;
                if (entry->avc_config) {
                        gf_isom_box_del((GF_Box*)entry->avc_config);
                        entry->avc_config = NULL;
@@ -272,11 +680,45 @@ static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber
                entry->svc_config->config = AVC_DuplicateConfig(cfg);
                entry->type = GF_ISOM_BOX_TYPE_SVC1;
                break;
+       /*AVCC removal and switch to avc3*/
+       case 3:
+               if (!entry->avc_config || !entry->avc_config->config) 
+                       return GF_BAD_PARAM;
+
+               if (entry->svc_config) {
+                       gf_isom_box_del((GF_Box*)entry->svc_config);
+                       entry->svc_config = NULL;
+               }
+
+               while (gf_list_count(entry->avc_config->config->sequenceParameterSets)) {
+                       GF_AVCConfigSlot *sl = gf_list_get(entry->avc_config->config->sequenceParameterSets, 0);
+                       gf_list_rem(entry->avc_config->config->sequenceParameterSets, 0);
+                       if (sl->data) gf_free(sl->data);
+                       gf_free(sl);
+               }
+
+               while (gf_list_count(entry->avc_config->config->pictureParameterSets)) {
+                       GF_AVCConfigSlot *sl = gf_list_get(entry->avc_config->config->pictureParameterSets, 0);
+                       gf_list_rem(entry->avc_config->config->pictureParameterSets, 0);
+                       if (sl->data) gf_free(sl->data);
+                       gf_free(sl);
+               }
+
+               if (entry->type == GF_ISOM_BOX_TYPE_AVC1)
+                       entry->type = GF_ISOM_BOX_TYPE_AVC3;
+               else if (entry->type == GF_ISOM_BOX_TYPE_AVC2)
+                       entry->type = GF_ISOM_BOX_TYPE_AVC4;
+               break;
        }
        AVC_RewriteESDescriptor(entry);
        return GF_OK;
 }
 
+GF_Err gf_isom_avc_set_inband_config(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
+{
+       return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, NULL, 3);
+}
+
 GF_EXPORT
 GF_Err gf_isom_avc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg)
 {
@@ -303,6 +745,8 @@ GF_Err gf_isom_svc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 Descrip
        switch (entry->type) {
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
                break;
        default:
@@ -334,7 +778,11 @@ GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber)
        switch (entry->type) {
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
                break;
        default:
                return GF_OK;
@@ -380,6 +828,79 @@ GF_Err gf_isom_svc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfi
        return e;
 }
 
+GF_Err gf_isom_hevc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_HEVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex)
+{
+       GF_TrackBox *trak;
+       GF_Err e;
+       u32 dataRefIndex;
+       GF_MPEGVisualSampleEntryBox *entry;
+
+       e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
+       if (e) return e;
+       
+       trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
+
+       //get or create the data ref
+       e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
+       if (e) return e;
+       if (!dataRefIndex) {
+               e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
+               if (e) return e;
+       }
+       trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
+
+       //create a new entry
+       entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_HVC1);
+       if (!entry) return GF_OUT_OF_MEM;
+       entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
+       entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
+       entry->dataReferenceIndex = dataRefIndex;
+       e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry);
+       *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes);
+       HEVC_RewriteESDescriptor(entry);
+       return e;
+}
+
+GF_Err gf_isom_hevc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg)
+{
+       u32 i, array_incomplete;
+       GF_TrackBox *trak;
+       GF_Err e;
+       GF_MPEGVisualSampleEntryBox *entry;
+
+       e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
+       if (e) return e;
+       trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!trak || !trak->Media || !cfg || !DescriptionIndex) return GF_BAD_PARAM;
+       entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1);
+       if (!entry) return GF_BAD_PARAM;
+       switch (entry->type) {
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
+               break;
+       default:
+               return GF_BAD_PARAM;
+       }
+
+       if (!entry->hevc_config) entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
+       if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
+       entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
+
+       array_incomplete = 0;
+       for (i=0; i<gf_list_count(entry->hevc_config->config->param_array); i++) {
+               GF_HEVCParamArray *ar = gf_list_get(entry->hevc_config->config->param_array, i);
+               if (!ar->array_completeness) {
+                       array_incomplete = 1;
+                       break;
+               }
+       }
+       entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV1 : GF_ISOM_BOX_TYPE_HVC1;
+       
+       HEVC_RewriteESDescriptor(entry);
+       return GF_OK;
+}
+
 #endif /*GPAC_DISABLE_ISOM_WRITE*/
 
 GF_EXPORT
@@ -389,13 +910,37 @@ GF_AVCConfig *gf_isom_avc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32
        GF_MPEGVisualSampleEntryBox *entry;
        trak = gf_isom_get_track_from_file(the_file, trackNumber);
        if (!trak || !trak->Media || !DescriptionIndex) return NULL;
+       if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
+               return NULL;
+
        entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1);
        if (!entry) return NULL;
-       //if (entry->type != GF_ISOM_BOX_TYPE_AVC1) return NULL;
+
        if (!entry->avc_config) return NULL;
        return AVC_DuplicateConfig(entry->avc_config->config);
 }
 
+GF_EXPORT
+GF_HEVCConfig *gf_isom_hevc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
+{
+       GF_TrackBox *trak;
+       GF_MPEGVisualSampleEntryBox *entry;
+       trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!trak || !trak->Media || !DescriptionIndex) return NULL;
+
+       entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1);
+       if (!entry) return NULL;
+       switch (entry->type) {
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
+               break;
+       default:
+               return NULL;
+       }
+       if (!entry->hevc_config) return NULL;
+       return HEVC_DuplicateConfig(entry->hevc_config->config);
+}
+
 GF_EXPORT
 GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
 {
@@ -403,12 +948,15 @@ GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32
        GF_MPEGVisualSampleEntryBox *entry;
        trak = gf_isom_get_track_from_file(the_file, trackNumber);
        if (!trak || !trak->Media || !DescriptionIndex) return NULL;
+       if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
+               return NULL;
        entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1);
        if (!entry) return NULL;
        if (!entry->svc_config) return NULL;
        return AVC_DuplicateConfig(entry->svc_config->config);
 }
 
+
 GF_EXPORT
 u32 gf_isom_get_avc_svc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
 {
@@ -416,11 +964,14 @@ u32 gf_isom_get_avc_svc_type(GF_ISOFile *the_file, u32 trackNumber, u32 Descript
        GF_MPEGVisualSampleEntryBox *entry;
        trak = gf_isom_get_track_from_file(the_file, trackNumber);
        if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_AVCTYPE_NONE;
+       if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_VISUAL) return GF_ISOM_AVCTYPE_NONE;
        entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1);
        if (!entry) return GF_ISOM_AVCTYPE_NONE;
        switch (entry->type) {
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
                break;
        default:
@@ -604,7 +1155,7 @@ GF_Err avcc_Read(GF_Box *s, GF_BitStream *bs)
                                AVCState avc;
                                s32 idx, vui_flag_pos;
                                GF_AVCConfigSlot *sl = gf_list_get(ptr->config->sequenceParameterSets, 0);
-                               idx = AVC_ReadSeqInfo(sl->data+1, sl->size-1, &avc, 0, &vui_flag_pos);
+                               idx = gf_media_avc_read_sps(sl->data+1, sl->size-1, &avc, 0, &vui_flag_pos);
                                if (idx>=0) {
                                        ptr->config->chroma_format = avc.sps[idx].chroma_format;
                                        ptr->config->luma_bit_depth = 8 + avc.sps[idx].luma_bit_depth_m8;
@@ -755,4 +1306,75 @@ GF_Err avcc_Size(GF_Box *s)
 #endif /*GPAC_DISABLE_ISOM_WRITE*/
 
 
+
+void hvcc_del(GF_Box *s)
+{
+       GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox*)s;
+       if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);
+       gf_free(ptr);
+}
+
+GF_Err hvcc_Read(GF_Box *s, GF_BitStream *bs)
+{
+       u64 pos;
+       GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
+
+       if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);
+       
+       pos = gf_bs_get_position(bs);
+       ptr->config = gf_odf_hevc_cfg_read_bs(bs);
+       pos = gf_bs_get_position(bs) - pos ;
+       if (pos < ptr->size)
+               ptr->size -= (u32) pos;
+
+       return GF_OK;
+}
+GF_Box *hvcc_New()
+{
+       GF_HEVCConfigurationBox *tmp = (GF_HEVCConfigurationBox *) gf_malloc(sizeof(GF_HEVCConfigurationBox));
+       if (tmp == NULL) return NULL;
+       memset(tmp, 0, sizeof(GF_HEVCConfigurationBox));
+       tmp->type = GF_ISOM_BOX_TYPE_HVCC;
+       return (GF_Box *)tmp;
+}
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+GF_Err hvcc_Write(GF_Box *s, GF_BitStream *bs)
+{
+       GF_Err e;
+       GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *) s;
+       if (!s) return GF_BAD_PARAM;
+       if (!ptr->config) return GF_OK;
+       e = gf_isom_box_write_header(s, bs);
+       if (e) return e;
+
+       return gf_odf_hevc_cfg_write_bs(ptr->config, bs);
+}
+GF_Err hvcc_Size(GF_Box *s)
+{
+       GF_Err e;
+       u32 i, count, j, subcount;
+       GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;
+       e = gf_isom_box_get_size(s);
+       if (e) return e;
+       if (!ptr->config) {
+               ptr->size = 0;
+               return e;
+       }
+       ptr->size += 16;
+
+       count = gf_list_count(ptr->config->param_array);
+       for (i=0; i<count; i++) {
+               GF_HEVCParamArray *ar = gf_list_get(ptr->config->param_array, i);
+               ptr->size += 3;
+               subcount = gf_list_count(ar->nalus);
+               for (j=0; j<subcount; j++) {
+                       ptr->size += 2 + ((GF_AVCConfigSlot *)gf_list_get(ar->nalus, j))->size;
+               }
+       }
+       return GF_OK;
+}
+#endif /*GPAC_DISABLE_ISOM_WRITE*/
+
+
 #endif /*GPAC_DISABLE_ISOM*/
index 32069d83f33f78e81d27dd089eaf983ebd08c705..37b98207000f0384b3c10c7b849d5f05c481a67c 100644 (file)
  *\r
  */\r
 \r
-#ifndef GPAC_DISABLE_ISOM_ADOBE\r
-\r
 #include <gpac/internal/isomedia_dev.h>\r
 \r
+#ifndef GPAC_DISABLE_ISOM_ADOBE\r
+\r
 #ifndef GPAC_DISABLE_ISOM\r
 \r
 #ifndef        GPAC_DISABLE_ISOM_FRAGMENTS\r
index f0eec99e34bda0c2844d10bfeaab44cd563f84b5..98e049c8eacd2cebb27afd05c11c600609cdda63 100644 (file)
@@ -3504,6 +3504,7 @@ void mp4v_del(GF_Box *s)
        if (ptr->slc) gf_odf_desc_del((GF_Descriptor *)ptr->slc);
        if (ptr->avc_config) gf_isom_box_del((GF_Box *) ptr->avc_config);
        if (ptr->svc_config) gf_isom_box_del((GF_Box *) ptr->svc_config);
+       if (ptr->hevc_config) gf_isom_box_del((GF_Box *) ptr->hevc_config);
        if (ptr->bitrate) gf_isom_box_del((GF_Box *) ptr->bitrate);
        if (ptr->descr) gf_isom_box_del((GF_Box *) ptr->descr);
        if (ptr->ipod_ext) gf_isom_box_del((GF_Box *)ptr->ipod_ext);
@@ -3531,6 +3532,10 @@ GF_Err mp4v_AddBox(GF_Box *s, GF_Box *a)
                if (ptr->avc_config) return GF_ISOM_INVALID_FILE;
                ptr->avc_config = (GF_AVCConfigurationBox *)a;
                break;
+       case GF_ISOM_BOX_TYPE_HVCC:
+               if (ptr->hevc_config) return GF_ISOM_INVALID_FILE;
+               ptr->hevc_config = (GF_HEVCConfigurationBox *)a;
+               break;
        case GF_ISOM_BOX_TYPE_SVCC:
                if (ptr->svc_config) return GF_ISOM_INVALID_FILE;
                ptr->svc_config = (GF_AVCConfigurationBox *)a;
@@ -3571,6 +3576,8 @@ GF_Err mp4v_Read(GF_Box *s, GF_BitStream *bs)
        if (e) return e;
        /*this is an AVC sample desc*/
        if (mp4v->avc_config || mp4v->svc_config) AVC_RewriteESDescriptor(mp4v);
+       /*this is an HEVC sample desc*/
+       if (mp4v->hevc_config ) HEVC_RewriteESDescriptor(mp4v);
        return GF_OK;
 }
 
@@ -3599,11 +3606,32 @@ GF_Box *avc2_New()
        return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_AVC2);
 }
 
+GF_Box *avc3_New()
+{
+       return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_AVC3);
+}
+
+GF_Box *avc4_New()
+{
+       return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_AVC4);
+}
+
 GF_Box *svc1_New()
 {
        return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_SVC1);
 }
 
+GF_Box *hvc1_New()
+{
+       return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_HVC1);
+}
+
+GF_Box *hev1_New()
+{
+       return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_HEV1);
+}
+
+
 GF_Box *encv_New()
 {
        return mp4v_encv_avc1_new(GF_ISOM_BOX_TYPE_ENCV);
@@ -3636,6 +3664,10 @@ GF_Err mp4v_Write(GF_Box *s, GF_BitStream *bs)
                        e = gf_isom_box_write((GF_Box *) ptr->avc_config, bs);
                        if (e) return e;
                }
+               if (ptr->hevc_config && ptr->hevc_config->config) {
+                       e = gf_isom_box_write((GF_Box *) ptr->hevc_config, bs);
+                       if (e) return e;
+               }
                if (ptr->ipod_ext)      {
                        e = gf_isom_box_write((GF_Box *) ptr->ipod_ext, bs);
                        if (e) return e;
@@ -3674,19 +3706,28 @@ GF_Err mp4v_Size(GF_Box *s)
                if (e) return e;
                ptr->size += ptr->esd->size;
        } else {
-               if (!ptr->avc_config && !ptr->svc_config)
+               if (!ptr->avc_config && !ptr->svc_config && !ptr->hevc_config) {
                        return GF_ISOM_INVALID_FILE;
+               }
 
+               if (ptr->hevc_config && ptr->hevc_config->config) {
+                       e = gf_isom_box_size((GF_Box *)ptr->hevc_config);
+                       if (e) return e;
+                       ptr->size += ptr->hevc_config->size;
+               } 
+               
                if (ptr->avc_config && ptr->avc_config->config) {
                        e = gf_isom_box_size((GF_Box *) ptr->avc_config); 
                        if (e) return e;
                        ptr->size += ptr->avc_config->size;
                }
+
                if (ptr->svc_config && ptr->svc_config->config) {
                        e = gf_isom_box_size((GF_Box *) ptr->svc_config); 
                        if (e) return e;
                        ptr->size += ptr->svc_config->size;
                }
+
                if (ptr->ipod_ext) {
                        e = gf_isom_box_size((GF_Box *) ptr->ipod_ext);
                        if (e) return e;
@@ -4902,7 +4943,11 @@ GF_Err stsd_AddBox(GF_SampleDescriptionBox *ptr, GF_Box *a)
        case GF_ISOM_BOX_TYPE_RTP_STSD:
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
        case GF_ISOM_BOX_TYPE_TX3G:
        case GF_ISOM_BOX_TYPE_TEXT:
        case GF_ISOM_BOX_TYPE_ENCT:
@@ -6104,10 +6149,14 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak)
                case GF_ISOM_SUBTYPE_3GP_H263:
                case GF_ISOM_BOX_TYPE_GHNT:
                case GF_ISOM_BOX_TYPE_RTP_STSD:
-               case GF_ISOM_BOX_TYPE_AVC1:
                case GF_ISOM_BOX_TYPE_METX:
                case GF_ISOM_BOX_TYPE_METT:
+               case GF_ISOM_BOX_TYPE_AVC1:
                case GF_ISOM_BOX_TYPE_AVC2:
+               case GF_ISOM_BOX_TYPE_AVC3:
+               case GF_ISOM_BOX_TYPE_AVC4:
+               case GF_ISOM_BOX_TYPE_HVC1:
+               case GF_ISOM_BOX_TYPE_HEV1:
                case GF_ISOM_BOX_TYPE_SVC1:
                case GF_ISOM_BOX_TYPE_TX3G:
                case GF_ISOM_BOX_TYPE_TEXT:
@@ -6473,6 +6522,11 @@ GF_Err trex_Read(GF_Box *s, GF_BitStream *bs)
        ptr->def_sample_duration = gf_bs_read_u32(bs);
        ptr->def_sample_size = gf_bs_read_u32(bs);
        ptr->def_sample_flags = gf_bs_read_u32(bs);
+
+       if (!ptr->def_sample_desc_index) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] TREX with default sample description set to 0, likely broken ! Fixing to 1\n" ));
+               ptr->def_sample_desc_index = 1;
+       }
        return GF_OK;
 }
 
@@ -8183,7 +8237,7 @@ static void       sgpd_del_entry(u32 grouping_type, void *entry)
        {
                GF_DefaultSampleGroupDescriptionEntry *ptr = (GF_DefaultSampleGroupDescriptionEntry *)entry;
                if (ptr->data) gf_free(ptr->data);
-               gf_free(ptr->data);
+               gf_free(ptr);
        }
 
        }
index 9d72e9272197c262fdc7834a4f34fcdfe2df3f9b..d6560a040294e8784a1d5547d349830aa6200a92 100644 (file)
@@ -305,13 +305,19 @@ GF_Err gf_box_dump(void *ptr, FILE * trace)
        case GF_ISOM_BOX_TYPE_AVCC: 
        case GF_ISOM_BOX_TYPE_SVCC: 
                return avcc_dump(a, trace);
+       case GF_ISOM_BOX_TYPE_HVCC: 
+               return hvcc_dump(a, trace);
        case GF_ISOM_BOX_TYPE_BTRT:
                return btrt_dump(a, trace);
        case GF_ISOM_BOX_TYPE_M4DS:
                return m4ds_dump(a, trace);
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2: 
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1: 
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                return mp4v_dump(a, trace);
        case GF_ISOM_BOX_TYPE_PASP:
                return pasp_dump(a, trace);
@@ -962,6 +968,7 @@ GF_Err mp4v_dump(GF_Box *a, FILE * trace)
        if (p->esd) {
                gf_box_dump(p->esd, trace);
        } else {
+               if (p->hevc_config) gf_box_dump(p->hevc_config, trace);
                if (p->avc_config) gf_box_dump(p->avc_config, trace);
                if (p->ipod_ext) gf_box_dump(p->ipod_ext, trace);
                if (p->descr) gf_box_dump(p->descr, trace);
@@ -1680,6 +1687,43 @@ GF_Err avcc_dump(GF_Box *a, FILE * trace)
        return GF_OK;
 }
 
+GF_Err hvcc_dump(GF_Box *a, FILE * trace)
+{
+       u32 i, count;
+       GF_HEVCConfigurationBox *p = (GF_HEVCConfigurationBox *) a;
+
+       fprintf(trace, "<HEVCConfigurationBox>\n");
+
+       fprintf(trace, "<HEVCDecoderConfigurationRecord nal_unit_size=\"%d\" configurationVersion=\"%d\" profile_space=\"%d\" profile_idc=\"%d\" constraint_indicator_flags=\"%d\" ",
+                                       p->config->nal_unit_size, p->config->configurationVersion, p->config->profile_space, p->config->profile_idc, p->config->constraint_indicator_flags);
+       fprintf(trace, "chroma_format=\"%d\" luma_bit_depth=\"%d\" chroma_bit_depth=\"%d\" avgFrameRate=\"%d\" constantFrameRate=\"%d\" numTemporalLayers=\"%d\"",
+               p->config->chromaFormat, p->config->luma_bit_depth, p->config->chroma_bit_depth, p->config->avgFrameRate, p->config->constantFrameRate, p->config->numTemporalLayers);
+
+       fprintf(trace, ">\n");
+
+       count = gf_list_count(p->config->param_array);
+       for (i=0; i<count; i++) {
+               u32 nalucount, j;
+               GF_HEVCParamArray *ar = gf_list_get(p->config->param_array, i);
+               fprintf(trace, "<ParameterSetArray nalu_type=\"%d\" complete_set=\"%d\">\n", ar->type, ar->array_completeness);
+               nalucount = gf_list_count(ar->nalus);
+               for (j=0; j<nalucount; j++) {
+                       GF_AVCConfigSlot *c = (GF_AVCConfigSlot *)gf_list_get(ar->nalus, j);
+                       fprintf(trace, "<ParameterSet size=\"%d\" content=\"", c->size);
+                       DumpData(trace, c->data, c->size);
+                       fprintf(trace, "\"/>\n");
+               }
+               fprintf(trace, "</ParameterSetArray>\n");
+       }
+
+       fprintf(trace, "</HEVCDecoderConfigurationRecord>\n");
+
+       DumpBox(a, trace);
+       gf_box_dump_done(NULL, a, trace);
+       fprintf(trace, "</HEVCConfigurationBox>\n");
+       return GF_OK;
+}
+
 GF_Err m4ds_dump(GF_Box *a, FILE * trace)
 {
        u32 i;
@@ -2299,6 +2343,19 @@ GF_Err mehd_dump(GF_Box *a, FILE * trace)
        return GF_OK;
 }
 
+void sample_flags_dump(const char *name, u32 sample_flags, FILE * trace)
+{
+       fprintf(trace, "<%s", name);
+       fprintf(trace, " IsLeading=\"%d\"", GF_ISOM_GET_FRAG_LEAD(sample_flags) );
+       fprintf(trace, " SampleDependsOn=\"%d\"", GF_ISOM_GET_FRAG_DEPENDS(sample_flags) );
+       fprintf(trace, " SampleIsDependedOn=\"%d\"", GF_ISOM_GET_FRAG_DEPENDED(sample_flags) );
+       fprintf(trace, " SampleHasRedundancy=\"%d\"", GF_ISOM_GET_FRAG_REDUNDANT(sample_flags) );
+       fprintf(trace, " SamplePadding=\"%d\"", GF_ISOM_GET_FRAG_PAD(sample_flags) );
+       fprintf(trace, " SampleSync=\"%d\"", GF_ISOM_GET_FRAG_SYNC(sample_flags));
+       fprintf(trace, " SampleDegradationPriority=\"%d\"", GF_ISOM_GET_FRAG_DEG(sample_flags));
+       fprintf(trace, "/>\n");
+}
+
 GF_Err trex_dump(GF_Box *a, FILE * trace)
 {
        GF_TrackExtendsBox *p;
@@ -2307,10 +2364,8 @@ GF_Err trex_dump(GF_Box *a, FILE * trace)
        fprintf(trace, "<TrackExtendsBox TrackID=\"%d\"", p->trackID);
 
        fprintf(trace, " SampleDescriptionIndex=\"%d\" SampleDuration=\"%d\" SampleSize=\"%d\"", p->def_sample_desc_index, p->def_sample_duration, p->def_sample_size);
-       fprintf(trace, " SamplePadding=\"%d\" SampleSync=\"%d\" SampleDegradationPriority=\"%d\"",
-               GF_ISOM_GET_FRAG_PAD(p->def_sample_flags), GF_ISOM_GET_FRAG_SYNC(p->def_sample_flags), GF_ISOM_GET_FRAG_DEG(p->def_sample_flags));
-
        fprintf(trace, ">\n");
+       sample_flags_dump("DefaultSampleFlags", p->def_sample_flags, trace);
        DumpBox(a, trace);
        gf_full_box_dump(a, trace);
        gf_box_dump_done("TrackExtendsBox", a, trace);
@@ -2402,10 +2457,11 @@ GF_Err trun_dump(GF_Box *a, FILE * trace)
 
        if (p->flags & GF_ISOM_TRUN_DATA_OFFSET)
                fprintf(trace, " DataOffset=\"%d\"", p->data_offset);
+       fprintf(trace, ">\n");
+
        if (p->flags & GF_ISOM_TRUN_FIRST_FLAG) {
-               fprintf(trace, " FirstSamplePadding=\"%d\" FirstSampleSync=\"%d\" FirstSampleDegradationPriority=\"%d\"", GF_ISOM_GET_FRAG_PAD(p->first_sample_flags), GF_ISOM_GET_FRAG_SYNC(p->first_sample_flags), GF_ISOM_GET_FRAG_DEG(p->first_sample_flags));
+               sample_flags_dump("FirstSampleFlags", p->first_sample_flags, trace);
        }
-       fprintf(trace, ">\n");
        DumpBox(a, trace);
        gf_full_box_dump(a, trace);
 
index ac7c77438a626f4c6953db3a8b3010fe98f8b7de..1daaf7953ddc728b19b6a46406cd4117d856f6d4 100644 (file)
@@ -501,12 +501,18 @@ GF_Box *gf_isom_box_new(u32 boxType)
                a = avcc_New();
                if (a) a->type = boxType;
                return a;
+       case GF_ISOM_BOX_TYPE_HVCC: 
+               return hvcc_New();
 
        case GF_ISOM_BOX_TYPE_BTRT: return btrt_New();
        case GF_ISOM_BOX_TYPE_M4DS: return m4ds_New();
        case GF_ISOM_BOX_TYPE_AVC1: return avc1_New();
        case GF_ISOM_BOX_TYPE_AVC2: return avc2_New();
+       case GF_ISOM_BOX_TYPE_AVC3: return avc3_New();
+       case GF_ISOM_BOX_TYPE_AVC4: return avc4_New();
        case GF_ISOM_BOX_TYPE_SVC1: return svc1_New();
+       case GF_ISOM_BOX_TYPE_HVC1: return hvc1_New();
+       case GF_ISOM_BOX_TYPE_HEV1: return hev1_New();
 
        /*3GPP streaming text*/
        case GF_ISOM_BOX_TYPE_FTAB: return ftab_New();
@@ -795,8 +801,13 @@ void gf_isom_box_del(GF_Box *a)
        case GF_ISOM_BOX_TYPE_M4DS: m4ds_del(a); return;
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2: 
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1: 
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
                mp4v_del(a); return;
+       case GF_ISOM_BOX_TYPE_HVCC: hvcc_del(a); return;
 
        /*3GPP streaming text*/
        case GF_ISOM_BOX_TYPE_FTAB: ftab_del(a); return;
@@ -1066,8 +1077,14 @@ GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs)
        case GF_ISOM_BOX_TYPE_M4DS: return m4ds_Read(a, bs);
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2: 
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1: 
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
                return mp4v_Read(a, bs);
+       case GF_ISOM_BOX_TYPE_HVCC: 
+               return hvcc_Read(a, bs);
 
        /*3GPP streaming text*/
        case GF_ISOM_BOX_TYPE_FTAB: return ftab_Read(a, bs);
@@ -1319,11 +1336,17 @@ GF_Err gf_isom_box_write_listing(GF_Box *a, GF_BitStream *bs)
        case GF_ISOM_BOX_TYPE_AVCC: 
        case GF_ISOM_BOX_TYPE_SVCC: 
                return avcc_Write(a, bs);
+       case GF_ISOM_BOX_TYPE_HVCC: 
+               return hvcc_Write(a, bs);
        case GF_ISOM_BOX_TYPE_BTRT: return btrt_Write(a, bs);
        case GF_ISOM_BOX_TYPE_M4DS: return m4ds_Write(a, bs);
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2: 
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1: 
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
                return mp4v_Write(a, bs);
 
        /*3GPP streaming text*/
@@ -1584,11 +1607,17 @@ static GF_Err gf_isom_box_size_listing(GF_Box *a)
        case GF_ISOM_BOX_TYPE_AVCC: 
        case GF_ISOM_BOX_TYPE_SVCC: 
                return avcc_Size(a);
+       case GF_ISOM_BOX_TYPE_HVCC: 
+               return hvcc_Size(a);
        case GF_ISOM_BOX_TYPE_BTRT: return btrt_Size(a);
        case GF_ISOM_BOX_TYPE_M4DS: return m4ds_Size(a);
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2: 
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1: 
+       case GF_ISOM_BOX_TYPE_HVC1:
+       case GF_ISOM_BOX_TYPE_HEV1:
                return mp4v_Size(a);
 
        /*3GPP streaming text*/
index 68bc03cc59b624042ade1f5cb068d748aa4802c5..298c3cb894f9e39ab9959691f3f60de4fcd38772 100644 (file)
@@ -130,6 +130,10 @@ GF_Err gf_isom_datamap_new(const char *location, const char *parentPath, u8 mode
 #else
                return GF_NOT_SUPPORTED;
 #endif
+       } else if (!strncmp(location, "gmem://", 7)) {
+               *outDataMap = gf_isom_fdm_new(location, GF_ISOM_DATA_MAP_READ);
+               if (! (*outDataMap)) return GF_IO_ERR;
+               return GF_OK;
        }
 
        extern_file = !gf_url_is_local(location);
@@ -340,6 +344,18 @@ GF_DataMap *gf_isom_fdm_new(const char *sPath, u8 mode)
                bs_mode = GF_BITSTREAM_READ;
        }
 #endif
+       if (!strncmp(sPath, "gmem://", 7)) {
+               u32 size;
+               void *mem_address;
+               if (sscanf(sPath, "gmem://%d@%p", &size, &mem_address) != 2)
+                       return NULL;
+               tmp->bs = gf_bs_new((const char *)mem_address, size, GF_BITSTREAM_READ);
+               if (!tmp->bs) {
+                       gf_free(tmp);
+                       return NULL;
+               }
+               return (GF_DataMap *)tmp;
+       }
 
        switch (mode) {
        case GF_ISOM_DATA_MAP_READ:
@@ -426,7 +442,7 @@ u32 gf_isom_fdm_get_data(GF_FileDataMap *ptr, char *buffer, u32 bufferLength, u6
                //rewind to original (if seek fails, return 0 cause this means:
                //1- no support for seek on the platform
                //2- corrupted file for the OS
-               fflush(ptr->stream);
+               if (ptr->stream) fflush(ptr->stream);
                gf_bs_seek(ptr->bs, ptr->curPos);
        }
        ptr->last_acces_was_read = 1;
@@ -472,7 +488,7 @@ GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize)
        }
        ptr->curPos = gf_bs_get_position(ptr->bs);
        //flush the stream !!
-       fflush(ptr->stream);
+       if (ptr->stream) fflush(ptr->stream);
        return GF_OK;
 }
 
index f94ed3374ea744c7b310fe44062712e28362f54d..1bf6093e5f5e78f712e73e43393a0c826ea056ef 100644 (file)
@@ -337,6 +337,7 @@ GF_Err gf_isom_remove_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber,
        gf_isom_box_array_del(sea->protections);
        sea->protections = gf_list_new();
        if (sea->type == GF_4CC('2','6','4','b')) sea->type = GF_ISOM_BOX_TYPE_AVC1;
+       if (sea->type == GF_4CC('2','6','5','b')) sea->type = GF_ISOM_BOX_TYPE_HVC1;
        return GF_OK;
 }
 
@@ -403,10 +404,17 @@ GF_Err gf_isom_set_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u3
        /*special case for AVC1*/
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1:
                original_format = GF_4CC('2','6','4','b');
                sea->type = GF_ISOM_BOX_TYPE_ENCV;
                break;
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
+               original_format = GF_4CC('2','6','5','b');
+               sea->type = GF_ISOM_BOX_TYPE_ENCV;
+               break;
        case GF_ISOM_BOX_TYPE_MP4S:
        case GF_ISOM_BOX_TYPE_LSR1:
                original_format = sea->type;
@@ -467,8 +475,12 @@ GF_Err gf_isom_set_oma_protection(GF_ISOFile *the_file, u32 trackNumber, u32 des
        case GF_ISOM_BOX_TYPE_MP4V:
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1:
        case GF_ISOM_BOX_TYPE_D263:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                original_format = sea->type;
                sea->type = GF_ISOM_BOX_TYPE_ENCV;
                break;
index 6d54c1f88c7c8f7f943cdd4a48682feb5fa2d077..30bf7698cdbee7d8d6a43c59f285d79fc1582bd9 100644 (file)
@@ -481,6 +481,20 @@ GF_TrackBox *gf_isom_get_track_from_id(GF_MovieBox *moov, u32 trackID)
        return NULL;
 }
 
+GF_TrackBox *gf_isom_get_track_from_original_id(GF_MovieBox *moov, u32 originalID, u32 originalFile) 
+{
+       u32 i, count;
+       GF_TrackBox *trak;
+       if (!moov || !originalID) return NULL;
+
+       count = gf_list_count(moov->trackList);
+       for (i = 0; i<count; i++) {
+               trak = (GF_TrackBox*)gf_list_get(moov->trackList, i);
+               if ((trak->originalFile == originalFile) && (trak->originalID == originalID)) return trak;
+       }
+       return NULL;
+}
+
 GF_TrackBox *gf_isom_get_track_from_file(GF_ISOFile *movie, u32 trackNumber)
 {
        GF_TrackBox *trak;
index 8638353a4105bcc1dcc7b6a47d618f84df76c986..5297372c3dc295571f7853f54aeb31c625e4c0c3 100644 (file)
@@ -92,17 +92,28 @@ void gf_isom_sample_del(GF_ISOSample **samp)
 GF_EXPORT
 Bool gf_isom_probe_file(const char *fileName)
 {
-       unsigned char data[4];
-       u32 type;
-       FILE *f = gf_f64_open(fileName, "rb");
-       if (!f) return 0;
-       type = 0;
-       if (fread(data, 1, 4, f) == 4) {
+       u32 type = 0;
+
+       if (!strncmp(fileName, "gmem://", 7)) {
+               u32 size;
+               u8 *mem_address;
+               if (sscanf(fileName, "gmem://%d@%p", &size, &mem_address) != 2) {
+                       return GF_URL_ERROR;
+               } 
+               if (size>8)
+                       type = GF_4CC(mem_address[4], mem_address[5], mem_address[6], mem_address[7]);
+       } else {
+               unsigned char data[4];
+               FILE *f = gf_f64_open(fileName, "rb");
+               if (!f) return 0;
+               type = 0;
                if (fread(data, 1, 4, f) == 4) {
-                       type = GF_4CC(data[0], data[1], data[2], data[3]);
+                       if (fread(data, 1, 4, f) == 4) {
+                               type = GF_4CC(data[0], data[1], data[2], data[3]);
+                       }
                }
+               fclose(f);
        }
-       fclose(f);
        switch (type) {
        case GF_ISOM_BOX_TYPE_MOOV:
        case GF_ISOM_BOX_TYPE_MDAT:
@@ -405,6 +416,16 @@ u32 gf_isom_get_track_by_id(GF_ISOFile *the_file, u32 trackID)
        return 0;
 }
 
+GF_EXPORT
+u32 gf_isom_get_track_original_id(GF_ISOFile *movie, u32 trackNumber)
+{
+       GF_TrackBox *trak;
+       if (!movie) return 0;
+       trak = gf_isom_get_track_from_file(movie, trackNumber);
+       if (!trak) return 0;
+       return trak->originalID;
+}
+
 //return the timescale of the movie, 0 if error
 GF_EXPORT
 Bool gf_isom_has_movie(GF_ISOFile *file)
@@ -568,7 +589,7 @@ GF_Err gf_isom_get_media_language(GF_ISOFile *the_file, u32 trackNumber, char *t
 
 
 //Return the number of track references of a track for a given ReferenceType
-//return -1 if error
+//return 0 if error
 GF_EXPORT
 s32 gf_isom_get_reference_count(GF_ISOFile *movie, u32 trackNumber, u32 referenceType)
 {
@@ -622,10 +643,35 @@ GF_Err gf_isom_get_reference(GF_ISOFile *movie, u32 trackNumber, u32 referenceTy
        return GF_OK;
 }
 
-//Return the number of track references of a track for a given ReferenceType
+//Return the referenced track ID for a track and a given ReferenceType and Index
+//return -1 if error, 0 if the reference is a NULL one, or the trackNumber
+GF_EXPORT
+GF_Err gf_isom_get_reference_ID(GF_ISOFile *movie, u32 trackNumber, u32 referenceType, u32 referenceIndex, u32 *refTrackID)
+{
+       GF_Err e;
+       GF_TrackBox *trak;
+       GF_TrackReferenceTypeBox *dpnd;
+       trak = gf_isom_get_track_from_file(movie, trackNumber);
+
+       *refTrackID = 0;
+       if (!trak || !trak->References) return GF_BAD_PARAM;
+
+       dpnd = NULL;
+       e = Track_FindRef(trak, referenceType, &dpnd);
+       if (e) return e;
+       if (!dpnd) return GF_BAD_PARAM;
+
+       if (referenceIndex > dpnd->trackIDCount) return GF_BAD_PARAM;
+
+       *refTrackID = dpnd->trackIDs[referenceIndex-1];
+
+       return GF_OK;
+}
+
+//Return referenceIndex if the given track has a reference to the given TreckID of a given ReferenceType
 //return -1 if error
 GF_EXPORT
-Bool gf_isom_has_track_reference(GF_ISOFile *movie, u32 trackNumber, u32 referenceType, u32 refTrackID)
+u32 gf_isom_has_track_reference(GF_ISOFile *movie, u32 trackNumber, u32 referenceType, u32 refTrackID)
 {
        u32 i;
        GF_TrackBox *trak;
@@ -638,7 +684,7 @@ Bool gf_isom_has_track_reference(GF_ISOFile *movie, u32 trackNumber, u32 referen
        if ( (movie->LastError = Track_FindRef(trak, referenceType, &dpnd)) ) return 0;
        if (!dpnd) return 0;
        for (i=0; i<dpnd->trackIDCount; i++) {
-               if (dpnd->trackIDs[i]==refTrackID) return 1;
+               if (dpnd->trackIDs[i]==refTrackID) return i+1;
        }
        return 0;
 }
@@ -2162,8 +2208,12 @@ GF_Err gf_isom_get_visual_info(GF_ISOFile *movie, u32 trackNumber, u32 StreamDes
        case GF_ISOM_SUBTYPE_3GP_H263:
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1:
        case GF_ISOM_BOX_TYPE_GNRV:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                *Width = ((GF_VisualSampleEntryBox*)entry)->Width;
                *Height = ((GF_VisualSampleEntryBox*)entry)->Height;
                return GF_OK;
@@ -2238,8 +2288,12 @@ GF_Err gf_isom_get_pixel_aspect_ratio(GF_ISOFile *movie, u32 trackNumber, u32 St
        case GF_ISOM_SUBTYPE_3GP_H263:
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3: 
+       case GF_ISOM_BOX_TYPE_AVC4: 
        case GF_ISOM_BOX_TYPE_SVC1:
        case GF_ISOM_BOX_TYPE_GNRV:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                *hSpacing = ((GF_VisualSampleEntryBox*)entry)->pasp ? ((GF_VisualSampleEntryBox*)entry)->pasp->hSpacing : 0;
                *vSpacing = ((GF_VisualSampleEntryBox*)entry)->pasp ? ((GF_VisualSampleEntryBox*)entry)->pasp->vSpacing : 0;
                return GF_OK;
@@ -2417,8 +2471,12 @@ u32 gf_isom_guess_specification(GF_ISOFile *file)
                        case GF_ISOM_SUBTYPE_3GP_EVRC: nb_evrc++; break;
                        case GF_ISOM_SUBTYPE_3GP_QCELP: nb_qcelp++; break;
                        case GF_ISOM_SUBTYPE_3GP_SMV: nb_smv++; break;
-                       case GF_ISOM_SUBTYPE_AVC_H264: nb_avc++; break;
-                       case GF_ISOM_SUBTYPE_AVC2_H264: nb_avc++; break;
+                       case GF_ISOM_SUBTYPE_AVC_H264:
+                       case GF_ISOM_SUBTYPE_AVC2_H264: 
+                       case GF_ISOM_SUBTYPE_AVC3_H264: 
+                       case GF_ISOM_SUBTYPE_AVC4_H264: 
+                               nb_avc++; 
+                               break;
                        case GF_ISOM_SUBTYPE_SVC_H264: nb_avc++; break;
                        case GF_ISOM_SUBTYPE_MPEG4:
                        case GF_ISOM_SUBTYPE_MPEG4_CRYP:
@@ -2681,8 +2739,12 @@ GF_Err gf_isom_get_rvc_config(GF_ISOFile *movie, u32 track, u32 sampleDescriptio
        case GF_ISOM_BOX_TYPE_MP4V:
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
        case GF_ISOM_BOX_TYPE_ENCV:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                break;
        default:
                return GF_BAD_PARAM;
@@ -2845,4 +2907,30 @@ u32 gf_isom_get_fragments_count(GF_ISOFile *movie, Bool segments_only)
 
 #endif
 
+GF_EXPORT
+GF_Err gf_isom_set_nalu_extract_mode(GF_ISOFile *the_file, u32 trackNumber, u32 nalu_extract_mode)
+{
+       GF_TrackReferenceTypeBox *dpnd;
+       GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!trak) return GF_BAD_PARAM;
+       trak->extractor_mode = nalu_extract_mode;
+
+       if (!trak->References) return GF_OK;
+
+       /*get base*/
+       dpnd = NULL;
+       trak->has_base_layer = 0;
+       Track_FindRef(trak, GF_ISOM_REF_SCAL, &dpnd);
+       if (dpnd) trak->has_base_layer = 1;
+       return GF_OK;
+}
+
+GF_EXPORT
+u32 gf_isom_get_nalu_extract_mode(GF_ISOFile *the_file, u32 trackNumber)
+{
+       GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber);
+       if (!trak) return 0;
+       return trak->extractor_mode;
+}
+
 #endif /*GPAC_DISABLE_ISOM*/
index f94d4df2a1002823ccf32faaf922b87539411318..587f9c0e7dac51ad3cc65df496efb21e88b9888d 100644 (file)
@@ -1171,7 +1171,11 @@ GF_Err gf_isom_set_visual_info(GF_ISOFile *movie, u32 trackNumber, u32 StreamDes
        case GF_ISOM_SUBTYPE_3GP_H263:
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                ((GF_VisualSampleEntryBox*)entry)->Width = Width;
                ((GF_VisualSampleEntryBox*)entry)->Height = Height;
                trak->Header->width = Width<<16;
@@ -1215,7 +1219,11 @@ GF_Err gf_isom_set_pixel_aspect_ratio(GF_ISOFile *movie, u32 trackNumber, u32 St
        case GF_ISOM_SUBTYPE_3GP_H263:
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                break;
        default:
                return GF_BAD_PARAM;
@@ -2451,6 +2459,7 @@ GF_Err gf_isom_clone_track(GF_ISOFile *orig_file, u32 orig_track, GF_ISOFile *de
        GF_TrackBox *trak, *new_tk;
        GF_BitStream *bs;
        char *data;
+       const char *buffer;
        u32 data_size;
        Double ts_scale;
        GF_Err e;
@@ -2510,6 +2519,12 @@ GF_Err gf_isom_clone_track(GF_ISOFile *orig_file, u32 orig_track, GF_ISOFile *de
 
        moov_AddBox((GF_Box*)dest_file->moov, (GF_Box *)new_tk);
 
+       /*set originalID*/
+       new_tk->originalID = trak->Header->trackID;
+       /*set originalFile*/
+       buffer = gf_isom_get_filename(orig_file);
+       new_tk->originalFile = gf_crc_32(buffer, sizeof(buffer));
+
        /*rewrite edit list segmentDuration to new movie timescale*/
        ts_scale = dest_file->moov->mvhd->timeScale;
        ts_scale /= orig_file->moov->mvhd->timeScale;
@@ -2974,6 +2989,36 @@ GF_Err gf_isom_set_track_id(GF_ISOFile *movie, u32 trackNumber, u32 trackID)
        return GF_OK;
 }
 
+/*force to rewrite all dependencies when the trackID of referenced track changes*/
+GF_EXPORT
+GF_Err gf_isom_rewrite_track_dependencies(GF_ISOFile *movie, u32 trackNumber)
+{
+       GF_TrackReferenceTypeBox *ref;
+       GF_TrackBox *trak, *a_trak;
+       u32 i, k;
+
+       trak = gf_isom_get_track_from_file(movie, trackNumber);
+       if (!trak)
+               return GF_BAD_PARAM;
+       if (!trak->References) 
+               return GF_OK;
+
+       i=0;
+       while ((ref = (GF_TrackReferenceTypeBox *)gf_list_enum(trak->References->other_boxes, &i))) {
+               for (k=0; k < ref->trackIDCount; k++) {
+                       a_trak = gf_isom_get_track_from_original_id(movie->moov, ref->trackIDs[k], trak->originalFile);
+                       if (a_trak) {
+                               ref->trackIDs[k] = a_trak->Header->trackID;
+                       } else {
+                               a_trak = gf_isom_get_track_from_id(movie->moov, ref->trackIDs[k]);
+                               /*we should have a track with no original ID (not imported) - should we rewrite the dependency ?*/
+                               if (! a_trak || a_trak->originalID) return GF_BAD_PARAM;
+                       }
+               }
+       }
+
+       return GF_OK;
+}
 
 GF_EXPORT
 GF_Err gf_isom_modify_cts_offset(GF_ISOFile *the_file, u32 trackNumber, u32 sample_number, u32 offset)
@@ -3259,21 +3304,25 @@ Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, u32 sdesc_index
                        break;
                case GF_ISOM_BOX_TYPE_AVC1:
                case GF_ISOM_BOX_TYPE_AVC2:
+               case GF_ISOM_BOX_TYPE_AVC3:
+               case GF_ISOM_BOX_TYPE_AVC4:
                case GF_ISOM_BOX_TYPE_SVC1:
+               case GF_ISOM_BOX_TYPE_HVC1:
+               case GF_ISOM_BOX_TYPE_HEV1:
                {
                        GF_MPEGVisualSampleEntryBox *avc1 = (GF_MPEGVisualSampleEntryBox *)ent1;
                        GF_MPEGVisualSampleEntryBox *avc2 = (GF_MPEGVisualSampleEntryBox *)ent2;
                        data1 = data2 = NULL;
 
                        bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
-                       a = (GF_Box *)avc1->avc_config;
+                       a = avc1->hevc_config ? (GF_Box *) avc1->hevc_config : (GF_Box *) avc1->avc_config;
                        gf_isom_box_size(a);
                        gf_isom_box_write(a, bs);
                        gf_bs_get_content(bs, &data1, &data1_size);
                        gf_bs_del(bs);
 
                        bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
-                       a = (GF_Box *)avc2->avc_config;
+                       a = avc2->hevc_config ? (GF_Box *) avc2->hevc_config : (GF_Box *) avc2->avc_config;
                        gf_isom_box_size(a);
                        gf_isom_box_write(a, bs);
                        gf_bs_get_content(bs, &data2, &data2_size);
@@ -4100,8 +4149,12 @@ GF_Err gf_isom_set_rvc_config(GF_ISOFile *movie, u32 track, u32 sampleDescriptio
        case GF_ISOM_BOX_TYPE_MP4V:
        case GF_ISOM_BOX_TYPE_AVC1: 
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
        case GF_ISOM_BOX_TYPE_ENCV:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                break;
        default:
                return GF_BAD_PARAM;
@@ -4410,7 +4463,6 @@ GF_Err gf_isom_set_composition_offset_mode(GF_ISOFile *file, u32 track, Bool use
        }
 }
 
-
 #endif /*!defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_WRITE)*/
 
 
index 24a6d200e98b5e7f49be4fdbc9a3b921d18f2a4f..1aa4762ec2ffbd9e31793f883995b624be03eb48 100644 (file)
@@ -173,7 +173,11 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
                break;
        case GF_ISOM_BOX_TYPE_AVC1:
        case GF_ISOM_BOX_TYPE_AVC2:
+       case GF_ISOM_BOX_TYPE_AVC3:
+       case GF_ISOM_BOX_TYPE_AVC4:
        case GF_ISOM_BOX_TYPE_SVC1:
+       case GF_ISOM_BOX_TYPE_HVC1: 
+       case GF_ISOM_BOX_TYPE_HEV1: 
                esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
                break;
        case GF_ISOM_BOX_TYPE_MP4A:
@@ -373,6 +377,10 @@ GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp,
                e = Media_RewriteODFrame(mdia, *samp);
                if (e) return e;
        }
+       else if (gf_isom_is_nalu_based_entry(mdia, entry)) {
+               e = gf_isom_nalu_sample_rewrite(mdia, *samp, sampleNumber, (GF_MPEGVisualSampleEntryBox *)entry);
+               if (e) return e;
+       } 
        else if (mdia->mediaTrack->moov->mov->convert_streaming_text 
                && ((mdia->handler->handlerType == GF_ISOM_MEDIA_TEXT) || (mdia->handler->handlerType == GF_ISOM_MEDIA_SUBT)) 
        ) {
index 02c44c028a9aa490a8288fb329750347df4c4acc..bf4580168a011111d70049d444903dbb753d34f7 100644 (file)
@@ -883,7 +883,7 @@ GF_Err gf_isom_allocate_sidx(GF_ISOFile *movie, s32 subsegs_per_sidx, Bool daisy
        if (e) return e;
 
        if (start_range) *start_range = (u32) movie->root_sidx_offset;
-       if (end_range) *end_range = (u32) gf_bs_get_position(bs);
+       if (end_range) *end_range = (u32) gf_bs_get_position(bs)-1;
 
        return GF_OK;
 }
index aee50e5eeacb0d3c66f8ad86d7e4d6dc2e055b76..90d75df5e95478df80d1cb4b41439ac975f1ff61 100644 (file)
@@ -78,7 +78,10 @@ GF_Err stbl_AddDTS(GF_SampleTableBox *stbl, u64 DTS, u32 *sampleNumber, u32 Last
                //we need to split the entry
                if (ent->sampleCount == 1) {
                        //use this one and adjust...
-                       ent->sampleDelta = (u32) (DTS - stts->w_LastDTS);
+                       if (stts->w_LastDTS)
+                               ent->sampleDelta += (u32) (DTS - stts->w_LastDTS);
+                       else
+                               ent->sampleDelta = (u32) DTS;
                        ent->sampleCount ++;
                        stts->w_currentSampleNum ++;
                        stts->w_LastDTS = DTS;
index b8b02de7831f3ce8355f27d3e7cbf630dcfea7ab..507b7e9f4777a9f15be37eb1e805df8b408fc850 100644 (file)
@@ -197,7 +197,7 @@ default_sync:
                        } else {
                                esd->decoderConfig->rvc_config = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
                                if (mime_type && !strcmp(mime_type, "application/rvc-config+xml+gz") ) {
-#ifndef GPAC_DISABLE_CORE_TOOLS
+#if !defined(GPAC_DISABLE_CORE_TOOLS) && !defined(GPAC_DISABLE_ZLIB)
                                        gf_gz_decompress_payload(rvc_cfg_data, rvc_cfg_size, &esd->decoderConfig->rvc_config->data, &esd->decoderConfig->rvc_config->dataLength);
                                        gf_free(rvc_cfg_data);
 #endif
@@ -877,8 +877,12 @@ GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex,
                        break;
                case GF_ISOM_BOX_TYPE_AVC1:
                case GF_ISOM_BOX_TYPE_AVC2:
+               case GF_ISOM_BOX_TYPE_AVC3:
+               case GF_ISOM_BOX_TYPE_AVC4:
                case GF_ISOM_BOX_TYPE_SVC1:
-                       e = AVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry, esd);
+               case GF_ISOM_BOX_TYPE_HVC1: 
+               case GF_ISOM_BOX_TYPE_HEV1: 
+                       e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry, esd);
                        if (e) return e;
                        break;
                case GF_ISOM_BOX_TYPE_LSR1:
@@ -887,7 +891,7 @@ GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex,
                        break;
                        
                default:
-                       gf_odf_desc_del((GF_Descriptor *) esd);
+                       //gf_odf_desc_del((GF_Descriptor *) esd);
                        break;
                }
        } else {
@@ -905,7 +909,12 @@ GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex,
                        if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) {
                                entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_AVC1);
                                if (!entry_v) return GF_OUT_OF_MEM;
-                               e = AVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd);
+                               e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd);
+                       } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_HEVC) {
+                               entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_HVC1);
+                               if (!entry_v) return GF_OUT_OF_MEM;
+                               e = AVC_HEVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd);
+                               
                        } else {
                                entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4V);
                                if (!entry_v) return GF_OUT_OF_MEM;
index d54f1d663a233dab5c1a72e2773938312b6864f3..74bc0797b4b8587c93d625bbb235dde1289e8063 100644 (file)
@@ -1461,7 +1461,7 @@ static u8 avc_golomb_bits[256] = {
        0
 };
 
-static u32 avc_get_ue(GF_BitStream *bs)
+static u32 bs_get_ue(GF_BitStream *bs)
 {
        u8 coded;
        u32 bits = 0, read = 0;
@@ -1478,14 +1478,14 @@ static u32 avc_get_ue(GF_BitStream *bs)
        return gf_bs_read_int(bs, bits + 1) - 1;
 }
 
-static s32 avc_get_se(GF_BitStream *bs) 
+static s32 bs_get_se(GF_BitStream *bs) 
 {
-       u32 v = avc_get_ue(bs);
+       u32 v = bs_get_ue(bs);
        if ((v & 0x1) == 0) return (s32) (0 - (v>>1));
        return (v + 1) >> 1;
 }
 
-u32 AVC_IsStartCode(GF_BitStream *bs)
+u32 gf_media_nalu_is_start_code(GF_BitStream *bs)
 {
        u8 s1, s2, s3, s4;
        Bool is_sc = 0;
@@ -1506,7 +1506,7 @@ u32 AVC_IsStartCode(GF_BitStream *bs)
 
 /*read that amount of data at each IO access rather than fetching byte by byte...*/
 #define AVC_CACHE_SIZE 4096
-u32 AVC_NextStartCode(GF_BitStream *bs)
+u32 gf_media_nalu_next_start_code_bs(GF_BitStream *bs)
 {
        u32 v, bpos;
        char avc_cache[AVC_CACHE_SIZE];
@@ -1539,7 +1539,37 @@ u32 AVC_NextStartCode(GF_BitStream *bs)
        return (u32) (end-start);
 }
 
-Bool AVC_SliceIsIntra(AVCState *avc) 
+u32 gf_media_nalu_next_start_code(u8 *data, u32 data_len, u32 *sc_size)
+{
+       u32 v, bpos;
+       u32 end;
+       
+       bpos = 0;
+       end = 0;
+       v = 0xffffffff;
+       while (!end) {
+               /*refill cache*/
+               if (bpos == (u32) data_len) 
+                       break;
+
+               v = ( (v<<8) & 0xFFFFFF00) | ((u32) data[bpos]);
+               bpos++;
+               if (v == 0x00000001) {
+                       end = bpos-4;
+                       *sc_size = 4;
+                       return end;
+               }
+               else if ( (v & 0x00FFFFFF) == 0x00000001) {
+                       end = bpos-3;
+                       *sc_size = 3;
+                       return end;
+               }
+       }
+       if (!end) end = data_len;
+       return (u32) (end);
+}
+
+Bool gf_media_avc_slice_is_intra(AVCState *avc) 
 {
        switch (avc->s_info.slice_type) {
                case GF_AVC_TYPE_I:
@@ -1552,7 +1582,7 @@ Bool AVC_SliceIsIntra(AVCState *avc)
        }
 }
 
-Bool AVC_SliceIsIDR(AVCState *avc) 
+Bool gf_media_avc_slice_is_IDR(AVCState *avc) 
 {
        if (avc->sei.recovery_point.valid)
        {
@@ -1561,7 +1591,7 @@ Bool AVC_SliceIsIDR(AVCState *avc)
        }
        if (avc->s_info.nal_unit_type != GF_AVC_NALU_IDR_SLICE)
                return 0;
-       return AVC_SliceIsIntra(avc);
+       return gf_media_avc_slice_is_intra(avc);
 }
 
 static const struct { u32 w, h; } avc_sar[14] =
@@ -1578,14 +1608,16 @@ static void avc_parse_hrd_parameters(GF_BitStream *bs, AVC_HRD *hrd)
 {
        int i, cpb_cnt_minus1;
 
-       cpb_cnt_minus1 = avc_get_ue(bs);        /*cpb_cnt_minus1*/
+       cpb_cnt_minus1 = bs_get_ue(bs);         /*cpb_cnt_minus1*/
+       if (cpb_cnt_minus1 > 31)
+               GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[avc-h264] invalid cpb_cnt_minus1 value: %d (expected in [0;31])\n", cpb_cnt_minus1));
        gf_bs_read_int(bs, 4);                          /*bit_rate_scale*/
        gf_bs_read_int(bs, 4);                          /*cpb_size_scale*/
 
        /*for( SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++ ) {*/
        for (i=0; i<=cpb_cnt_minus1; i++) {
-               avc_get_ue(bs);                                 /*bit_rate_value_minus1[ SchedSelIdx ]*/
-               avc_get_ue(bs);                                 /*cpb_size_value_minus1[ SchedSelIdx ]*/
+               bs_get_ue(bs);                                  /*bit_rate_value_minus1[ SchedSelIdx ]*/
+               bs_get_ue(bs);                                  /*cpb_size_value_minus1[ SchedSelIdx ]*/
                gf_bs_read_int(bs, 1);                  /*cbr_flag[ SchedSelIdx ]*/
        }
        gf_bs_read_int(bs, 5);                                                                                  /*initial_cpb_removal_delay_length_minus1*/
@@ -1733,7 +1765,7 @@ static u32 avc_remove_emulation_bytes(const unsigned char *buffer_src, unsigned
        return nal_size-emulation_bytes_count; 
 } 
 
-s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, u32 *vui_flag_pos)
+s32 gf_media_avc_read_sps(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, u32 *vui_flag_pos)
 {
        AVC_SPS *sps;
        u32 ChromaArrayType = 0;
@@ -1753,6 +1785,8 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        }
        if (vui_flag_pos) *vui_flag_pos = 0;
 
+       /*nal hdr*/ gf_bs_read_int(bs, 8);
+
        profile_idc = gf_bs_read_int(bs, 8);
 
        pcomp = gf_bs_read_int(bs, 8);
@@ -1765,7 +1799,7 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        /*SubsetSps is used to be sure that AVC SPS are not going to be scratched
        by subset SPS. According to the SVC standard, subset SPS can have the same sps_id 
        than its base layer, but it does not refer to the same SPS. */
-       sps_id = avc_get_ue(bs) + GF_SVC_SSPS_ID_SHIFT * subseq_sps;
+       sps_id = bs_get_ue(bs) + GF_SVC_SSPS_ID_SHIFT * subseq_sps;
        if (sps_id >=32) {
                sps_id = -1;
                goto exit;
@@ -1789,7 +1823,7 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        case 86:
        case 118:
        case 128:
-               chroma_format_idc = avc_get_ue(bs);
+               chroma_format_idc = bs_get_ue(bs);
                ChromaArrayType = chroma_format_idc;
                if (chroma_format_idc == 3) {
                        u8 separate_colour_plane_flag = gf_bs_read_int(bs, 1);
@@ -1800,8 +1834,8 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
                        */
                        if (separate_colour_plane_flag) ChromaArrayType = 0;
                }
-               luma_bd = avc_get_ue(bs);
-               chroma_bd = avc_get_ue(bs);
+               luma_bd = bs_get_ue(bs);
+               chroma_bd = bs_get_ue(bs);
                /*qpprime_y_zero_transform_bypass_flag = */ gf_bs_read_int(bs, 1);
                /*seq_scaling_matrix_present_flag*/
                if (gf_bs_read_int(bs, 1)) {
@@ -1812,7 +1846,7 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
                                        u32 sl = k<6 ? 16 : 64;
                                        for (z=0; z<sl; z++) {
                                                if (next) {
-                                                       s32 delta = avc_get_se(bs);
+                                                       s32 delta = bs_get_se(bs);
                                                        next = (last + delta + 256) % 256;
                                                }
                                                last = next ? next : last;
@@ -1826,29 +1860,29 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        sps->profile_idc = profile_idc;
        sps->level_idc = level_idc;
        sps->prof_compat = pcomp;
-       sps->log2_max_frame_num = avc_get_ue(bs) + 4;
-       sps->poc_type = avc_get_ue(bs);
+       sps->log2_max_frame_num = bs_get_ue(bs) + 4;
+       sps->poc_type = bs_get_ue(bs);
        sps->chroma_format = chroma_format_idc;
        sps->luma_bit_depth_m8 = luma_bd;
        sps->chroma_bit_depth_m8 = chroma_bd;
 
        if (sps->poc_type == 0) {
-               sps->log2_max_poc_lsb = avc_get_ue(bs) + 4;
+               sps->log2_max_poc_lsb = bs_get_ue(bs) + 4;
        } else if(sps->poc_type == 1) {
                sps->delta_pic_order_always_zero_flag = gf_bs_read_int(bs, 1);
-               sps->offset_for_non_ref_pic = avc_get_se(bs);
-               sps->offset_for_top_to_bottom_field = avc_get_se(bs);
-               sps->poc_cycle_length = avc_get_ue(bs);
-               for(i=0; i<sps->poc_cycle_length; i++) sps->offset_for_ref_frame[i] = avc_get_se(bs);
+               sps->offset_for_non_ref_pic = bs_get_se(bs);
+               sps->offset_for_top_to_bottom_field = bs_get_se(bs);
+               sps->poc_cycle_length = bs_get_ue(bs);
+               for(i=0; i<sps->poc_cycle_length; i++) sps->offset_for_ref_frame[i] = bs_get_se(bs);
        }
        if (sps->poc_type > 2) {
                sps_id = -1;
                goto exit;
        }
-       avc_get_ue(bs); /*ref_frame_count*/
+       bs_get_ue(bs); /*ref_frame_count*/
        gf_bs_read_int(bs, 1); /*gaps_in_frame_num_allowed_flag*/
-       mb_width = avc_get_ue(bs) + 1;
-       mb_height= avc_get_ue(bs) + 1;
+       mb_width = bs_get_ue(bs) + 1;
+       mb_height= bs_get_ue(bs) + 1;
 
        sps->frame_mbs_only_flag = gf_bs_read_int(bs, 1);
 
@@ -1860,10 +1894,10 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
        gf_bs_read_int(bs, 1); /*direct_8x8_inference_flag*/
        cl = cr = ct = cb = 0;
        if (gf_bs_read_int(bs, 1)) /*crop*/ {
-               cl = avc_get_ue(bs); /*crop_left*/
-               cr = avc_get_ue(bs); /*crop_right*/
-               ct = avc_get_ue(bs); /*crop_top*/
-               cb = avc_get_ue(bs); /*crop_bottom*/
+               cl = bs_get_ue(bs); /*crop_left*/
+               cr = bs_get_ue(bs); /*crop_right*/
+               ct = bs_get_ue(bs); /*crop_top*/
+               cb = bs_get_ue(bs); /*crop_bottom*/
 
                sps->width = 16*mb_width - 2*(cl + cr);
                sps->height -= (2-sps->frame_mbs_only_flag)*2*(ct + cb);
@@ -1899,8 +1933,8 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
                }
 
                if (gf_bs_read_int(bs, 1)) {    /* chroma_location_info_present_flag */
-                       avc_get_ue(bs);                         /* chroma_sample_location_type_top_field */
-                       avc_get_ue(bs);                         /* chroma_sample_location_type_bottom_field */
+                       bs_get_ue(bs);                          /* chroma_sample_location_type_top_field */
+                       bs_get_ue(bs);                          /* chroma_sample_location_type_bottom_field */
                }
 
                sps->vui.timing_info_present_flag = gf_bs_read_int(bs, 1);
@@ -1943,10 +1977,10 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
                                        /*seq_ref_layer_chroma_phase_x_plus1_flag*/gf_bs_read_int(bs, 1);
                                        /*seq_ref_layer_chroma_phase_y_plus1*/gf_bs_read_int(bs, 2);
                                }
-                               /*seq_scaled_ref_layer_left_offset*/ avc_get_se(bs);
-                               /*seq_scaled_ref_layer_top_offset*/avc_get_se(bs); 
-                               /*seq_scaled_ref_layer_right_offset*/avc_get_se(bs);
-                               /*seq_scaled_ref_layer_bottom_offset*/avc_get_se(bs);
+                               /*seq_scaled_ref_layer_left_offset*/ bs_get_se(bs);
+                               /*seq_scaled_ref_layer_top_offset*/bs_get_se(bs); 
+                               /*seq_scaled_ref_layer_right_offset*/bs_get_se(bs);
+                               /*seq_scaled_ref_layer_bottom_offset*/bs_get_se(bs);
                        }
                        if (/*seq_tcoeff_level_prediction_flag*/gf_bs_read_int(bs, 1)) {
                                /*adaptive_tcoeff_level_prediction_flag*/ gf_bs_read_int(bs, 1);
@@ -1956,7 +1990,7 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps,
                        /*svc_vui_parameters_present*/
                        if (gf_bs_read_int(bs, 1)) {
                                u32 i, vui_ext_num_entries_minus1;
-                               vui_ext_num_entries_minus1 = avc_get_ue(bs);
+                               vui_ext_num_entries_minus1 = bs_get_ue(bs);
 
                                for (i=0; i <= vui_ext_num_entries_minus1; i++) {
                                        u8 vui_ext_nal_hrd_parameters_present_flag, vui_ext_vcl_hrd_parameters_present_flag, vui_ext_timing_info_present_flag;
@@ -2001,7 +2035,7 @@ exit:
        return sps_id;
 }
 
-s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc)
+s32 gf_media_avc_read_pps(char *pps_data, u32 pps_size, AVCState *avc)
 {
        GF_BitStream *bs;
        char *pps_data_without_emulation_bytes = NULL;
@@ -2017,7 +2051,10 @@ s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc)
                pps_id = -1;
                goto exit;
        }
-       pps_id = avc_get_ue(bs);
+       /*nal hdr*/gf_bs_read_u8(bs);
+
+
+       pps_id = bs_get_ue(bs);
        if (pps_id>=255) {
                pps_id = -1;
                goto exit;
@@ -2025,7 +2062,7 @@ s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc)
        pps = &avc->pps[pps_id];
    
        if (!pps->status) pps->status = 1;
-       pps->sps_id = avc_get_ue(bs);
+       pps->sps_id = bs_get_ue(bs);
        if (pps->sps_id >= 32) {
                pps->sps_id = 0;
                pps_id = -1;
@@ -2039,19 +2076,19 @@ s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc)
        avc->sps_active_idx = pps->sps_id; /*set active sps*/
        /*pps->cabac = */gf_bs_read_int(bs, 1);
        pps->pic_order_present= gf_bs_read_int(bs, 1);
-       pps->slice_group_count= avc_get_ue(bs) + 1;
-       if (pps->slice_group_count > 1 ) /*pps->mb_slice_group_map_type = */avc_get_ue(bs);
-       /*pps->ref_count[0]= */avc_get_ue(bs) /*+ 1*/;
-       /*pps->ref_count[1]= */avc_get_ue(bs) /*+ 1*/;
+       pps->slice_group_count= bs_get_ue(bs) + 1;
+       if (pps->slice_group_count > 1 ) /*pps->mb_slice_group_map_type = */bs_get_ue(bs);
+       /*pps->ref_count[0]= */bs_get_ue(bs) /*+ 1*/;
+       /*pps->ref_count[1]= */bs_get_ue(bs) /*+ 1*/;
        /*
        if ((pps->ref_count[0] > 32) || (pps->ref_count[1] > 32)) goto exit;
        */
        
        /*pps->weighted_pred = */gf_bs_read_int(bs, 1);
        /*pps->weighted_bipred_idc = */gf_bs_read_int(bs, 2);
-       /*pps->init_qp = */avc_get_se(bs) /*+ 26*/;
-       /*pps->init_qs= */avc_get_se(bs) /*+ 26*/;
-       /*pps->chroma_qp_index_offset = */avc_get_se(bs);
+       /*pps->init_qp = */bs_get_se(bs) /*+ 26*/;
+       /*pps->init_qs= */bs_get_se(bs) /*+ 26*/;
+       /*pps->chroma_qp_index_offset = */bs_get_se(bs);
        /*pps->deblocking_filter_parameters_present = */gf_bs_read_int(bs, 1);
        /*pps->constrained_intra_pred = */gf_bs_read_int(bs, 1);
        pps->redundant_pic_cnt_present = gf_bs_read_int(bs, 1);
@@ -2062,7 +2099,7 @@ exit:
        return pps_id;
 }
 
-s32 AVC_ReadSeqParamSetExtId(char *spse_data, u32 spse_size)
+s32 gf_media_avc_read_sps_ext(char *spse_data, u32 spse_size)
 {
        GF_BitStream *bs;
        char *spse_data_without_emulation_bytes = NULL;
@@ -2074,9 +2111,9 @@ s32 AVC_ReadSeqParamSetExtId(char *spse_data, u32 spse_size)
        spse_data_without_emulation_bytes_size = avc_remove_emulation_bytes(spse_data, spse_data_without_emulation_bytes, spse_size);
        bs = gf_bs_new(spse_data_without_emulation_bytes, spse_data_without_emulation_bytes_size, GF_BITSTREAM_READ);
        
-       sps_id = -1;
-       if (bs) 
-               sps_id = avc_get_ue(bs);
+       /*nal header*/gf_bs_read_u8(bs);
+
+       sps_id = bs_get_ue(bs);
 
        gf_bs_del(bs);
        gf_free(spse_data_without_emulation_bytes);
@@ -2104,11 +2141,11 @@ static s32 avc_parse_slice(GF_BitStream *bs, AVCState *avc, Bool svc_idr_flag, A
        s32 pps_id;
 
        /*s->current_picture.reference= h->nal_ref_idc != 0;*/
-       /*first_mb_in_slice = */avc_get_ue(bs);
-       si->slice_type = avc_get_ue(bs);
+       /*first_mb_in_slice = */bs_get_ue(bs);
+       si->slice_type = bs_get_ue(bs);
        if (si->slice_type > 9) return -1;
 
-       pps_id = avc_get_ue(bs);
+       pps_id = bs_get_ue(bs);
        if (pps_id>255) return -1;
        si->pps = &avc->pps[pps_id];
        if (!si->pps->slice_group_count) return -2;
@@ -2125,20 +2162,20 @@ static s32 avc_parse_slice(GF_BitStream *bs, AVCState *avc, Bool svc_idr_flag, A
                        si->bottom_field_flag = gf_bs_read_int(bs, 1);
        }
        if ((si->nal_unit_type==GF_AVC_NALU_IDR_SLICE) || svc_idr_flag)
-               si->idr_pic_id = avc_get_ue(bs);
+               si->idr_pic_id = bs_get_ue(bs);
    
        if (si->sps->poc_type==0) {
                si->poc_lsb = gf_bs_read_int(bs, si->sps->log2_max_poc_lsb);
                if (si->pps->pic_order_present && !si->field_pic_flag) {
-                       si->delta_poc_bottom = avc_get_se(bs);
+                       si->delta_poc_bottom = bs_get_se(bs);
                }
        } else if ((si->sps->poc_type==1) && !si->sps->delta_pic_order_always_zero_flag) {
-               si->delta_poc[0] = avc_get_se(bs);
+               si->delta_poc[0] = bs_get_se(bs);
                if ((si->pps->pic_order_present==1) && !si->field_pic_flag)
-                       si->delta_poc[1] = avc_get_se(bs);
+                       si->delta_poc[1] = bs_get_se(bs);
        }
        if (si->pps->redundant_pic_cnt_present) {
-               si->redundant_pic_cnt = avc_get_ue(bs);
+               si->redundant_pic_cnt = bs_get_ue(bs);
        }
        return 0;
 }
@@ -2149,11 +2186,11 @@ static s32 svc_parse_slice(GF_BitStream *bs, AVCState *avc, AVCSliceInfo *si)
        s32 pps_id;
 
        /*s->current_picture.reference= h->nal_ref_idc != 0;*/
-       /*first_mb_in_slice = */avc_get_ue(bs);
-       si->slice_type = avc_get_ue(bs);
+       /*first_mb_in_slice = */bs_get_ue(bs);
+       si->slice_type = bs_get_ue(bs);
        if (si->slice_type > 9) return -1;
 
-       pps_id = avc_get_ue(bs);
+       pps_id = bs_get_ue(bs);
        if (pps_id>255)
                return -1;
        si->pps = &avc->pps[pps_id];
@@ -2174,20 +2211,20 @@ static s32 svc_parse_slice(GF_BitStream *bs, AVCState *avc, AVCSliceInfo *si)
                if (si->field_pic_flag) si->bottom_field_flag = gf_bs_read_int(bs, 1);
        }
        if (si->nal_unit_type == GF_AVC_NALU_IDR_SLICE || si ->NalHeader.idr_pic_flag)
-               si->idr_pic_id = avc_get_ue(bs);
+               si->idr_pic_id = bs_get_ue(bs);
    
        if (si->sps->poc_type==0) {
                si->poc_lsb = gf_bs_read_int(bs, si->sps->log2_max_poc_lsb);
        if (si->pps->pic_order_present && !si->field_pic_flag) {
-                       si->delta_poc_bottom = avc_get_se(bs);
+                       si->delta_poc_bottom = bs_get_se(bs);
                }
        } else if ((si->sps->poc_type==1) && !si->sps->delta_pic_order_always_zero_flag) {
-               si->delta_poc[0] = avc_get_se(bs);
+               si->delta_poc[0] = bs_get_se(bs);
                if ((si->pps->pic_order_present==1) && !si->field_pic_flag)
-                       si->delta_poc[1] = avc_get_se(bs);
+                       si->delta_poc[1] = bs_get_se(bs);
        }
        if (si->pps->redundant_pic_cnt_present) {
-               si->redundant_pic_cnt = avc_get_ue(bs);
+               si->redundant_pic_cnt = bs_get_ue(bs);
        }
        return 0;
 }
@@ -2197,7 +2234,7 @@ static s32 avc_parse_recovery_point_sei(GF_BitStream *bs, AVCState *avc)
 {
        AVCSeiRecoveryPoint *rp = &avc->sei.recovery_point;
 
-       rp->frame_cnt = avc_get_ue(bs);
+       rp->frame_cnt = bs_get_ue(bs);
        rp->exact_match_flag = gf_bs_read_int(bs, 1);
        rp->broken_link_flag = gf_bs_read_int(bs, 1);
        rp->changing_slice_group_idc = gf_bs_read_int(bs, 2);
@@ -2379,7 +2416,7 @@ static void avc_compute_poc(AVCSliceInfo *si)
                si->poc = field_poc[1];
 }
 
-s32 AVC_ParseNALU(GF_BitStream *bs, u32 nal_hdr, AVCState *avc)
+s32 gf_media_avc_parse_nalu(GF_BitStream *bs, u32 nal_hdr, AVCState *avc)
 {
        u8 idr_flag;
        s32 slice, ret;
@@ -2483,6 +2520,7 @@ s32 AVC_ParseNALU(GF_BitStream *bs, u32 nal_hdr, AVCState *avc)
                break;
        case GF_AVC_NALU_SEQ_PARAM:
        case GF_AVC_NALU_PIC_PARAM:
+       case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
                return 0;
        default:
                if (avc->s_info.nal_unit_type <= GF_AVC_NALU_IDR_SLICE) ret = 1;
@@ -2511,7 +2549,7 @@ s32 AVC_ParseNALU(GF_BitStream *bs, u32 nal_hdr, AVCState *avc)
        return ret;
 }
 
-u32 AVC_ReformatSEI_NALU(char *buffer, u32 nal_size, AVCState *avc)
+u32 gf_media_avc_reformat_sei(char *buffer, u32 nal_size, AVCState *avc)
 {
        u32 ptype, psize, hdr, written, var;
        u64 start;
@@ -2671,7 +2709,7 @@ static u8 avc_get_sar_idx(u32 w, u32 h)
        return 0xFF;
 }
 
-GF_Err AVC_ChangePAR(GF_AVCConfig *avcc, s32 ar_n, s32 ar_d)
+GF_Err gf_media_avc_change_par(GF_AVCConfig *avcc, s32 ar_n, s32 ar_d)
 {
        GF_BitStream *orig, *mod;
        AVCState avc;
@@ -2687,7 +2725,7 @@ GF_Err AVC_ChangePAR(GF_AVCConfig *avcc, s32 ar_n, s32 ar_d)
        while ((slc = (GF_AVCConfigSlot *)gf_list_enum(avcc->sequenceParameterSets, &i))) {
                char *no_emulation_buf = NULL;
                u32 no_emulation_buf_size = 0, emulation_bytes = 0;
-               idx = AVC_ReadSeqInfo(slc->data+1/*skip NALU type*/, slc->size-1, &avc, 0, &bit_offset);
+               idx = gf_media_avc_read_sps(slc->data, slc->size, &avc, 0, &bit_offset);
                if (idx<0) {
                        if ( orig )
                                gf_bs_del(orig);
@@ -2704,14 +2742,15 @@ GF_Err AVC_ChangePAR(GF_AVCConfig *avcc, s32 ar_n, s32 ar_d)
                mod = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
 
                /*copy over till vui flag*/
-               while (bit_offset) {
+               assert(bit_offset>=8);
+               while (bit_offset-8/*bit_offset doesn't take care of the first byte (NALU type)*/) {
                        flag = gf_bs_read_int(orig, 1);
                        gf_bs_write_int(mod, flag, 1);
                        bit_offset--;
                }
                /*check VUI*/
                flag = gf_bs_read_int(orig, 1);
-               gf_bs_write_int(mod, 1, 1);
+               gf_bs_write_int(mod, 1, 1); /*vui_parameters_present_flag*/
                if (flag) {
                        /*aspect_ratio_info_present_flag*/
                        if (gf_bs_read_int(orig, 1)) {
@@ -2778,7 +2817,7 @@ GF_Err gf_avc_get_sps_info(char *sps_data, u32 sps_size, u32 *sps_id, u32 *width
        memset(&avc, 0, sizeof(AVCState));
        avc.sps_active_idx = -1;
 
-       idx = AVC_ReadSeqInfo(sps_data+1/*skip NALU type*/, sps_size-1, &avc, 0, NULL);
+       idx = gf_media_avc_read_sps(sps_data, sps_size, &avc, 0, NULL);
        if (idx<0) {
                return GF_NON_COMPLIANT_BITSTREAM;
        }
@@ -2792,11 +2831,634 @@ GF_Err gf_avc_get_sps_info(char *sps_data, u32 sps_size, u32 *sps_id, u32 *width
        return GF_OK;
 }
 
-#endif /*GPAC_DISABLE_AV_PARSERS*/
+GF_EXPORT
+GF_Err gf_avc_get_pps_info(char *pps_data, u32 pps_size, u32 *pps_id, u32 *sps_id)
+{
+       GF_BitStream *bs;
+       char *pps_data_without_emulation_bytes = NULL;
+       u32 pps_data_without_emulation_bytes_size = 0;
+       GF_Err e = GF_OK;
+
+       /*PPS still contains emulation bytes*/
+       pps_data_without_emulation_bytes = gf_malloc(pps_size*sizeof(char));
+       pps_data_without_emulation_bytes_size = avc_remove_emulation_bytes(pps_data, pps_data_without_emulation_bytes, pps_size);
+       bs = gf_bs_new(pps_data_without_emulation_bytes, pps_data_without_emulation_bytes_size, GF_BITSTREAM_READ);
+       if (!bs) {
+               e = GF_NON_COMPLIANT_BITSTREAM;
+               goto exit;
+       }
+       *pps_id = bs_get_ue(bs);  
+       *sps_id = bs_get_ue(bs);
 
+exit:
+       gf_bs_del(bs);
+       gf_free(pps_data_without_emulation_bytes);
+       return e;
+}
 
 
-#ifndef GPAC_DISABLE_AV_PARSERS
+/**********
+HEVC parsing
+**********/
+
+Bool gf_media_hevc_slice_is_intra(HEVCState *hevc)
+{
+       switch (hevc->s_info.nal_unit_type) {
+       case GF_HEVC_NALU_SLICE_BLA_W_LP:
+       case GF_HEVC_NALU_SLICE_BLA_W_DLP:
+       case GF_HEVC_NALU_SLICE_BLA_N_LP:
+       case GF_HEVC_NALU_SLICE_IDR_W_DLP:
+       case GF_HEVC_NALU_SLICE_IDR_N_LP:
+       case GF_HEVC_NALU_SLICE_CRA:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+Bool gf_media_hevc_slice_is_IDR(HEVCState *hevc) 
+{
+       if (hevc->sei.recovery_point.valid)
+       {
+               hevc->sei.recovery_point.valid = 0;
+               return 1;
+       }
+       switch (hevc->s_info.nal_unit_type) {
+       case GF_HEVC_NALU_SLICE_IDR_W_DLP:
+       case GF_HEVC_NALU_SLICE_IDR_N_LP:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static s32 hevc_parse_slice_segment(GF_BitStream *bs, HEVCState *hevc, HEVCSliceInfo *si) 
+{
+       HEVC_PPS *pps;
+       HEVC_SPS *sps;
+       s32 pps_id;
+       Bool dependent_slice_segment_flag = 0;
+       Bool first_slice_segment_in_pic_flag = gf_bs_read_int(bs, 1);
+       Bool RapPicFlag = 0;
+       Bool IDRPicFlag = 0;
+       
+       switch (si->nal_unit_type) {
+       case GF_HEVC_NALU_SLICE_IDR_W_DLP:
+       case GF_HEVC_NALU_SLICE_IDR_N_LP:
+               IDRPicFlag = 1;
+               RapPicFlag = 1;
+               break;
+       case GF_HEVC_NALU_SLICE_BLA_W_LP:
+       case GF_HEVC_NALU_SLICE_BLA_W_DLP:
+       case GF_HEVC_NALU_SLICE_BLA_N_LP:
+       case GF_HEVC_NALU_SLICE_CRA:
+               RapPicFlag = 1;
+               break;
+       }
+
+       if (RapPicFlag) {
+               /*Bool no_output_of_prior_pics_flag = */gf_bs_read_int(bs, 1);
+       }
+       pps_id = bs_get_ue(bs);
+       if (pps_id>=64) return -1;
+
+       pps = &hevc->pps[pps_id];
+       sps = &hevc->sps[pps->sps_id];
+       si->sps = sps;
+       si->pps = pps;
+
+       if (!first_slice_segment_in_pic_flag && pps->dependent_slice_segments_enabled_flag) {
+               dependent_slice_segment_flag = gf_bs_read_int(bs, 1);
+       }
+
+       {
+               if (!first_slice_segment_in_pic_flag) {
+                       /*slice_segment_address = */gf_bs_read_int(bs, sps->bitsSliceSegmentAddress);
+               }
+       }
+       
+       if( !dependent_slice_segment_flag ) {
+               gf_bs_read_int(bs, pps->num_extra_slice_header_bits);
+
+               si->slice_type = bs_get_ue(bs);
+
+               if(pps->output_flag_present_flag)
+                       /*pic_output_flag = */gf_bs_read_int(bs, 1);
+               
+               if (sps->separate_colour_plane_flag == 1)
+                       /*colour_plane_id = */gf_bs_read_int(bs, 2);
+
+               if (IDRPicFlag) {
+                       si->poc_lsb = 0;
+               } else {
+                       si->poc_lsb = gf_bs_read_int(bs, sps->log2_max_pic_order_cnt_lsb);
+               }
+       }
+       return 0;
+}
+
+static void hevc_compute_poc(HEVCSliceInfo *si)
+{
+       u32 max_poc_lsb = 1 << (si->sps->log2_max_pic_order_cnt_lsb);
+
+       /* frame_num_offset */
+       switch (si->nal_unit_type) {
+       case GF_HEVC_NALU_SLICE_IDR_W_DLP:
+       case GF_HEVC_NALU_SLICE_IDR_N_LP:
+       case GF_HEVC_NALU_SLICE_CRA:
+               si->poc_lsb_prev = 0;
+               si->poc_msb_prev = 0;
+               break;
+       }
+       
+       if ((si->poc_lsb < si->poc_lsb_prev) && (si->poc_lsb_prev - si->poc_lsb >= max_poc_lsb / 2) )
+               si->poc_msb = si->poc_msb_prev + max_poc_lsb;
+       else if ((si->poc_lsb > si->poc_lsb_prev) && (si->poc_lsb - si->poc_lsb_prev > max_poc_lsb / 2))
+               si->poc_msb = si->poc_msb_prev - max_poc_lsb;
+       else
+               si->poc_msb = si->poc_msb_prev;
+
+       switch (si->nal_unit_type) {
+       case GF_HEVC_NALU_SLICE_BLA_W_LP:
+       case GF_HEVC_NALU_SLICE_BLA_W_DLP:
+       case GF_HEVC_NALU_SLICE_BLA_N_LP:
+               si->poc_msb  = 0;
+               break;
+       }
+       si->poc = si->poc_msb + si->poc_lsb;
+}
+
+void profile_tier_level(GF_BitStream *bs, Bool ProfilePresentFlag, u8 MaxNumSubLayersMinus1, HEVC_ProfileTierLevel *ptl)
+{
+       u32 i;
+       if (ProfilePresentFlag) {
+               ptl->profile_space = gf_bs_read_int(bs, 2);
+               ptl->tier_flag = gf_bs_read_int(bs, 1);
+               ptl->profile_idc = gf_bs_read_int(bs, 5);
+
+               ptl->profile_compatibility_flag = gf_bs_read_int(bs, 32);
+
+               /*general_reserved_zero_16bits  = */gf_bs_read_int(bs, 16);
+       }
+       ptl->level_idc = gf_bs_read_int(bs, 8);
+       for (i=0; i<MaxNumSubLayersMinus1; i++) {
+               if (ProfilePresentFlag)
+                       ptl->sub_ptl[i].profile_present_flag = gf_bs_read_int(bs, 1);
+               ptl->sub_ptl[i].level_present_flag = gf_bs_read_int(bs, 1);
+               if (ProfilePresentFlag && ptl->sub_ptl[i].profile_present_flag) {
+                       ptl->sub_ptl[i].profile_space = gf_bs_read_int(bs, 2);
+                       ptl->sub_ptl[i].tier_flag = gf_bs_read_int(bs, 1);
+                       ptl->sub_ptl[i].profile_idc = gf_bs_read_int(bs, 5);
+                       ptl->sub_ptl[i].profile_compatibility_flag = gf_bs_read_int(bs, 32);
+                       /*sub_layer_reserved_zero_16bits*/gf_bs_read_int(bs, 16);
+               }
+               if (ptl->sub_ptl[i].level_present_flag)
+                       ptl->sub_ptl[i].level_idc = gf_bs_read_int(bs, 8);
+       }
+}
+
+void bit_rate_pic_rate_info(GF_BitStream *bs, u8 level_low, u8 level_high, HEVC_VPS *vps)
+{
+       u8 i;
+       for (i=level_low; i<=level_high; i++) {
+               Bool bit_rate_info_present_flag = gf_bs_read_int(bs, 1);
+               Bool pic_rate_info_present_flag = gf_bs_read_int(bs, 1);
+               if (bit_rate_info_present_flag) {
+                       vps->rates[i].avg_bit_rate = gf_bs_read_int(bs, 16);
+                       vps->rates[i].max_bit_rate = gf_bs_read_int(bs, 16);
+               }
+               if (pic_rate_info_present_flag) {
+                       vps->rates[i].constand_pic_rate_idc = gf_bs_read_int(bs, 2);
+                       vps->rates[i].avg_pic_rate = gf_bs_read_int(bs, 16);
+               }
+       }
+}
+
+s32 gf_media_hevc_read_vps(char *data, u32 size, HEVCState *hevc)
+{
+       GF_BitStream *bs;
+       char *data_without_emulation_bytes = NULL;
+       u32 data_without_emulation_bytes_size = 0;
+       s32 vps_id = -1;
+       HEVC_VPS *vps;
+
+       /*still contains emulation bytes*/
+       data_without_emulation_bytes = gf_malloc(size*sizeof(char));
+       data_without_emulation_bytes_size = avc_remove_emulation_bytes(data, data_without_emulation_bytes, size);
+       bs = gf_bs_new(data_without_emulation_bytes, data_without_emulation_bytes_size, GF_BITSTREAM_READ);
+       if (!bs) goto exit;
+       
+       gf_bs_read_u16(bs);
+
+       vps_id = gf_bs_read_int(bs, 4);
+
+       if (vps_id>=16) goto exit;
+
+       vps = &hevc->vps[vps_id];   
+       if (!vps->state) {
+               vps->id = vps_id;
+               vps->state = 1;
+       }
+
+       /*vps_temporal_id_nesting_flag = */ gf_bs_read_int(bs, 1);
+       gf_bs_read_int(bs, 2);
+       gf_bs_read_int(bs, 6);
+       vps->max_sub_layer = gf_bs_read_int(bs, 3) + 1;
+       gf_bs_read_int(bs, 16);
+       profile_tier_level(bs, 1, vps->max_sub_layer-1, &vps->ptl);
+       bit_rate_pic_rate_info(bs, 0, vps->max_sub_layer-1, vps);
+
+
+       //and we don't care about the rest for now
+exit:
+       gf_bs_del(bs);
+       gf_free(data_without_emulation_bytes);
+       return vps_id;
+}
+
+
+static Bool parse_short_term_ref_pic_set(GF_BitStream *bs, HEVC_SPS *sps, u32 idx_rps) 
+{
+       u32 i;
+       Bool inter_ref_pic_set_prediction_flag = 0;
+       if (idx_rps != 0)
+               inter_ref_pic_set_prediction_flag = gf_bs_read_int(bs, 1);
+
+       if (inter_ref_pic_set_prediction_flag ) {
+               HEVC_ReferencePictureSets *ref_ps, *rps;
+               u32 delta_idx_minus1 = 0;
+               u32 ref_idx;
+               u32 delta_rps_sign;
+               u32 abs_delta_rps_minus1, nb_ref_pics;
+               s32 deltaRPS;
+           u32 k = 0, k0 = 0, k1 = 0;
+               if (idx_rps == sps->num_short_term_ref_pic_sets)
+                       delta_idx_minus1 = bs_get_ue(bs);
+
+               assert(delta_idx_minus1 <= idx_rps - 1);
+               ref_idx = idx_rps - 1 - delta_idx_minus1;
+               delta_rps_sign = gf_bs_read_int(bs, 1);
+               abs_delta_rps_minus1 = bs_get_ue(bs);
+               deltaRPS = (1 - (delta_rps_sign<<1)) * (abs_delta_rps_minus1 + 1);
+
+               rps = &sps->rps[idx_rps];
+               ref_ps = &sps->rps[ref_idx];
+               nb_ref_pics = ref_ps->num_negative_pics + ref_ps->num_positive_pics;
+               for (i=0; i<=nb_ref_pics; i++) {
+                       s32 ref_idc;
+                       s32 used_by_curr_pic_flag = gf_bs_read_int(bs, 1);
+                       ref_idc = used_by_curr_pic_flag ? 1 : 0;
+                       if ( !used_by_curr_pic_flag ) {
+                               used_by_curr_pic_flag = gf_bs_read_int(bs, 1);
+                               ref_idc = used_by_curr_pic_flag << 1;
+                       }
+                       if ((ref_idc==1) || (ref_idc== 2)) {
+                               s32 deltaPOC = deltaRPS;
+                               if (i < nb_ref_pics) 
+                                       deltaPOC += ref_ps->delta_poc[i];
+                               
+                               rps->delta_poc[k] = deltaPOC;
+
+                               if (deltaPOC < 0)  k0++;
+                               else k1++;
+                               
+                               k++;
+                       }
+               }
+               rps->num_negative_pics = k0;
+               rps->num_positive_pics = k1;
+       } else {
+               s32 prev = 0, poc = 0;
+               sps->rps[idx_rps].num_negative_pics = bs_get_ue(bs);
+               sps->rps[idx_rps].num_positive_pics = bs_get_ue(bs);
+               for (i=0; i<sps->rps[idx_rps].num_negative_pics; i++) {
+                       u32 delta_poc_s0_minus1 = bs_get_ue(bs);
+                       poc = prev - delta_poc_s0_minus1 - 1;
+                       prev = poc;
+                       sps->rps[idx_rps].delta_poc[i] = poc;
+                       /*used_by_curr_pic_s1_flag[ i ] = */gf_bs_read_int(bs, 1);
+               }
+               for (i=0; i<sps->rps[idx_rps].num_positive_pics; i++) {
+                       u32 delta_poc_s1_minus1 = bs_get_ue(bs);
+                       poc = prev + delta_poc_s1_minus1 + 1;
+                       prev = poc;
+                       sps->rps[idx_rps].delta_poc[i] = poc;
+                       /*used_by_curr_pic_s1_flag[ i ] = */gf_bs_read_int(bs, 1);
+               }
+       }
+       return 1;
+}
+
+s32 gf_media_hevc_read_sps(char *data, u32 size, HEVCState *hevc)
+{
+       GF_BitStream *bs;
+       char *data_without_emulation_bytes = NULL;
+       u32 data_without_emulation_bytes_size = 0;
+       s32 vps_id, sps_id = -1;
+       u8 max_sub_layers_minus1;
+       u32 i, nb_CTUs, depth;
+       u32 log2_diff_max_min_luma_coding_block_size;
+       u32 log2_min_transform_block_size, log2_min_luma_coding_block_size;
+
+       Bool sps_sub_layer_ordering_info_present_flag;
+       HEVC_SPS *sps;
+       HEVC_ProfileTierLevel ptl;
+
+       /*still contains emulation bytes*/
+       data_without_emulation_bytes = gf_malloc(size*sizeof(char));
+       data_without_emulation_bytes_size = avc_remove_emulation_bytes(data, data_without_emulation_bytes, size);
+       bs = gf_bs_new(data_without_emulation_bytes, data_without_emulation_bytes_size, GF_BITSTREAM_READ);
+       if (!bs) goto exit;
+       
+       gf_bs_read_u16(bs);
+
+       vps_id = gf_bs_read_int(bs, 4);
+       if (vps_id>=16) goto exit;
+
+       max_sub_layers_minus1 = gf_bs_read_int(bs, 3);
+       /*temporal_id_nesting_flag = */gf_bs_read_int(bs, 1);
+       memset(&ptl, 0, sizeof(ptl));
+       profile_tier_level(bs, 1, max_sub_layers_minus1, &ptl);
+
+       sps_id = bs_get_ue(bs);
+       if (sps_id>=16) goto exit;
+       sps = &hevc->sps[sps_id];
+       if (!sps->state) {
+               sps->state = 1;
+               sps->id = sps_id;
+               sps->vps_id = vps_id;
+       }
+       sps->ptl = ptl;
+
+       sps->chroma_format_idc = bs_get_ue(bs);
+       if (sps->chroma_format_idc==3)
+               sps->separate_colour_plane_flag = gf_bs_read_int(bs, 1);
+       sps->width = bs_get_ue(bs);
+       sps->height = bs_get_ue(bs);
+       if (gf_bs_read_int(bs, 1)) {
+               sps->cw_left = bs_get_ue(bs);
+               sps->cw_right = bs_get_ue(bs);
+               sps->cw_top = bs_get_ue(bs);
+               sps->cw_bottom = bs_get_ue(bs);
+       }
+       sps->bit_depth_luma = 8 + bs_get_ue(bs);
+       sps->bit_depth_chroma = 8 + bs_get_ue(bs);
+
+       sps->log2_max_pic_order_cnt_lsb = 4 + bs_get_ue(bs);
+
+       sps_sub_layer_ordering_info_present_flag = gf_bs_read_int(bs, 1);
+       for(i= sps_sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; i<=max_sub_layers_minus1; i++) {
+               /*max_dec_pic_buffering = */ bs_get_ue(bs);
+               /*num_reorder_pics = */ bs_get_ue(bs);
+               /*max_latency_increase = */ bs_get_ue(bs);
+       }
+
+       log2_min_luma_coding_block_size = 3 + bs_get_ue(bs);
+       log2_diff_max_min_luma_coding_block_size = bs_get_ue(bs);
+       sps->max_CU_width = ( 1<<(log2_min_luma_coding_block_size + log2_diff_max_min_luma_coding_block_size) );
+       sps->max_CU_height = ( 1<<(log2_min_luma_coding_block_size + log2_diff_max_min_luma_coding_block_size) );
+
+       log2_min_transform_block_size = 2 + bs_get_ue(bs);
+       /*log2_max_transform_block_size = log2_min_transform_block_size  + */bs_get_ue(bs);
+
+       depth = 0;
+       /*u32 max_transform_hierarchy_depth_inter = */bs_get_ue(bs);
+       /*u32 max_transform_hierarchy_depth_intra = */bs_get_ue(bs);
+       while( (u32) ( sps->max_CU_width >> log2_diff_max_min_luma_coding_block_size ) > (u32) ( 1 << ( log2_min_transform_block_size + depth )  ) )
+       {
+               depth++;
+       }
+       sps->max_CU_depth = log2_diff_max_min_luma_coding_block_size + depth; 
+
+       nb_CTUs = ((sps->width + sps->max_CU_width -1) / sps->max_CU_width) * ((sps->height + sps->max_CU_height-1) / sps->max_CU_height);
+       sps->bitsSliceSegmentAddress = 0;
+       while (nb_CTUs > (u32) (1 << sps->bitsSliceSegmentAddress)) {
+               sps->bitsSliceSegmentAddress++;
+       }
+
+       if (/*scaling_list_enable_flag = */ gf_bs_read_int(bs, 1)) { 
+               if (/*sps_scaling_list_data_present_flag=*/gf_bs_read_int(bs, 1) ) {
+                       //scaling_list_data( )
+               }
+       }
+       /*asymmetric_motion_partitions_enabled_flag= */ gf_bs_read_int(bs, 1);
+       /*sample_adaptive_offset_enabled_flag= */ gf_bs_read_int(bs, 1);
+       if (/*pcm_enabled_flag= */ gf_bs_read_int(bs, 1) ) {
+               /*pcm_sample_bit_depth_luma_minus1=*/gf_bs_read_int(bs, 4);
+               /*pcm_sample_bit_depth_chroma_minus1=*/gf_bs_read_int(bs, 4);
+               /*log2_min_pcm_luma_coding_block_size_minus3= */ bs_get_ue(bs);
+               /*log2_diff_max_min_pcm_luma_coding_block_size = */ bs_get_ue(bs);
+               /*pcm_loop_filter_disable_flag=*/gf_bs_read_int(bs, 1);
+       }
+       sps->num_short_term_ref_pic_sets = bs_get_ue(bs);
+       for (i=0;i<sps->num_short_term_ref_pic_sets; i++) {
+               Bool ret = parse_short_term_ref_pic_set(bs, sps, i); 
+               /*cannot parse short_term_ref_pic_set, skip VUI parsing*/
+               if (!ret) goto exit;
+       }
+       if (/*long_term_ref_pics_present_flag */ gf_bs_read_int(bs, 1) ) {
+               sps->num_long_term_ref_pic_sps = bs_get_ue(bs);
+               for (i=0; i<sps->num_long_term_ref_pic_sps; i++) {
+                       /*lt_ref_pic_poc_lsb_sps=*/gf_bs_read_int(bs, sps->log2_max_pic_order_cnt_lsb);
+                       /*used_by_curr_pic_lt_sps_flag*/gf_bs_read_int(bs, 1);
+               }
+       }
+       /*sps_temporal_mvp_enable_flag*/gf_bs_read_int(bs, 1);
+       /*strong_intra_smoothing_enable_flag*/gf_bs_read_int(bs, 1);
+       if (/*vui_parameters_present_flag*/gf_bs_read_int(bs, 1)) {
+               //vui param
+       }
+       if (/*sps_extension_flag*/gf_bs_read_int(bs, 1)) {
+               while (gf_bs_available(bs)) {
+               }
+       }
+
+exit:
+       gf_bs_del(bs);
+       gf_free(data_without_emulation_bytes);
+       return sps_id;
+}
+
+s32 gf_media_hevc_read_pps(char *data, u32 size, HEVCState *hevc)
+{
+       u32 i;
+       GF_BitStream *bs;
+       char *data_without_emulation_bytes = NULL;
+       u32 data_without_emulation_bytes_size = 0;
+       s32 pps_id = -1;
+       HEVC_PPS *pps;
+
+       /*still contains emulation bytes*/
+       data_without_emulation_bytes = gf_malloc(size*sizeof(char));
+       data_without_emulation_bytes_size = avc_remove_emulation_bytes(data, data_without_emulation_bytes, size);
+       bs = gf_bs_new(data_without_emulation_bytes, data_without_emulation_bytes_size, GF_BITSTREAM_READ);
+       if (!bs) goto exit;
+       
+       gf_bs_read_u16(bs);
+
+       pps_id = bs_get_ue(bs);
+
+       if (pps_id>=64) goto exit;
+       pps = &hevc->pps[pps_id];
+   
+       if (!pps->state) {
+               pps->id = pps_id;
+               pps->state = 1;
+       }
+       pps->sps_id = bs_get_ue(bs);
+       hevc->sps_active_idx = pps->sps_id; /*set active sps*/
+       pps->dependent_slice_segments_enabled_flag = gf_bs_read_int(bs, 1);
+
+       /*sign_data_hiding_flag = */gf_bs_read_int(bs, 1);
+       /*cabac_init_present_flag = */gf_bs_read_int(bs, 1);
+       /*num_ref_idx_l0_default_active_minus1 = */bs_get_ue(bs);
+       /*num_ref_idx_l1_default_active_minus1 = */bs_get_ue(bs);
+       /*pic_init_qp_minus26 = */bs_get_se(bs);
+       /*constrained_intra_pred_flag = */gf_bs_read_int(bs, 1);
+       /*transform_skip_enabled_flag = */gf_bs_read_int(bs, 1);
+       if (/*cu_qp_delta_enabled_flag = */gf_bs_read_int(bs, 1) )
+               /*diff_cu_qp_delta_depth = */bs_get_ue(bs);
+
+       /*pic_cb_qp_offset = */bs_get_se(bs);
+       /*pic_cr_qp_offset = */bs_get_se(bs);
+       /*pic_slice_chroma_qp_offsets_present_flag = */gf_bs_read_int(bs, 1);
+       /*weighted_pred_flag = */gf_bs_read_int(bs, 1);
+       /*weighted_bipred_flag = */gf_bs_read_int(bs, 1);
+       pps->output_flag_present_flag = gf_bs_read_int(bs, 1);
+       /*transquant_bypass_enable_flag = */gf_bs_read_int(bs, 1);
+       pps->tiles_enabled_flag = gf_bs_read_int(bs, 1);
+       /*entropy_coding_sync_enabled_flag = */gf_bs_read_int(bs, 1);
+       if (pps->tiles_enabled_flag) {
+               u32 num_tile_columns_minus1 = bs_get_ue(bs);
+               u32 num_tile_rows_minus1 = bs_get_ue(bs);
+               pps->uniform_spacing_flag = gf_bs_read_int(bs, 1);
+               if (!pps->uniform_spacing_flag ) {
+                       for( i = 0; i < num_tile_columns_minus1; i++ ) {
+                               /*column_width_minus1[ i ] = */bs_get_ue(bs);
+                       }
+                       for( i = 0; i < num_tile_rows_minus1; i++ ) {
+                               /*row_height_minus1[ i ] = */bs_get_ue(bs);
+                       }
+               }
+               /*loop_filter_across_tiles_enabled_flag  = */gf_bs_read_int(bs, 1);
+       }
+       /*loop_filter_across_slices_enabled_flag = */gf_bs_read_int(bs, 1);
+       if( /*deblocking_filter_control_present_flag = */gf_bs_read_int(bs, 1)  ) {
+               /*deblocking_filter_override_enabled_flag= */gf_bs_read_int(bs, 1);
+               if (/*pic_disable_deblocking_filter_flag= */gf_bs_read_int(bs, 1) ) {
+                       /*beta_offset_div2 = */bs_get_se(bs);
+                       /*tc_offset_div2 = */bs_get_se(bs);
+               }
+       }
+       if (/*pic_scaling_list_data_present_flag        = */gf_bs_read_int(bs, 1) ) {
+               //scaling_list_data( )
+               assert(0 && "not implemented");
+       }
+       /*lists_modification_present_flag       = */gf_bs_read_int(bs, 1);
+       /*log2_parallel_merge_level_minus2 = */bs_get_ue(bs);
+       pps->num_extra_slice_header_bits = gf_bs_read_int(bs, 3);
+       pps->slice_segment_header_extension_present_flag = gf_bs_read_int(bs, 1);
+       if ( /*pps_extension_flag= */gf_bs_read_int(bs, 1) ) {
+               while (gf_bs_available(bs) ) {
+                       //pps_extension_data_flag       u(1)
+               }
+       }
+
+exit:
+       gf_bs_del(bs);
+       gf_free(data_without_emulation_bytes);
+       return pps_id;
+}
+
+
+s32 gf_media_hevc_parse_nalu(GF_BitStream *bs, HEVCState *hevc, u8 *nal_unit_type, u8 *temporal_id)
+{
+       u32 reserved;
+       s32 slice, ret;
+       HEVCSliceInfo n_state;
+
+       slice = 0;
+       memcpy(&n_state, &hevc->s_info, sizeof(HEVCSliceInfo));
+
+       reserved = gf_bs_read_int(bs, 1);
+       if (reserved) return -1;
+
+       *nal_unit_type = n_state.nal_unit_type = gf_bs_read_int(bs, 6);
+       reserved = gf_bs_read_int(bs, 6);
+//     if (reserved) return -1;
+
+       *temporal_id = n_state.temporal_id = gf_bs_read_int(bs, 3);
+
+       ret = 0;
+       switch (n_state.nal_unit_type) {
+       case GF_HEVC_NALU_ACCESS_UNIT:
+       case GF_HEVC_NALU_END_OF_SEQ:
+       case GF_HEVC_NALU_END_OF_STREAM:
+               ret = 1;
+               break;
+
+
+       /*slice_layer_rbsp*/
+//     case GF_HEVC_NALU_SLICE_STSA_N:
+//     case GF_HEVC_NALU_SLICE_STSA_R:
+       case GF_HEVC_NALU_SLICE_RADL_N:
+//     case GF_HEVC_NALU_SLICE_RADL_R:
+       case GF_HEVC_NALU_SLICE_RASL_N:
+//     case GF_HEVC_NALU_SLICE_RASL_R:
+               break;
+
+       /*slice_segment_layer_rbsp*/
+       case GF_HEVC_NALU_SLICE_TRAIL_N:
+       case GF_HEVC_NALU_SLICE_TRAIL_R:
+       case GF_HEVC_NALU_SLICE_TSA_N:
+       case GF_HEVC_NALU_SLICE_TSA_R:
+       case GF_HEVC_NALU_SLICE_STSA_N:
+       case GF_HEVC_NALU_SLICE_STSA_R:
+
+       case GF_HEVC_NALU_SLICE_BLA_W_LP:
+       case GF_HEVC_NALU_SLICE_BLA_W_DLP:
+       case GF_HEVC_NALU_SLICE_BLA_N_LP:
+       case GF_HEVC_NALU_SLICE_IDR_W_DLP:
+       case GF_HEVC_NALU_SLICE_IDR_N_LP:
+       case GF_HEVC_NALU_SLICE_CRA:
+       case GF_HEVC_NALU_SLICE_RADL_R:
+       case GF_HEVC_NALU_SLICE_RASL_R:
+               slice = 1;
+               /* slice - read the info and compare.*/
+               ret = hevc_parse_slice_segment(bs, hevc, &n_state);
+               if (ret<0) return ret;
+
+               hevc_compute_poc(&n_state);
+               
+               ret = 0;
+
+               if (hevc->s_info.poc != n_state.poc) {
+                       ret=1;
+                       break;
+               }
+               break;
+       case GF_HEVC_NALU_SEQ_PARAM:
+       case GF_HEVC_NALU_PIC_PARAM:
+       case GF_HEVC_NALU_VID_PARAM:
+               return 0;
+       default:
+               break;
+       } 
+
+       /* save _prev values */
+       if (ret && hevc->s_info.sps) {
+               n_state.frame_num_offset_prev = hevc->s_info.frame_num_offset;
+               n_state.frame_num_prev = hevc->s_info.frame_num;
+
+               n_state.poc_lsb_prev = hevc->s_info.poc_lsb;
+               n_state.poc_msb_prev = hevc->s_info.poc_msb;
+
+       }
+       if (slice) hevc_compute_poc(&n_state);
+       memcpy(&hevc->s_info, &n_state, sizeof(HEVCSliceInfo));
+       return ret;
+}
+
 
 static u32 AC3_FindSyncCode(u8 *buf, u32 buflen)
 {
index 3336f9eec8c2ab242827f41096c6bc44fe5a316d..9b30691c3181e064adb66d1d5c36ca37dccf44a3 100644 (file)
 #include <gpac/dash.h>\r
 #include <gpac/internal/mpd.h>\r
 #include <gpac/internal/m3u8.h>\r
+#include <gpac/internal/isomedia_dev.h>\r
 #include <string.h>\r
 \r
+#ifndef _WIN32_WCE\r
+#include <time.h>\r
+#endif\r
+\r
 #ifndef GPAC_DISABLE_DASH_CLIENT\r
 \r
 /*set to 1 if you want MPD to use SegmentTemplate if possible instead of SegmentList*/\r
@@ -60,6 +65,7 @@ struct __dash_client
        u32 max_cache_duration;\r
        u32 auto_switch_count;\r
        Bool keep_files, disable_switching, allow_local_mpd_update;\r
+       Bool is_m3u8;\r
 \r
        GF_DASHInitialSelectionMode first_select_mode;\r
 \r
@@ -135,6 +141,8 @@ struct __dash_group
 \r
        u32 prev_active_rep_index;\r
 \r
+       Bool timeline_setup;\r
+\r
        GF_DASHGroupSelection selection;\r
 \r
 \r
@@ -148,6 +156,7 @@ struct __dash_group
        u32 nb_segments_in_rep;\r
        Double segment_duration;\r
 \r
+       Bool was_segment_base;\r
        /*local file playback, do not delete them*/\r
        Bool local_files;\r
        /*next segment to download for this group*/\r
@@ -207,6 +216,64 @@ Bool gf_dash_check_mpd_root_type(const char *local_url)
        return 0;\r
 }\r
 \r
+static void gf_dash_group_timeline_setup(GF_MPD *mpd, GF_DASH_Group *group)\r
+{\r
+       u32 sec, frac;\r
+#ifndef _WIN32_WCE\r
+       time_t gtime;\r
+       struct tm *_t;\r
+#endif\r
+       u64 current_time;\r
+       \r
+       if (mpd->type==GF_MPD_TYPE_STATIC) \r
+               return;\r
+       \r
+       /*M3U8 does not use NTP sync */\r
+       if (group->dash->is_m3u8)\r
+               return;\r
+\r
+       gf_net_get_ntp(&sec, &frac);\r
+\r
+#ifndef _WIN32_WCE\r
+       gtime = sec - GF_NTP_SEC_1900_TO_1970;\r
+       _t = gmtime(&gtime);\r
+       current_time = mktime(_t);\r
+#else\r
+       current_time = sec - GF_NTP_SEC_1900_TO_1970;\r
+#endif\r
+       if (current_time < mpd->availabilityStartTime) current_time = 0;\r
+       else current_time -= mpd->availabilityStartTime;\r
+\r
+       if (current_time < group->period->start) current_time = 0;\r
+       else current_time -= group->period->start;\r
+\r
+#if 0\r
+       {\r
+               s32 diff = (s32) current_time - (s32) (mpd->media_presentation_duration/1000);\r
+               if (ABS(diff)>10) {\r
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Broken UTC timing in client or server - got Media URL is not set in segment list\n"));\r
+                               \r
+               }\r
+               current_time = mpd->media_presentation_duration/1000;\r
+       }\r
+#endif\r
+\r
+       frac = mpd->time_shift_buffer_depth/1000;\r
+       if (current_time < frac) current_time = 0;\r
+       else current_time -= frac;\r
+\r
+\r
+       if (group->segment_duration) {\r
+               Double nb_seg = (Double) current_time;\r
+               nb_seg /= group->segment_duration;\r
+               frac = (u32) nb_seg;\r
+               group->download_segment_index = frac;\r
+               group->nb_segments_in_rep = frac + 10;\r
+       } else {\r
+               GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Segment duration unknown - cannot estimate current startNumber\n"));\r
+       }\r
+}\r
+\r
 void gf_dash_group_check_switch(GF_DASHFileIO *dash_io, GF_DASH_Group *group, Bool download_active)\r
 {\r
        u32 download_rate;\r
@@ -279,7 +346,7 @@ static Bool gf_dash_is_m3u8_mime(const char * mime) {
 * Parameters are identical to the ones of gf_term_download_new.\r
 * \see gf_term_download_new()\r
 */\r
-GF_Err gf_dash_download_resource(GF_DASHFileIO *dash_io, GF_DASHFileIOSession *sess, const char *url, u64 start_range, u64 end_range, Bool persistent, GF_DASH_Group *group)\r
+GF_Err gf_dash_download_resource(GF_DASHFileIO *dash_io, GF_DASHFileIOSession *sess, const char *url, u64 start_range, u64 end_range, u32 persistent_mode, GF_DASH_Group *group)\r
 {\r
        Bool had_sess = 0;\r
        Bool retry = 1;\r
@@ -288,7 +355,7 @@ GF_Err gf_dash_download_resource(GF_DASHFileIO *dash_io, GF_DASHFileIOSession *s
        GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Downloading %s...\n", url));\r
 \r
        if (! *sess) {\r
-               *sess = dash_io->create(dash_io, persistent, url);\r
+               *sess = dash_io->create(dash_io, persistent_mode ? 1 : 0, url);\r
                if (!(*sess)){\r
                        assert(0);\r
                        GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot try to download %s... OUT of memory ?\n", url));\r
@@ -296,22 +363,24 @@ GF_Err gf_dash_download_resource(GF_DASHFileIO *dash_io, GF_DASHFileIOSession *s
                }\r
        } else {\r
                had_sess = 1;\r
-               e = dash_io->setup_from_url(dash_io, *sess, url);\r
-               if (e) {\r
-                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot resetup session for url %s: %s\n", url, gf_error_to_string(e) ));\r
-                       return e;\r
+               if (persistent_mode!=2) {\r
+                       e = dash_io->setup_from_url(dash_io, *sess, url);\r
+                       if (e) {\r
+                               GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot resetup session for url %s: %s\n", url, gf_error_to_string(e) ));\r
+                               return e;\r
+                       }\r
                }\r
        }\r
 \r
 retry:\r
 \r
        if (end_range) {\r
-               e = dash_io->set_range(dash_io, *sess, start_range, end_range);\r
+               e = dash_io->set_range(dash_io, *sess, start_range, end_range, (persistent_mode==2) ? 0 : 1);\r
                if (e) {\r
                        if (had_sess) {\r
                                dash_io->del(dash_io, *sess);\r
                                *sess = NULL;\r
-                               return gf_dash_download_resource(dash_io, sess, url, start_range, end_range, persistent, group);\r
+                               return gf_dash_download_resource(dash_io, sess, url, start_range, end_range, persistent_mode ? 1 : 0, group);\r
                        }\r
                        GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot setup byte-range download for %s: %s\n", url, gf_error_to_string(e) ));\r
                        return e;\r
@@ -411,13 +480,6 @@ static void gf_dash_get_segment_duration(GF_MPD_Representation *rep, GF_MPD_Adap
        *nb_segments = timescale = 0;\r
        duration = 0;\r
 \r
-       /*single segment*/\r
-       if (rep->segment_base || set->segment_base || period->segment_base) {\r
-               *max_seg_duration = mpd->media_presentation_duration;\r
-               *max_seg_duration /= 1000;\r
-               *nb_segments = 1;\r
-               return;\r
-       }\r
        if (rep->segment_list || set->segment_list || period->segment_list) {\r
                GF_List *segments = NULL;\r
                if (period->segment_list) {\r
@@ -454,6 +516,14 @@ static void gf_dash_get_segment_duration(GF_MPD_Representation *rep, GF_MPD_Adap
                return;\r
        }\r
 \r
+       /*single segment*/\r
+       if (rep->segment_base || set->segment_base || period->segment_base) {\r
+               *max_seg_duration = mpd->media_presentation_duration;\r
+               *max_seg_duration /= 1000;\r
+               *nb_segments = 1;\r
+               return;\r
+       }\r
+\r
        single_segment = 1;\r
        if (period->segment_template) {\r
                single_segment = 0;\r
@@ -657,6 +727,10 @@ static void gf_dash_resolve_duration(GF_MPD_Representation *rep, GF_MPD_Adaptati
                GF_MPD_SegmentTimelineEntry *ent = gf_list_get(segment_timeline->entries, 0);\r
                if (ent) *out_duration = ent->duration;\r
        }\r
+       else if (rep->segment_list) {\r
+               GF_MPD_SegmentURL *url = gf_list_get(rep->segment_list->segment_URLs, 0);\r
+               if (url && url->duration) *out_duration = url->duration;\r
+       }\r
 }\r
 \r
 static GF_Err gf_dash_merge_segment_timeline(GF_MPD_SegmentList *old_list, GF_MPD_SegmentTemplate *old_template, GF_MPD_SegmentList *new_list, GF_MPD_SegmentTemplate *new_template, Double min_start_time)\r
@@ -935,6 +1009,7 @@ static GF_Err gf_dash_update_manifest(GF_DashClient *dash)
                                for (group_idx=0; group_idx<gf_list_count(dash->groups); group_idx++) {\r
                                        GF_MPD_AdaptationSet *set, *new_set;\r
                                        GF_DASH_Group *group = gf_list_get(dash->groups, group_idx);\r
+\r
                                        if (group->selection != GF_DASH_GROUP_SELECTED) continue;\r
                                        set = group->adaptation_set;\r
                                        new_set = gf_list_get(new_period->adaptation_sets, group_idx);\r
@@ -1075,6 +1150,10 @@ static GF_Err gf_dash_update_manifest(GF_DashClient *dash)
                                                }\r
                                        }\r
 \r
+                                       if (new_mpd->availabilityStartTime != dash->mpd->availabilityStartTime) {\r
+                                               gf_dash_group_timeline_setup(new_mpd, group);\r
+                                       }\r
+\r
                                        /*update number of segments in active rep*/\r
                                        gf_dash_get_segment_duration(gf_list_get(group->adaptation_set->representations, group->active_rep_index), group->adaptation_set, group->period, new_mpd, &group->nb_segments_in_rep, NULL);\r
 \r
@@ -1210,7 +1289,8 @@ typedef enum
 } GF_DASHURLResolveType;\r
 \r
 \r
-GF_Err gf_dash_resolve_url(GF_MPD *mpd, GF_MPD_Representation *rep, GF_DASH_Group *group, char *mpd_url, GF_DASHURLResolveType resolve_type, u32 item_index, char **out_url, u64 *out_range_start, u64 *out_range_end, u64 *segment_duration)\r
+\r
+GF_Err gf_dash_resolve_url(GF_MPD *mpd, GF_MPD_Representation *rep, GF_DASH_Group *group, const char *mpd_url, GF_DASHURLResolveType resolve_type, u32 item_index, char **out_url, u64 *out_range_start, u64 *out_range_end, u64 *segment_duration, Bool *is_in_base_url)\r
 {\r
        GF_MPD_BaseURL *url_child;\r
        GF_MPD_SegmentTimeline *timeline = NULL;\r
@@ -1225,6 +1305,15 @@ GF_Err gf_dash_resolve_url(GF_MPD *mpd, GF_MPD_Representation *rep, GF_DASH_Grou
        *out_range_start = *out_range_end = 0;\r
        *out_url = NULL;\r
 \r
+\r
+       if (!group->timeline_setup) {\r
+               gf_dash_group_timeline_setup(mpd, group);\r
+               group->timeline_setup = 1;\r
+       }\r
+\r
+\r
+\r
+\r
        /*resolve base URLs from document base (download location) to representation (media)*/\r
        url = gf_strdup(mpd_url);\r
 \r
@@ -1260,8 +1349,10 @@ GF_Err gf_dash_resolve_url(GF_MPD *mpd, GF_MPD_Representation *rep, GF_DASH_Grou
        *segment_duration = (u32) ((Double) (*segment_duration) * 1000.0 / timescale);\r
 \r
        /*single URL*/\r
-       if (rep->segment_base || set->segment_base || period->segment_base) {\r
+//     if (rep->segment_base || set->segment_base || period->segment_base) {\r
+       if (!rep->segment_list && !set->segment_list && !period->segment_list && !rep->segment_template && !set->segment_template && !period->segment_template) {       \r
                GF_MPD_URL *res_url;\r
+               GF_MPD_SegmentBase *base_seg = NULL;\r
                if (item_index>0) return GF_EOS;\r
                switch (resolve_type) {\r
                case GF_DASH_RESOLVE_URL_MEDIA:\r
@@ -1271,29 +1362,32 @@ GF_Err gf_dash_resolve_url(GF_MPD *mpd, GF_MPD_Representation *rep, GF_DASH_Grou
                case GF_DASH_RESOLVE_URL_INIT:\r
                case GF_DASH_RESOLVE_URL_INDEX:\r
                        res_url = NULL;\r
-                       if (resolve_type == GF_DASH_RESOLVE_URL_INDEX) {\r
-                               if (period->segment_base) res_url = period->segment_base->representation_index;\r
-                               if (set->segment_base) res_url = set->segment_base->representation_index;\r
-                               if (rep->segment_base) res_url = rep->segment_base->representation_index;\r
-                       } else {\r
-                               if (period->segment_base) res_url = period->segment_base->initialization_segment;\r
-                               if (set->segment_base) res_url = set->segment_base->initialization_segment;\r
-                               if (rep->segment_base) res_url = rep->segment_base->initialization_segment;\r
-                       }\r
-                       /*no initialization segment / index*/\r
-                       if (!res_url) {\r
-                               gf_free(url);\r
-                               return GF_OK;\r
+                       base_seg = rep->segment_base;\r
+                       if (!base_seg) base_seg = set->segment_base;\r
+                       if (!base_seg) base_seg = period->segment_base;\r
+\r
+                       if (base_seg) {\r
+                               if (resolve_type == GF_DASH_RESOLVE_URL_INDEX) {\r
+                                       res_url = base_seg->representation_index;\r
+                               } else {\r
+                                       res_url = base_seg->initialization_segment;\r
+                               }\r
                        }\r
-                       if (res_url->sourceURL) {\r
+                       if (is_in_base_url) *is_in_base_url = 0;\r
+                       /*no initialization segment / index, use base URL*/\r
+                       if (res_url && res_url->sourceURL) {\r
                                *out_url = gf_url_concatenate(url, res_url->sourceURL);\r
                                gf_free(url);\r
                        } else {\r
                                *out_url = url;\r
+                               if (is_in_base_url) *is_in_base_url = 1;\r
                        }\r
-                       if (res_url->byte_range) {\r
+                       if (res_url && res_url->byte_range) {\r
                                *out_range_start = res_url->byte_range->start_range;\r
                                *out_range_end = res_url->byte_range->end_range;\r
+                       } else if (base_seg && base_seg->index_range && (resolve_type == GF_DASH_RESOLVE_URL_INDEX)) {\r
+                               *out_range_start = base_seg->index_range->start_range;\r
+                               *out_range_end = base_seg->index_range->end_range;\r
                        }\r
                        return GF_OK;\r
                default:\r
@@ -1374,6 +1468,9 @@ GF_Err gf_dash_resolve_url(GF_MPD *mpd, GF_MPD_Representation *rep, GF_DASH_Grou
                                *out_range_start = segment->media_range->start_range;\r
                                *out_range_end = segment->media_range->end_range;\r
                        }\r
+                       if (segment->duration) {\r
+                               *segment_duration = (u32) ((Double) (segment->duration) * 1000.0 / timescale);\r
+                       }\r
                        return GF_OK;\r
                case GF_DASH_RESOLVE_URL_INDEX:\r
                        if (item_index >= segment_count) {\r
@@ -1574,7 +1671,7 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
        }\r
        start_range = end_range = 0;\r
 \r
-       e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration);\r
+       e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration, NULL);\r
        if (e) {\r
                gf_mx_v(dash->dl_mutex);\r
                GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Unable to resolve initialization URL: %s\n", gf_error_to_string(e) ));\r
@@ -1583,7 +1680,7 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
 \r
        /*no error and no init segment, go for media segment*/\r
        if (!base_init_url) {\r
-               e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_MEDIA, group->download_segment_index, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration);\r
+               e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_MEDIA, group->download_segment_index, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration, NULL);\r
                if (e) {\r
                        gf_mx_v(dash->dl_mutex);\r
                        GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Unable to resolve media URL: %s\n", gf_error_to_string(e) ));\r
@@ -1594,7 +1691,7 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
                group->dont_delete_first_segment = 1;\r
        }\r
 \r
-       if (!strstr(base_init_url, "://") || !strnicmp(base_init_url, "file://", 7) || !strnicmp(base_init_url, "views://", 8)) {\r
+       if (!strstr(base_init_url, "://") || !strnicmp(base_init_url, "file://", 7) || !strnicmp(base_init_url, "gmem://", 7) || !strnicmp(base_init_url, "views://", 8)) {\r
                assert(!group->nb_cached_segments);\r
                group->cached[0].cache = gf_strdup(base_init_url);\r
                group->cached[0].url = gf_strdup(base_init_url);\r
@@ -1603,7 +1700,7 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
 \r
                group->nb_cached_segments = 1;\r
                /*do not erase local files*/\r
-               group->local_files = 1;\r
+               group->local_files = group->was_segment_base ? 0 : 1;\r
                group->download_segment_index += nb_segment_read;\r
                group->segment_local_url = group->cached[0].cache;\r
                group->local_url_start_range = start_range;\r
@@ -1623,11 +1720,11 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
                                if (a_rep==rep) continue;\r
                                if (a_rep->playback.disabled) continue;\r
 \r
-                               e = gf_dash_resolve_url(dash->mpd, a_rep, group, dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &a_base_init_url, &a_start, &a_end, &a_dur);\r
+                               e = gf_dash_resolve_url(dash->mpd, a_rep, group, dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &a_base_init_url, &a_start, &a_end, &a_dur, NULL);\r
                                if (!e && a_base_init_url) {\r
                                        a_rep->playback.cached_init_segment_url = a_base_init_url;\r
-                                       rep->playback.init_start_range = a_start;\r
-                                       rep->playback.init_end_range =a_end ;\r
+                                       a_rep->playback.init_start_range = a_start;\r
+                                       a_rep->playback.init_end_range =a_end ;\r
                                } else if (e) {\r
                                        GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot solve initialization segment for representation: %s - discarding representation\n", gf_error_to_string(e) ));\r
                                        a_rep->playback.disabled = 1;\r
@@ -1658,7 +1755,7 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
 \r
                gf_free(base_init_url);\r
 \r
-               e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_MEDIA, group->download_segment_index + 1, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration);\r
+               e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_MEDIA, group->download_segment_index + 1, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration, NULL);\r
                if (!e) {\r
                        gf_mx_v(dash->dl_mutex);\r
                        return e;\r
@@ -1761,7 +1858,7 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
                                if (a_rep==rep) continue;\r
                                if (a_rep->playback.disabled) continue;\r
 \r
-                               e = gf_dash_resolve_url(dash->mpd, a_rep, group, dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &a_base_init_url, &a_start, &a_end, &a_dur);\r
+                               e = gf_dash_resolve_url(dash->mpd, a_rep, group, dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &a_base_init_url, &a_start, &a_end, &a_dur, NULL);\r
                                if (!e && a_base_init_url) {\r
                                        e = gf_dash_download_resource(dash->dash_io, &(group->segment_download), a_base_init_url, a_start, a_end, 1, group);\r
                                        if (e) {\r
@@ -1769,8 +1866,8 @@ static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *
                                                a_rep->playback.disabled = 1;\r
                                        } else {\r
                                                a_rep->playback.cached_init_segment_url = gf_strdup( dash->dash_io->get_cache_name(dash->dash_io, group->segment_download) );\r
-                                               rep->playback.init_start_range = 0;\r
-                                               rep->playback.init_end_range = 0;\r
+                                               a_rep->playback.init_start_range = 0;\r
+                                               a_rep->playback.init_end_range = 0;\r
                                        }\r
                                        gf_free(a_base_init_url);\r
                                } else if (e) {\r
@@ -1882,8 +1979,14 @@ GF_Err gf_dash_setup_groups(GF_DashClient *dash)
                for (j=0; j<gf_list_count(set->representations); j++) {\r
                        Double dur;\r
                        u32 nb_seg;\r
-                       gf_dash_get_segment_duration(gf_list_get(set->representations, j), set, period, dash->mpd, &nb_seg, &dur);\r
+                       GF_MPD_Representation *rep = gf_list_get(set->representations, j);\r
+                       gf_dash_get_segment_duration(rep, set, period, dash->mpd, &nb_seg, &dur);\r
                        if (dur>seg_dur) seg_dur = dur;\r
+\r
+                       if (rep->width>set->max_width) {\r
+                               set->max_width = rep->width;\r
+                               set->max_height = rep->height;\r
+                       }\r
                }\r
 \r
                if (!seg_dur) {\r
@@ -1918,10 +2021,278 @@ GF_Err gf_dash_setup_groups(GF_DashClient *dash)
        return GF_OK;\r
 }\r
 \r
+static GF_Err gf_dash_load_sidx(GF_BitStream *bs, GF_MPD_Representation *rep, Bool seperate_index, u64 sidx_offset)\r
+{\r
+#ifdef GPAC_DISABLE_ISOM\r
+       return GF_NOT_SUPPORTED;\r
+#else\r
+       u64 anchor_position, prev_pos;\r
+       GF_SegmentIndexBox *sidx = NULL;\r
+       u32 i, size, type;\r
+       GF_Err e;\r
+       u64 offset;\r
+       \r
+       prev_pos = gf_bs_get_position(bs);\r
+       gf_bs_seek(bs, sidx_offset);\r
+       size = gf_bs_read_u32(bs);\r
+       type = gf_bs_read_u32(bs);\r
+       if (type != GF_4CC('s','i','d','x')) {\r
+               GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error parsing SIDX: type is %s (box start offset "LLD")\n", gf_4cc_to_str(type), gf_bs_get_position(bs)-8 ));\r
+               return GF_ISOM_INVALID_FILE;\r
+       }\r
+\r
+       gf_bs_seek(bs, sidx_offset);\r
+\r
+       anchor_position = sidx_offset + size;\r
+       if (seperate_index) \r
+               anchor_position = 0;\r
+\r
+       e = gf_isom_parse_box((GF_Box **) &sidx, bs);\r
+       if (e) return e;\r
+\r
+       GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Loading SIDX - %d entries - Earliest Presentation Time "LLD"\n", sidx->nb_refs, sidx->earliest_presentation_time));\r
+\r
+       offset = sidx->first_offset + anchor_position;\r
+       rep->segment_list->timescale = sidx->timescale;\r
+       for (i=0; i<sidx->nb_refs; i++) {\r
+               GF_MPD_SegmentURL *seg;\r
+               if (sidx->refs[i].reference_type) {\r
+                       e = gf_dash_load_sidx(bs, rep, seperate_index, offset);\r
+                       if (e) {\r
+                               break;\r
+                       }\r
+               } else {\r
+                       GF_SAFEALLOC(seg, GF_MPD_SegmentURL);\r
+                       GF_SAFEALLOC(seg->media_range, GF_MPD_ByteRange);\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Found media segment size %d - duration %d - start with SAP: %d - SAP type %d - SAP Deltat Time %d\n",\r
+                               sidx->refs[i].reference_size, sidx->refs[i].subsegment_duration, sidx->refs[i].starts_with_SAP, sidx->refs[i].SAP_type, sidx->refs[i].SAP_delta_time));\r
+\r
+                       seg->media_range->start_range = offset;\r
+                       offset += sidx->refs[i].reference_size;\r
+                       seg->media_range->end_range = offset - 1;\r
+                       seg->duration = sidx->refs[i].subsegment_duration;\r
+                       gf_list_add(rep->segment_list->segment_URLs, seg);\r
+               }\r
+       }\r
+       gf_isom_box_del((GF_Box*)sidx);\r
+       gf_bs_seek(bs, prev_pos);\r
+       return e;\r
+#endif\r
+}\r
+\r
+static GF_Err gf_dash_load_representation_sidx(GF_DASH_Group *group, GF_MPD_Representation *rep, const char *cache_name, Bool seperate_index, Bool needs_mov_range)\r
+{\r
+       GF_Err e;\r
+       GF_BitStream *bs;\r
+       FILE *f=NULL;\r
+       if (!strncmp(cache_name, "gmem://", 7)) {\r
+               u32 size;\r
+               u8 *mem_address;\r
+               if (sscanf(cache_name, "gmem://%d@%p", &size, &mem_address) != 2) {\r
+                       return GF_IO_ERR;\r
+               } \r
+               bs = gf_bs_new(mem_address, size, GF_BITSTREAM_READ);\r
+       } else {\r
+               FILE *f = gf_f64_open(cache_name, "rb");\r
+               if (!f) return GF_IO_ERR;\r
+               bs = gf_bs_from_file(f, GF_BITSTREAM_READ);\r
+       }\r
+       e = GF_OK;\r
+       while (gf_bs_available(bs)) {\r
+               u32 size = gf_bs_read_u32(bs);\r
+               u32 type = gf_bs_read_u32(bs);\r
+               if (type != GF_4CC('s','i','d','x')) {\r
+                       gf_bs_skip_bytes(bs, size-8);\r
+\r
+                       if (needs_mov_range && (type==GF_4CC('m','o','o','v') )) {\r
+                               GF_SAFEALLOC(rep->segment_list->initialization_segment->byte_range, GF_MPD_ByteRange);\r
+                               rep->segment_list->initialization_segment->byte_range->end_range = gf_bs_get_position(bs);\r
+                       }\r
+                       continue;\r
+               }\r
+               gf_bs_seek(bs, gf_bs_get_position(bs)-8);\r
+               e = gf_dash_load_sidx(bs, rep, seperate_index, gf_bs_get_position(bs) );\r
+\r
+               /*we could also parse the sub sidx*/\r
+               break;\r
+       }\r
+       gf_bs_del(bs);\r
+       if (f) fclose(f);\r
+       return e;\r
+}\r
+\r
+static GF_Err dash_load_box_type(const char *cache_name, u32 offset, u32 *box_type, u32 *box_size)\r
+{\r
+       *box_type = *box_size = 0;\r
+       if (!strncmp(cache_name, "gmem://", 7)) {\r
+               u32 size;\r
+               u8 *mem_address;\r
+               if (sscanf(cache_name, "gmem://%d@%p", &size, &mem_address) != 2) {\r
+                       return GF_IO_ERR;\r
+               } \r
+               if (offset+8 > size) \r
+                       return GF_IO_ERR;\r
+               mem_address+=offset;\r
+               *box_size = GF_4CC(mem_address[0], mem_address[1], mem_address[2], mem_address[3]);\r
+               *box_type = GF_4CC(mem_address[4], mem_address[5], mem_address[6], mem_address[7]);\r
+       } else {\r
+               unsigned char data[4];\r
+               FILE *f = gf_f64_open(cache_name, "rb");\r
+               if (!f) return GF_IO_ERR;\r
+               if (gf_f64_seek(f, offset, SEEK_SET))\r
+                       return GF_IO_ERR;\r
+               if (fread(data, 1, 4, f) == 4) {\r
+                       *box_size = GF_4CC(data[0], data[1], data[2], data[3]);\r
+                       if (fread(data, 1, 4, f) == 4) {\r
+                               *box_type = GF_4CC(data[0], data[1], data[2], data[3]);\r
+                       }\r
+               }\r
+               fclose(f);\r
+       }\r
+       return GF_OK;\r
+}\r
+\r
+static GF_Err gf_dash_setup_single_index_mode(GF_DASH_Group *group)\r
+{\r
+       u32 i;\r
+       GF_Err e;\r
+       char *init_url = NULL;\r
+       char *index_url = NULL;\r
+       GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, 0);\r
+       \r
+       if (rep->segment_template || group->adaptation_set->segment_template || group->period->segment_template) return GF_OK;\r
+       if (rep->segment_list || group->adaptation_set->segment_list || group->period->segment_list) return GF_OK;\r
+\r
+       /*OK we are in single-file mode, download all required indexes & co*/\r
+       for (i=0; i<gf_list_count(group->adaptation_set->representations); i++) {\r
+               char *sidx_file = NULL;\r
+               u64 duration, index_start_range, index_end_range, init_start_range, init_end_range;\r
+               Bool index_in_base, init_in_base;\r
+               Bool init_needs_byte_range = 0;\r
+               Bool has_seen_sidx = 0;\r
+               Bool is_isom = 1;\r
+               rep = gf_list_get(group->adaptation_set->representations, i);\r
+\r
+               index_in_base = init_in_base = 0;\r
+               e = gf_dash_resolve_url(group->dash->mpd, rep, group, group->dash->base_url, GF_DASH_RESOLVE_URL_INIT, 0, &init_url, &init_start_range, &init_end_range, &duration, &init_in_base);\r
+               if (e) goto exit;\r
+\r
+               e = gf_dash_resolve_url(group->dash->mpd, rep, group, group->dash->base_url, GF_DASH_RESOLVE_URL_INDEX, 0, &index_url, &index_start_range, &index_end_range, &duration, &index_in_base);\r
+               if (e) goto exit;\r
+\r
+\r
+               if (is_isom && (init_in_base || index_in_base)) {       \r
+                       if (!strstr(init_url, "://") || (!strnicmp(init_url, "file://", 7) || !strnicmp(init_url, "views://", 7)) ) {\r
+                               GF_SAFEALLOC(rep->segment_list, GF_MPD_SegmentList);\r
+                               rep->segment_list->segment_URLs  =gf_list_new();\r
+\r
+                               if (init_in_base) {\r
+                                       GF_SAFEALLOC(rep->segment_list->initialization_segment, GF_MPD_URL);\r
+                                       rep->segment_list->initialization_segment->sourceURL = gf_strdup(init_url);\r
+                                       /*we don't want to load the entire movie */\r
+                                       init_needs_byte_range = 1;\r
+                               }\r
+                               if (index_in_base) {\r
+                                       sidx_file = (char *)init_url;\r
+                               }\r
+                       }\r
+                       /*we need to download the init segement, at least partially*/\r
+                       else {\r
+                               u32 offset = 0;\r
+                               u32 box_type=0;\r
+                               u32 box_size=0;\r
+                               const char *cache_name;\r
+\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Downloading init segment and SIDX for representation %s\n", init_url));\r
+\r
+                               /*download first 8 bytes and check if we do have a box starting there*/\r
+                               e = gf_dash_download_resource(group->dash->dash_io, &(group->segment_download), init_url, offset, 7, 1, group);\r
+                               if (e) goto exit;\r
+                               cache_name = group->dash->dash_io->get_cache_name(group->dash->dash_io, group->segment_download);\r
+                               e = dash_load_box_type(cache_name, offset, &box_type, &box_size);\r
+                               offset=8;\r
+                               while (box_type) {\r
+                                       /*we got the moov , stop here */\r
+                                       if (!index_in_base && (box_type==GF_4CC('m','o','o','v'))) {\r
+                                               e = gf_dash_download_resource(group->dash->dash_io, &(group->segment_download), init_url, offset, offset+box_size-8, 2, group);\r
+                                               break;\r
+                                       } else {\r
+                                               e = gf_dash_download_resource(group->dash->dash_io, &(group->segment_download), init_url, offset, offset+box_size-1, 2, group);\r
+                                               offset += box_size;\r
+                                               /*we need to refresh the cache name because of our memory astorage thing ...*/\r
+                                               cache_name = group->dash->dash_io->get_cache_name(group->dash->dash_io, group->segment_download);\r
+                                               e = dash_load_box_type(cache_name, offset-8, &box_type, &box_size);\r
+\r
+                                               if (box_type==GF_4CC('s','i','d','x'))\r
+                                                       has_seen_sidx = 1;\r
+                                               else if (has_seen_sidx)\r
+                                                       break;\r
+       \r
+       \r
+                                       }\r
+                               }\r
+                               if (e<0) goto exit;\r
+\r
+                               if (box_type==0) {\r
+                                       e = GF_ISOM_INVALID_FILE;\r
+                                       goto exit;\r
+                               }\r
+                               GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Done downloading init segment and SIDX\n"));\r
+\r
+                               GF_SAFEALLOC(rep->segment_list, GF_MPD_SegmentList);\r
+                               rep->segment_list->segment_URLs  =gf_list_new();\r
+\r
+                               cache_name = group->dash->dash_io->get_cache_name(group->dash->dash_io, group->segment_download);\r
+                               if (init_in_base) {\r
+                                       GF_SAFEALLOC(rep->segment_list->initialization_segment, GF_MPD_URL);\r
+                                       rep->segment_list->initialization_segment->sourceURL = gf_strdup(cache_name);\r
+                               }\r
+                               if (index_in_base) {\r
+                                       sidx_file = (char *)cache_name;\r
+                               }\r
+                       }\r
+               }\r
+               /*we have index url, download it*/\r
+               if (! index_in_base) {\r
+                       e = gf_dash_download_resource(group->dash->dash_io, &(group->segment_download), index_url, index_start_range, index_end_range, 1, group);\r
+                       if (e) goto exit;\r
+                       sidx_file = (char *)group->dash->dash_io->get_cache_name(group->dash->dash_io, group->segment_download);\r
+               }\r
+\r
+               /*load sidx*/\r
+               e = gf_dash_load_representation_sidx(group, rep, sidx_file, !index_in_base, init_needs_byte_range);\r
+               if (e) {\r
+                       rep->playback.disabled = 1;\r
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to load segment index for this representation - disabling\n"));\r
+               }\r
+\r
+               /*reset all seg based stuff*/\r
+               if (rep->segment_base) { \r
+                       gf_mpd_segment_base_free(rep->segment_base);\r
+                       rep->segment_base = NULL;\r
+               }\r
+\r
+               gf_free(index_url);\r
+               index_url = NULL;\r
+               gf_free(init_url);\r
+               init_url = NULL;\r
+       }\r
+       if (group->adaptation_set->segment_base) { \r
+               gf_mpd_segment_base_free(group->adaptation_set->segment_base);\r
+               group->adaptation_set->segment_base = NULL;\r
+       }\r
+       group->was_segment_base = 1;\r
+\r
+exit:\r
+       if (init_url) gf_free(init_url);\r
+       if (index_url) gf_free(index_url);\r
+       return e;\r
+}\r
+\r
 static GF_Err gf_dash_setup_period(GF_DashClient *dash)\r
 {\r
+       GF_MPD_Period *period;\r
        u32 rep_i, group_i, nb_groups_ok;\r
-\r
        /*setup all groups*/\r
        gf_dash_setup_groups(dash);\r
 \r
@@ -1930,6 +2301,7 @@ static GF_Err gf_dash_setup_period(GF_DashClient *dash)
                GF_MPD_Representation *rep_sel;\r
                u32 active_rep, nb_rep;\r
                const char *mime_type;\r
+               u32 nb_rep_ok = 0;\r
                GF_DASH_Group *group = gf_list_get(dash->groups, group_i);\r
 \r
                nb_rep = gf_list_count(group->adaptation_set->representations);\r
@@ -1943,6 +2315,9 @@ static GF_Err gf_dash_setup_period(GF_DashClient *dash)
                        continue;\r
                }\r
 \r
+               /*translate from single-indexed file to SegmentList*/\r
+               gf_dash_setup_single_index_mode(group);\r
+\r
                /* Select the appropriate representation in the given period */\r
                active_rep = 0;\r
                for (rep_i = 0; rep_i < nb_rep; rep_i++) {\r
@@ -1952,7 +2327,8 @@ static GF_Err gf_dash_setup_period(GF_DashClient *dash)
                        if (rep_i) {\r
                                Bool ok;\r
                                char *sep;\r
-                               if ( !rep->codecs || !rep_sel->codecs ) continue;\r
+                               if ( !rep->codecs || !rep_sel->codecs) continue;\r
+\r
                                sep = strchr(rep_sel->codecs, '.');\r
                                if (sep) sep[0] = 0;\r
                                ok = !strnicmp(rep->codecs, rep_sel->codecs, strlen(rep_sel->codecs) );\r
@@ -1986,10 +2362,11 @@ static GF_Err gf_dash_setup_period(GF_DashClient *dash)
                                }\r
                                break;\r
                        case GF_DASH_SELECT_QUALITY_HIGHEST:\r
+                               /*fallthrough if quality is not indicated*/\r
                                if (rep->quality_ranking > rep_sel->quality_ranking) {\r
                                        active_rep = rep_i;\r
                                        break;\r
-                               }/*fallthrough if quality is not indicated*/\r
+                               }\r
                        case GF_DASH_SELECT_BANDWIDTH_HIGHEST:\r
                                if (rep->bandwidth > rep_sel->bandwidth) {\r
                                        active_rep = rep_i;\r
@@ -1999,8 +2376,20 @@ static GF_Err gf_dash_setup_period(GF_DashClient *dash)
                                break;\r
                        }\r
                }\r
+               for (rep_i = 0; rep_i < nb_rep; rep_i++) {\r
+                       GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_i);\r
+                       if (!rep->playback.disabled) \r
+                               nb_rep_ok++;\r
+               }\r
+\r
+               if (! nb_rep_ok) {\r
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] No valid representation in this group - disabling\n"));\r
+                       group->selection = GF_DASH_GROUP_NOT_SELECTABLE;\r
+                       continue;\r
+               }\r
 \r
                rep_sel = gf_list_get(group->adaptation_set->representations, active_rep);\r
+\r
                gf_dash_set_group_representation(group, rep_sel);\r
 \r
                if (dash->playback_start_range>=0) \r
@@ -2026,6 +2415,14 @@ static GF_Err gf_dash_setup_period(GF_DashClient *dash)
                group->selection = GF_DASH_GROUP_NOT_SELECTED;\r
                nb_groups_ok++;\r
        }\r
+\r
+       period = gf_list_get(dash->mpd->periods, dash->active_period_index);\r
+       \r
+       if (period->segment_base) { \r
+               gf_mpd_segment_base_free(period->segment_base);\r
+               period->segment_base = NULL;\r
+       }\r
+\r
        if (!nb_groups_ok) {\r
                GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] No AdaptationSet could be selected in the MPD - Cannot play\n"));\r
                return GF_NON_COMPLIANT_BITSTREAM;\r
@@ -2059,6 +2456,14 @@ restart_period:
 \r
        dash->in_period_setup = 1;\r
 \r
+       /*setup period*/\r
+       e = gf_dash_setup_period(dash);\r
+       if (e) {\r
+               dash->dash_io->on_dash_event(dash->dash_io, GF_DASH_EVENT_PERIOD_SETUP_ERROR, e);\r
+               ret = 1;\r
+               goto exit;\r
+       }\r
+\r
        dash->dash_io->on_dash_event(dash->dash_io, GF_DASH_EVENT_SELECT_GROUPS, GF_OK);\r
 \r
        e = GF_OK;\r
@@ -2108,9 +2513,8 @@ restart_period:
                /*wait until next segment is needed*/\r
                while (!dash->mpd_stop_request) {\r
                        u32 timer = gf_sys_clock() - dash->last_update_time;\r
-                       Bool shouldParsePlaylist = dash->mpd->minimum_update_period && (timer > dash->mpd->minimum_update_period); \r
 \r
-                       if (shouldParsePlaylist) {\r
+                       if (dash->mpd->minimum_update_period && (timer > dash->mpd->minimum_update_period)) {\r
                                GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Time to update the playlist (%u ms ellapsed since last refresh and min reoad rate is %u)\n", timer, dash->mpd->minimum_update_period));\r
                                e = gf_dash_update_manifest(dash);\r
                                group_count = gf_list_count(dash->groups);\r
@@ -2140,13 +2544,12 @@ restart_period:
                                        if (dash->request_period_switch == 1) \r
                                                dash->active_period_index++;\r
 \r
-                                       gf_dash_setup_period(dash);\r
                                        dash->request_period_switch = 0;\r
 \r
                                        goto restart_period;\r
                                }\r
 \r
-                               gf_sleep(16);\r
+                               gf_sleep(30);\r
                        }\r
                }\r
 \r
@@ -2178,8 +2581,16 @@ restart_period:
                        we need to check if a new playlist is ready */\r
                        if (group->nb_segments_in_rep && (group->download_segment_index>=group->nb_segments_in_rep)) {\r
                                u32 timer = gf_sys_clock() - dash->last_update_time;\r
+                               Bool update_playlist = 0;\r
                                /* update of the playlist, only if indicated */\r
-                               if (dash->mpd->minimum_update_period && timer > dash->mpd->minimum_update_period) {\r
+                               if (dash->mpd->minimum_update_period && (timer > dash->mpd->minimum_update_period)) {\r
+                                       update_playlist = 1;\r
+                               }\r
+                               /* if media_presentation_duration is 0 and we are in live, force a refresh (not in the spec but safety check*/\r
+                               else if ((dash->mpd->type==GF_MPD_TYPE_DYNAMIC) && !dash->mpd->media_presentation_duration) {\r
+                                       update_playlist = 1;\r
+                               }\r
+                               if (update_playlist) {\r
                                        GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Last segment in current playlist downloaded, checking updates after %u ms\n", timer));\r
                                        e = gf_dash_update_manifest(dash);\r
                                        if (e) {\r
@@ -2192,8 +2603,8 @@ restart_period:
                                }\r
                                /* Now that the playlist is up to date, we can check again */\r
                                if (group->download_segment_index >= group->nb_segments_in_rep) {\r
-                                       if (dash->mpd->minimum_update_period) {\r
-                                               /* if there is a specified update period, we redo the whole process */\r
+                                       /* if there is a specified update period, we redo the whole process */\r
+                                       if (dash->mpd->minimum_update_period ) {\r
                                                continue;\r
                                        } else {\r
                                                /* if not, we are really at the end of the playlist, we can quit */\r
@@ -2205,10 +2616,16 @@ restart_period:
                        }\r
                        gf_mx_p(dash->dl_mutex);\r
 \r
-                       /*todo for live - check we don't attempt to request segments before their availabilityStartTime !*/\r
+                       if (group->force_switch_bandwidth && !dash->auto_switch_count) {\r
+                               gf_dash_switch_group_representation(dash, group);\r
+                               /*restart*/\r
+                               i--;\r
+                               gf_mx_v(dash->dl_mutex);\r
+                               continue;\r
+                       }\r
 \r
                        /* At this stage, there are some segments left to be downloaded */\r
-                       e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_MEDIA, group->download_segment_index, &new_base_seg_url, &start_range, &end_range, &group->current_downloaded_segment_duration);\r
+                       e = gf_dash_resolve_url(dash->mpd, rep, group, dash->base_url, GF_DASH_RESOLVE_URL_MEDIA, group->download_segment_index, &new_base_seg_url, &start_range, &end_range, &group->current_downloaded_segment_duration, NULL);\r
                        gf_mx_v(dash->dl_mutex);\r
                        if (e) {\r
                                /*do something!!*/\r
@@ -2221,7 +2638,7 @@ restart_period:
                        }\r
 \r
                        /*local file*/\r
-                       if (!strstr(new_base_seg_url, "://") || !strnicmp(new_base_seg_url, "file://", 7)) {\r
+                       if (!strstr(new_base_seg_url, "://") || (!strnicmp(new_base_seg_url, "file://", 7) || !strnicmp(new_base_seg_url, "gmem://", 7)) ) {\r
                                resource_name = local_file_name = (char *) new_base_seg_url; \r
                                e = GF_OK;\r
                                /*do not erase local files*/\r
@@ -2565,7 +2982,6 @@ GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url)
        GF_Err e;\r
        GF_MPD_Period *period;\r
        GF_DOMParser *mpd_parser;\r
-       Bool is_m3u8 = 0;\r
        Bool is_local = 0;\r
 \r
        if (!dash || !manifest_url) return GF_BAD_PARAM;\r
@@ -2592,7 +3008,7 @@ GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url)
                local_url = manifest_url + 7;\r
                is_local = 1;\r
                if (strstr(manifest_url, ".m3u8")) {\r
-                       is_m3u8 = 1;\r
+                       dash->is_m3u8 = 1;\r
                }\r
        } else if (strstr(manifest_url, "://")) {\r
                const char *reloc_url, *mtype;\r
@@ -2612,7 +3028,7 @@ GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url)
                reloc_url = dash->dash_io->get_url(dash->dash_io, dash->mpd_dnload);\r
                /* Some servers, for instance http://tv.freebox.fr, serve m3u8 as text/plain */\r
                if (gf_dash_is_m3u8_mime(mime) || strstr(reloc_url, ".m3u8") || strstr(reloc_url, ".M3U8")) {\r
-                       is_m3u8 = 1;\r
+                       dash->is_m3u8 = 1;\r
                } else if (!gf_dash_is_dash_mime(mime) && !strstr(reloc_url, ".mpd") && !strstr(reloc_url, ".MPD")) {\r
                        GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] mime '%s' for '%s' should be m3u8 or mpd\n", mime, reloc_url));\r
                        dash->dash_io->del(dash->dash_io, dash->mpd_dnload);\r
@@ -2631,7 +3047,7 @@ GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url)
                local_url = manifest_url;\r
                is_local = 1;\r
                if (strstr(manifest_url, ".m3u8"))\r
-                       is_m3u8 = 1;\r
+                       dash->is_m3u8 = 1;\r
        }\r
 \r
        if (is_local) {\r
@@ -2640,7 +3056,7 @@ GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url)
                fclose(f);\r
        }\r
 \r
-       if (is_m3u8) {\r
+       if (dash->is_m3u8) {\r
                if (is_local) {\r
                        char *sep;\r
                        strcpy(local_path, local_url);\r
@@ -2707,11 +3123,8 @@ GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url)
                goto exit;\r
        }\r
 \r
-       e = gf_dash_setup_period(dash);\r
-       if (e) goto exit;\r
-\r
        e = gf_th_run(dash->dash_thread, dash_main_thread_proc, dash);\r
-       gf_sleep(0);\r
+\r
        return e;\r
 exit:\r
        dash->dash_io->del(dash->dash_io, dash->mpd_dnload);\r
@@ -2754,7 +3167,7 @@ GF_DashClient *gf_dash_new(GF_DASHFileIO *dash_io, u32 max_cache_duration_sec, u
 \r
        dash->dash_thread = gf_th_new("MPD Segment Downloader Thread");\r
        dash->dl_mutex = gf_mx_new("MPD Segment Downloader Mutex");\r
-       dash->mimeTypeForM3U8Segments = gf_strdup( M3U8_UNKOWN_MIME_TYPE );\r
+       dash->mimeTypeForM3U8Segments = gf_strdup( "video/mp2t" );\r
 \r
        dash->max_cache_duration = max_cache_duration_sec;\r
 \r
@@ -2823,46 +3236,67 @@ void gf_dash_get_info(GF_DashClient *dash, const char **title, const char **sour
 }\r
 \r
 GF_EXPORT\r
-void gf_dash_switch_quality(GF_DashClient *dash, Bool switch_up)\r
+void gf_dash_switch_quality(GF_DashClient *dash, Bool switch_up, Bool immediate_switch)\r
 {\r
        u32 i;\r
        for (i=0; i<gf_list_count(dash->groups); i++) {\r
-               Bool do_switch = 0;\r
+               u32 switch_to_rep_idx = 0;\r
+               u32 bandwidth, quality, k;\r
+               GF_MPD_Representation *rep, *active_rep;\r
                GF_DASH_Group *group = gf_list_get(dash->groups, i);\r
                u32 current_idx = group->active_rep_index;\r
                if (group->selection != GF_DASH_GROUP_SELECTED) continue;\r
 \r
                if (group->force_representation_idx_plus_one) current_idx = group->force_representation_idx_plus_one - 1;\r
-               if (switch_up) {\r
-                       if (current_idx + 1 < gf_list_count(group->adaptation_set->representations)) {\r
-                               group->force_representation_idx_plus_one = 1 + current_idx+1;\r
-                               do_switch = 1;\r
-                       }\r
-               } else {\r
-                       if (current_idx) {\r
-                               group->force_representation_idx_plus_one = 1 + current_idx - 1;\r
-                               do_switch = 1;\r
+\r
+               active_rep = gf_list_get(group->adaptation_set->representations, current_idx);\r
+               if (!active_rep) continue;\r
+               bandwidth = switch_up ? (u32) -1 : 0;\r
+               quality = switch_up ? (u32) -1 : 0;\r
+\r
+               for (k=0; k<gf_list_count(group->adaptation_set->representations); k++) {\r
+                       rep = gf_list_get(group->adaptation_set->representations, k);\r
+                       if (switch_up) {\r
+                               if ((rep->quality_ranking>active_rep->quality_ranking) || (rep->bandwidth>active_rep->bandwidth)) {\r
+                                       if ((rep->quality_ranking < quality) || (rep->bandwidth < bandwidth)) {\r
+                                               bandwidth = rep->bandwidth;\r
+                                               quality = rep->quality_ranking;\r
+                                               switch_to_rep_idx = k+1;\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               if ((rep->quality_ranking < active_rep->quality_ranking) || (rep->bandwidth < active_rep->bandwidth)) {\r
+                                       if ((rep->quality_ranking > quality) || (rep->bandwidth > bandwidth)) {\r
+                                               bandwidth = rep->bandwidth;\r
+                                               quality = rep->quality_ranking;\r
+                                               switch_to_rep_idx = k+1;\r
+                                       }\r
+                               }\r
                        }\r
                }\r
-               if (do_switch) {\r
+               if (switch_to_rep_idx && (switch_to_rep_idx-1 != current_idx) ) {\r
                        gf_mx_p(dash->dl_mutex);\r
                        group->force_switch_bandwidth = 1;\r
-                       /*in local playback just switch at the end of the current segment\r
-                       for remote, we should let the user decide*/\r
-                       while (group->nb_cached_segments>1) {\r
-                               group->nb_cached_segments--;\r
-                               gf_free(group->cached[group->nb_cached_segments].url);\r
-                               group->cached[group->nb_cached_segments].url = NULL;\r
-                               if (!group->local_files && group->cached[group->nb_cached_segments].cache) {\r
-                                       gf_delete_file( group->cached[group->nb_cached_segments].cache );\r
-                                       gf_free(group->cached[group->nb_cached_segments].cache);\r
-                                       group->cached[group->nb_cached_segments].cache = NULL;\r
+                       group->force_representation_idx_plus_one = switch_to_rep_idx;\r
+\r
+                       if (group->local_files || immediate_switch) {\r
+                               /*in local playback just switch at the end of the current segment\r
+                               for remote, we should let the user decide*/\r
+                               while (group->nb_cached_segments>1) {\r
+                                       group->nb_cached_segments--;\r
+                                       gf_free(group->cached[group->nb_cached_segments].url);\r
+                                       group->cached[group->nb_cached_segments].url = NULL;\r
+                                       if (!group->local_files && group->cached[group->nb_cached_segments].cache) {\r
+                                               gf_delete_file( group->cached[group->nb_cached_segments].cache );\r
+                                               gf_free(group->cached[group->nb_cached_segments].cache);\r
+                                               group->cached[group->nb_cached_segments].cache = NULL;\r
+                                       }\r
+                                       group->cached[group->nb_cached_segments].representation_index = 0;\r
+                                       group->cached[group->nb_cached_segments].start_range = 0;\r
+                                       group->cached[group->nb_cached_segments].end_range = 0;\r
+                                       if (group->download_segment_index>1)\r
+                                               group->download_segment_index--;\r
                                }\r
-                               group->cached[group->nb_cached_segments].representation_index = 0;\r
-                               group->cached[group->nb_cached_segments].start_range = 0;\r
-                               group->cached[group->nb_cached_segments].end_range = 0;\r
-                               assert(group->download_segment_index>1);\r
-                               group->download_segment_index--;\r
                        }\r
                        gf_mx_v(dash->dl_mutex);\r
                }\r
@@ -3075,7 +3509,7 @@ GF_Err gf_dash_group_get_presentation_time_offset(GF_DashClient *dash, u32 idx,
 }\r
 \r
 GF_EXPORT\r
-GF_Err gf_dash_group_get_next_segment_location(GF_DashClient *dash, u32 idx, const char **url, u64 *start_range, u64 *end_range, const char **switching_url, u64 *switching_start_range, u64 *switching_end_range, const char **original_url)\r
+GF_Err gf_dash_group_get_next_segment_location(GF_DashClient *dash, u32 idx, const char **url, u64 *start_range, u64 *end_range, s32 *switching_index, const char **switching_url, u64 *switching_start_range, u64 *switching_end_range, const char **original_url)\r
 {\r
        GF_DASH_Group *group;\r
 \r
@@ -3086,6 +3520,7 @@ GF_Err gf_dash_group_get_next_segment_location(GF_DashClient *dash, u32 idx, con
        if (switching_start_range) *switching_start_range = 0;\r
        if (switching_end_range) *switching_end_range = 0;\r
        if (original_url) *original_url = NULL;\r
+       if (switching_index) *switching_index = -1;\r
 \r
        gf_mx_p(dash->dl_mutex);        \r
        group = gf_list_get(dash->groups, idx);\r
@@ -3102,6 +3537,8 @@ GF_Err gf_dash_group_get_next_segment_location(GF_DashClient *dash, u32 idx, con
 \r
        if (group->cached[0].representation_index != group->prev_active_rep_index) {\r
                GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->cached[0].representation_index);\r
+               if (switching_index)\r
+                       *switching_index = group->cached[0].representation_index;\r
                if (switching_start_range)\r
                        *switching_start_range = rep->playback.init_start_range;\r
                if (switching_end_range)\r
@@ -3149,5 +3586,35 @@ Double gf_dash_group_current_segment_start_time(GF_DashClient *dash, u32 idx)
        return gf_dash_get_segment_start_time(group);\r
 }\r
 \r
+GF_EXPORT\r
+GF_Err gf_dash_group_get_video_info(GF_DashClient *dash, u32 idx, u32 *max_width, u32 *max_height)\r
+{\r
+       GF_DASH_Group *group = gf_list_get(dash->groups, idx);\r
+       if (!group || !max_width || !max_height) return GF_BAD_PARAM;\r
+\r
+       *max_width = group->adaptation_set->max_width;\r
+       *max_height = group->adaptation_set->max_height;\r
+       return GF_OK;\r
+}\r
+\r
+GF_EXPORT\r
+GF_Err gf_dash_group_get_representation_info(GF_DashClient *dash, u32 idx, u32 representation_idx, u32 *width, u32 *height, u32 *audio_samplerate, u32 *bandwidth, const char **codecs)\r
+{\r
+       GF_DASH_Group *group = gf_list_get(dash->groups, idx);\r
+       GF_MPD_Representation *rep;\r
+       if (!group) return GF_BAD_PARAM;\r
+       rep = gf_list_get(group->adaptation_set->representations, representation_idx);\r
+       if (!rep) return GF_BAD_PARAM;\r
+\r
+       if (width) *width = rep->width ? rep->width : group->adaptation_set->width;\r
+       if (height) *width = rep->height ? rep->height : group->adaptation_set->height;\r
+       if (codecs) *codecs = rep->codecs ? rep->codecs : group->adaptation_set->codecs;\r
+       if (bandwidth) *bandwidth = rep->bandwidth;\r
+       if (audio_samplerate) *audio_samplerate = rep->samplerate ? rep->samplerate : group->adaptation_set->samplerate;\r
+\r
+       return GF_OK;\r
+}\r
+\r
+\r
 #endif //GPAC_DISABLE_DASH_CLIENT\r
 \r
index f82e72517ade44e22f189f1b24038da79c8a067a..476f2740f30a6f83ad38495794d97fa9528bd70b 100644 (file)
@@ -52,7 +52,7 @@ struct _dash_component
        /*for audio*/\r
        u32 sample_rate, channels;\r
        /*for anything*/\r
-       char szLang[4];\r
+       char szLang[5];\r
 };     \r
 \r
 typedef struct\r
@@ -68,6 +68,7 @@ typedef struct
        s32 time_shift_depth;\r
        Double subduration;\r
        const char *bs_switch_segment_file;\r
+       Bool inband_param_set;\r
 \r
        /*set if seg_rad_name depends on input file name (had %s in it). In this case, SegmentTemplate cannot be used at adaptation set level*/\r
        Bool variable_seg_rad_name;\r
@@ -85,6 +86,7 @@ struct _dash_segment_input
        char *file_name;\r
        char representationID[100];\r
        char periodID[100];\r
+       char role[100];\r
        u32 bandwidth;\r
 \r
        /*if 0, input is disabled*/\r
@@ -100,7 +102,7 @@ struct _dash_segment_input
        /*assigns the different media to the same adaptation set or group than the input_idx one*/\r
        GF_Err (* dasher_input_classify) (GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 input_idx, u32 *current_group_id, u32 *max_sap_type);\r
        GF_Err ( *dasher_get_components_info) (GF_DashSegInput *dash_input, GF_DASHSegmenterOptions *opts);\r
-       GF_Err ( *dasher_create_init_segment) (GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 adaptation_set, char *szInitName, const char *tmpdir, Bool *disable_bs_switching);\r
+       GF_Err ( *dasher_create_init_segment) (GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 adaptation_set, char *szInitName, const char *tmpdir, Bool use_inband_param_set, Bool *disable_bs_switching);\r
        GF_Err ( *dasher_segment_file) (GF_DashSegInput *dash_input, const char *szOutName, GF_DASHSegmenterOptions *opts, Bool first_in_set);\r
 \r
        /*shall be set after call to dasher_input_classify*/\r
@@ -285,6 +287,8 @@ GF_Err gf_media_get_rfc_6381_codec_name(GF_ISOFile *movie, u32 track, char *szCo
 \r
        case GF_ISOM_SUBTYPE_AVC_H264:\r
        case GF_ISOM_SUBTYPE_AVC2_H264:\r
+       case GF_ISOM_SUBTYPE_AVC3_H264:\r
+       case GF_ISOM_SUBTYPE_AVC4_H264:\r
        case GF_ISOM_SUBTYPE_SVC_H264:\r
                avcc = gf_isom_avc_config_get(movie, track, 1);\r
                sps = gf_list_get(avcc->sequenceParameterSets, 0);\r
@@ -315,7 +319,7 @@ typedef struct
        Bool done;\r
        u32 TrackID;\r
        u32 SampleNum, SampleCount;\r
-       u32 FragmentLength;\r
+       u64 FragmentLength;\r
        u32 OriginalTrack;\r
        u32 finalSampleDescriptionIndex;\r
        u32 TimeScale, MediaType, DefaultDuration, InitialTSOffset;\r
@@ -363,7 +367,7 @@ static GF_Err gf_media_isom_segment_file(GF_ISOFile *input, const char *output_f
        GF_ISOFile *output, *bs_switch_segment;\r
        GF_ISOSample *sample, *next;\r
        GF_List *fragmenters;\r
-       u32 MaxFragmentDuration, MaxSegmentDuration, SegmentDuration, maxFragDurationOverSegment;\r
+       u64 MaxFragmentDuration, MaxSegmentDuration, SegmentDuration, maxFragDurationOverSegment;\r
        u32 presentationTimeOffset = 0;\r
        Double segment_start_time, file_duration, period_duration, max_segment_duration;\r
        u32 nb_segments, width, height, sample_rate, nb_channels, sar_w, sar_h, fps_num, fps_denum, startNumber, startNumberRewind;\r
@@ -383,7 +387,8 @@ static GF_Err gf_media_isom_segment_file(GF_ISOFile *input, const char *output_f
        u32 tfref_timescale = 0;\r
        u32 bandwidth = 0;\r
        GF_ISOMTrackFragmenter *tf, *tfref;\r
-       FILE *mpd_segs = NULL;\r
+       GF_BitStream *mpd_bs = NULL;\r
+       char szMPDTempLine[2048];\r
        char SegmentName[GF_MAX_PATH];\r
        char RepSecName[200];\r
        char RepURLsSecName[200];\r
@@ -503,12 +508,12 @@ static GF_Err gf_media_isom_segment_file(GF_ISOFile *input, const char *output_f
                        opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "Bandwidth");\r
                        if (opt) sscanf(opt, "%u", &bandwidth);\r
                }\r
-               mpd_segs = gf_temp_file_new();\r
+               mpd_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);\r
        } else {\r
                output = gf_isom_open(output_file, GF_ISOM_OPEN_WRITE, NULL);\r
                if (!output) return gf_isom_last_error(NULL);\r
        }\r
-       \r
+\r
        nb_sync = 0;\r
        nb_samp = 0;\r
        fragmenters = gf_list_new();\r
@@ -561,6 +566,7 @@ static GF_Err gf_media_isom_segment_file(GF_ISOFile *input, const char *output_f
                if (mtype == GF_ISOM_MEDIA_HINT) continue;\r
 \r
                if (! dash_moov_setup) {\r
+                       u32 avctype;\r
                        e = gf_isom_clone_track(input, i+1, output, 0, &TrackNum);\r
                        if (e) goto err_exit;\r
 \r
@@ -576,6 +582,16 @@ static GF_Err gf_media_isom_segment_file(GF_ISOFile *input, const char *output_f
 \r
                                continue;\r
                        }\r
+                       avctype = gf_isom_get_avc_svc_type(input, i+1, 1);\r
+                       if (avctype==GF_ISOM_AVCTYPE_AVC_ONLY) {\r
+                               /*for AVC we concatenate SPS/PPS*/\r
+                               if (dash_cfg->inband_param_set) \r
+                                       gf_isom_set_nalu_extract_mode(input, i+1, GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG);\r
+                       }\r
+                       else if (avctype > GF_ISOM_AVCTYPE_AVC_ONLY) {\r
+                               /*for SVC we don't want any rewrite of extractors, and we don't concatenate SPS/PPS*/\r
+                               gf_isom_set_nalu_extract_mode(input, i+1, GF_ISOM_NALU_EXTRACT_INSPECT);\r
+                       }\r
                } else {\r
                        TrackNum = gf_isom_get_track_by_id(output, gf_isom_get_track_id(input, i+1));\r
                        count = gf_isom_get_sample_count(input, i+1);\r
@@ -824,7 +840,8 @@ restart_fragmentation_pass:
                for (i=0; i<count; i++) {\r
                        const char *key_name = gf_cfg_get_key_name(dash_cfg->dash_ctx, RepURLsSecName, i);\r
                        opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepURLsSecName, key_name);\r
-                       fprintf(mpd_segs, "     %s\n", opt);    \r
+                       sprintf(szMPDTempLine, "     %s\n", opt);       \r
+                       gf_bs_write_data(mpd_bs, szMPDTempLine, strlen(szMPDTempLine));\r
                }\r
 \r
                opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "NextSegmentIndex");\r
@@ -834,18 +851,21 @@ restart_fragmentation_pass:
                opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "CumulatedDuration");\r
                if (opt) period_duration = atof(opt);\r
 \r
-               sprintf(sKey, "TKID_%d_NextSampleNum", tf->TrackID);\r
-               opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey);\r
-               if (opt) tf->SampleNum = atoi(opt);\r
+               for (i=0; i<gf_list_count(fragmenters); i++) {\r
+                       tf = (GF_ISOMTrackFragmenter *)gf_list_get(fragmenters, i);\r
+                       sprintf(sKey, "TKID_%d_NextSampleNum", tf->TrackID);\r
+                       opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey);\r
+                       if (opt) tf->SampleNum = atoi(opt);\r
 \r
-               sprintf(sKey, "TKID_%d_LastSampleCTS", tf->TrackID);\r
-               opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey);\r
-               if (opt) sscanf(opt, LLU, &tf->last_sample_cts);\r
+                       sprintf(sKey, "TKID_%d_LastSampleCTS", tf->TrackID);\r
+                       opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey);\r
+                       if (opt) sscanf(opt, LLU, &tf->last_sample_cts);\r
 \r
-               sprintf(sKey, "TKID_%d_NextSampleDTS", tf->TrackID);\r
-               opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey);\r
-               if (opt) {\r
-                       sscanf(opt, LLU, &tf->next_sample_dts);\r
+                       sprintf(sKey, "TKID_%d_NextSampleDTS", tf->TrackID);\r
+                       opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey);\r
+                       if (opt) {\r
+                               sscanf(opt, LLU, &tf->next_sample_dts);\r
+                       }\r
                }\r
        }\r
        gf_isom_set_next_moof_number(output, fragment_index);\r
@@ -886,7 +906,8 @@ restart_fragmentation_pass:
 \r
                                        if (!use_url_template) {\r
                                                const char *name = gf_url_get_resource_name(SegmentName);\r
-                                               fprintf(mpd_segs, "     <SegmentURL media=\"%s\"/>\n", name );  \r
+                                               sprintf(szMPDTempLine, "     <SegmentURL media=\"%s\"/>\n", name );     \r
+                                               gf_bs_write_data(mpd_bs, szMPDTempLine, strlen(szMPDTempLine));\r
                                                if (dash_cfg->dash_ctx) {\r
                                                        char szKey[100], szVal[4046];\r
                                                        sprintf(szKey, "UrlInfo%d", cur_seg );\r
@@ -988,11 +1009,11 @@ restart_fragmentation_pass:
 \r
                                if (tf->splitable) {\r
                                        if (tfref==tf) {\r
-                                               u32 frag_dur = (tf->FragmentLength + defaultDuration) * 1000 / tf->TimeScale;\r
+                                               u64 frag_dur = (tf->FragmentLength + defaultDuration) * 1000 / tf->TimeScale;\r
                                                /*if media segment about to be produced is longer than max segment length, force segment split*/\r
                                                if (SegmentDuration + frag_dur > MaxSegmentDuration) {\r
                                                        split_sample_duration = defaultDuration;\r
-                                                       defaultDuration = tf->TimeScale * (MaxSegmentDuration - SegmentDuration) / 1000 - tf->FragmentLength;\r
+                                                       defaultDuration = (u32) (tf->TimeScale * (MaxSegmentDuration - SegmentDuration) / 1000 - tf->FragmentLength);\r
                                                        split_sample_duration -= defaultDuration;\r
                                                }\r
                                        } else if ((tf->last_sample_cts + defaultDuration) * tfref_timescale > tfref->next_sample_dts * tf->TimeScale) {\r
@@ -1083,7 +1104,7 @@ restart_fragmentation_pass:
                                                }\r
                                                else if (split_seg_at_rap) {\r
                                                        u64 next_sap_time;\r
-                                                       u32 frag_dur, next_dur;\r
+                                                       u64 frag_dur, next_dur;\r
                                                        next_dur = gf_isom_get_sample_duration(input, tf->OriginalTrack, tf->SampleNum + 1);\r
                                                        if (!next_dur) next_dur = defaultDuration;\r
                                                        /*duration of fragment if we add this rap*/\r
@@ -1177,7 +1198,7 @@ restart_fragmentation_pass:
                                segment_start_time += SegmentDuration;\r
                                nb_segments++;\r
                                if (max_segment_duration * 1000 <= SegmentDuration) {\r
-                                       max_segment_duration = SegmentDuration;\r
+                                       max_segment_duration = (Double) (s64) SegmentDuration;\r
                                        max_segment_duration /= 1000;\r
                                }\r
                                force_switch_segment=0;\r
@@ -1198,11 +1219,14 @@ restart_fragmentation_pass:
                                                file_size = gf_isom_get_file_size(output);\r
                                                end_range = file_size - 1;\r
                                                if (dash_cfg->single_file_mode!=1) {\r
-                                                       fprintf(mpd_segs, "      <SegmentURL mediaRange=\""LLD"-"LLD"\"", start_range, end_range);      \r
+                                                       sprintf(szMPDTempLine, "      <SegmentURL mediaRange=\""LLD"-"LLD"\"", start_range, end_range); \r
+                                                       gf_bs_write_data(mpd_bs, szMPDTempLine, strlen(szMPDTempLine));\r
                                                        if (idx_start_range || idx_end_range) {\r
-                                                               fprintf(mpd_segs, " indexRange=\""LLD"-"LLD"\"", idx_start_range, idx_end_range);       \r
+                                                               sprintf(szMPDTempLine, " indexRange=\""LLD"-"LLD"\"", idx_start_range, idx_end_range);  \r
+                                                               gf_bs_write_data(mpd_bs, szMPDTempLine, strlen(szMPDTempLine));\r
                                                        }\r
-                                                       fprintf(mpd_segs, "/>\n");      \r
+                                                       gf_bs_write_data(mpd_bs, "/>\n", 3);\r
+\r
                                                        if (dash_cfg->dash_ctx) {\r
                                                                char szKey[100], szVal[4046];\r
                                                                sprintf(szKey, "UrlInfo%d", cur_seg );\r
@@ -1246,14 +1270,12 @@ restart_fragmentation_pass:
        }\r
 \r
        if (dash_cfg) {\r
-               char buffer[1000];\r
-\r
                /*flush last segment*/\r
                if (!switch_segment) {\r
                        u64 idx_start_range, idx_end_range;\r
 \r
                        if (max_segment_duration * 1000 <= SegmentDuration) {\r
-                               max_segment_duration = SegmentDuration;\r
+                               max_segment_duration = (Double) (s64) SegmentDuration;\r
                                max_segment_duration /= 1000;\r
                        }\r
 \r
@@ -1266,11 +1288,13 @@ restart_fragmentation_pass:
                                file_size = gf_isom_get_file_size(output);\r
                                end_range = file_size - 1;\r
                                if (dash_cfg->single_file_mode!=1) {\r
-                                       fprintf(mpd_segs, "     <SegmentURL mediaRange=\""LLD"-"LLD"\"", start_range, end_range);\r
+                                       sprintf(szMPDTempLine, "     <SegmentURL mediaRange=\""LLD"-"LLD"\"", start_range, end_range);\r
+                                       gf_bs_write_data(mpd_bs, szMPDTempLine, strlen(szMPDTempLine));\r
                                        if (idx_start_range || idx_end_range) {\r
-                                               fprintf(mpd_segs, " indexRange=\""LLD"-"LLD"\"", idx_start_range, idx_end_range);\r
+                                               sprintf(szMPDTempLine, " indexRange=\""LLD"-"LLD"\"", idx_start_range, idx_end_range);\r
+                                               gf_bs_write_data(mpd_bs, szMPDTempLine, strlen(szMPDTempLine));\r
                                        }\r
-                                       fprintf(mpd_segs, "/>\n");\r
+                                       gf_bs_write_data(mpd_bs, "/>\n", 3);\r
 \r
                                        if (dash_cfg->dash_ctx) {\r
                                                char szKey[100], szVal[4046];\r
@@ -1405,11 +1429,12 @@ restart_fragmentation_pass:
                                fprintf(dash_cfg->mpd, "/>\n");\r
                        }\r
                }\r
-\r
-               gf_f64_seek(mpd_segs, 0, SEEK_SET);\r
-               while (!feof(mpd_segs)) {\r
-                       u32 r = fread(buffer, 1, 100, mpd_segs);\r
-                       gf_fwrite(buffer, 1, r, dash_cfg->mpd);\r
+               if (mpd_bs) {\r
+                       char *mpd_seg_info = NULL;\r
+                       u32 size;\r
+                       gf_bs_get_content(mpd_bs, &mpd_seg_info, &size);\r
+                       gf_fwrite(mpd_seg_info, 1, size, dash_cfg->mpd);\r
+                       gf_free(mpd_seg_info);\r
                }\r
 \r
                if (!use_url_template && (dash_cfg->single_file_mode!=1)) {\r
@@ -1480,7 +1505,7 @@ err_exit:
        if (!bs_switching_is_output && bs_switch_segment) \r
                gf_isom_delete(bs_switch_segment);\r
        gf_set_progress("ISO File Fragmenting", nb_samp, nb_samp);\r
-       if (mpd_segs) fclose(mpd_segs);\r
+       if (mpd_bs) gf_bs_del(mpd_bs);\r
        return e;\r
 }\r
 \r
@@ -1544,6 +1569,9 @@ static GF_Err dasher_isom_classify_input(GF_DashSegInput *dash_inputs, u32 nb_da
                if (strcmp(dash_inputs[input_idx].szMime, dash_inputs[i].szMime))\r
                        continue;\r
 \r
+               if (strcmp(dash_inputs[input_idx].role, dash_inputs[i].role))\r
+                       continue;\r
+\r
                in = gf_isom_open(dash_inputs[i].file_name, GF_ISOM_OPEN_READ, NULL);\r
 \r
                for (j=0; j<gf_isom_get_track_count(set_file); j++) {\r
@@ -1568,6 +1596,8 @@ static GF_Err dasher_isom_classify_input(GF_DashSegInput *dash_inputs, u32 nb_da
                                || (msub_type==GF_ISOM_SUBTYPE_MPEG4_CRYP) \r
                                || (msub_type==GF_ISOM_SUBTYPE_AVC_H264)\r
                                || (msub_type==GF_ISOM_SUBTYPE_AVC2_H264)\r
+                               || (msub_type==GF_ISOM_SUBTYPE_AVC3_H264)\r
+                               || (msub_type==GF_ISOM_SUBTYPE_AVC4_H264)\r
                                || (msub_type==GF_ISOM_SUBTYPE_SVC_H264)\r
                                || (msub_type==GF_ISOM_SUBTYPE_LSR1)\r
                                ) {\r
@@ -1633,11 +1663,12 @@ static GF_Err dasher_isom_classify_input(GF_DashSegInput *dash_inputs, u32 nb_da
        return GF_OK;\r
 }\r
 \r
-static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 adaptation_set, char *szInitName, const char *tmpdir, Bool *disable_bs_switching)\r
+static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 adaptation_set, char *szInitName, const char *tmpdir, Bool use_inband_param_set, Bool *disable_bs_switching)\r
 {\r
        GF_Err e = GF_OK;\r
        u32 i;\r
        Bool sps_merge_failed = 0;\r
+       Bool use_avc3 = 0;\r
        GF_ISOFile *init_seg = gf_isom_open(szInitName, GF_ISOM_OPEN_WRITE, tmpdir);\r
 \r
        for (i=0; i<nb_dash_inputs; i++) {\r
@@ -1668,21 +1699,28 @@ static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32
 \r
                                /*if not the same sample desc we might need to clone it*/\r
                                if (! gf_isom_is_same_sample_description(in, j+1, 1, init_seg, track, 1)) {\r
-                                       Bool do_merge = 1;\r
+                                       u32 merge_mode = 1;\r
                                        u32 stype1, stype2;\r
                                        stype1 = gf_isom_get_media_subtype(in, j+1, 1);\r
                                        stype2 = gf_isom_get_media_subtype(init_seg, track, 1);\r
-                                       if (stype1 != stype2) do_merge = 0;\r
+                                       if (stype1 != stype2) merge_mode = 0;\r
                                        switch (stype1) {\r
                                                case GF_4CC( 'a', 'v', 'c', '1'):\r
                                                case GF_4CC( 'a', 'v', 'c', '2'):\r
                                                case GF_4CC( 's', 'v', 'c', '1'):\r
+                                                       if (use_avc3) \r
+                                                               merge_mode = 2;\r
+                                                       break;\r
+                                               case GF_4CC( 'a', 'v', 'c', '3'):\r
+                                               case GF_4CC( 'a', 'v', 'c', '4'):\r
+                                                       /*we don't want to clone SPS/PPS since they are already inside the samples*/\r
+                                                       merge_mode = 2;\r
                                                        break;\r
                                                default:\r
-                                                       do_merge = 0;\r
+                                                       merge_mode = 0;\r
                                                        break;\r
                                        }\r
-                                       if (do_merge) {\r
+                                       if (merge_mode==1) {\r
                                                u32 k, l, sps_id1, sps_id2;\r
                                                GF_AVCConfig *avccfg1 = gf_isom_avc_config_get(in, j+1, 1);\r
                                                GF_AVCConfig *avccfg2 = gf_isom_avc_config_get(init_seg, track, 1);\r
@@ -1694,14 +1732,14 @@ static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32
                                                                GF_AVCConfigSlot *slc_orig = gf_list_get(avccfg1->sequenceParameterSets, l);\r
                                                                gf_avc_get_sps_info(slc_orig->data, slc_orig->size, &sps_id2, NULL, NULL, NULL, NULL);\r
                                                                if (sps_id2==sps_id1) {\r
-                                                                       do_merge = 0;\r
+                                                                       merge_mode = 0;\r
                                                                        break;\r
                                                                }\r
                                                        }\r
                                                }\r
 #endif\r
                                                /*no conflicts in SPS ids, merge all SPS in a single sample desc*/\r
-                                               if (do_merge) {\r
+                                               if (merge_mode==1) {\r
                                                        while (gf_list_count(avccfg1->sequenceParameterSets)) {\r
                                                                GF_AVCConfigSlot *slc = gf_list_get(avccfg1->sequenceParameterSets, 0);\r
                                                                gf_list_rem(avccfg1->sequenceParameterSets, 0);\r
@@ -1721,7 +1759,7 @@ static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32
                                        }\r
 \r
                                        /*cannot merge, clone*/\r
-                                       if (!do_merge)\r
+                                       if (merge_mode==0)\r
                                                gf_isom_clone_sample_description(init_seg, track, in, j+1, 1, NULL, NULL, &outDescIndex);\r
                                }\r
                        } else {\r
@@ -1731,6 +1769,18 @@ static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32
 \r
                                gf_isom_clone_track(in, j+1, init_seg, 0, &track);\r
 \r
+                               switch (gf_isom_get_media_subtype(in, j+1, 1)) {\r
+                               case GF_4CC( 'a', 'v', 'c', '1'):\r
+                               case GF_4CC( 'a', 'v', 'c', '2'):\r
+                               case GF_4CC( 's', 'v', 'c', '1'):\r
+                                       if (use_inband_param_set) {\r
+                                               gf_isom_avc_set_inband_config(init_seg, track, 1);\r
+                                               use_avc3 = 1;\r
+                                       }\r
+                                       break;\r
+                               }\r
+\r
+\r
                                gf_isom_get_fragment_defaults(in, j+1, &defaultDuration, &defaultSize, \r
                                                                                &defaultDescriptionIndex, &defaultRandomAccess, \r
                                                                                &defaultPadding, &defaultDegradationPriority);\r
@@ -1740,11 +1790,18 @@ static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32
                                                        defaultSize, (u8) defaultRandomAccess,\r
                                                        defaultPadding, defaultDegradationPriority);\r
                                if (e) break;\r
+\r
+                       }\r
+               }\r
+               if (!i) {\r
+                       if (use_avc3) {\r
+                               gf_isom_set_brand_info(init_seg, GF_4CC('i','s','o','6'), 1);\r
+                       } else {\r
+                               gf_isom_set_brand_info(init_seg, GF_4CC('i','s','o','5'), 1);\r
                        }\r
+                       gf_isom_modify_alternate_brand(init_seg, GF_4CC('d','a','s','h'), 1);\r
                }\r
-               gf_isom_set_brand_info(init_seg, GF_4CC('i','s','o','5'), 1);\r
-               gf_isom_modify_alternate_brand(init_seg, GF_4CC('d','a','s','h'), 1);\r
-               if (i) gf_isom_close(in);\r
+               gf_isom_close(in);\r
        }\r
        if (e) {\r
                GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH]: Couldn't create initialization segment: error %s\n", gf_error_to_string(e) ));\r
@@ -1757,10 +1814,11 @@ static GF_Err dasher_isom_create_init_segment(GF_DashSegInput *dash_inputs, u32
                *disable_bs_switching = 1;\r
                gf_isom_delete(init_seg);\r
                gf_delete_file(szInitName);\r
+               return GF_OK;\r
        } else {\r
-               gf_isom_close(init_seg);\r
+               e = gf_isom_close(init_seg);\r
        }\r
-       return GF_OK;\r
+       return e;\r
 }\r
 \r
 static GF_Err dasher_isom_segment_file(GF_DashSegInput *dash_input, const char *szOutName, GF_DASHSegmenterOptions *dash_cfg, Bool first_in_set)\r
@@ -1772,6 +1830,8 @@ static GF_Err dasher_isom_segment_file(GF_DashSegInput *dash_input, const char *
 }\r
 #endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/\r
 \r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
 static GF_Err dasher_generic_classify_input(GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 input_idx, u32 *current_group_id, u32 *max_sap_type)\r
 {\r
 #ifdef GPAC_DISABLE_MEDIA_IMPORT\r
@@ -1797,6 +1857,9 @@ static GF_Err dasher_generic_classify_input(GF_DashSegInput *dash_inputs, u32 nb
                if (strcmp(dash_inputs[input_idx].szMime, dash_inputs[i].szMime))\r
                        continue;\r
 \r
+               if (strcmp(dash_inputs[input_idx].role, dash_inputs[i].role))\r
+                       continue;\r
+\r
                memset(&probe, 0, sizeof(GF_MediaImporter));\r
                probe.flags = GF_IMPORT_PROBE_ONLY;\r
                probe.in_name = (char *)dash_inputs[i].file_name;\r
@@ -1863,6 +1926,10 @@ static GF_Err dasher_generic_classify_input(GF_DashSegInput *dash_inputs, u32 nb
        return GF_OK;\r
 }\r
 \r
+#endif\r
+\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
 static GF_Err dasher_generic_get_components_info(GF_DashSegInput *input, GF_DASHSegmenterOptions *opts)\r
 {\r
 #ifdef GPAC_DISABLE_MEDIA_IMPORT\r
@@ -1894,6 +1961,8 @@ static GF_Err dasher_generic_get_components_info(GF_DashSegInput *input, GF_DASH
 #endif\r
        return GF_OK;\r
 }\r
+#endif\r
+\r
 \r
 #ifndef GPAC_DISABLE_MPEG2TS\r
 \r
@@ -2445,6 +2514,8 @@ static GF_Err dasher_mp2t_get_components_info(GF_DashSegInput *dash_input, GF_DA
        return GF_OK;\r
 }\r
 \r
+#define NB_TSPCK_IO_BYTES 18800\r
+\r
 static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *szOutName, GF_DASHSegmenterOptions *dash_cfg, Bool first_in_set)\r
 {      \r
        GF_TSSegmenter ts_seg;\r
@@ -2457,8 +2528,7 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
        const char *opt;\r
        u32 i, startNumberRewind;\r
        GF_Err e;\r
-       u64 start, pcr_shift, next_pcr_shift, next_dts;\r
-       Bool store_params=0;\r
+       u64 start, pcr_shift, next_pcr_shift;\r
        Double cumulated_duration = 0;\r
        u32 bandwidth = 0;\r
        u32 segment_index;\r
@@ -2475,17 +2545,23 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
        ts_seg.bandwidth = (u32) (ts_seg.file_size * 8 / dash_input->duration); \r
 \r
        /*create bitstreams*/\r
-       gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_REPINDEX, 1, IdxName, basename, dash_input->representationID, dash_cfg->seg_rad_name, "six", 0, 0, 0);        \r
 \r
        segment_index = 1;\r
        startNumberRewind = 0;\r
-\r
        ts_seg.index_file = NULL;\r
        ts_seg.index_bs = NULL;\r
        if (!dash_cfg->dash_ctx && (dash_cfg->use_url_template != 2)) {\r
 #ifndef GPAC_DISABLE_ISOM_FRAGMENTS\r
                GF_SegmentTypeBox *styp;\r
+\r
+               gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_REPINDEX, 1, IdxName, szOutName, dash_input->representationID, dash_cfg->seg_rad_name, "six", 0, 0, 0);       \r
+\r
                ts_seg.index_file = gf_f64_open(IdxName, "wb");\r
+               if (!ts_seg.index_file) {\r
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: Cannot create index file %s\n", IdxName));\r
+                       e = GF_IO_ERR;\r
+                       goto exit;\r
+               }\r
                ts_seg.index_bs = gf_bs_from_file(ts_seg.index_file, GF_BITSTREAM_WRITE);\r
 \r
                styp = (GF_SegmentTypeBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_STYP);\r
@@ -2500,6 +2576,8 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
 #endif\r
        }\r
 \r
+       gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_REPINDEX, 1, IdxName, basename, dash_input->representationID, dash_cfg->seg_rad_name, "six", 0, 0, 0);        \r
+\r
        ts_seg.PCR_DTS_initial_diff = (u64) -1;\r
        ts_seg.subduration = (u32) (dash_cfg->subduration * 90000);\r
 \r
@@ -2515,10 +2593,11 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                        sscanf(opt, LLU, &offset);\r
 \r
                        while (!feof(ts_seg.src) && !ts_seg.has_seen_pat) {\r
-                               char data[188];\r
-                               u32 size = fread(data, 1, 188, ts_seg.src);\r
-                               if (size<188) break;\r
+                               char data[NB_TSPCK_IO_BYTES];\r
+                               u32 size = fread(data, 1, NB_TSPCK_IO_BYTES, ts_seg.src);\r
                                gf_m2ts_process_data(ts_seg.ts, data, size);\r
+\r
+                               if (size<NB_TSPCK_IO_BYTES) break;\r
                        }\r
                        gf_m2ts_reset_parsers(ts_seg.ts);\r
 \r
@@ -2533,10 +2612,10 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
 \r
        /*index the file*/\r
        while (!feof(ts_seg.src) && !ts_seg.suspend_indexing) {\r
-               char data[188];\r
-               u32 size = fread(data, 1, 188, ts_seg.src);\r
-               if (size<188) break;\r
+               char data[NB_TSPCK_IO_BYTES];\r
+               u32 size = fread(data, 1, NB_TSPCK_IO_BYTES, ts_seg.src);\r
                gf_m2ts_process_data(ts_seg.ts, data, size);\r
+               if (size<NB_TSPCK_IO_BYTES) break;\r
        }\r
        if (feof(ts_seg.src)) ts_seg.suspend_indexing = 0;\r
 \r
@@ -2544,7 +2623,6 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
        if (!ts_seg.suspend_indexing) {\r
                next_pcr_shift = ts_seg.last_DTS + ts_seg.last_frame_duration - ts_seg.PCR_DTS_initial_diff;\r
        }\r
-       next_dts = ts_seg.last_DTS + ts_seg.last_frame_duration;\r
 \r
        /* flush SIDX entry for the last packets */\r
        m2ts_sidx_flush_entry(&ts_seg);\r
@@ -2569,7 +2647,6 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                if (!opt || strcmp(opt, "yes")) {\r
                        gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "Setup", "yes");\r
                        gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "ID", dash_input->representationID);\r
-                       store_params = 1;\r
                } else {\r
                        if (!bandwidth) {\r
                                opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "Bandwidth");\r
@@ -2601,7 +2678,7 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                        gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE, 1, IdxName, basename, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "six", 0, bandwidth, segment_index);\r
                        fprintf(dash_cfg->mpd, " index=\"%s\"", IdxName); \r
                } \r
-               fprintf(dash_cfg->mpd, "/>\n", (u32) (90000*dash_cfg->segment_duration), segment_index, SegName); \r
+               fprintf(dash_cfg->mpd, "/>\n");\r
        }\r
 \r
 \r
@@ -2618,9 +2695,6 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
 \r
                if (dash_input->components[i].sample_rate) \r
                        fprintf(dash_cfg->mpd, " audioSamplingRate=\"%d\"", dash_input->components[i].sample_rate);\r
-\r
-               if (dash_input->components[i].szLang[0]) \r
-                       fprintf(dash_cfg->mpd, " lang=\"%s\"", dash_input->components[i].szLang);\r
        }\r
        if (strlen(szCodecs))\r
                fprintf(dash_cfg->mpd, " codecs=\"%s\"", szCodecs);\r
@@ -2631,14 +2705,14 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
 \r
        if (dash_cfg->single_file_mode==1) {\r
                gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, 1, SegName, basename, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "ts", 0, bandwidth, segment_index);\r
-               fprintf(dash_cfg->mpd, "    <BaseURL>%s</BaseURL>\n", dash_cfg->seg_rad_name ? SegName : dash_input->file_name);\r
+               fprintf(dash_cfg->mpd, "    <BaseURL>%s</BaseURL>\n", SegName);\r
 \r
                fprintf(dash_cfg->mpd, "    <SegmentBase>\n");\r
                fprintf(dash_cfg->mpd, "     <RepresentationIndex sourceURL=\"%s\"/>\n", IdxName);\r
                fprintf(dash_cfg->mpd, "    </SegmentBase>\n");\r
 \r
                /*we rewrite the file*/\r
-               if (dash_cfg->seg_rad_name) rewrite_input = 1;\r
+               rewrite_input = 1;\r
        } else {\r
                if (dash_cfg->seg_rad_name && dash_cfg->use_url_template) {\r
                        if (dash_cfg->variable_seg_rad_name) {\r
@@ -2650,18 +2724,19 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                                }\r
 \r
                                if (dash_cfg->time_shift_depth>=0) \r
-                                       fprintf(dash_cfg->mpd, " presentationTimeOffset=\"%d\"", ts_seg.sidx->earliest_presentation_time + pcr_shift); \r
+                                       fprintf(dash_cfg->mpd, " presentationTimeOffset=\""LLD"\"", ts_seg.sidx->earliest_presentation_time + pcr_shift); \r
                                fprintf(dash_cfg->mpd, "/>\n"); \r
                        } else if (dash_cfg->time_shift_depth>=0) {\r
-                               fprintf(dash_cfg->mpd, "    <SegmentTemplate presentationTimeOffset=\"%d\"/>\n", ts_seg.sidx->earliest_presentation_time + pcr_shift); \r
+                               fprintf(dash_cfg->mpd, "    <SegmentTemplate presentationTimeOffset=\""LLD"\"/>\n", ts_seg.sidx->earliest_presentation_time + pcr_shift); \r
                                GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH]: PTSOffset "LLD" - startNumber %d - time %g\n", ts_seg.sidx->earliest_presentation_time + pcr_shift, segment_index, (Double) (s64) (ts_seg.sidx->earliest_presentation_time + pcr_shift) / 90000.0));\r
                        }\r
                } else {\r
                        gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, 1, SegName, basename, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "ts", 0, bandwidth, segment_index);\r
-                       fprintf(dash_cfg->mpd, "    <BaseURL>%s</BaseURL>\n", dash_cfg->seg_rad_name ? SegName : dash_input->file_name);\r
+                       if (dash_cfg->single_file_mode)\r
+                               fprintf(dash_cfg->mpd, "    <BaseURL>%s</BaseURL>\n",SegName);\r
                        fprintf(dash_cfg->mpd, "    <SegmentList timescale=\"90000\" duration=\"%d\"", (u32) (90000*dash_cfg->segment_duration)); \r
                        if (dash_cfg->time_shift_depth>=0) \r
-                               fprintf(dash_cfg->mpd, " presentationTimeOffset=\"%d\"", ts_seg.sidx->earliest_presentation_time + pcr_shift); \r
+                               fprintf(dash_cfg->mpd, " presentationTimeOffset=\""LLD"\"", ts_seg.sidx->earliest_presentation_time + pcr_shift); \r
                        fprintf(dash_cfg->mpd, ">\n"); \r
 \r
                        if (!dash_cfg->dash_ctx) {\r
@@ -2670,7 +2745,7 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                }\r
 \r
                /*rewrite previous SegmentList entries*/\r
-               if ((dash_cfg->single_file_mode==2) || (!dash_cfg->single_file_mode && !dash_cfg->use_url_template)) {\r
+               if ( dash_cfg->dash_ctx && ((dash_cfg->single_file_mode==2) || (!dash_cfg->single_file_mode && !dash_cfg->use_url_template))) {\r
                        /*rewrite previous URLs*/\r
                        const char *opt;\r
                        u32 count, i;\r
@@ -2690,7 +2765,7 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                                fprintf(dash_cfg->mpd, "     <SegmentURL mediaRange=\""LLD"-"LLD"\"/>\n", start, start+ref->reference_size-1);\r
                                start += ref->reference_size;\r
                        }\r
-                       if (dash_cfg->seg_rad_name) rewrite_input = 1;\r
+                       rewrite_input = 1;\r
 \r
                } else {\r
                        FILE *src, *dst;\r
@@ -2699,15 +2774,21 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                        src = gf_f64_open(dash_input->file_name, "rb");\r
                        start = ts_seg.sidx->first_offset;\r
                        for (i=0; i<ts_seg.sidx->nb_refs; i++) {\r
-                               char buf[4096];\r
+                               char buf[NB_TSPCK_IO_BYTES];\r
                                GF_SIDXReference *ref = &ts_seg.sidx->refs[i];\r
 \r
-                               gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, 1, SegName, basename, dash_input->representationID, dash_cfg->seg_rad_name, "ts", 0, bandwidth, segment_index);\r
+                               gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, 1, SegName, szOutName, dash_input->representationID, dash_cfg->seg_rad_name, "ts", 0, bandwidth, segment_index);\r
 \r
                                /*warning - we may introduce repeated sequence number when concatenating files. We should use switching \r
                                segments to force reset of the continuity counter for all our pids - we don't because most players don't car ...*/\r
                                if (dash_cfg->use_url_template != 2) {\r
                                        dst = gf_f64_open(SegName, "wb");\r
+                                       if (!dst) {\r
+                                               fclose(src);\r
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: Cannot create segment file %s\n", SegName));\r
+                                               e = GF_IO_ERR;\r
+                                               goto exit;\r
+                                       }\r
 \r
                                        gf_dasher_store_segment_info(dash_cfg, SegName, current_time);\r
                                        dur = ref->subsegment_duration;\r
@@ -2719,8 +2800,8 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                                        end = start+ref->reference_size;\r
                                        while (pos<end) {\r
                                                u32 res;\r
-                                               u32 to_read = 3760;\r
-                                               if (pos+3760 >= end) {\r
+                                               u32 to_read = NB_TSPCK_IO_BYTES;\r
+                                               if (pos+NB_TSPCK_IO_BYTES >= end) {\r
                                                        to_read = (u32) (end-pos);\r
                                                }\r
                                                res = fread(buf, 1, to_read, src);\r
@@ -2737,9 +2818,9 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                                        fclose(dst);\r
                                }\r
                                start += ref->reference_size;\r
-                               segment_index++;\r
 \r
                                if (!dash_cfg->use_url_template) {\r
+                                       gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, 1, SegName, basename, dash_input->representationID, dash_cfg->seg_rad_name, "ts", 0, bandwidth, segment_index);\r
                                        fprintf(dash_cfg->mpd, "     <SegmentURL media=\"%s\"/>\n", SegName);\r
 \r
                                        if (dash_cfg->dash_ctx) {\r
@@ -2750,6 +2831,7 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                                        }\r
                                }\r
 \r
+                               segment_index++;\r
                                gf_set_progress("Extracting segment ", i+1, ts_seg.sidx->nb_refs);\r
                        }\r
                        fclose(src);\r
@@ -2762,15 +2844,28 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
 \r
        if (rewrite_input) {\r
                FILE *in, *out;\r
-               char buf[3760];\r
+               u64 fsize, done;\r
+               char buf[NB_TSPCK_IO_BYTES];\r
 \r
-               in = gf_f64_open(dash_input->file_name, "rb");\r
+               gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, 1, SegName, dash_cfg->seg_rad_name ? basename : szOutName, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "ts", 0, bandwidth, segment_index);\r
                out = gf_f64_open(SegName, "wb");\r
+               if (!out) {\r
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: Cannot create segment file %s\n", SegName));\r
+                       e = GF_IO_ERR;\r
+                       goto exit;\r
+               }\r
+               in = gf_f64_open(dash_input->file_name, "rb");\r
+               gf_f64_seek(in, 0, SEEK_END);\r
+               fsize = gf_f64_tell(in);\r
+               gf_f64_seek(in, 0, SEEK_SET);\r
+               done = 0;\r
                while (1) {\r
-                       u32 read = fread(buf, 1, 3760, in);\r
-                       if (!read) break;\r
+                       u32 read = fread(buf, 1, NB_TSPCK_IO_BYTES, in);\r
                        gf_m2ts_restamp(buf, read, pcr_shift, is_pes);\r
                        fwrite(buf, 1, read, out);\r
+                       done+=read;\r
+                       gf_set_progress("Extracting segment ", done/188, fsize/188);\r
+                       if (read<NB_TSPCK_IO_BYTES) break;\r
                }\r
                fclose(in);\r
                fclose(out);\r
@@ -2810,13 +2905,13 @@ static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *
                gf_isom_box_write((GF_Box *)ts_seg.pcrb, ts_seg.index_bs);\r
        }\r
 \r
+exit:\r
        if (ts_seg.sidx) gf_isom_box_del((GF_Box *)ts_seg.sidx);\r
        if (ts_seg.pcrb) gf_isom_box_del((GF_Box *)ts_seg.pcrb);\r
        if (ts_seg.index_file) fclose(ts_seg.index_file);\r
        if (ts_seg.index_bs) gf_bs_del(ts_seg.index_bs);\r
        dasher_del_ts_demux(&ts_seg);\r
-\r
-       return GF_OK;\r
+       return e;\r
 }\r
 \r
 #endif //GPAC_DISABLE_MPEG2TS\r
@@ -2892,7 +2987,7 @@ static GF_Err write_mpd_header(FILE *mpd, const char *mpd_name, GF_Config *dash_
                }\r
                gtime = sec - GF_NTP_SEC_1900_TO_1970;\r
                t = gmtime(&gtime);\r
-               fprintf(mpd, " availabilityStartTime=\"%d-%02d-%02dT%02d:%02d:%02dZ\"", 1900+t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);\r
+               fprintf(mpd, " availabilityStartTime=\"%d-%02d-%02dT%02d:%02d:%02dZ\"", 1900+t->tm_year, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);\r
 #endif\r
 \r
                if ((s32)time_shift_depth>=0) {\r
@@ -3000,8 +3095,6 @@ static GF_Err write_adaptation_header(FILE *mpd, GF_DashProfile profile, Bool us
        \r
        if (first_rep) {\r
                u32 i;\r
-               char langCode[4];\r
-               langCode[3] = 0;\r
 \r
                if (bitstream_switching_mode) {\r
                        for (i=0; i<first_rep->nb_components; i++) {\r
@@ -3011,6 +3104,18 @@ static GF_Err write_adaptation_header(FILE *mpd, GF_DashProfile profile, Bool us
                                }\r
                        }\r
                }\r
+\r
+               /*set role*/\r
+               if (strlen(first_rep->role)) {\r
+                       if (!strcmp(first_rep->role, "caption") || !strcmp(first_rep->role, "subtitle") || !strcmp(first_rep->role, "main")\r
+                                || !strcmp(first_rep->role, "alternate") || !strcmp(first_rep->role, "supplementary") || !strcmp(first_rep->role, "commentary")\r
+                                || !strcmp(first_rep->role, "dub")\r
+                       ) {\r
+                               fprintf(mpd, "   <Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", first_rep->role);\r
+                       }\r
+               }\r
+\r
+\r
                if (first_rep->nb_components>1) {\r
                        for (i=0; i<first_rep->nb_components; i++) {\r
                                struct _dash_component *comp = &first_rep->components[i];\r
@@ -3034,7 +3139,7 @@ static GF_Err write_adaptation_header(FILE *mpd, GF_DashProfile profile, Bool us
                                }\r
                                /*if lang not specified at adaptationSet level, put it here*/\r
                                if ((!szLang || !szLang[0]) && comp->szLang[0]) {\r
-                                       fprintf(mpd, " lang=\"%s\"", langCode);\r
+                                       fprintf(mpd, " lang=\"%s\"", comp->szLang);\r
                                }\r
                                fprintf(mpd, "/>\n");\r
                        }\r
@@ -3049,7 +3154,7 @@ static GF_Err write_adaptation_header(FILE *mpd, GF_DashProfile profile, Bool us
        return GF_OK;\r
 }\r
 \r
-static GF_Err gf_dasher_init_context(GF_Config *dash_ctx, Bool *dynamic, u32 *timeShiftBufferDepth, const char *periodID)\r
+static GF_Err gf_dasher_init_context(GF_Config *dash_ctx, u32 *dynamic, u32 *timeShiftBufferDepth, const char *periodID)\r
 {\r
        const char *opt;\r
        char szVal[100];\r
@@ -3066,11 +3171,13 @@ static GF_Err gf_dasher_init_context(GF_Config *dash_ctx, Bool *dynamic, u32 *ti
        if (!opt) {\r
                first_run = 1;\r
                sprintf(szVal, "%d", *timeShiftBufferDepth);\r
-               gf_cfg_set_key(dash_ctx, "DASH", "SessionType", *dynamic ? "dynamic" : "static");\r
+               gf_cfg_set_key(dash_ctx, "DASH", "SessionType", (*dynamic==2) ? "dynamic-debug" : ( *dynamic ? "dynamic" : "static" ) );\r
                gf_cfg_set_key(dash_ctx, "DASH", "TimeShiftBufferDepth", szVal);\r
                gf_cfg_set_key(dash_ctx, "DASH", "StoreParams", "yes");\r
        } else {\r
-               *dynamic = !strcmp(opt, "dynamic") ? 1 : 0;\r
+               *dynamic = 0;\r
+               if (!strcmp(opt, "dynamic")) *dynamic = 1;\r
+               else if (!strcmp(opt, "dynamic-debug")) *dynamic = 2;\r
                opt = gf_cfg_get_key(dash_ctx, "DASH", "TimeShiftBufferDepth");\r
                *timeShiftBufferDepth = atoi(opt);\r
                gf_cfg_set_key(dash_ctx, "DASH", "StoreParams", "no");\r
@@ -3158,7 +3265,7 @@ u32 gf_dasher_next_update_time(GF_Config *dash_ctx, u32 mpd_update_time)
 }\r
 \r
 /*peform all file cleanup*/\r
-static Bool gf_dasher_cleanup(GF_Config *dash_ctx, Bool dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double dash_duration)\r
+static Bool gf_dasher_cleanup(GF_Config *dash_ctx, u32 dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double dash_duration)\r
 {\r
        Double max_dur = 0;\r
        Double ellapsed = 0;\r
@@ -3187,18 +3294,22 @@ static Bool gf_dasher_cleanup(GF_Config *dash_ctx, Bool dash_dynamic, u32 mpd_up
        if (!max_dur) return 1;\r
        gf_net_get_ntp(&ntp_sec, &frac);\r
 \r
-       ellapsed = ntp_sec;\r
-       ellapsed -= prev_sec;\r
-       /*check if we need to generate */\r
-       if (ellapsed < max_dur - safety_dur ) {\r
-               GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Asked to regenerate segments before expiration of the current segment list, please wait %g seconds - ignoring\n", max_dur + prev_sec - ntp_sec ));\r
-               return 0;\r
-       }\r
-       if (ellapsed > max_dur) {\r
-               GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Generating segments and MPD %g seconds too late\n", ellapsed - (u32) max_dur));\r
+       if (dash_dynamic==2) {\r
+               ellapsed = (u32)-1;\r
        } else {\r
-               /*generate as if max_dur has been reached*/\r
-               ellapsed = max_dur;\r
+               ellapsed = ntp_sec;\r
+               ellapsed -= prev_sec;\r
+               /*check if we need to generate */\r
+               if (ellapsed < max_dur - safety_dur ) {\r
+                       GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Asked to regenerate segments before expiration of the current segment list, please wait %g seconds - ignoring\n", max_dur + prev_sec - ntp_sec ));\r
+                       return 0;\r
+               }\r
+               if (ellapsed > max_dur) {\r
+                       GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Generating segments and MPD %g seconds too late\n", ellapsed - (u32) max_dur));\r
+               } else {\r
+                       /*generate as if max_dur has been reached*/\r
+                       ellapsed = max_dur;\r
+               }\r
        }\r
 \r
        /*cleanup old segments*/\r
@@ -3252,10 +3363,10 @@ GF_EXPORT
 GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *inputs, u32 nb_dash_inputs, GF_DashProfile dash_profile, \r
                                                           const char *mpd_title, const char *mpd_source, const char *mpd_copyright,\r
                                                           const char *mpd_moreInfoURL, const char **mpd_base_urls, u32 nb_mpd_base_urls, \r
-                                                          Bool use_url_template, Bool single_segment, Bool single_file, Bool bitstream_switching_mode\r
+                                                          Bool use_url_template, Bool single_segment, Bool single_file, GF_DashSwitchingMode bitstream_switching\r
                                                           Bool seg_at_rap, Double dash_duration, char *seg_name, char *seg_ext,\r
                                                           Double frag_duration, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool frag_at_rap, const char *tmpdir,\r
-                                                          GF_Config *dash_ctx, Bool dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double subduration)\r
+                                                          GF_Config *dash_ctx, u32 dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double subduration)\r
 {\r
        u32 i, j, segment_mode;\r
        char *sep, szSegName[GF_MAX_PATH], szSolvedSegName[GF_MAX_PATH], szTempMPD[GF_MAX_PATH];\r
@@ -3267,6 +3378,7 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
        u32 max_sap_type = 0;\r
        Bool none_supported = 1;\r
        Bool has_mpeg2 = 0;\r
+       Bool has_role = 0;\r
        Double presentation_duration = 0;\r
        GF_Err e = GF_OK;\r
        FILE *mpd = NULL;\r
@@ -3284,7 +3396,6 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                        if (opt) {\r
                                Double seg_dur = atof(opt);\r
                                if (seg_dur != dash_duration) {\r
-                                       gf_cfg_del(dash_ctx);\r
                                        return GF_NOT_SUPPORTED;\r
                                }\r
                        } else {\r
@@ -3307,8 +3418,12 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                dash_inputs[i].file_name = inputs[i].file_name;\r
                strcpy(dash_inputs[i].representationID, inputs[i].representationID);\r
                strcpy(dash_inputs[i].periodID, inputs[i].periodID);\r
+               strcpy(dash_inputs[i].role, inputs[i].role);\r
                dash_inputs[i].bandwidth = inputs[i].bandwidth;\r
 \r
+               if (strlen(inputs[i].role) && strcmp(inputs[i].role, "main"))\r
+                       has_role = 1;\r
+\r
                if (!strlen(dash_inputs[i].periodID)) {\r
                        max_period = 1;\r
                        dash_inputs[i].period = 1;\r
@@ -3322,6 +3437,14 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
        }\r
        memset(&dash_opts, 0, sizeof(GF_DASHSegmenterOptions));\r
 \r
+       /*set all default roles to main if needed*/\r
+       if (has_role) {\r
+               for (i=0; i<nb_dash_inputs; i++) {\r
+                       if (!strlen(dash_inputs[i].role))\r
+                               strcpy(dash_inputs[i].role, "main");\r
+               }\r
+       }\r
+\r
        for (i=0; i<nb_dash_inputs; i++) {\r
                if (dash_inputs[i].period) \r
                        continue;\r
@@ -3368,7 +3491,6 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                }\r
        }\r
 \r
-\r
        /*check requested profiles can be generated, or adjust them*/\r
        if (max_sap_type>=3) {\r
                if (dash_profile) {\r
@@ -3390,7 +3512,6 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                }\r
        }\r
 \r
-\r
        /*adjust params based on profiles*/\r
        switch (dash_profile) {\r
        case GF_DASH_PROFILE_LIVE:\r
@@ -3402,7 +3523,7 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                seg_at_rap = 1;\r
                single_segment = 1;\r
                /*BS switching is meaningless in onDemand profile*/\r
-               bitstream_switching_mode = 0;\r
+               bitstream_switching = GF_DASH_BSMODE_NONE;\r
                use_url_template = single_file = 0;\r
                break;\r
        case GF_DASH_PROFILE_MAIN:\r
@@ -3437,7 +3558,6 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("Spliting segments %sat GOP boundaries\n", frag_at_rap ? "and fragments " : ""));\r
        }\r
 \r
-\r
        dash_opts.mpd_name = mpdfile;\r
        dash_opts.segments_start_with_rap = seg_at_rap;\r
        dash_opts.segment_duration = dash_duration;\r
@@ -3452,6 +3572,7 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
        dash_opts.dash_ctx = dash_ctx;\r
        dash_opts.time_shift_depth = (s32) time_shift_depth;\r
        dash_opts.subduration = subduration;\r
+       dash_opts.inband_param_set = ((bitstream_switching == GF_DASH_BSMODE_INBAND) || (bitstream_switching == GF_DASH_BSMODE_SINGLE) ) ? 1 : 0;\r
 \r
        for (cur_period=0; cur_period<max_period; cur_period++) {\r
                u32 first_in_period = 0;\r
@@ -3516,7 +3637,7 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                        u32 max_height = 0;\r
                        u32 fps_num = 0;\r
                        u32 fps_denum = 0;\r
-                       Bool use_bs_switching = bitstream_switching_mode ? 1 : 0;\r
+                       Bool use_bs_switching = bitstream_switching ? 1 : 0;\r
                        char szLang[4];\r
                        char szFPS[100];\r
                        Bool is_first_rep=0;\r
@@ -3539,7 +3660,8 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
                        } else {\r
                                sprintf(szInit, "%s_set%d_init.mp4", tmp, cur_adaptation_set+1);\r
                        }\r
-                       if ((bitstream_switching_mode==1) && dash_inputs[first_rep_in_set].nb_rep_in_adaptation_set==1)\r
+                       /*unless asked to do BS switching on single rep, don't do it ...*/\r
+                       if ((bitstream_switching < GF_DASH_BSMODE_SINGLE) && dash_inputs[first_rep_in_set].nb_rep_in_adaptation_set==1)\r
                                use_bs_switching = 0;\r
 \r
                        if (! use_bs_switching) {\r
@@ -3561,7 +3683,7 @@ GF_Err gf_dasher_segment_files(const char *mpdfile, GF_DashSegmenterInput *input
 \r
                        if (!skip_init_segment_creation) {\r
                                Bool disable_bs_switching = 0;\r
-                               e = dash_inputs[first_rep_in_set].dasher_create_init_segment(dash_inputs, nb_dash_inputs, cur_adaptation_set+1, szInit, tmpdir, &disable_bs_switching);\r
+                               e = dash_inputs[first_rep_in_set].dasher_create_init_segment(dash_inputs, nb_dash_inputs, cur_adaptation_set+1, szInit, tmpdir, dash_opts.inband_param_set, &disable_bs_switching);\r
                                if (e) goto exit;\r
                                if (disable_bs_switching)\r
                                        use_bs_switching = 0;\r
index e3072e88251191fdd38149b5d4aeeeea41b17d0d..cc1c4375197467c31550fe5e65c90672785fcdc5 100644 (file)
@@ -460,6 +460,8 @@ GF_ISOMRTPStreamer *gf_isom_streamer_new(const char *file_name, const char *ip_d
                        break;
                case GF_ISOM_SUBTYPE_AVC_H264:
                case GF_ISOM_SUBTYPE_AVC2_H264:
+               case GF_ISOM_SUBTYPE_AVC3_H264:
+               case GF_ISOM_SUBTYPE_AVC4_H264:
                case GF_ISOM_SUBTYPE_SVC_H264:
                {
                        GF_AVCConfig *avcc = gf_isom_avc_config_get(streamer->isom, track->track_num, 1);
index 05ebaee38c4e7018cf6bbb8a57011722f08e6486..253a53a718140a0d34bbcd639d791a434c8f4a52 100644 (file)
@@ -444,16 +444,20 @@ GF_RTPHinter *gf_hinter_track_new(GF_ISOFile *file, u32 TrackNum,
                        break;
                case GF_ISOM_SUBTYPE_AVC_H264:
                case GF_ISOM_SUBTYPE_AVC2_H264:
+               case GF_ISOM_SUBTYPE_AVC3_H264:
+               case GF_ISOM_SUBTYPE_AVC4_H264:
                case GF_ISOM_SUBTYPE_SVC_H264:
                {
                        GF_AVCConfig *avcc = gf_isom_avc_config_get(file, TrackNum, 1);
+                       GF_AVCConfig *svcc = gf_isom_svc_config_get(file, TrackNum, 1);
                        required_rate = 90000;  /* "90 kHz clock rate MUST be used"*/
                        hintType = GF_RTP_PAYT_H264_AVC;
                        streamType = GF_STREAM_VISUAL;
-                       avc_nalu_size = avcc->nal_unit_size;
+                       avc_nalu_size = avcc ? avcc->nal_unit_size : svcc->nal_unit_size;
                        oti = GPAC_OTI_VIDEO_AVC;
                        PL_ID = 0x0F;
                        gf_odf_avc_cfg_del(avcc);
+                       gf_odf_avc_cfg_del(svcc);
                }
                        break;
                case GF_ISOM_SUBTYPE_3GP_QCELP:
@@ -755,7 +759,51 @@ GF_Err gf_hinter_track_process(GF_RTPHinter *tkHint)
        return GF_OK;
 }
 
+static u32 write_nalu_config_array(char *sdpLine, GF_List *nalus)
+{
+       u32 i, count, b64s;
+       char b64[200];
+
+       count = gf_list_count(nalus);
+       for (i=0; i<count; i++) {
+               GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(nalus, i);
+               b64s = gf_base64_encode(sl->data, sl->size, b64, 200);
+               b64[b64s]=0;
+               strcat(sdpLine, b64);
+               if (i+1<count) strcat(sdpLine, ",");
+       }
+       return count;
+}
 
+static void write_avc_config(char *sdpLine, GF_AVCConfig *avcc, GF_AVCConfig *svcc)
+{
+       u32 count = 0;
+
+       if (avcc) count += gf_list_count(avcc->sequenceParameterSets) + gf_list_count(avcc->pictureParameterSets) + gf_list_count(avcc->sequenceParameterSetExtensions);
+       if (svcc) count += gf_list_count(svcc->sequenceParameterSets) + gf_list_count(svcc->pictureParameterSets);
+       if (!count) return;
+
+       strcat(sdpLine, "; sprop-parameter-sets=");
+
+       if (avcc) {
+               count = write_nalu_config_array(sdpLine, avcc->sequenceParameterSets);
+               if (count) strcat(sdpLine, ",");
+               count = write_nalu_config_array(sdpLine, avcc->sequenceParameterSetExtensions);
+               if (count) strcat(sdpLine, ",");
+               count = write_nalu_config_array(sdpLine, avcc->pictureParameterSets);
+               if (count) strcat(sdpLine, ",");
+       }
+               
+       if (svcc) {
+               count = write_nalu_config_array(sdpLine, svcc->sequenceParameterSets);
+               if (count) strcat(sdpLine, ",");
+               count = write_nalu_config_array(sdpLine, svcc->pictureParameterSets);
+               if (count) strcat(sdpLine, ",");
+       }
+       count = strlen(sdpLine);
+       if (sdpLine[count-1] == ',')
+               sdpLine[count-1] = 0;
+}
 
 GF_EXPORT
 GF_Err gf_hinter_track_finalize(GF_RTPHinter *tkHint, Bool AddSystemInfo)
@@ -817,31 +865,20 @@ GF_Err gf_hinter_track_finalize(GF_RTPHinter *tkHint, Bool AddSystemInfo)
        /*H264/AVC*/
        else if (tkHint->rtp_p->rtp_payt == GF_RTP_PAYT_H264_AVC) {
                GF_AVCConfig *avcc = gf_isom_avc_config_get(tkHint->file, tkHint->TrackNum, 1);
-               sprintf(sdpLine, "a=fmtp:%d profile-level-id=%02X%02X%02X; packetization-mode=1", tkHint->rtp_p->PayloadType, avcc->AVCProfileIndication, avcc->profile_compatibility, avcc->AVCLevelIndication);
-               if (gf_list_count(avcc->pictureParameterSets) || gf_list_count(avcc->sequenceParameterSets)) {
-                       u32 i, count, b64s;
-                       char b64[200];
-                       strcat(sdpLine, "; sprop-parameter-sets=");
-                       count = gf_list_count(avcc->sequenceParameterSets);
-                       for (i=0; i<count; i++) {
-                               GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(avcc->sequenceParameterSets, i);
-                               b64s = gf_base64_encode(sl->data, sl->size, b64, 200);
-                               b64[b64s]=0;
-                               strcat(sdpLine, b64);
-                               if (i+1<count) strcat(sdpLine, ",");
-                       }
-                       if (i) strcat(sdpLine, ",");
-                       count = gf_list_count(avcc->pictureParameterSets);
-                       for (i=0; i<count; i++) {
-                               GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(avcc->pictureParameterSets, i);
-                               b64s = gf_base64_encode(sl->data, sl->size, b64, 200);
-                               b64[b64s]=0;
-                               strcat(sdpLine, b64);
-                               if (i+1<count) strcat(sdpLine, ",");
-                       }
+               GF_AVCConfig *svcc = gf_isom_svc_config_get(tkHint->file, tkHint->TrackNum, 1);
+               /*TODO - check syntax for SVC (might be some extra signaling)*/
+
+               if (avcc) {
+                       sprintf(sdpLine, "a=fmtp:%d profile-level-id=%02X%02X%02X; packetization-mode=1", tkHint->rtp_p->PayloadType, avcc->AVCProfileIndication, avcc->profile_compatibility, avcc->AVCLevelIndication);
+               } else {
+                       sprintf(sdpLine, "a=fmtp:%d profile-level-id=%02X%02X%02X; packetization-mode=1", tkHint->rtp_p->PayloadType, svcc->AVCProfileIndication, svcc->profile_compatibility, svcc->AVCLevelIndication);
                }
+
+               write_avc_config(sdpLine, avcc, svcc);
+
                gf_isom_sdp_add_track_line(tkHint->file, tkHint->HintTrack, sdpLine);
                gf_odf_avc_cfg_del(avcc);
+               gf_odf_avc_cfg_del(svcc);
        }
        /*MPEG-4 decoder config*/
        else if (tkHint->rtp_p->rtp_payt==GF_RTP_PAYT_MPEG4) {
index 1d982045297d68a898df14bfeaf1f5882f9995bf..9f4c1bc5d17e8953dcae4fbf299c815a58626616 100644 (file)
@@ -40,10 +40,14 @@ GF_Err gf_media_change_par(GF_ISOFile *file, u32 track, s32 ar_num, s32 ar_den)
        if (e) return e;
 
        stype = gf_isom_get_media_subtype(file, track, 1);
-       if ((stype==GF_ISOM_SUBTYPE_AVC_H264) || (stype==GF_ISOM_SUBTYPE_AVC2_H264) ) {
+       if ((stype==GF_ISOM_SUBTYPE_AVC_H264) 
+               || (stype==GF_ISOM_SUBTYPE_AVC2_H264) 
+               || (stype==GF_ISOM_SUBTYPE_AVC3_H264) 
+               || (stype==GF_ISOM_SUBTYPE_AVC4_H264) 
+       ) {
 #ifndef GPAC_DISABLE_AV_PARSERS
                GF_AVCConfig *avcc = gf_isom_avc_config_get(file, track, 1);
-               AVC_ChangePAR(avcc, ar_num, ar_den);
+               gf_media_avc_change_par(avcc, ar_num, ar_den);
                e = gf_isom_avc_config_update(file, track, 1, avcc);
                gf_odf_avc_cfg_del(avcc);
                if (e) return e;
@@ -543,6 +547,8 @@ GF_Err gf_media_make_3gpp(GF_ISOFile *mp4file)
                                break;
                        case GF_ISOM_SUBTYPE_AVC_H264:
                        case GF_ISOM_SUBTYPE_AVC2_H264:
+                       case GF_ISOM_SUBTYPE_AVC3_H264:
+                       case GF_ISOM_SUBTYPE_AVC4_H264:
                        case GF_ISOM_SUBTYPE_SVC_H264:
                                nb_vid++;
                                nb_avc++;
@@ -748,10 +754,14 @@ GF_ESD *gf_media_map_esd(GF_ISOFile *mp4, u32 track)
        case GF_ISOM_SUBTYPE_MPEG4_CRYP:
        case GF_ISOM_SUBTYPE_AVC_H264:
        case GF_ISOM_SUBTYPE_AVC2_H264:
+       case GF_ISOM_SUBTYPE_AVC3_H264:
+       case GF_ISOM_SUBTYPE_AVC4_H264:
        case GF_ISOM_SUBTYPE_SVC_H264:
        case GF_ISOM_SUBTYPE_3GP_EVRC:
        case GF_ISOM_SUBTYPE_3GP_QCELP:
        case GF_ISOM_SUBTYPE_3GP_SMV:
+       case GF_ISOM_SUBTYPE_HVC1:
+       case GF_ISOM_SUBTYPE_HEV1:
                return gf_isom_get_esd(mp4, track, 1);
        }
 
@@ -884,21 +894,32 @@ static s32 gf_get_DQId(GF_ISOFile *file, u32 track)
 {
        GF_AVCConfig *svccfg;
        GF_ISOSample *samp;
-       u32 di = 0;
+       u32 di = 0, cur_extract_mode;
        char *buffer;
        GF_BitStream *bs;
        u32 max_size = 4096;
        u32 size, nalu_size_length;
        u8 nal_type;
+       s32 DQId=0;
 
+       samp = NULL;
+       bs = NULL;
+       cur_extract_mode = gf_isom_get_nalu_extract_mode(file, track);
+       gf_isom_set_nalu_extract_mode(file, track, GF_ISOM_NALU_EXTRACT_INSPECT);
+       buffer = (char*)gf_malloc(sizeof(char) * max_size);
        svccfg = gf_isom_svc_config_get(file, track, 1);
        if (!svccfg)
-               return 0;
+       {
+               DQId = 0;
+               goto exit;
+       }
        samp = gf_isom_get_sample(file, track, 1, &di);
        if (!samp)
-               return -1;
+       {
+               DQId = -1;
+               goto exit;
+       }
        bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
-       buffer = (char*)gf_malloc(sizeof(char) * max_size);
        nalu_size_length = 8 * svccfg->nal_unit_size;
        while (gf_bs_available(bs))
        {
@@ -910,10 +931,48 @@ static s32 gf_get_DQId(GF_ISOFile *file, u32 track)
                gf_bs_read_data(bs, buffer, size);
                nal_type = buffer[0] & 0x1F;
                if (nal_type == GF_AVC_NALU_SVC_SLICE)
-                       return buffer[2] & 0x7F;
+               {
+                       DQId = buffer[2] & 0x7F;
+                       goto exit;
+               }
        }
-       return -1;
+exit:
+       if (svccfg) gf_odf_avc_cfg_del(svccfg);
+       if (samp) gf_isom_sample_del(&samp);
+       if (buffer) gf_free(buffer);
+       if (bs) gf_bs_del(bs);
+       gf_isom_set_nalu_extract_mode(file, track, cur_extract_mode);
+       return DQId;;
 }
+
+static Bool gf_isom_has_svc_explicit(GF_ISOFile *file, u32 track)
+{
+       GF_AVCConfig *svccfg;
+       GF_AVCConfigSlot *slc;
+       u32 i;
+       u8 type;
+       Bool ret = 0;
+
+       svccfg = gf_isom_svc_config_get(file, track, 1);
+       if (!svccfg)
+               return 0;
+
+       for (i = 0; i < gf_list_count(svccfg->sequenceParameterSets); i++)
+       {
+               slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->sequenceParameterSets, i);
+               type = slc->data[0] & 0x1F;
+               if (type == GF_AVC_NALU_SEQ_PARAM)
+               {
+                       ret = 1;
+                       break;
+               }
+       }
+
+       if (svccfg) gf_odf_avc_cfg_del(svccfg);
+       return ret;
+}
+
+
 static u32 gf_isom_get_track_id_max(GF_ISOFile *file)
 {
        u32 num_track, i, trackID;
@@ -934,87 +993,116 @@ static u32 gf_isom_get_track_id_max(GF_ISOFile *file)
 GF_EXPORT
 GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
 {
-       GF_AVCConfig *avccfg, *svccfg;
-       u32 num_svc_track, num_sample, svc_track, dst_track, ref_trackID, ref_trackNum, max_id;
-       u32 di, width, height, size, nalu_size_length;
-       u32 i, j, t;
+       GF_AVCConfig *svccfg, *cfg;
+       u32 num_svc_track, num_sample, svc_track, dst_track, ref_trackID, ref_trackNum, max_id, di, width, height, size, nalu_size_length, i, j, t, max_size, num_pps, num_sps, num_subseq, NALUnitHeader, data_offset, data_length, count, timescale, cur_extract_mode;
        GF_Err e; 
-       GF_AVCConfigSlot *slc;
+       GF_AVCConfigSlot *slc, *sl;
        AVCState avc;
        s32 sps_id, pps_id;
-       GF_ISOSample *samp;
-       GF_BitStream *bs;
+       GF_ISOSample *samp, *dst_samp;
+       GF_BitStream *bs, *dst_bs;
        GF_BitStream ** sample_bs;
-       u8 nal_type, nal_hdr;
-       GF_ISOSample  *dst_samp;
-       GF_BitStream *dst_bs;
-       char *buffer; 
-       //u8 dependency_id, quality_id, temporal_id, avc_dependency_id, avc_quality_id;
-       u32 max_size = 4096;
+       u8 nal_type, nal_hdr, track_ref_index;
+       char *buffer;
        s32 *sps_track, *sps, *pps;
-       u32 num_pps, num_sps;
        u64 offset;
        Bool is_splited;
-       Bool *first_sample_track;
+       Bool *first_sample_track, *is_subseq_pps;
        u64 *first_DTS_track;
-       u32 NALUnitHeader;
-       u8 track_ref_index;
        s8 sample_offset;
-       u32 data_offset;
-       u32 data_length;
-       u32 count, timescale;
 
-       avccfg = gf_isom_avc_config_get(file, track, 1);
+       max_size = 4096;
+       e = GF_OK;
+       samp = dst_samp = NULL;
+       bs = NULL;
+       sample_bs = NULL;
+       sps_track = sps = pps = NULL;
+       first_DTS_track = NULL;
+       first_sample_track = is_subseq_pps = NULL;
+       buffer = NULL;
+       cfg = NULL;
+       num_svc_track=0;
+       cur_extract_mode = gf_isom_get_nalu_extract_mode(file, track);
+       gf_isom_set_nalu_extract_mode(file, track, GF_ISOM_NALU_EXTRACT_INSPECT);
        svccfg = gf_isom_svc_config_get(file, track, 1);
-
-       is_splited = (avccfg) ? 0 : 1;
-
-       /*if we have not any SVC -> stop*/
        if (!svccfg)
-               return GF_OK;
-
-       timescale = gf_isom_get_media_timescale(file, track);
-
+       {
+               e = GF_OK;
+               goto exit;
+       }
        num_sps = gf_list_count(svccfg->sequenceParameterSets);
+       if (!num_sps)
+       {
+               e = GF_OK;
+               goto exit;
+       }
        num_pps = gf_list_count(svccfg->pictureParameterSets);
-       /*we have a splited file with 1 SVC / track*/
-       if (is_splited && num_pps == 1)
+       if ((gf_isom_get_avc_svc_type(file, track, 1) == GF_ISOM_AVCTYPE_SVC_ONLY) && !gf_isom_has_svc_explicit(file, track))
+               is_splited = 1;
+       else
+               is_splited = 0;
+       num_subseq = gf_isom_has_svc_explicit(file, track) ? num_sps - 1 : num_sps;
+
+       if (is_splited)
        {
-               /*use 'all' mode -> stop*/
-               if (splitAll)
-                       return GF_OK;
-               /*use 'base' mode -> merge SVC tracks*/
-               else
-                       return gf_media_merge_svc(file, track, 0);
+               /*this track has only one SVC ...*/
+               if (num_sps == 1)
+               {
+                       /*use 'all' mode -> stop*/
+                       if (splitAll)
+                               goto exit;
+                       /*use 'base' mode -> merge SVC tracks*/
+                       else
+                       {
+                               e = gf_media_merge_svc(file, track, 0);
+                               goto exit;
+                       }
+               }
+               /*this file has been in 'splitbase' mode*/
+               else if (!splitAll)
+                       goto exit;
+
        }
-       num_svc_track = splitAll ? num_sps : 1;
+
+       timescale = gf_isom_get_media_timescale(file, track);
+       num_svc_track = splitAll ? num_subseq : 1;
        max_id = gf_isom_get_track_id_max(file);
        di = 0;
        
        memset(&avc, 0, sizeof(AVCState));
        avc.sps_active_idx = -1;
        nalu_size_length = 8 * svccfg->nal_unit_size;
-       /*read all sps*/
-       sps =  (s32 *) gf_malloc(num_sps * sizeof(s32));
-       sps_track = (s32 *) gf_malloc(num_sps * sizeof(s32));
+       /*read all sps, but we need only the subset sequence parameter sets*/
+       sps =  (s32 *) gf_malloc(num_subseq * sizeof(s32));
+       sps_track = (s32 *) gf_malloc(num_subseq * sizeof(s32));
+       count = 0;
        for (i = 0; i < num_sps; i++)
        {
-               slc = gf_list_get(svccfg->sequenceParameterSets, i);
-               sps_id = AVC_ReadSeqInfo(slc->data+1, slc->size-1, &avc,0, NULL);
+               slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->sequenceParameterSets, i);
+               nal_type = slc->data[0] & 0x1F;
+               sps_id = gf_media_avc_read_sps(slc->data, slc->size, &avc, 0, NULL);
                if (sps_id < 0) {
-                       return GF_NON_COMPLIANT_BITSTREAM;
+                       e = GF_NON_COMPLIANT_BITSTREAM;
+                       goto exit;
+               }
+               if (nal_type == GF_AVC_NALU_SVC_SUBSEQ_PARAM)
+               {
+                       sps[count] = sps_id;
+                       sps_track[count] = i;
+                       count++;
                }
-               sps[i] = sps_id;
-               sps_track[i] = i;
        }
+       /*for testing*/
+       assert(count == num_subseq);
        /*read all pps*/
        pps =  (s32 *) gf_malloc(num_pps * sizeof(s32));
        for (j = 0; j < num_pps; j++)
        {
-               slc = gf_list_get(svccfg->pictureParameterSets, j);
-               pps_id = AVC_ReadPictParamSet(slc->data+1, slc->size-1, &avc);
+               slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->pictureParameterSets, j);
+               pps_id = gf_media_avc_read_pps(slc->data, slc->size, &avc);
                if (pps_id < 0) {
-                       return GF_NON_COMPLIANT_BITSTREAM;
+                       e = GF_NON_COMPLIANT_BITSTREAM;
+                       goto exit;
                }
                pps[j] = pps_id;
        }
@@ -1025,14 +1113,21 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                gf_isom_get_reference(file, track, GF_ISOM_REF_BASE, 1, &ref_trackNum);
                ref_trackID = gf_isom_get_track_id(file, ref_trackNum);
        }
+
+       buffer = (char*)gf_malloc(sizeof(char) * max_size);
        /*read first sample for determinating the order of SVC tracks*/
        count = 0;
        samp = gf_isom_get_sample(file, track, 1, &di);
        if (!samp)
-               return GF_IO_ERR;
+       {
+               e = gf_isom_last_error(file);
+               goto exit;
+       }
        bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
        offset = 0;
-       buffer = (char*)gf_malloc(sizeof(char) * max_size);
+       is_subseq_pps = (Bool *) gf_malloc(num_pps*sizeof(Bool));
+       for (i = 0; i < num_pps; i++)
+               is_subseq_pps[i] = 0;
        while (gf_bs_available(bs))
        {
                size = gf_bs_read_int(bs, nalu_size_length);
@@ -1042,16 +1137,28 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                }
                nal_hdr = gf_bs_read_u8(bs);
                nal_type = nal_hdr & 0x1F;
-               AVC_ParseNALU(bs, nal_hdr, &avc);
-               gf_bs_seek(bs, offset+nalu_size_length/8);
+               gf_media_avc_parse_nalu(bs, nal_hdr, &avc);
+               e = gf_bs_seek(bs, offset+nalu_size_length/8);
+               if (e)
+                       goto exit;
                gf_bs_read_data(bs, buffer, size);
                offset += size + nalu_size_length/8;
                if (nal_type == GF_AVC_NALU_SVC_SLICE)
                {
+                       for (i = 0; i < num_pps; i++)
+                       {
+                               if (avc.s_info.pps->id == pps[i])
+                               {
+                                       is_subseq_pps[i] = 1;
+                                       break;
+                               }
+                       }
+                       if ((count > 0) && (avc.s_info.pps->sps_id == sps[count-1]))
+                               continue;
                        /*verify the order of SPS, reorder if necessary*/
                        if (avc.s_info.pps->sps_id != sps[count])
                        {
-                               for (i = count+1; i < num_sps; i++)
+                               for (i = count+1; i < num_subseq; i++)
                                {
                                        /*swap two SPS*/
                                        if (avc.s_info.pps->sps_id == sps[i])
@@ -1062,36 +1169,37 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                                                break;
                                        }
                                }
-                               /*for testing: ensure that there are not two NALU which use the same SPS, so that we can use sps for separating layers*/
-                               assert(i < num_sps);
                        }
                        count++;
                }
        }
-       /*for testing: ensure that the number of SPS is equal to the number of SVC layers*/
-       assert(count == num_sps);
+       gf_bs_del(bs);
+       bs = NULL;
 
-       gf_free(buffer);
-       buffer = NULL;
+       gf_isom_sample_del(&samp);
+       samp = NULL;
        
        for (t = 0; t < num_svc_track; t++)
        {
-               GF_AVCConfig *cfg;
-
                e = GF_OK;
                svc_track = gf_isom_new_track(file, t+1+max_id, GF_ISOM_MEDIA_VISUAL, timescale);
                if (!svc_track) 
                {
                        e = gf_isom_last_error(file);
-                       return e;
+                       goto exit;
                }
                gf_isom_set_track_enabled(file, svc_track, 1);
                gf_isom_set_track_reference(file, svc_track, GF_ISOM_REF_BASE, ref_trackID);
                cfg = gf_odf_avc_cfg_new();
                cfg->complete_representation = 1; //SVC
+               /*this layer depends on the base layer and the lower layers*/
+               gf_isom_set_track_reference(file, svc_track, GF_ISOM_REF_SCAL, ref_trackID);
+               for (i = 0; i < t; i++)
+                       gf_isom_set_track_reference(file, svc_track, GF_ISOM_REF_SCAL, i+1+max_id);
+
                e = gf_isom_svc_config_new(file, svc_track, cfg, NULL, NULL, &di);
                if (e)
-                       return e;
+                       goto exit;
                if (splitAll)
                {
                        sps_id = sps[t];
@@ -1106,19 +1214,31 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                        cfg->AVCLevelIndication = avc.sps[sps_id].level_idc;
                        cfg->AVCProfileIndication = avc.sps[sps_id].profile_idc;
                        cfg->nal_unit_size = svccfg->nal_unit_size;
-                       gf_list_add(cfg->sequenceParameterSets,  gf_list_get(svccfg->sequenceParameterSets, sps_track[t]));
+                       slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->sequenceParameterSets, sps_track[t]);
+                       sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                       sl->id = slc->id;
+                       sl->size = slc->size;
+                       sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
+                       memcpy(sl->data, slc->data, sizeof(char)*sl->size);
+                       gf_list_add(cfg->sequenceParameterSets, sl);
                        for (j = 0; j < num_pps; j++)
                        {
                                pps_id = pps[j];
-                               if (avc.pps[pps_id].sps_id == sps_id)
+                               if (is_subseq_pps[j] && (avc.pps[pps_id].sps_id == sps_id))
                                {
-                                       gf_list_add(cfg->pictureParameterSets,  gf_list_get(svccfg->pictureParameterSets, j));
+                                       slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->pictureParameterSets, j);
+                                       sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                                       sl->id = slc->id;
+                                       sl->size = slc->size;
+                                       sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
+                                       memcpy(sl->data, slc->data, sizeof(char)*sl->size);
+                                       gf_list_add(cfg->pictureParameterSets, sl);
                                }
                        }
                }
                else
                {
-                       for (i = 0; i < num_sps; i++)
+                       for (i = 0; i < num_subseq; i++)
                        {
                                sps_id = sps[i];
                                width = avc.sps[sps_id].width;
@@ -1132,22 +1252,34 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                                cfg->AVCLevelIndication = avc.sps[sps_id].level_idc;
                                cfg->AVCProfileIndication = avc.sps[sps_id].profile_idc;
                                cfg->nal_unit_size = svccfg->nal_unit_size;
-                               gf_list_add(cfg->sequenceParameterSets,  gf_list_get(svccfg->sequenceParameterSets, sps_track[i]));
+                               slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->sequenceParameterSets, sps_track[i]);
+                               sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                               sl->id = slc->id;
+                               sl->size = slc->size;
+                               sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
+                               memcpy(sl->data, slc->data, sizeof(char)*sl->size);
+                               gf_list_add(cfg->sequenceParameterSets, sl);
                                for (j = 0; j < num_pps; j++)
                                {
-                                       slc = gf_list_get(svccfg->pictureParameterSets, t);
-                                       pps_id = AVC_ReadPictParamSet(slc->data+1, slc->size-1, &avc);
-                                       if (pps_id < 0) {
-                                               return GF_NON_COMPLIANT_BITSTREAM;
-                                       }
+                                       pps_id = pps[j];
                                        if (avc.pps[pps_id].sps_id == sps_id)
                                        {
-                                               gf_list_add(cfg->pictureParameterSets,  gf_list_get(svccfg->pictureParameterSets, j));
+                                               slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->pictureParameterSets, j);
+                                               sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                                               sl->id = slc->id;
+                                               sl->size = slc->size;
+                                               sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
+                                               memcpy(sl->data, slc->data, sizeof(char)*sl->size);
+                                               gf_list_add(cfg->pictureParameterSets, sl);
                                        }
                                }
                        }
                }
-               gf_isom_svc_config_update(file, svc_track, 1, cfg, 0);
+               e = gf_isom_svc_config_update(file, svc_track, 1, cfg, 0);
+               if (e)
+                       goto exit;
+               gf_odf_avc_cfg_del(cfg);
+               cfg = NULL;
        }
 
        num_sample = gf_isom_get_sample_count(file, track);
@@ -1157,28 +1289,69 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
        first_DTS_track = (u64 *) gf_malloc((num_svc_track+1) * sizeof(u64));
        for (t = 0; t <= num_svc_track; t++)
                first_DTS_track[t] = 0;
-
        for (i = 1; i <= num_sample; i++)
        {
-               u32 *prev_layer;
-               u32 count_prev_layer;
-
-               prev_layer = (u32 *) gf_malloc(num_svc_track * sizeof(u32));
-               count_prev_layer = 0;
+               /*reset*/
+               memset(buffer, 0, max_size);
                
-
                samp = gf_isom_get_sample(file, track, i, &di);
                if (!samp)
-                       return GF_IO_ERR;
+               {
+                       e = GF_IO_ERR;
+                       goto exit;
+               }
 
                /* Create (num_svc_track) SVC bitstreams + 1 AVC bitstream*/
                sample_bs = (GF_BitStream **) gf_malloc(sizeof(GF_BitStream *) * (num_svc_track+1));
                for (j = 0; j <= num_svc_track; j++)
                        sample_bs[j] = (GF_BitStream *) gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
 
+               /*write extractor*/
+               for (t = 0; t < num_svc_track; t++)
+               {
+                       //reference to base layer
+                       gf_bs_write_int(sample_bs[t+1], 14, nalu_size_length); // extractor 's size = 14
+                       NALUnitHeader = 0; //reset
+                       NALUnitHeader |= 0x1F000000; // NALU type = 31
+                       gf_bs_write_u32(sample_bs[t+1], NALUnitHeader);
+                       track_ref_index = (u8) gf_isom_has_track_reference(file, t+1+max_id, GF_ISOM_REF_SCAL, ref_trackID);
+                       if (!track_ref_index)
+                       {
+                               e = GF_CORRUPTED_DATA;
+                               goto exit;
+                       }
+                       gf_bs_write_u8(sample_bs[t+1], track_ref_index);
+                       sample_offset = 0;
+                       gf_bs_write_u8(sample_bs[t+1], sample_offset);
+                       data_offset = 0;
+                       gf_bs_write_u32(sample_bs[t+1], data_offset);
+                       data_length = 0;
+                       gf_bs_write_u32(sample_bs[t+1], data_length);
+                       //reference to previous layer(s)
+                       for (j = 0; j < t; j++)
+                       {
+                               gf_bs_write_int(sample_bs[t+1], 14, nalu_size_length);
+                               NALUnitHeader = 0;
+                               NALUnitHeader |= 0x1F000000;
+                               gf_bs_write_u32(sample_bs[t+1], NALUnitHeader);
+                               track_ref_index = (u8) gf_isom_has_track_reference(file, t+1+max_id, GF_ISOM_REF_SCAL, j+1+max_id);
+                               if (!track_ref_index)
+                               {
+                                       e = GF_CORRUPTED_DATA;
+                                       goto exit;
+                               }
+                               gf_bs_write_u8(sample_bs[t+1], track_ref_index);
+                               sample_offset = 0;
+                               gf_bs_write_u8(sample_bs[t+1], sample_offset);
+                               data_offset = (j+1) * (nalu_size_length/8 + 14); // (nalu_size_length/8) bytes of NALU length field + 14 bytes of extractor per layer
+                               gf_bs_write_u32(sample_bs[t+1], data_offset);
+                               data_length = 0;
+                               gf_bs_write_u32(sample_bs[t+1], data_length);
+                       }
+               }
+
                bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
                offset = 0;
-               buffer = (char*)gf_malloc(sizeof(char) * max_size);
                while (gf_bs_available(bs))
                {
                        size = gf_bs_read_int(bs, nalu_size_length);
@@ -1188,20 +1361,50 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                        }
                        nal_hdr = gf_bs_read_u8(bs);
                        nal_type = nal_hdr & 0x1F;
-                       AVC_ParseNALU(bs, nal_hdr, &avc);
-                       gf_bs_seek(bs, offset+nalu_size_length/8);
+                       gf_media_avc_parse_nalu(bs, nal_hdr, &avc);
+                       e = gf_bs_seek(bs, offset+nalu_size_length/8);
+                       if (e)
+                               goto exit;
                        gf_bs_read_data(bs, buffer, size);
                        offset += size + nalu_size_length/8;
-                       
+                                       
                        switch (nal_type) {
-                               //case GF_AVC_NALU_SVC_PREFIX_NALU:
-                               case GF_AVC_NALU_SVC_SLICE:
+                               case GF_AVC_NALU_PIC_PARAM:
+                                       pps_id = gf_media_avc_read_pps(buffer, size, &avc);;
+                                       j = 0;
+                                       dst_track = 0;
+                                       while (j < num_pps)
+                                       {
+                                               if (pps_id == pps[j])
+                                                       break;
+                                               j++;
+                                       }
+                                       if ((j < num_pps) && (is_subseq_pps[j]))
+                                       {
+                                               if (splitAll)
+                                               {
+                                                       for (t = 0; t < num_svc_track; t++)
+                                                       {
+                                                               if (sps[t] == avc.pps[pps_id].sps_id)
+                                                               {
+                                                                       dst_track = t + 1;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                                       dst_track = 1;
+                                       }
+                                       dst_bs = sample_bs[dst_track];
+                                       break;
+                               case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
+                                       sps_id = gf_media_avc_read_sps(buffer, size, &avc, 0, NULL);
                                        dst_track = 0;
                                        if (splitAll)
                                        {
-                                               for (t = 0; t < num_svc_track; t++) // num_svc_track == num_pps
+                                               for (t = 0; t < num_svc_track; t++)
                                                {
-                                                       if (sps_track[t] == (avc.s_info.pps)->sps_id)
+                                                       if (sps[t] == sps_id)
                                                        {
                                                                dst_track = t + 1;
                                                                break;
@@ -1211,42 +1414,23 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                                        else
                                                dst_track = 1;
                                        dst_bs = sample_bs[dst_track];
-                                       /*write extractor*/
-                                       if (!gf_bs_get_position(dst_bs))
+                                       break;
+                               case GF_AVC_NALU_SVC_SLICE:
+                                       dst_track = 0;
+                                       if (splitAll)
                                        {
-                                               //reference to base layer
-                                               gf_bs_write_int(dst_bs, 14, nalu_size_length); // extractor 's size = 14
-                                               NALUnitHeader = 0; //reset
-                                               NALUnitHeader |= 0x1F000000; // NALU type = 31
-                                               gf_bs_write_u32(dst_bs, NALUnitHeader);
-                                               //track_ref_index is a trackID, not a trackNum. So when rewrite, gf_isom_get_track_id must be used to find trackNum
-                                               track_ref_index = ref_trackID; 
-                                               gf_bs_write_u8(dst_bs, track_ref_index);
-                                               sample_offset = 0;
-                                               gf_bs_write_u8(dst_bs, sample_offset);
-                                               data_offset = 0;
-                                               gf_bs_write_u32(dst_bs, data_offset);
-                                               data_length = 0;
-                                               gf_bs_write_u32(dst_bs, data_length);
-                                               //reference to previous layer(s)
-                                               for (t = 0; t < count_prev_layer; t++)
+                                               for (t = 0; t < num_svc_track; t++)
                                                {
-                                                       gf_bs_write_int(dst_bs, 14, nalu_size_length);
-                                                       NALUnitHeader = 0;
-                                                       NALUnitHeader |= 0x1F000000;
-                                                       gf_bs_write_u32(dst_bs, NALUnitHeader);
-                                                       track_ref_index = max_id + prev_layer[t];
-                                                       gf_bs_write_u8(dst_bs, track_ref_index);
-                                                       sample_offset = 0;
-                                                       gf_bs_write_u8(dst_bs, sample_offset);
-                                                       data_offset = (t+1) * (nalu_size_length/8 + 14); // (nalu_size_length/8) bytes of NALU length field + 14 bytes of extractor per layer
-                                                       gf_bs_write_u32(dst_bs, data_offset);
-                                                       data_length = 0;
-                                                       gf_bs_write_u32(dst_bs, data_length);
+                                                       if (sps[t] == (avc.s_info.pps)->sps_id)
+                                                       {
+                                                               dst_track = t + 1;
+                                                               break;
+                                                       }
                                                }
                                        }
-                                       prev_layer[count_prev_layer] = dst_track;
-                                       count_prev_layer++;
+                                       else
+                                               dst_track = 1;
+                                       dst_bs = sample_bs[dst_track];
                                        break;
                                default:
                                        dst_bs = sample_bs[0];
@@ -1275,7 +1459,7 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                                else
                                        e = gf_isom_update_sample(file, track, i, dst_samp, 1);
                                if (e)
-                                       return e;
+                                       goto exit;
                                gf_isom_sample_del(&dst_samp);
                                dst_samp = NULL;
                        }
@@ -1283,7 +1467,11 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                        sample_bs[j] = NULL;
                }
                gf_free(sample_bs);
-               gf_free(bs);
+               sample_bs = NULL;
+               gf_bs_del(bs);
+               bs = NULL;
+               gf_isom_sample_del(&samp);
+               samp = NULL;
        }
 
        /*add Editlist entry if DTS of the first sample is not zero*/
@@ -1302,84 +1490,131 @@ GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll)
                }
        }
        
-       /*if this is a merged file: delete SVC config*/
+       /*if this is a merged file*/
        if (!is_splited)
-               gf_isom_svc_config_del(file, track, 1);
+       {
+               /*a normal stream: delete SVC config*/
+               if (!gf_isom_has_svc_explicit(file, track))
+               {
+                       gf_isom_svc_config_del(file, track, 1);
+               }
+               else
+               {
+                       s32 shift=0;
+                       
+                       for (i = 0; i < gf_list_count(svccfg->sequenceParameterSets); i++)
+                       {
+                               slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->sequenceParameterSets, i);
+                               sps_id = gf_media_avc_read_sps(slc->data, slc->size, &avc, 0, NULL);
+                               if (sps_id < 0) {
+                                       e = GF_NON_COMPLIANT_BITSTREAM;
+                                       goto exit;
+                               }
+                               nal_type = slc->data[0] & 0x1F;
+                               if (nal_type == GF_AVC_NALU_SVC_SUBSEQ_PARAM)
+                               {
+                                       gf_list_rem(svccfg->sequenceParameterSets, i);
+                                       gf_free(slc->data);
+                                       gf_free(slc);
+                                       i--;
+                               }
+                       }
+
+                       for (j = 0; j < gf_list_count(svccfg->pictureParameterSets); j++)
+                               {
+                                       slc = (GF_AVCConfigSlot *)gf_list_get(svccfg->pictureParameterSets, j);
+                                       pps_id = gf_media_avc_read_pps(slc->data, slc->size, &avc);
+                                       if (pps_id < 0) {
+                                               e = GF_NON_COMPLIANT_BITSTREAM;
+                                               goto exit;
+                                       }
+                                       if (is_subseq_pps[j+shift])
+                                       {
+                                               gf_list_rem(svccfg->pictureParameterSets, j);
+                                               gf_free(slc->data);
+                                               gf_free(slc);
+                                               j--;
+                                       }
+                               }
+                       e = gf_isom_svc_config_update(file, track, 1, svccfg, 0);
+                       if (e)
+                               goto exit;
+               }
+       }
        /*if this is as splited file: delete this track*/
        else
        {
                gf_isom_remove_track(file, track);
        }
-       return GF_OK;
+
+exit:
+       if (svccfg) gf_odf_avc_cfg_del(svccfg);
+       if (cfg) gf_odf_avc_cfg_del(cfg);
+       if (samp) gf_isom_sample_del(&samp);
+       if (dst_samp) gf_isom_sample_del(&dst_samp);
+       if (bs) gf_bs_del(bs);
+       if (sample_bs)
+       {
+               for (i = 0; i <= num_svc_track; i++)
+                       gf_bs_del(sample_bs[i]);
+               gf_free(sample_bs);
+       }
+       if (sps_track) gf_free(sps_track);
+       if (sps) gf_free(sps);
+       if (pps) gf_free(pps);
+       if (first_sample_track) gf_free(first_sample_track);
+       if (first_DTS_track) gf_free(first_DTS_track);
+       if (buffer) gf_free(buffer);
+       if (is_subseq_pps) gf_free(is_subseq_pps);
+       gf_isom_set_nalu_extract_mode(file, track, cur_extract_mode);
+       return e;
 }
 
 /* Merge SVC layers*/
 GF_EXPORT
 GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
 {
-       GF_AVCConfig *avccfg, *svccfg, *cfg;
-       u32 merge_track;
-       u32 num_track, num_sample;
+       GF_AVCConfig *svccfg, *cfg;
+       u32 merge_track,  num_track, num_sample, size, i, t, di, max_size, nalu_size_length, ref_trackNum, ref_trackID, count, width, height, nb_EditList, media_ts, moov_ts;
        GF_ISOSample *avc_samp, *samp, *dst_samp;
        GF_BitStream *bs, *dst_bs;
        GF_Err e;
-       u32 size;
-       u32 i, t;
-       u32 di = 0;
        char *buffer;
-       u32 max_size = 4096;
-       u32 nalu_size_length;
-       u32 ref_trackNum, ref_trackID;
        s32 *DQId;
-       u32 count;
-       u32 *list_track_sorted;
-       u32 *cur_sample, *max_sample;
-       u32 width = 0, height = 0;
+       u32 *list_track_sorted, *cur_sample, *max_sample;
        u64 *DTS_offset;
-       u32 nb_EditList;
-       u32 media_ts, moov_ts;
        u64 EditTime, SegmentDuration, MediaTime;
-       u8 EditMode;
+       u8 EditMode, nal_type;
        Bool first_sample;
-       u64 first_DTS, offset, dur;
-       u32 max_id;
-       u32 timescale;
-       u8 nal_type;
-
-       avc_samp = samp = NULL;
-
-       avccfg = gf_isom_avc_config_get(file, track, 1);
-       if (!avccfg && mergeAll)
-               return GF_BAD_PARAM;
-       timescale = gf_isom_get_media_timescale(file, track);
+       u64 first_DTS, offset, dur; 
+       GF_AVCConfigSlot *slc, *sl;
+
+       e = GF_OK;
+       di = 1;
+       max_size = 4096;
+       width = height = 0;
+       avc_samp = samp = dst_samp = NULL;
+       svccfg = cfg = NULL;
+       buffer = NULL;
+       bs = dst_bs = NULL;
+       DQId = NULL;
+       list_track_sorted = cur_sample = max_sample = NULL;
+       DTS_offset = NULL;
+       
+       if (gf_isom_get_avc_svc_type(file, track, 1) == GF_ISOM_AVCTYPE_AVC_SVC)
+               goto exit;
 
        num_track = gf_isom_get_track_count(file);
-       if (num_track == 1) {
-               if (avccfg) gf_odf_avc_cfg_del(avccfg);
-               return GF_OK;
-       }
-
-       /*create a new merged track*/
-       max_id = gf_isom_get_track_id_max(file);
-       merge_track = gf_isom_new_track(file, max_id+1, GF_ISOM_MEDIA_VISUAL, timescale);
-       gf_isom_set_track_enabled(file, merge_track, 1);
-       /*add avc configuration if any*/
-       if (avccfg)
-               gf_isom_avc_config_new(file, merge_track, avccfg, NULL, NULL, &di);
-
-       svccfg = gf_odf_avc_cfg_new();
-       svccfg->complete_representation = 1; 
-       e = gf_isom_svc_config_new(file, merge_track, svccfg, NULL, NULL, &di);
-       if (e) goto exit;
-
-       if (avccfg) {
-               ref_trackNum = track;
-               ref_trackID = gf_isom_get_track_id(file, track);
-       } else {
-               gf_isom_get_reference(file, track, GF_ISOM_REF_BASE, 1, &ref_trackNum);
-               ref_trackID = gf_isom_get_track_id(file, ref_trackNum);
+       if (num_track == 1) 
+               goto exit;
+       gf_isom_get_reference(file, track, GF_ISOM_REF_BASE, 1, &ref_trackNum);
+       ref_trackID = gf_isom_get_track_id(file, ref_trackNum);
+       if (!ref_trackID)
+       {
+               e = GF_ISOM_INVALID_MEDIA;
+               goto exit;
        }
-
+       
        list_track_sorted = (u32 *) gf_malloc(num_track * sizeof(u32));
        DQId = (s32 *) gf_malloc(num_track * sizeof(s32));
        count = 0;
@@ -1390,8 +1625,13 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                        e = GF_ISOM_INVALID_MEDIA;
                        goto exit;
                }
-               if ((t != track) && !gf_isom_has_track_reference(file, t, GF_ISOM_REF_BASE, ref_trackID))
-                       continue;
+
+               if (!gf_isom_has_track_reference(file, t, GF_ISOM_REF_BASE, ref_trackID))
+               {
+                       if (t != ref_trackNum) continue;
+                       else if (!mergeAll) continue;
+               }
+
                while ((pos < count ) && (DQId[pos] <= track_DQId))
                        pos++;
                for (i = count; i > pos; i--)
@@ -1404,16 +1644,20 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                count++;
        }
 
-       if (mergeAll)
-       {
-               gf_isom_get_visual_info(file, list_track_sorted[0], 1, &width, &height);
-       }
-       else
+       merge_track = list_track_sorted[0];
+       gf_isom_set_track_enabled(file, merge_track, 1);
+       /*rewrite svccfg*/
+       svccfg = gf_odf_avc_cfg_new();
+       svccfg->complete_representation = 1; 
+       e = gf_isom_svc_config_new(file, merge_track, svccfg, NULL, NULL, &di);
+       if (e) goto exit;
+       /*rewrite visual info*/
+       if (!mergeAll)
        {
                for (t = 0; t < count; t++)
                        gf_isom_get_visual_info(file, list_track_sorted[t], 1, &width, &height);
+               gf_isom_set_visual_info(file, merge_track, 1, width, height);
        }
-       gf_isom_set_visual_info(file, merge_track, 1, width, height);
 
        for (t = 0; t < count; t++)
        {
@@ -1430,18 +1674,30 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                svccfg->nal_unit_size = cfg->nal_unit_size;
                for (i = 0; i < gf_list_count(cfg->sequenceParameterSets); i++)
                {
-                       gf_list_add(svccfg->sequenceParameterSets,  gf_list_get(cfg->sequenceParameterSets, i));
-                       }
+                       slc = (GF_AVCConfigSlot *)gf_list_get(cfg->sequenceParameterSets, i);
+                       sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                       sl->id = slc->id;
+                       sl->size = slc->size;
+                       sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
+                       memcpy(sl->data, slc->data, sizeof(char)*sl->size);
+                       gf_list_add(svccfg->sequenceParameterSets, sl);
+               }
                for (i = 0; i < gf_list_count(cfg->pictureParameterSets); i++)
                {
-                       gf_list_add(svccfg->pictureParameterSets, gf_list_get(cfg->pictureParameterSets, i));
+                       slc = (GF_AVCConfigSlot *)gf_list_get(cfg->pictureParameterSets, i);
+                       sl = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                       sl->id = slc->id;
+                       sl->size = slc->size;
+                       sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
+                       memcpy(sl->data, slc->data, sizeof(char)*sl->size);
+                       gf_list_add(svccfg->pictureParameterSets, sl);
                }
                if (mergeAll)
                        gf_isom_svc_config_update(file, merge_track, 1, svccfg, 1);
                else
                        gf_isom_svc_config_update(file, merge_track, 1, svccfg, 0);
-               
                gf_odf_avc_cfg_del(cfg);
+               cfg = NULL;
        }
 
        cur_sample = (u32 *) gf_malloc(count * sizeof(u32));
@@ -1479,6 +1735,9 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
        nalu_size_length = 8 * svccfg->nal_unit_size;
        first_sample = 1;
        first_DTS = 0;
+       buffer = (char*)gf_malloc(sizeof(char) * max_size);
+       for (t = 1; t <= num_track; t++)
+               gf_isom_set_nalu_extract_mode(file, t, GF_ISOM_NALU_EXTRACT_INSPECT);
        for (i = 1; i <= num_sample; i++)
        {
                dst_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
@@ -1494,7 +1753,12 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                        gf_bs_write_int(dst_bs, 14, nalu_size_length); // extractor 's size = 14
                        NALUnitHeader |= 0x1F000000; // NALU type = 31
                        gf_bs_write_u32(dst_bs, NALUnitHeader);
-                       track_ref_index = ref_trackID;
+                       track_ref_index = (u8) gf_isom_has_track_reference(file, merge_track, GF_ISOM_REF_SCAL, ref_trackID);
+                       if (!track_ref_index)
+                       {
+                               e = GF_CORRUPTED_DATA;
+                               goto exit;
+                       }
                        gf_bs_write_u8(dst_bs, track_ref_index);
                        sample_offset = 0;
                        gf_bs_write_u8(dst_bs, sample_offset);
@@ -1503,7 +1767,6 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                        data_length = 0;
                        gf_bs_write_u32(dst_bs, data_length);
                }
-               buffer = (char*)gf_malloc(sizeof(char) * max_size);
 
                avc_samp = gf_isom_get_sample(file, ref_trackNum, i, &di);
                if (!avc_samp) {
@@ -1524,6 +1787,8 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                        if ((samp->DTS + DTS_offset[t]) != avc_samp->DTS)
                                continue;
                        bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
+                       /*reset*/
+                       memset(buffer, 0, sizeof(char) * max_size);
                        while (gf_bs_available(bs))
                        {
                                size = gf_bs_read_int(bs, nalu_size_length);
@@ -1560,15 +1825,16 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
                        dst_samp->DTS = avc_samp->DTS - first_DTS;
                        dst_samp->IsRAP = avc_samp->IsRAP;
                        gf_bs_get_content(dst_bs, &dst_samp->data, &dst_samp->dataLength);
-                       e = gf_isom_add_sample(file, merge_track, 1, dst_samp);
-                       gf_bs_del(dst_bs);
-                       dst_bs = NULL;
-                       gf_isom_sample_del(&dst_samp);
+                       e = gf_isom_update_sample(file, merge_track, i, dst_samp, 1);
                        if (e)
                                goto exit;
                }
                gf_isom_sample_del(&avc_samp);
                avc_samp = NULL;
+               gf_bs_del(dst_bs);
+               dst_bs = NULL;
+               gf_isom_sample_del(&dst_samp);
+               dst_samp = NULL;
        }
 
        /*Add EditList if nessessary*/
@@ -1585,18 +1851,30 @@ GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll)
        /*Delete SVC track(s) that references to ref_track*/
        for (t = 1; t <= num_track; t++)
        {
-               if ((t != track) && !gf_isom_has_track_reference(file, t, GF_ISOM_REF_BASE, ref_trackID))
-                       continue;
-               gf_isom_remove_track(file, t);
-               num_track--; //we removed one track from file
-               t--;
+               if (gf_isom_has_track_reference(file, t, GF_ISOM_REF_BASE, ref_trackID) && (t != merge_track))
+               {
+                       gf_isom_remove_track(file, t);
+                       num_track--; //we removed one track from file
+                       t--;
+               }
        }
 
 exit:
        if (avc_samp) gf_isom_sample_del(&avc_samp);
        if (samp) gf_isom_sample_del(&samp);
-       if (avccfg) gf_odf_avc_cfg_del(avccfg);
+       if (dst_samp) gf_isom_sample_del(&dst_samp);
        if (svccfg) gf_odf_avc_cfg_del(svccfg);
+       if (cfg) gf_odf_avc_cfg_del(cfg);
+       if (bs) gf_bs_del(bs);
+       if (dst_bs) gf_bs_del(dst_bs);
+       if (buffer) gf_free(buffer);
+       if (DQId) gf_free(DQId);
+       if (list_track_sorted) gf_free(list_track_sorted);
+       if (cur_sample) gf_free(cur_sample);
+       if (max_sample) gf_free(max_sample);
+       if (DTS_offset) gf_free(DTS_offset);
+       for (t = 1; t <= gf_isom_get_track_count(file); t++)
+               gf_isom_set_nalu_extract_mode(file, t, GF_ISOM_NALU_EXTRACT_DEFAULT);
        return e;
 }
 
index ed1f57855d3295a851866fad91472ebca393f2de..05bb8fcdacc0fb376ba3c3b1657bf16c5fb60dd5 100644 (file)
@@ -1619,9 +1619,17 @@ GF_M2TS_Mux_Stream *gf_m2ts_program_stream_add(GF_M2TS_Mux_Program *program, str
                        break;
                case GPAC_OTI_VIDEO_AVC:
                        stream->mpeg2_stream_type = GF_M2TS_VIDEO_H264;
-                       /*make sure we send AU delim NALU in same PES as first VCL NAL: 6 bytes (AU delim) + 4 byte start code + first nal header*/
+                       /*make sure we send AU delim NALU in same PES as first VCL NAL: 6 bytes (start code + 1 nal hdr + AU delim) 
+                       + 4 byte start code + first nal header*/
                        stream->min_bytes_copy_from_next = 11;
                        break;
+               case GPAC_OTI_VIDEO_HEVC:
+                       stream->mpeg2_stream_type = GF_M2TS_VIDEO_HEVC;
+                       /*make sure we send AU delim NALU in same PES as first VCL NAL: 7 bytes (4 start code + 2 nal header + 1 AU delim)
+                       + 4 byte start code + first nal header*/
+                       stream->min_bytes_copy_from_next = 12;
+                       break;
+                       
                case GPAC_OTI_VIDEO_MPEG1:
                        stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG1;
                        break;
@@ -1739,6 +1747,7 @@ GF_M2TS_Mux_Program *gf_m2ts_mux_program_add(GF_M2TS_Mux *muxer, u32 program_num
        }
        program->pmt = gf_m2ts_stream_new(pmt_pid);
        program->pmt->program = program;
+       program->pmt->table_needs_update = 1;
        muxer->pat->table_needs_update = 1;
        program->pmt->process = gf_m2ts_stream_process_pmt;
        program->pmt->refresh_rate_ms = pmt_refresh_rate ? pmt_refresh_rate : (u32) -1;
index b8777bcd72574832f4bafd97b0c70730af0d5c16..fdaad15c6f99c5865050fcdaf86d8c6585f1c9e8 100644 (file)
@@ -495,20 +495,30 @@ GF_Err parse_root_playlist(const char * file, VariantPlaylist ** playlist, const
 GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const char * baseURL, Program * in_program, PlaylistElement *sub_playlist)
 {
        int len, i, currentLineNumber;
-       FILE * f;
+       FILE * f=NULL;
+       char *m3u8_payload;
+       u32 m3u8_size, m3u8pos;
        VariantPlaylist * pl;
        char currentLine[M3U8_BUF_SIZE];
        char ** attributes = NULL;
        s_accumulated_attributes attribs;
-       f = gf_f64_open(file, "rt");
-       if (!f) {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_DASH,("[M3U8] Cannot Open m3u8 file %s for reading\n", file));
-               return GF_SERVICE_ERROR;
+
+       if (!strncmp(file, "gmem://", 7)) {
+               if (sscanf(file, "gmem://%d@%p", &m3u8_size, &m3u8_payload) != 2) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH,("[M3U8] Cannot Open m3u8 source %s for reading\n", file));
+                       return GF_SERVICE_ERROR;
+               }
+       } else {
+               f = gf_f64_open(file, "rt");
+               if (!f) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_DASH,("[M3U8] Cannot Open m3u8 file %s for reading\n", file));
+                       return GF_SERVICE_ERROR;
+               }
        }
        if (*playlist == NULL) {
                *playlist = variant_playlist_new();
                if (!(*playlist)) {
-                       fclose(f);
+                       if (f) fclose(f);
                        return GF_OUT_OF_MEM;
                }
        }
@@ -522,8 +532,26 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
        attribs.isPlaylistEnded = 0;
        attribs.minMediaSequence = 0;
        attribs.currentMediaSequence = 0;
-       while (fgets(currentLine, sizeof(currentLine), f)) {
+       m3u8pos=0;
+       while (1) {
                char * eof;
+               if (f) {
+                       if (!fgets(currentLine, sizeof(currentLine), f))
+                               break;
+               } else {
+                       u32 __idx=0;
+                       if (m3u8pos>=m3u8_size)
+                               break;
+                       while (1) {
+                               currentLine[__idx] = m3u8_payload[m3u8pos];
+                               __idx++;
+                               m3u8pos++;
+                               if ((currentLine[__idx-1]=='\n') || (currentLine[__idx-1]=='\r')) {
+                                       currentLine[__idx]=0;
+                                       break;
+                               }
+                       }
+               }
                currentLineNumber++;
                eof = strchr(currentLine, '\r');
                if (eof)
@@ -601,7 +629,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                        if (program == NULL) {
                                                /* OUT of memory */
                                                variant_playlist_del(*playlist);
-                                               fclose(f);
+                                               if (f) fclose(f);
                                                playlist = NULL;
                                                return GF_OUT_OF_MEM;
                                        }
@@ -643,7 +671,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                /* OUT of memory */
                                                variant_playlist_del(*playlist);
                                                playlist = NULL;
-                                               fclose(f);
+                                               if (f) fclose(f);
                                                return GF_OUT_OF_MEM;
                                        }
                                        assert( fullURL);
@@ -671,7 +699,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        /* OUT of memory */
                                                        variant_playlist_del(*playlist);
                                                        playlist = NULL;
-                                                       fclose(f);
+                                                       if (f) fclose(f);
                                                        return GF_OUT_OF_MEM;
                                                }
                                                assert(currentPlayList->element.playlist.elements);
@@ -690,7 +718,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        variant_playlist_del(*playlist);
                                                        playlist_element_del(currentPlayList);
                                                        playlist = NULL;
-                                                       fclose(f);
+                                                       if (f) fclose(f);
                                                        return GF_OUT_OF_MEM;
                                                }
                                                gf_list_add(currentPlayList->element.playlist.elements, subElement);
@@ -717,7 +745,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                                                        variant_playlist_del(*playlist);
                                                        playlist_element_del(currentPlayList);
                                                        playlist = NULL;
-                                                       fclose(f);
+                                                       if (f) fclose(f);
                                                        return GF_OUT_OF_MEM;
                                                }
                                                gf_list_add(currentPlayList->element.playlist.elements, subElement);
@@ -763,7 +791,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const
                        }
                }
        }
-       fclose(f);
+       if (f) fclose(f);
 
        for (i=0; i < (int) gf_list_count(pl->programs); i++) {
                u32 j;
index d112e288015956e0b627fdfbabb7d467b8f3a3c2..ccb528333636e0dd2a3722cd371ca2633b30c2a2 100644 (file)
@@ -42,8 +42,9 @@
 #include <gpac/internal/vobsub.h>
 #endif
 
-
+#ifndef GPAC_DISABLE_ZLIB
 #include <zlib.h>
+#endif
 
 GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc);
 
@@ -287,9 +288,13 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper)
                                gf_export_message(dumper, GF_OK, "Dumping MPEG-4 Visual sample%s", szNum);
                                break;
                        case GPAC_OTI_VIDEO_AVC:
-                               strcpy(szEXT, ".h264");
+                               strcpy(szEXT, ".264");
                                gf_export_message(dumper, GF_OK, "Dumping MPEG-4 AVC-H264 Visual sample%s", szNum);
                                break;
+                       case GPAC_OTI_VIDEO_HEVC:
+                               strcpy(szEXT, ".hvc");
+                               gf_export_message(dumper, GF_OK, "Dumping MPEG-H HEVC Visual sample%s", szNum);
+                               break;
                        case GPAC_OTI_IMAGE_JPEG:
                                strcpy(szEXT, ".jpg");
                                gf_export_message(dumper, GF_OK, "Dumping JPEG image%s", szNum);
@@ -374,9 +379,19 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper)
        } else if (m_stype==GF_ISOM_SUBTYPE_AC3) {
                gf_export_message(dumper, GF_OK, "Extracting AC3 sample%s", szNum);
                strcpy(szEXT, ".ac3");
-       } else if ((m_stype==GF_ISOM_SUBTYPE_AVC_H264) || (m_stype==GF_ISOM_SUBTYPE_AVC2_H264) || (m_stype==GF_ISOM_SUBTYPE_SVC_H264) ) {
+       } else if ((m_stype==GF_ISOM_SUBTYPE_AVC_H264) 
+                       || (m_stype==GF_ISOM_SUBTYPE_AVC2_H264)
+                       || (m_stype==GF_ISOM_SUBTYPE_AVC3_H264)
+                       || (m_stype==GF_ISOM_SUBTYPE_AVC4_H264)
+                       || (m_stype==GF_ISOM_SUBTYPE_SVC_H264)
+               ) {
                strcpy(szEXT, ".h264");
                gf_export_message(dumper, GF_OK, "Dumping MPEG-4 AVC-H264 Visual sample%s", szNum);
+       } else if ((m_stype==GF_ISOM_SUBTYPE_HVC1) 
+                       || (m_stype==GF_ISOM_SUBTYPE_HEV1)
+               ) {
+               strcpy(szEXT, ".hvc");
+               gf_export_message(dumper, GF_OK, "Dumping MPEG-H HEVC Visual sample%s", szNum);
        } else if (m_type==GF_ISOM_MEDIA_FLASH) {
                gf_export_message(dumper, GF_OK, "Extracting Macromedia Flash Movie sample%s", szNum);
                strcpy(szEXT, ".swf");
@@ -617,7 +632,8 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
        char szName[1000], szEXT[5], GUID[16];
        FILE *out;
        unsigned int *qcp_rates, rt_cnt;        /*contains constants*/
-       GF_AVCConfig *avccfg;
+       GF_AVCConfig *avccfg, *svccfg;
+       GF_HEVCConfig *hevccfg;
        GF_M4ADecSpecInfo a_cfg;
        GF_BitStream *bs;
        u32 track, i, di, count, m_type, m_stype, dsi_size, qcp_type;
@@ -629,8 +645,10 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
 
        dsi_size = 0;
        dsi = NULL;
+       hevccfg = NULL;
        avccfg = NULL;
-
+       svccfg = NULL;
+       
        if (!(track = gf_isom_get_track_by_id(dumper->file, dumper->trackID))) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Wrong track ID %d for file %s \n", dumper->trackID, gf_isom_get_filename(dumper->file)));
                return GF_BAD_PARAM;
@@ -667,10 +685,17 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                                break;
                        case GPAC_OTI_VIDEO_AVC:
                                avccfg = gf_isom_avc_config_get(dumper->file, track, 1);
+                               svccfg = gf_isom_svc_config_get(dumper->file, track, 1);
                                if (add_ext) 
                                        strcat(szName, ".h264");
                                gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AVC-H264 stream to h264");
                                break;
+                       case GPAC_OTI_VIDEO_HEVC:
+                               hevccfg = gf_isom_hevc_config_get(dumper->file, track, 1);
+                               if (add_ext) 
+                                       strcat(szName, ".hvc");
+                               gf_export_message(dumper, GF_OK, "Extracting MPEG-H HEVC stream to hevc");
+                               break;
                        case GPAC_OTI_VIDEO_MPEG1:
                                if (add_ext) 
                                        strcat(szName, ".m1v");
@@ -827,11 +852,24 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                                strcat(szName, ".263");
                } else if (m_stype==GF_ISOM_SUBTYPE_3GP_DIMS) {
                        return gf_media_export_nhml(dumper, 1);
-               } else if ((m_stype==GF_ISOM_SUBTYPE_AVC_H264) || (m_stype==GF_ISOM_SUBTYPE_AVC2_H264) || (m_stype==GF_ISOM_SUBTYPE_SVC_H264) ) {
+               } else if ((m_stype==GF_ISOM_SUBTYPE_AVC_H264) 
+                               || (m_stype==GF_ISOM_SUBTYPE_AVC2_H264) 
+                               || (m_stype==GF_ISOM_SUBTYPE_AVC3_H264) 
+                               || (m_stype==GF_ISOM_SUBTYPE_AVC4_H264) 
+                               || (m_stype==GF_ISOM_SUBTYPE_SVC_H264)
+                       ) {
                        avccfg = gf_isom_avc_config_get(dumper->file, track, 1);
+                       svccfg = gf_isom_svc_config_get(dumper->file, track, 1);
                        if (add_ext) 
                                strcat(szName, ".h264");
                        gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AVC-H264 stream to h264");
+               } else if ((m_stype==GF_ISOM_SUBTYPE_HEV1) 
+                               || (m_stype==GF_ISOM_SUBTYPE_HVC1) 
+                       ) {
+                       hevccfg = gf_isom_hevc_config_get(dumper->file, track, 1);
+                       if (add_ext) 
+                               strcat(szName, ".hvc");
+                       gf_export_message(dumper, GF_OK, "Extracting MPEG-H HEVC stream to hevc");
                } else if (m_type==GF_ISOM_MEDIA_FLASH) {
                        gf_export_message(dumper, GF_OK, "Extracting Macromedia Flash Movie");
                        if (add_ext) 
@@ -863,8 +901,12 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
        if (dumper->flags & GF_EXPORT_PROBE_ONLY) {
                if (dsi) gf_free(dsi);
                if (avccfg) gf_odf_avc_cfg_del(avccfg);
+               if (svccfg) gf_odf_avc_cfg_del(svccfg);
+               if (hevccfg) gf_odf_hevc_cfg_del(hevccfg);
                return GF_OK;
        }
+       if (dumper->flags & GF_EXPORT_SVC_LAYER)
+               gf_isom_set_nalu_extract_mode(dumper->file, track, GF_ISOM_NALU_EXTRACT_LAYER_ONLY);
 
        if (is_ogg) return gf_dump_to_ogg(dumper, is_stdout ? NULL : szName, track);
 
@@ -897,6 +939,8 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
        if (!out) {
                if (dsi) gf_free(dsi);
                if (avccfg) gf_odf_avc_cfg_del(avccfg);
+               if (svccfg) gf_odf_avc_cfg_del(svccfg);
+               if (hevccfg) gf_odf_hevc_cfg_del(hevccfg);
                return gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName);
        }
        bs = gf_bs_from_file(out, GF_BITSTREAM_WRITE);
@@ -925,6 +969,92 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                        gf_bs_write_data(bs, sl->data, sl->size);
                }
        }
+       if (svccfg) {
+               if (!(dumper->flags & GF_EXPORT_SVC_LAYER))
+               {
+                       GF_AVCConfig *cfg;
+                       u32 ref_track = 0, t;
+                       s32 countRef;
+
+                       // copy avcC and svcC from base layer
+                       gf_isom_get_reference(dumper->file, track, GF_ISOM_REF_BASE, 1, &ref_track);
+                       cfg = gf_isom_avc_config_get(dumper->file, ref_track, 1);
+                       if (cfg)
+                       {
+                               count = gf_list_count(cfg->sequenceParameterSets);
+                               for (i  =0; i < count; i++) {
+                                       GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->sequenceParameterSets, i);
+                                       gf_bs_write_u32(bs, 1);
+                                       gf_bs_write_data(bs, sl->data, sl->size);
+                               }
+                               count = gf_list_count(cfg->pictureParameterSets);
+                               for (i = 0; i < count; i++) {
+                                       GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->pictureParameterSets, i);
+                                       gf_bs_write_u32(bs, 1);
+                                       gf_bs_write_data(bs, sl->data, sl->size);
+                               }
+                               gf_odf_avc_cfg_del(cfg);
+                               cfg = NULL;
+                       }
+
+                       // copy avcC and svcC from lower layer
+                       countRef = gf_isom_get_reference_count(dumper->file, track, GF_ISOM_REF_SCAL);
+                       if (countRef < 0)
+                       {
+                               e = gf_isom_last_error(dumper->file);
+                               goto exit;
+                       }
+                       for (t = 2; t <= (u32) countRef; t++) // referenceIndex 1 is the base layer
+                       {
+                               gf_isom_get_reference(dumper->file, track, GF_ISOM_REF_SCAL, t, &ref_track);
+                               cfg = gf_isom_svc_config_get(dumper->file, ref_track, 1);
+                               if (cfg)
+                               {
+                                       count = gf_list_count(cfg->sequenceParameterSets);
+                                       for (i  = 0; i < count; i++) {
+                                               GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->sequenceParameterSets, i);
+                                               gf_bs_write_u32(bs, 1);
+                                               gf_bs_write_data(bs, sl->data, sl->size);
+                                       }
+                                       count = gf_list_count(cfg->pictureParameterSets);
+                                       for (i = 0; i < count; i++) {
+                                               GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->pictureParameterSets, i);
+                                               gf_bs_write_u32(bs, 1);
+                                               gf_bs_write_data(bs, sl->data, sl->size);
+                                       }
+                                       gf_odf_avc_cfg_del(cfg);
+                                       cfg = NULL;
+                               }
+                       }
+               }
+
+               count = gf_list_count(svccfg->sequenceParameterSets);
+               for (i=0;i<count;i++) {
+                       GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(svccfg->sequenceParameterSets, i);
+                       gf_bs_write_u32(bs, 1);
+                       gf_bs_write_data(bs, sl->data, sl->size);
+               }
+               count = gf_list_count(svccfg->pictureParameterSets);
+               for (i=0;i<count;i++) {
+                       GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(svccfg->pictureParameterSets, i);
+                       gf_bs_write_u32(bs, 1);
+                       gf_bs_write_data(bs, sl->data, sl->size);
+               }
+       }
+
+
+       if (hevccfg) {
+               count = gf_list_count(hevccfg->param_array);
+               for (i=0;i<count;i++) {
+                       u32 j;
+                       GF_HEVCParamArray *ar = gf_list_get(hevccfg->param_array, i);
+                       for (j=0; j<gf_list_count(ar->nalus); j++) {
+                               GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ar->nalus, j);
+                               gf_bs_write_u32(bs, 1);
+                               gf_bs_write_data(bs, sl->data, sl->size);
+                       }
+               }
+       }
 
        qcp_rates = NULL;
        count = gf_isom_get_sample_count(dumper->file, track);
@@ -1039,19 +1169,23 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                        break;
                }
                /*AVC sample to NALU*/
-               if (avccfg) {
-                       u32 j, nal_size, remain;
+               if (avccfg || svccfg || hevccfg) {
+                       u32 j, nal_size, remain, nal_unit_size;
                        char *ptr = samp->data;
+                       nal_unit_size = 0;
+                       if (avccfg) nal_unit_size= avccfg->nal_unit_size;
+                       else if (svccfg) nal_unit_size = svccfg->nal_unit_size;
+                       else if (hevccfg) nal_unit_size = hevccfg->nal_unit_size;
                        remain = samp->dataLength;
                        while (remain) {
                                nal_size = 0;
-                               if (remain<avccfg->nal_unit_size){
-                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Sample %d (size %d): Corrupted NAL Unit: header size %d - bytes left %d\n", i+1, samp->dataLength, avccfg->nal_unit_size, remain) );
+                               if (remain<nal_unit_size){
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Sample %d (size %d): Corrupted NAL Unit: header size %d - bytes left %d\n", i+1, samp->dataLength, nal_unit_size, remain) );
                                        break;
                                }
-                               for (j=0; j<avccfg->nal_unit_size; j++) {
+                               for (j=0; j<nal_unit_size; j++) {
                                        nal_size |= ((u8) *ptr);
-                                       if (j+1<avccfg->nal_unit_size) nal_size<<=8;
+                                       if (j+1<nal_unit_size) nal_size<<=8;
                                        remain--;
                                        ptr++;
                                }
@@ -1090,14 +1224,15 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper)
                                }
                        }
                }
-               if (!avccfg) gf_bs_write_data(bs, samp->data, samp->dataLength);
+               if (!avccfg && !svccfg && !hevccfg) gf_bs_write_data(bs, samp->data, samp->dataLength);
                gf_isom_sample_del(&samp);
                gf_set_progress("Media Export", i+1, count);
                if (dumper->flags & GF_EXPORT_DO_ABORT) break;
        }
        if (has_qcp_pad) gf_bs_write_u8(bs, 0);
-
+exit:
        if (avccfg) gf_odf_avc_cfg_del(avccfg);
+       if (svccfg) gf_odf_avc_cfg_del(svccfg);
        gf_bs_del(bs);
        if (!is_stdout) 
                fclose(out);
@@ -1429,7 +1564,11 @@ static GF_Err MP4T_CopyTrack(GF_MediaExporter *dumper, GF_ISOFile *infile, u32 i
 
        if (msubtype == GF_ISOM_SUBTYPE_MPEG4_CRYP) {
                esd = gf_isom_get_esd(infile, inTrackNum, 1);
-       } else if ((msubtype == GF_ISOM_SUBTYPE_AVC_H264) || (msubtype == GF_ISOM_SUBTYPE_AVC2_H264) ) {
+       } else if ((msubtype == GF_ISOM_SUBTYPE_AVC_H264) 
+               || (msubtype == GF_ISOM_SUBTYPE_AVC2_H264) 
+               || (msubtype == GF_ISOM_SUBTYPE_AVC3_H264) 
+               || (msubtype == GF_ISOM_SUBTYPE_AVC4_H264) 
+       ) {
                return gf_isom_set_pl_indication(outfile, GF_ISOM_PL_VISUAL, 0x0F);
        } 
        /*likely 3gp or any non-MPEG-4 isomedia file*/
@@ -1848,6 +1987,7 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
                                if (flags & GF_DIMS_UNIT_C) fprintf(nhml, " compressed=\"yes\"");
                                fprintf(nhml, ">");
                                if (uncompress && (flags & GF_DIMS_UNIT_C)) {
+#ifndef GPAC_DISABLE_ZLIB
                                        char svg_data[2049];
                                        int err;
                                        u32 done = 0;
@@ -1874,6 +2014,14 @@ GF_Err gf_media_export_nhml(GF_MediaExporter *dumper, Bool dims_doc)
                                                }
                                                inflateEnd(&d_stream);
                                        }
+#else
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("Error: your version of GPAC was compile with no libz support."));
+                                       gf_bs_del(bs);
+                                       gf_isom_sample_del(&samp);
+                                       if (med) fclose(med);
+                                       fclose(nhml);
+                                       return GF_NOT_SUPPORTED;
+#endif
                                } else {
                                        gf_fwrite(samp->data+pos+3, size-1, 1, nhml);
                                }
@@ -2028,6 +2176,7 @@ GF_Err gf_media_export_saf(GF_MediaExporter *dumper)
 void m2ts_export_check(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) 
 {
        if (evt_type == GF_M2TS_EVT_PAT_REPEAT) ts->user = NULL;
+       else if (evt_type == GF_M2TS_EVT_PAT_FOUND) ts->segment_switch = 1;
 }
 void m2ts_export_dump(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) 
 {
@@ -2073,11 +2222,12 @@ GF_Err gf_media_export_ts_native(GF_MediaExporter *dumper)
                gf_m2ts_process_data(ts, data, (u32)size);
                if (!ts->user) break;
        }
-       if (ts->user) {
+       if (!ts->segment_switch && ts->user) {
                fclose(src);
                gf_m2ts_demux_del(ts);
                return gf_export_message(dumper, GF_URL_ERROR, "Cannot locate program association table");
        }
+       ts->segment_switch = 0;
 
        stream = NULL;
        for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {
@@ -2127,6 +2277,10 @@ GF_Err gf_media_export_ts_native(GF_MediaExporter *dumper)
                strcat(szFile, ".264");
                gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AVC/H264 Visual stream to h264");
                break;
+       case GF_M2TS_VIDEO_HEVC:
+               strcat(szFile, ".hvc");
+               gf_export_message(dumper, GF_OK, "Extracting MPEG-H HEVC Visual stream to hvc");
+               break;
        default:
                strcat(szFile, ".raw");
                gf_export_message(dumper, GF_OK, "Extracting Unknown stream to raw");
index 30c6365328cc7a0400f89cb99fc20bebdcb4daeb..6eda07d5ea29686dfd3096da2af714aed242e943 100644 (file)
@@ -38,8 +38,6 @@
 #include <gpac/xml.h>
 #include <gpac/mpegts.h>
 #include <gpac/constants.h>
-/*since 0.2.2, we use zlib for xmt/x3d reading to handle gz files*/
-#include <zlib.h>
 
 
 #ifndef GPAC_DISABLE_MEDIA_IMPORT
@@ -71,7 +69,9 @@ static GF_Err gf_media_update_par(GF_ISOFile *file, u32 track)
        if (e) return e;
 
        stype = gf_isom_get_media_subtype(file, track, 1);
-       if ((stype==GF_ISOM_SUBTYPE_AVC_H264) || (stype==GF_ISOM_SUBTYPE_AVC2_H264) ) {
+       if ((stype==GF_ISOM_SUBTYPE_AVC_H264) || (stype==GF_ISOM_SUBTYPE_AVC2_H264)
+               || (stype==GF_ISOM_SUBTYPE_AVC3_H264) || (stype==GF_ISOM_SUBTYPE_AVC4_H264)
+       ) {
                s32 par_n, par_d;
                GF_AVCConfig *avcc = gf_isom_avc_config_get(file, track, 1);
                GF_AVCConfigSlot *slc = (GF_AVCConfigSlot *)gf_list_get(avcc->sequenceParameterSets, 0);
@@ -118,7 +118,7 @@ static void MP4T_RecomputeBitRate(GF_ISOFile *file, u32 track)
        esd->decoderConfig->avgBitrate = 0;
        esd->decoderConfig->maxBitrate = 0;
        rate = max_rate = avg_rate = time_wnd = 0;
-
+       
        timescale = gf_isom_get_media_timescale(file, track);
        count = gf_isom_get_sample_count(file, track);
        for (i=0; i<count; i++) {
@@ -1542,13 +1542,13 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
 {
        GF_Err e;
        u64 offset, sampDTS, duration;
-       u32 track, di, trackID, track_in, i, num_samples, mtype, stype, w, h, sr, sbr_sr, ch, mstype;
+       u32 track, di, trackID, track_in, i, num_samples, mtype, w, h, sr, sbr_sr, ch, mstype, cur_extract_mode;
        s32 trans_x, trans_y;
        s16 layer;
        u8 bps;
        char lang[4];
-       const char *url, *urn;
-       Bool sbr, ps, is_clone;
+       const char *orig_name = gf_url_get_resource_name(gf_isom_get_filename(import->orig));
+       Bool sbr, ps;
        GF_ISOSample *samp;
        GF_ESD *origin_esd;
        GF_InitialObjectDescriptor *iod;
@@ -1589,6 +1589,7 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
        ps = 0;
        sbr = 0;
        sbr_sr = 0;
+       cur_extract_mode = gf_isom_get_nalu_extract_mode(import->orig, track_in);
        iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(import->orig);
        if (iod && (iod->tag != GF_ODF_IOD_TAG)) {
                gf_odf_desc_del((GF_Descriptor *) iod);
@@ -1643,72 +1644,16 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
 
        gf_odf_desc_del((GF_Descriptor *) iod);
 
-       /*check if MPEG-4 or not - if crypted use clone track */
-       is_clone = 0;
-       stype = gf_isom_get_media_subtype(import->orig, track_in, 1);
-       if ((stype==GF_ISOM_SUBTYPE_MPEG4) /*|| (stype==GF_ISOM_SUBTYPE_MPEG4_CRYP)*/) {
-               track = gf_isom_new_track(import->dest, import->esd ? import->esd->ESID : 0, gf_isom_get_media_type(import->orig, track_in), gf_isom_get_media_timescale(import->orig, track_in));
-               if (!track) {
-                       e = gf_isom_last_error(import->dest);
-                       goto exit;
-               }
-               gf_isom_set_track_enabled(import->dest, track, 1);
-               if (import->esd && !import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track);
-               /*setup data ref*/
-               urn = url = NULL;
-               if (import->flags & GF_IMPORT_USE_DATAREF) {
-                       url = gf_isom_get_filename(import->orig);
-                       if (!gf_isom_is_self_contained(import->orig, track_in, 1)) {
-                               e = gf_isom_get_data_reference(import->orig, track_in, 1, &url, &urn);
-                               if (e) goto exit;
-                       }
-               }
-               e = gf_isom_new_mpeg4_description(import->dest, track, origin_esd, (char *) url, (char *) urn, &di);
-               if (e) goto exit;
-               /*copy over language*/
-               lang[3] = 0;
-               gf_isom_get_media_language(import->orig, track_in, lang);
-               gf_isom_set_media_language(import->dest, track, lang);
+       e = gf_isom_clone_track(import->orig, track_in, import->dest, (import->flags & GF_IMPORT_USE_DATAREF), &track);
+       if (e) goto exit;
 
-       } else {
-               if (! (import->flags & GF_IMPORT_KEEP_ALL_TRACKS) ) {
-                       mstype = gf_isom_get_media_subtype(import->orig, track_in, 1);
-                       switch (mstype) {
-                       case GF_ISOM_SUBTYPE_MPEG4:
-                       case GF_ISOM_SUBTYPE_MPEG4_CRYP:
-                       case GF_ISOM_SUBTYPE_AVC_H264:
-                       case GF_ISOM_SUBTYPE_AVC2_H264:
-                       case GF_ISOM_SUBTYPE_SVC_H264:
-                       case GF_ISOM_SUBTYPE_3GP_H263:
-                       case GF_ISOM_SUBTYPE_3GP_AMR:
-                       case GF_ISOM_SUBTYPE_3GP_AMR_WB:
-                       case GF_ISOM_SUBTYPE_3GP_EVRC:
-                       case GF_ISOM_SUBTYPE_3GP_QCELP:
-                       case GF_ISOM_SUBTYPE_3GP_SMV:
-                               break;
-                       default:
-                               switch (mtype) {
-                               case GF_ISOM_MEDIA_HINT:
-                               case GF_ISOM_MEDIA_TEXT:
-                               case GF_ISOM_MEDIA_SUBT:
-                                       break;
-                               default:
-                                       return gf_import_message(import, GF_OK, "IsoMedia import - skipping track ID %d (unknown type \'%s\')", trackID, gf_4cc_to_str(mstype));
-                               }
-                       }
+       di = 1;
 
-               }
-               e = gf_isom_clone_track(import->orig, track_in, import->dest, (import->flags & GF_IMPORT_USE_DATAREF), &track);
-               is_clone = 1;
-               di = 1;
+       if (import->esd && import->esd->ESID) {
+               e = gf_isom_set_track_id(import->dest, track, import->esd->ESID);
                if (e) goto exit;
-
-               if (import->esd && import->esd->ESID) {
-                       e = gf_isom_set_track_id(import->dest, track, import->esd->ESID);
-                       if (e) goto exit;
-               }
        }
-       if (e) goto exit;
+
        import->final_trackID = gf_isom_get_track_id(import->dest, track);
        if (import->esd && import->esd->dependsOnESID) {
                gf_isom_set_track_reference(import->dest, track, GF_ISOM_REF_DECODE, import->esd->dependsOnESID);
@@ -1716,29 +1661,21 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
 
        switch (mtype) {
        case GF_ISOM_MEDIA_VISUAL:
-               if (!is_clone) {
-                       gf_isom_set_visual_info(import->dest, track, di, w, h);
-                       gf_media_update_par(import->dest, track);
-               }
-               gf_import_message(import, GF_OK, "IsoMedia import - track ID %d - Video (size %d x %d)", trackID, w, h);
+               gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - Video (size %d x %d)", orig_name, trackID, w, h);
                break;
        case GF_ISOM_MEDIA_AUDIO:
        {
-               if (!is_clone) gf_isom_set_audio_info(import->dest, track, di, (sbr==2) ? sbr_sr : sr, (ch>1) ? 2 : 1, bps);
                if (ps) {
-                       gf_import_message(import, GF_OK, "IsoMedia import - track ID %d - HE-AACv2 (SR %d - SBR-SR %d - %d channels)", trackID, sr, sbr_sr, ch);
+                       gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - HE-AACv2 (SR %d - SBR-SR %d - %d channels)", orig_name, trackID, sr, sbr_sr, ch);
                } else if (sbr) {
-                       gf_import_message(import, GF_OK, "IsoMedia import - track ID %d - HE-AAC (SR %d - SBR-SR %d - %d channels)", trackID, sr, sbr_sr, ch);
+                       gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - HE-AAC (SR %d - SBR-SR %d - %d channels)", orig_name, trackID, sr, sbr_sr, ch);
                } else {
-                       gf_import_message(import, GF_OK, "IsoMedia import - track ID %d - Audio (SR %d - %d channels)", trackID, sr, ch);
+                       gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - Audio (SR %d - %d channels)", orig_name, trackID, sr, ch);
                }
        }
                break;
        case GF_ISOM_MEDIA_SUBPIC:
-               if (!is_clone) {
-                       gf_isom_set_track_layout_info(import->dest, track, w << 16, h << 16, trans_x, trans_y, layer);
-               }
-               gf_import_message(import, GF_OK, "IsoMedia import - track ID %d - VobSub (size %d x %d)", trackID, w, h);
+               gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - VobSub (size %d x %d)", orig_name, trackID, w, h);
                break;
        default:
        {
@@ -1746,14 +1683,13 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
                mstype = gf_isom_get_mpeg4_subtype(import->orig, track_in, di);
                if (!mstype) mstype = gf_isom_get_media_subtype(import->orig, track_in, di);
                strcpy(szT, gf_4cc_to_str(mtype));
-               gf_import_message(import, GF_OK, "IsoMedia import - track ID %d - media type \"%s:%s\"",
-                       trackID, szT, gf_4cc_to_str(mstype));
+               gf_import_message(import, GF_OK, "IsoMedia import %s - track ID %d - media type \"%s:%s\"", orig_name, trackID, szT, gf_4cc_to_str(mstype));
        }
                break;
        }
 
        duration = (u64) (((Double)import->duration * gf_isom_get_media_timescale(import->orig, track_in)) / 1000);
-
+       gf_isom_set_nalu_extract_mode(import->orig, track_in, GF_ISOM_NALU_EXTRACT_INSPECT);
        num_samples = gf_isom_get_sample_count(import->orig, track_in);
        for (i=0; i<num_samples; i++) {
                if (import->flags & GF_IMPORT_USE_DATAREF) {
@@ -1808,6 +1744,7 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import)
 
 exit:
        if (origin_esd) gf_odf_desc_del((GF_Descriptor *) origin_esd);
+       gf_isom_set_nalu_extract_mode(import->orig, track_in, cur_extract_mode);
        return e;
 }
 
@@ -2478,6 +2415,12 @@ exit:
        return e;
 }
 
+
+#ifndef GPAC_DISABLE_ZLIB
+
+/*since 0.2.2, we use zlib for xmt/x3d reading to handle gz files*/
+#include <zlib.h>
+
 #define ZLIB_COMPRESS_SAFE     4
 
 static GF_Err compress_sample_data(GF_ISOSample *samp, u32 *max_size, char **dict, u32 offset)
@@ -2534,6 +2477,8 @@ static GF_Err compress_sample_data(GF_ISOSample *samp, u32 *max_size, char **dic
        return GF_OK;
 }
 
+#endif /*GPAC_DISABLE_ZLIB*/
+
 static void nhml_on_progress(void *cbk, u64 done, u64 tot)
 {
        gf_set_progress("NHML Loading", done, tot);
@@ -3003,6 +2948,7 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc)
                }
 
                if (compress) {
+#ifndef GPAC_DISABLE_ZLIB
                        e = compress_sample_data(samp, &max_size, use_dict ? &dictionary : NULL, is_dims ? 3 : 0);
                        if (e) goto exit;
                        if (is_dims) {
@@ -3010,6 +2956,11 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc)
                                gf_bs_write_u16(bs, samp->dataLength-2);
                                gf_bs_del(bs);
                        }
+#else
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error: your version of GPAC was compile with no libz support. Abort."));
+                       e = GF_NOT_SUPPORTED;
+                       goto exit;
+#endif
                }
                if (is_dims && (samp->dataLength > 0xFFFF)) {
                        e = gf_import_message(import, GF_BAD_PARAM, "DIMS import failure: sample data is too long - maximum size allowed: 65532 bytes");
@@ -3768,7 +3719,7 @@ GF_Err gf_media_avc_rewrite_samples(GF_ISOFile *file, u32 track, u32 prev_size,
 
 #ifndef GPAC_DISABLE_AV_PARSERS
 
-GF_Err gf_import_h264(GF_MediaImporter *import)
+static GF_Err gf_import_avc_h264(GF_MediaImporter *import)
 {
        u64 nal_start, nal_end, total_size;
        u32 nal_size, track, trackID, di, cur_samp, nb_i, nb_idr, nb_p, nb_b, nb_sp, nb_si, nb_sei, max_w, max_h, max_total_delay;
@@ -3837,7 +3788,7 @@ restart_import:
        sei_recovery_frame_count = -1;
 
        bs = gf_bs_from_file(mdia, GF_BITSTREAM_READ);
-       if (!AVC_IsStartCode(bs)) {
+       if (!gf_media_nalu_is_start_code(bs)) {
                e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Cannot find H264 start code");
                goto exit;
        }
@@ -3893,7 +3844,7 @@ restart_import:
 
        while (gf_bs_available(bs)) {
                u8 nal_hdr, skip_nal, is_subseq, add_sps;
-               nal_size = AVC_NextStartCode(bs);
+               nal_size = gf_media_nalu_next_start_code_bs(bs);
 
                if (nal_size>max_size) {
                        buffer = (char*)gf_realloc(buffer, sizeof(char)*nal_size);
@@ -3915,7 +3866,7 @@ restart_import:
                        avc.is_svc = 1;
                }
 
-               switch (AVC_ParseNALU(bs, nal_hdr, &avc)) {
+               switch (gf_media_avc_parse_nalu(bs, nal_hdr, &avc)) {
                case 1:
                        flush_sample = 1;
                        break;
@@ -3933,7 +3884,7 @@ restart_import:
                case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
                        is_subseq = 1;
                case GF_AVC_NALU_SEQ_PARAM:
-                       idx = AVC_ReadSeqInfo(buffer+1/*skip NALU type*/, nal_size-1, &avc, is_subseq, NULL);
+                       idx = gf_media_avc_read_sps(buffer, nal_size, &avc, is_subseq, NULL);
                        if (idx<0) {
                                if (avc.sps[0].profile_idc) {
                                        GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("Error parsing SeqInfo"));
@@ -4050,7 +4001,7 @@ restart_import:
                        }
                        break;
                case GF_AVC_NALU_PIC_PARAM:
-                       idx = AVC_ReadPictParamSet(buffer+1/*skip NALU type*/, nal_size-1, &avc);
+                       idx = gf_media_avc_read_pps(buffer, nal_size, &avc);
                        if (idx<0) {
                                e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Error parsing Picture Param");
                                goto exit;
@@ -4075,12 +4026,15 @@ restart_import:
                                  they will be moved to the SVC layer upon analysis of SVC slice. */
                                dstcfg = avccfg;
 
+                               if (import->flags & GF_IMPORT_SVC_EXPLICIT)
+                                       dstcfg = svccfg;
+
                                gf_list_add(dstcfg->pictureParameterSets, slc);
                        }
                        break;
                case GF_AVC_NALU_SEI:
                        if (avc.sps_active_idx != -1) {
-                               copy_size = AVC_ReformatSEI_NALU(buffer, nal_size, &avc);
+                               copy_size = gf_media_avc_reformat_sei(buffer, nal_size, &avc);
                                if (copy_size)
                                        nb_sei++;
                        }
@@ -4149,7 +4103,7 @@ restart_import:
                        break;
 
                case GF_AVC_NALU_SEQ_PARAM_EXT:
-                       idx = AVC_ReadSeqParamSetExtId(buffer+1/*skip NALU type*/, nal_size-1);
+                       idx = gf_media_avc_read_sps_ext(buffer, nal_size);
                        if (idx<0) {
                                e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Error parsing Sequence Param Extension");
                                goto exit;
@@ -4363,7 +4317,7 @@ restart_import:
                                if (first_nal) {
                                        first_nal = 0;
                                        if (avc.sei.recovery_point.valid || (import->flags & GF_IMPORT_FORCE_SYNC)) {
-                                               Bool bIntraSlice = AVC_SliceIsIntra(&avc);
+                                               Bool bIntraSlice = gf_media_avc_slice_is_intra(&avc);
                                                assert(avc.s_info.nal_unit_type!=GF_AVC_NALU_IDR_SLICE || bIntraSlice);
 
                                                sei_recovery_frame_count = avc.sei.recovery_point.frame_cnt;
@@ -4380,7 +4334,7 @@ restart_import:
                                                if (bIntraSlice && (import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) 
                                                        slice_force_ref = 1;
                                        }
-                                       sample_is_rap = AVC_SliceIsIDR(&avc);
+                                       sample_is_rap = gf_media_avc_slice_is_IDR(&avc);
                                }
 
                                if (avc.s_info.poc<poc_shift) {
@@ -4463,19 +4417,19 @@ restart_import:
                if (import->flags & GF_IMPORT_DO_ABORT) break;
 
                /*consume next start code*/
-               nal_start = AVC_NextStartCode(bs);
+               nal_start = gf_media_nalu_next_start_code_bs(bs);
                if (nal_start) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[avc-h264] invalid nal_size (%u)? Skipping "LLU" bytes to reach next start code\n", nal_size, nal_start));
                        gf_bs_skip_bytes(bs, nal_start);
                }
-               nal_start = AVC_IsStartCode(bs);
+               nal_start = gf_media_nalu_is_start_code(bs);
                if (!nal_start) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[avc-h264] error: no start code found ("LLU" bytes read out of "LLU") - leaving\n", gf_bs_get_position(bs), gf_bs_get_size(bs)));
                        break;
                }
                nal_start = gf_bs_get_position(bs);
        }
-
+       
        /*final flush*/
        if (sample_data) {
                GF_ISOSample *samp = gf_isom_sample_new();
@@ -4644,157 +4598,901 @@ exit:
        return e;
 }
 
-#endif /*GPAC_DISABLE_AV_PARSERS*/
 
-#ifndef GPAC_DISABLE_OGG
+static GF_Err gf_import_hevc(GF_MediaImporter *import)
+{
+       u64 nal_start, nal_end, total_size;
+       u32 nal_size, track, trackID, di, cur_samp, nb_i, nb_idr, nb_p, nb_b, nb_sp, nb_si, nb_sei, max_w, max_h, max_total_delay;
+       s32 idx, sei_recovery_frame_count;
+       u64 duration;
+       GF_Err e;
+       FILE *mdia;
+       HEVCState hevc;
+       GF_AVCConfigSlot *slc;
+       GF_HEVCConfig *hevccfg;
+       GF_HEVCParamArray *spss, *ppss, *vpss;
+       GF_BitStream *bs;
+       GF_BitStream *sample_data;
+       Bool flush_sample, sample_is_rap, sample_has_islice, first_nal, slice_is_ref, has_cts_offset, is_paff, set_subsamples, slice_force_ref;
+       u32 ref_frame, timescale, copy_size, size_length, dts_inc;
+       s32 last_poc, max_last_poc, max_last_b_poc, poc_diff, prev_last_poc, min_poc, poc_shift;
+       Bool first_avc;
+       Bool use_opengop_gdr = 0;
 
-#define OGG_BUFFER_SIZE 4096
+       Double FPS;
+       char *buffer;
+       u32 max_size = 4096;
 
-Bool OGG_ReadPage(FILE *f_in, ogg_sync_state *oy, ogg_page *oggpage)
-{
-       if (feof(f_in)) return 0;
-       while (ogg_sync_pageout(oy, oggpage ) != 1 ) {
-               char *buffer = ogg_sync_buffer(oy, OGG_BUFFER_SIZE);
-               u32 bytes = fread(buffer, sizeof(char), OGG_BUFFER_SIZE, f_in);
-               ogg_sync_wrote(oy, bytes);
-               if (feof(f_in)) return 1;
+       if (import->flags & GF_IMPORT_PROBE_ONLY) {
+               import->nb_tracks = 1;
+               import->tk_info[0].track_num = 1;
+               import->tk_info[0].type = GF_ISOM_MEDIA_VISUAL;
+               import->tk_info[0].flags = GF_IMPORT_OVERRIDE_FPS | GF_IMPORT_FORCE_PACKED;
+               return GF_OK;
        }
-       return 1;
-}
 
-static u32 get_ogg_serial_no_for_stream(char *fileName, u32 stream_num, Bool is_video)
-{
-       ogg_sync_state oy;
-       u32 track, serial_no;
-       ogg_page oggpage;
-       ogg_packet oggpacket;
-       ogg_stream_state os;
-       FILE *f_in;
+       set_subsamples = (import->flags & GF_IMPORT_SET_SUBSAMPLES) ? 1 : 0;
 
-       /*means first one*/
-       if (!stream_num) return 0;
+       mdia = gf_f64_open(import->in_name, "rb");
+       if (!mdia) return gf_import_message(import, GF_URL_ERROR, "Cannot find file %s", import->in_name);
 
-       f_in = gf_f64_open(fileName, "rb");
-       if (!f_in) return 0;
+       //detect_fps = 1;
+       FPS = (Double) import->video_fps;
+       if (!FPS) {
+               FPS = GF_IMPORT_DEFAULT_FPS;
+       } else {
+               if (import->video_fps == GF_IMPORT_AUTO_FPS) {
+                       import->video_fps = GF_IMPORT_DEFAULT_FPS;      /*fps=auto is handled as auto-detection is h264*/
+               } else {
+                       /*fps is forced by the caller*/
+                       //detect_fps = 0;
+               }       
+       }
+       get_video_timing(FPS, &timescale, &dts_inc);
 
-       track = 0;
-       serial_no = 0;
-       ogg_sync_init(&oy);
-       while (1) {
-               if (!OGG_ReadPage(f_in, &oy, &oggpage)) break;
-               if (!ogg_page_bos(&oggpage)) break;
-               track ++;
-               if (track != stream_num) continue;
+       poc_diff = 0;
 
-               serial_no = ogg_page_serialno(&oggpage);
-               ogg_stream_init(&os, serial_no);
-               ogg_stream_pagein(&os, &oggpage);
-               ogg_stream_packetpeek(&os, &oggpacket);
 
-               if (is_video && (oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "theora", 6)) {
-                       ogg_stream_clear(&os);
-                       break;
-               }
-               if (!is_video && (oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "vorbis", 6)) {
-                       ogg_stream_clear(&os);
-                       break;
-               }
-               ogg_stream_clear(&os);
-               serial_no = 0;
-       }
-       ogg_sync_clear(&oy);
-       fclose(f_in);
-       return serial_no;
-}
+//restart_import:
 
-GF_Err gf_import_ogg_video(GF_MediaImporter *import)
-{
-       GF_Err e;
-       ogg_sync_state oy;
-       u32 di, track;
-       u64 tot_size, done, duration;
-       u32 w, h, fps_num, fps_den, keyframe_freq_force, theora_kgs, flag, dts_inc, timescale;
-       Double FPS;
-       Bool destroy_esd, go;
-       u32 serial_no, sno, num_headers;
-       ogg_packet oggpacket;
-       ogg_page oggpage;
-       ogg_stream_state os;
-       oggpack_buffer opb;
-       GF_BitStream *bs;
-       FILE *f_in;
-       GF_ISOSample *samp;
+       memset(&hevc, 0, sizeof(HEVCState));
+       hevc.sps_active_idx = -1;
+       hevccfg = gf_odf_hevc_cfg_new();
+       buffer = (char*)gf_malloc(sizeof(char) * max_size);
+       sample_data = NULL;
+       first_avc = 1;
+       sei_recovery_frame_count = -1;
+       spss = ppss = vpss = NULL;
 
+       bs = gf_bs_from_file(mdia, GF_BITSTREAM_READ);
+       if (!gf_media_nalu_is_start_code(bs)) {
+               e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Cannot find H264 start code");
+               goto exit;
+       }
 
-       dts_inc = 0;
-       /*assume audio or simple AV file*/
-       if (import->flags & GF_IMPORT_PROBE_ONLY) {
-               f_in = gf_f64_open(import->in_name, "rb");
-               if (!f_in) return GF_URL_ERROR;
+       /*NALU size packing disabled*/
+       if (!(import->flags & GF_IMPORT_FORCE_PACKED)) size_length = 32;
+       /*if import in edit mode, use smallest NAL size and adjust on the fly*/
+       else if (gf_isom_get_mode(import->dest)!=GF_ISOM_OPEN_WRITE) size_length = 8;
+       else size_length = 32;
 
-               import->nb_tracks = 0;
-               go = 1;
-               ogg_sync_init(&oy);
-               while (go) {
-                       if (!OGG_ReadPage(f_in, &oy, &oggpage)) break;
+       trackID = 0;
+       e = GF_OK;
+       if (import->esd) trackID = import->esd->ESID;
 
-                       if (!ogg_page_bos(&oggpage)) {
-                               go = 0;
-                               continue;
-                       }
-                       serial_no = ogg_page_serialno(&oggpage);
-                       ogg_stream_init(&os, serial_no);
-                       ogg_stream_pagein(&os, &oggpage);
-                       ogg_stream_packetpeek(&os, &oggpacket);
+       track = gf_isom_new_track(import->dest, trackID, GF_ISOM_MEDIA_VISUAL, timescale);
+       if (!track) {
+               e = gf_isom_last_error(import->dest);
+               goto exit;
+       }
+       gf_isom_set_track_enabled(import->dest, track, 1);
+       if (import->esd && !import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track);
+       import->final_trackID = gf_isom_get_track_id(import->dest, track);
+       if (import->esd && import->esd->dependsOnESID) {
+               gf_isom_set_track_reference(import->dest, track, GF_ISOM_REF_DECODE, import->esd->dependsOnESID);
+       }
 
-                       import->tk_info[import->nb_tracks].track_num = import->nb_tracks+1;
-                       if ((oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "theora", 6)) {
-                               import->tk_info[import->nb_tracks].type = GF_ISOM_MEDIA_VISUAL;
-                               import->tk_info[import->nb_tracks].flags = GF_IMPORT_OVERRIDE_FPS;
+       e = gf_isom_hevc_config_new(import->dest, track, hevccfg, NULL, NULL, &di);
+       if (e) goto exit;
 
-                               bs = gf_bs_new((char*)oggpacket.packet, oggpacket.bytes, GF_BITSTREAM_READ);
-                               gf_bs_read_int(bs, 80);
-                               import->tk_info[import->nb_tracks].video_info.width = gf_bs_read_u16(bs) << 4;
-                               import->tk_info[import->nb_tracks].video_info.height = gf_bs_read_u16(bs) << 4;
-                               gf_bs_read_int(bs, 64);
-                               fps_num = gf_bs_read_u32(bs);
-                               fps_den = gf_bs_read_u32(bs);
-                               gf_bs_del(bs);
-                               import->tk_info[import->nb_tracks].video_info.FPS = fps_num;
-                               import->tk_info[import->nb_tracks].video_info.FPS /= fps_den;
-                               import->tk_info[import->nb_tracks].media_type = GF_4CC('t','h','e','o');
-                       } else if ((oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "vorbis", 6)) {
-                               import->tk_info[import->nb_tracks].type = GF_ISOM_MEDIA_AUDIO;
-                               import->tk_info[import->nb_tracks].flags = 0;
-                       }
-                       ogg_stream_clear(&os);
-                       import->nb_tracks++;
-               }
-               ogg_sync_clear(&oy);
-               fclose(f_in);
-               return GF_OK;
-       }
+       sample_data = NULL;
+       sample_is_rap = 0;
+       sample_has_islice = 0;
+       cur_samp = 0;
+       is_paff = 0;
+       total_size = gf_bs_get_size(bs);
+       nal_start = gf_bs_get_position(bs);
+       duration = (u64) ( ((Double)import->duration) * timescale / 1000.0);
 
-       if (import->flags & GF_IMPORT_USE_DATAREF) return gf_import_message(import, GF_NOT_SUPPORTED, "Cannot use data referencing with OGG files");
+       nb_i = nb_idr = nb_p = nb_b = nb_sp = nb_si = nb_sei = 0;
+       max_w = max_h = 0;
+       first_nal = 1;
+       ref_frame = 0;
+       last_poc = max_last_poc = max_last_b_poc = prev_last_poc = 0;
+       max_total_delay = 0;
 
-       sno = get_ogg_serial_no_for_stream(import->in_name, import->trackID, 1);
-       /*not our stream*/
-       if (!sno && import->trackID) return GF_OK;
+       gf_isom_set_cts_packing(import->dest, track, 1);
+       has_cts_offset = 0;
+       min_poc = 0;
+       poc_shift = 0;
 
-       f_in = gf_f64_open(import->in_name, "rb");
-       if (!f_in) return gf_import_message(import, GF_URL_ERROR, "Opening file %s failed", import->in_name);
+       while (gf_bs_available(bs)) {
+               s32 res;
+               u8 nal_unit_type, temporal_id;
+               Bool skip_nal, add_sps, is_slice;
+               nal_size = gf_media_nalu_next_start_code_bs(bs);
 
-       e = GF_OK;
-       done = 0;
-       gf_f64_seek(f_in, 0, SEEK_END);
-       tot_size = gf_f64_tell(f_in);
-       gf_f64_seek(f_in, 0, SEEK_SET);
+               if (nal_size>max_size) {
+                       buffer = (char*)gf_realloc(buffer, sizeof(char)*nal_size);
+                       max_size = nal_size;
+               }
 
+               /*read the file, and work on a memory buffer*/
+               gf_bs_read_data(bs, buffer, nal_size);
 
-       destroy_esd = 0;
-       samp = gf_isom_sample_new();
+               gf_bs_seek(bs, nal_start);
 
-       /*avoids gcc warnings*/
+               res = gf_media_hevc_parse_nalu(bs, &hevc, &nal_unit_type, &temporal_id);
+
+               skip_nal = 0;
+               copy_size = flush_sample = 0;
+               is_slice = 0;
+
+               switch (res) {
+               case 1:
+                       flush_sample = 1;
+                       break;
+               case -1:
+                       gf_import_message(import, GF_OK, "Waring: Error parsing NAL unit");
+                       skip_nal = 1;
+                       break;
+               case -2:
+                       skip_nal = 1;
+                       break;
+               default:
+                       break;
+               }
+               switch (nal_unit_type) {
+               case GF_HEVC_NALU_VID_PARAM:
+                       idx = gf_media_hevc_read_vps(buffer, nal_size , &hevc);
+                       if (idx<0) {
+                               e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Error parsing Picture Param");
+                               goto exit;
+                       }
+                       /*if we get twice the same VPS put in the the bitstream and set array_completeness to 0 ...*/
+                       if (hevc.vps[idx].state == 2) {
+                               copy_size = nal_size;
+                               assert(vpss);
+                               vpss->array_completeness = 0;
+                       }
+
+                       if (hevc.vps[idx].state==1) {
+                               hevc.vps[idx].state = 2;
+
+                               hevccfg->avgFrameRate = hevc.vps[idx].rates[0].avg_pic_rate;
+                               hevccfg->constantFrameRate = hevc.vps[idx].rates[0].constand_pic_rate_idc;
+                               hevccfg->numTemporalLayers = hevc.vps[idx].max_sub_layer;
+
+                               if (!vpss) {
+                                       GF_SAFEALLOC(vpss, GF_HEVCParamArray);
+                                       vpss->nalus = gf_list_new();
+                                       gf_list_add(hevccfg->param_array, vpss);
+                                       vpss->array_completeness = 1;
+                                       vpss->type = GF_HEVC_NALU_VID_PARAM;
+                               }
+
+                               slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                               slc->size = nal_size;
+                               slc->id = idx;
+                               slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
+                               memcpy(slc->data, buffer, sizeof(char)*slc->size);
+
+                               gf_list_add(vpss->nalus, slc);
+                       }
+                       break;
+               case GF_HEVC_NALU_SEQ_PARAM:
+                       idx = gf_media_hevc_read_sps(buffer, nal_size, &hevc);
+                       if (idx<0) {
+                               e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Error parsing SeqInfo");
+                               goto exit;
+                       }
+                       add_sps = 0;
+                       if ((hevc.sps[idx].state & AVC_SPS_PARSED) && !(hevc.sps[idx].state & AVC_SPS_DECLARED)) {
+                               hevc.sps[idx].state |= AVC_SPS_DECLARED;
+                               add_sps = 1;
+                       }
+
+                       /*if we get twice the same VPS put in the the bitstream and set array_completeness to 0 ...*/
+                       if (hevc.sps[idx].state & AVC_SUBSPS_DECLARED) {
+                               if (import->flags & GF_IMPORT_SVC_NONE) {
+                                       copy_size = 0;
+                               } else {
+                                       copy_size = nal_size;
+                                       assert(spss);
+                                       spss->array_completeness = 0;
+                               }
+                       }
+
+                       if (add_sps) {
+                               hevccfg->configurationVersion = 1;
+                               hevccfg->profile_space = hevc.sps[idx].ptl.profile_space;
+                               hevccfg->profile_idc = hevc.sps[idx].ptl.profile_idc;
+                               hevccfg->constraint_indicator_flags = 0;
+                               hevccfg->level_idc = hevc.sps[idx].ptl.level_idc;
+                               hevccfg->profile_compatibility_indications = hevc.sps[idx].ptl.profile_compatibility_flag;
+                               hevccfg->chromaFormat = hevc.sps[idx].chroma_format_idc;
+                               hevccfg->luma_bit_depth = hevc.sps[idx].bit_depth_luma;
+                               hevccfg->chroma_bit_depth = hevc.sps[idx].bit_depth_chroma;
+
+                               /*
+                               todo FPS detection
+                                       
+                                       timescale = 2 * avc.sps[idx].vui.time_scale;
+                                       dts_inc =   2 * avc.sps[idx].vui.num_units_in_tick * DeltaTfiDivisorIdx;
+                                       FPS = (Double)timescale / dts_inc;
+                                       detect_fps = 0;
+                                       gf_isom_remove_track(import->dest, track);
+                                       if (sample_data) gf_bs_del(sample_data);
+                                       gf_odf_avc_cfg_del(avccfg);
+                                       avccfg = NULL;
+                                       gf_free(buffer);
+                                       buffer = NULL;
+                                       gf_bs_del(bs);
+                                       bs = NULL;
+                                       gf_f64_seek(mdia, 0, SEEK_SET);
+                                       goto restart_import;
+                               }
+                       */
+
+                               if (!spss) {
+                                       GF_SAFEALLOC(spss, GF_HEVCParamArray);
+                                       spss->nalus = gf_list_new();
+                                       gf_list_add(hevccfg->param_array, spss);
+                                       spss->array_completeness = 1;
+                                       spss->type = GF_HEVC_NALU_SEQ_PARAM;
+                               }
+
+                               slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                               slc->size = nal_size;
+                               slc->id = idx;
+                               slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
+                               memcpy(slc->data, buffer, sizeof(char)*slc->size);
+                               gf_list_add(spss->nalus, slc);
+
+                               if (first_avc) {
+                                       first_avc = 0;
+                                       gf_import_message(import, GF_OK, "AVC-H264 import - frame size %d x %d at %02.3f FPS", hevc.sps[idx].width, hevc.sps[idx].height, FPS);
+                               }
+
+                               if ((max_w <= hevc.sps[idx].width) && (max_h <= hevc.sps[idx].height)) {
+                                       max_w = hevc.sps[idx].width;
+                                       max_h = hevc.sps[idx].height;
+                               }
+                       }
+                       break;
+
+               case GF_HEVC_NALU_PIC_PARAM:
+                       idx = gf_media_hevc_read_pps(buffer, nal_size, &hevc);
+                       if (idx<0) {
+                               e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Error parsing Picture Param");
+                               goto exit;
+                       }
+                       /*if we get twice the same VPS put in the the bitstream and set array_completeness to 0 ...*/
+                       if (hevc.pps[idx].state == 2) {
+                               copy_size = nal_size;
+                               assert(ppss);
+                               ppss->array_completeness = 0;
+                       }
+
+                       if (hevc.pps[idx].state==1) {
+                               hevc.pps[idx].state = 2;
+
+                               if (!ppss) {
+                                       GF_SAFEALLOC(ppss, GF_HEVCParamArray);
+                                       ppss->nalus = gf_list_new();
+                                       gf_list_add(hevccfg->param_array, ppss);
+                                       ppss->array_completeness = 1;
+                                       ppss->type = GF_HEVC_NALU_PIC_PARAM;
+                               }
+
+                               slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
+                               slc->size = nal_size;
+                               slc->id = idx;
+                               slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
+                               memcpy(slc->data, buffer, sizeof(char)*slc->size);
+
+                               gf_list_add(ppss->nalus, slc);
+                       }
+                       break;
+               case GF_HEVC_NALU_SEI_PREFIX:
+                       if (hevc.sps_active_idx != -1) {
+                               /*TODO*/
+                               //copy_size = gf_media_avc_reformat_sei(buffer, nal_size, &hevc);
+                               copy_size = nal_size;
+                               if (copy_size)
+                                       nb_sei++;
+                       }
+                       break;
+
+               /*slice_layer_rbsp*/
+//             case GF_HEVC_NALU_SLICE_STSA_N:
+//             case GF_HEVC_NALU_SLICE_STSA_R:
+               case GF_HEVC_NALU_SLICE_RADL_N:
+//             case GF_HEVC_NALU_SLICE_RADL_R:
+               case GF_HEVC_NALU_SLICE_RASL_N:
+//             case GF_HEVC_NALU_SLICE_RASL_R:         
+                       is_slice = 1;
+                       if (! skip_nal) {
+                               copy_size = nal_size;
+                       }
+                       break;
+
+               /*slice_segment_layer_rbsp*/
+               case GF_HEVC_NALU_SLICE_STSA_N:
+               case GF_HEVC_NALU_SLICE_STSA_R:
+               case GF_HEVC_NALU_SLICE_RADL_R:
+               case GF_HEVC_NALU_SLICE_RASL_R:         
+               case GF_HEVC_NALU_SLICE_TRAIL_N:
+               case GF_HEVC_NALU_SLICE_TRAIL_R:
+               case GF_HEVC_NALU_SLICE_TSA_N:
+               case GF_HEVC_NALU_SLICE_TSA_R:
+               case GF_HEVC_NALU_SLICE_BLA_W_LP:
+               case GF_HEVC_NALU_SLICE_BLA_W_DLP:
+               case GF_HEVC_NALU_SLICE_BLA_N_LP:
+               case GF_HEVC_NALU_SLICE_IDR_W_DLP:
+               case GF_HEVC_NALU_SLICE_IDR_N_LP:
+               case GF_HEVC_NALU_SLICE_CRA:
+                       is_slice = 1;
+                       if (! skip_nal) {
+                               copy_size = nal_size;
+                               switch (hevc.s_info.slice_type) {
+                               case GF_HEVC_TYPE_P: nb_p++; break;
+                               case GF_HEVC_TYPE_I: nb_i++; 
+                                       sample_has_islice = 1;
+                                       break;
+                               case GF_HEVC_TYPE_B: nb_b++; break;
+                               }
+                       }
+                       break;
+
+               /*remove*/
+               case GF_HEVC_NALU_ACCESS_UNIT:
+               case GF_HEVC_NALU_FILLER_DATA:
+               case GF_HEVC_NALU_END_OF_SEQ:
+               case GF_HEVC_NALU_END_OF_STREAM:
+                       break;
+
+               default:
+                       gf_import_message(import, GF_OK, "WARNING: NAL Unit type %d not handled - adding", nal_unit_type);
+                       copy_size = nal_size;
+                       break;
+               }
+
+               if (!nal_size) break;
+
+               if (flush_sample && sample_data) {
+                       GF_ISOSample *samp = gf_isom_sample_new();
+                       samp->DTS = (u64)dts_inc*cur_samp;
+                       samp->IsRAP = sample_is_rap;
+                       if (!sample_is_rap) {
+                               if (sample_has_islice && (import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) {
+                                       samp->IsRAP = 1;
+                                       if (!use_opengop_gdr) {
+                                               use_opengop_gdr = 1;
+                                               GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[AVC Import] Forcing non-IDR samples with I slices to be marked as sync points - resulting file will not be ISO conformant\n"));
+                                       }
+                               }
+                       }
+                       gf_bs_get_content(sample_data, &samp->data, &samp->dataLength);
+                       gf_bs_del(sample_data);
+                       sample_data = NULL;
+
+
+
+                       /*CTS recomuting is much trickier than with MPEG-4 ASP due to b-slice used as references - we therefore
+                       store the POC as the CTS offset and update the whole table at the end*/
+                       samp->CTS_Offset = last_poc - poc_shift;
+                       assert(last_poc >= poc_shift);
+                       e = gf_isom_add_sample(import->dest, track, di, samp);
+                       if (e) goto exit;
+
+                       cur_samp++;
+
+                       /*write sampleGroups info*/
+                       if (!samp->IsRAP && (sei_recovery_frame_count>=0)) {
+                               /*generic GDR*/
+                               if (sei_recovery_frame_count) {
+                                       if (!use_opengop_gdr) use_opengop_gdr = 1;
+                                       e = gf_isom_set_sample_roll_group(import->dest, track, cur_samp, (s16) sei_recovery_frame_count);
+                               } 
+                               /*open-GOP*/
+                               else if (sample_has_islice) {
+                                       if (!use_opengop_gdr) use_opengop_gdr = 2;
+                                       e = gf_isom_set_sample_rap_group(import->dest, track, cur_samp, 0);
+                               }
+                               if (e) goto exit;
+                       }
+
+                       gf_isom_sample_del(&samp);
+                       gf_set_progress("Importing AVC-H264", (u32) (nal_start/1024), (u32) (total_size/1024) );
+                       first_nal = 1;
+
+                       if (min_poc > last_poc)
+                               min_poc = last_poc;
+
+                       sample_has_islice = 0;
+                       sei_recovery_frame_count = -1;
+               }
+
+               if (copy_size) {
+                       if ((size_length<32) && ( (u32) (1<<size_length)-1 < copy_size)) {
+                               u32 diff_size = 8;
+                               while ((size_length<32) && ( (u32) (1<<(size_length+diff_size))-1 < copy_size)) diff_size+=8;
+                               /*only 8bits, 16bits and 32 bits*/
+                               if (size_length+diff_size == 24) diff_size+=8;
+
+                               gf_import_message(import, GF_OK, "Adjusting AVC SizeLength to %d bits", size_length+diff_size);
+                               gf_media_avc_rewrite_samples(import->dest, track, size_length, size_length+diff_size);
+
+                               /*rewrite current sample*/
+                               if (sample_data) {
+                                       char *sd;
+                                       u32 sd_l;
+                                       GF_BitStream *prev_sd;
+                                       gf_bs_get_content(sample_data, &sd, &sd_l);
+                                       gf_bs_del(sample_data);
+                                       sample_data = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+                                       prev_sd = gf_bs_new(sd, sd_l, GF_BITSTREAM_READ);
+                                       while (gf_bs_available(prev_sd)) {
+                                               char *buf;
+                                               u32 s = gf_bs_read_int(prev_sd, size_length);
+                                               gf_bs_write_int(sample_data, s, size_length+diff_size);
+                                               buf = (char*)gf_malloc(sizeof(char)*s);
+                                               gf_bs_read_data(prev_sd, buf, s);
+                                               gf_bs_write_data(sample_data, buf, s);
+                                               gf_free(buf);
+                                       }
+                                       gf_bs_del(prev_sd);
+                                       gf_free(sd);
+                               }
+                               size_length+=diff_size;
+
+                       }
+                       if (!sample_data) sample_data = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+                       gf_bs_write_int(sample_data, copy_size, size_length);
+                       gf_bs_write_data(sample_data, buffer, copy_size);
+
+                       if (set_subsamples) {
+                               /* use the res and priority value of last prefix NALU */
+                               gf_isom_add_subsample(import->dest, track, cur_samp+1, copy_size+size_length/8, 0, 0, 0);
+                       }
+
+                       if (is_slice) {
+                               slice_is_ref = gf_media_hevc_slice_is_IDR(&hevc);
+                               if (slice_is_ref) 
+                                       nb_idr++;
+                               slice_force_ref = 0;
+
+                               /*we only indicate TRUE IDRs for sync samples (cf AVC file format spec).
+                               SEI recovery should be used to build sampleToGroup & RollRecovery tables*/
+                               if (first_nal) {
+                                       first_nal = 0;
+                                       if (hevc.sei.recovery_point.valid || (import->flags & GF_IMPORT_FORCE_SYNC)) {
+                                               Bool bIntraSlice = gf_media_hevc_slice_is_intra(&hevc);
+                                               assert(hevc.s_info.nal_unit_type!=GF_AVC_NALU_IDR_SLICE || bIntraSlice);
+
+                                               sei_recovery_frame_count = hevc.sei.recovery_point.frame_cnt;
+
+                                               /*we allow to mark I-frames as sync on open-GOPs (with sei_recovery_frame_count=0) when forcing sync even when the SEI RP is not available*/
+                                               if (!hevc.sei.recovery_point.valid && bIntraSlice) {
+                                                       sei_recovery_frame_count = 0;
+                                                       if (use_opengop_gdr == 1) {
+                                                               use_opengop_gdr = 2; /*avoid message flooding*/
+                                                               GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[AVC Import] No valid SEI Recovery Point found although needed - forcing\n"));
+                                                       }
+                                               }
+                                               hevc.sei.recovery_point.valid = 0;
+                                               if (bIntraSlice && (import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) 
+                                                       slice_force_ref = 1;
+                                       }
+                                       sample_is_rap = gf_media_hevc_slice_is_IDR(&hevc);
+                               }
+
+                               if (hevc.s_info.poc<poc_shift) {
+                                       u32 j;
+                                       if (ref_frame) {
+                                               for (j=ref_frame; j<=cur_samp; j++) {
+                                                       GF_ISOSample *samp = gf_isom_get_sample_info(import->dest, track, j, NULL, NULL);
+                                                       if (!samp) break;
+                                                       samp->CTS_Offset += poc_shift;
+                                                       samp->CTS_Offset -= hevc.s_info.poc;
+                                                       gf_isom_modify_cts_offset(import->dest, track, j, samp->CTS_Offset);
+                                                       gf_isom_sample_del(&samp);
+                                               }
+                                       }
+                                       poc_shift = hevc.s_info.poc;
+                               }
+
+                               /*if #pics, compute smallest POC increase*/
+                               if (hevc.s_info.poc != last_poc) {
+                                       if (!poc_diff || (poc_diff > abs(hevc.s_info.poc-last_poc))) {
+                                               poc_diff = abs(hevc.s_info.poc - last_poc);/*ideally we would need to start the parsing again as poc_diff helps computing max_total_delay*/
+                                       }
+                                       last_poc = hevc.s_info.poc;
+                               }
+
+                               /*ref slice, reset poc*/
+                               if (slice_is_ref) {
+                                       ref_frame = cur_samp+1;
+                                       max_last_poc = last_poc = max_last_b_poc = 0;
+                                       poc_shift = 0;
+                               }
+                               /*forced ref slice*/
+                               else if (slice_force_ref) {
+                                       ref_frame = cur_samp+1; 
+                                       /*adjust POC shift as sample will now be marked as sync, so wo must store poc as if IDR (eg POC=0) for our CTS offset computing to be correct*/
+                                       poc_shift = hevc.s_info.poc;
+                               }
+                               /*strictly less - this is a new P slice*/
+                               else if (max_last_poc<last_poc) {
+                                       max_last_b_poc = 0;
+                                       prev_last_poc = max_last_poc;
+                                       max_last_poc = last_poc;
+                               }
+                               /*stricly greater*/
+                               else if (max_last_poc>last_poc) {
+                                       /*need to store TS offsets*/
+                                       has_cts_offset = 1;
+                                       switch (hevc.s_info.slice_type) {
+                                       case GF_AVC_TYPE_B:
+                                       case GF_AVC_TYPE2_B:
+                                               if (!max_last_b_poc) {
+                                                       max_last_b_poc = last_poc;
+                                               }
+                                               /*if same poc than last max, this is a B-slice*/
+                                               else if (last_poc>max_last_b_poc) {
+                                                       max_last_b_poc = last_poc;
+                                               }
+                                               /*otherwise we had a B-slice reference: do nothing*/
+
+                                               break;
+                                       }
+                               }
+
+                               /*compute max delay (applicable when B slice are present)*/
+                               if (ref_frame && poc_diff && (s32)(cur_samp-(ref_frame-1)-last_poc/poc_diff)>(s32)max_total_delay) {
+                                       max_total_delay = cur_samp - (ref_frame-1) - last_poc/poc_diff;
+                               }
+                       }
+               }
+
+               gf_bs_align(bs);
+               nal_end = gf_bs_get_position(bs);
+               assert(nal_start <= nal_end);
+               assert(nal_end <= nal_start + nal_size);
+               if (nal_end != nal_start + nal_size)
+                       gf_bs_seek(bs, nal_start + nal_size);
+
+               if (!gf_bs_available(bs)) break;
+               if (duration && (dts_inc*cur_samp > duration)) break;
+               if (import->flags & GF_IMPORT_DO_ABORT) break;
+
+               /*consume next start code*/
+               nal_start = gf_media_nalu_next_start_code_bs(bs);
+               if (nal_start) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[avc-h264] invalid nal_size (%u)? Skipping "LLU" bytes to reach next start code\n", nal_size, nal_start));
+                       gf_bs_skip_bytes(bs, nal_start);
+               }
+               nal_start = gf_media_nalu_is_start_code(bs);
+               if (!nal_start) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[avc-h264] error: no start code found ("LLU" bytes read out of "LLU") - leaving\n", gf_bs_get_position(bs), gf_bs_get_size(bs)));
+                       break;
+               }
+               nal_start = gf_bs_get_position(bs);
+       }
+       
+       /*final flush*/
+       if (sample_data) {
+               GF_ISOSample *samp = gf_isom_sample_new();
+               samp->DTS = (u64)dts_inc*cur_samp;
+               samp->IsRAP = sample_is_rap;
+               if (!sample_is_rap && sample_has_islice && (import->flags & GF_IMPORT_FORCE_SYNC)) {
+                       samp->IsRAP = 1;
+               }
+               /*we store the frame order (based on the POC) as the CTS offset and update the whole table at the end*/
+               samp->CTS_Offset = last_poc - poc_shift;
+               gf_bs_get_content(sample_data, &samp->data, &samp->dataLength);
+               gf_bs_del(sample_data);
+               sample_data = NULL;
+               e = gf_isom_add_sample(import->dest, track, di, samp);
+               if (e) goto exit;
+               gf_isom_sample_del(&samp);
+               gf_set_progress("Importing AVC-H264", (u32) cur_samp, cur_samp+1);
+               cur_samp++;
+       }
+
+
+       /*recompute all CTS offsets*/
+       if (has_cts_offset) {
+               u32 i, last_cts_samp;
+               u64 last_dts, max_cts;
+               if (!poc_diff) poc_diff = 1;
+               /*no b-frame references, no need to cope with negative poc*/
+               if (!max_total_delay) {
+                       min_poc=0;
+                       max_total_delay = 1;
+               }
+               cur_samp = gf_isom_get_sample_count(import->dest, track);
+               min_poc *= -1;
+               last_dts = 0;
+               max_cts = 0;
+               last_cts_samp = 0;
+
+               for (i=0; i<cur_samp; i++) {
+                       u64 cts;
+                       /*not using descIdx and data_offset will only fecth DTS, CTS and RAP which is all we need*/
+                       GF_ISOSample *samp = gf_isom_get_sample_info(import->dest, track, i+1, NULL, NULL);
+                       /*poc re-init (RAP and POC to 0, otherwise that's SEI recovery), update base DTS*/
+                       if (samp->IsRAP /*&& !samp->CTS_Offset*/)
+                               last_dts = samp->DTS * (1+is_paff);
+
+                       /*CTS offset is frame POC (refers to last IDR)*/
+                       cts = (min_poc + (s32) samp->CTS_Offset) * dts_inc/poc_diff + (u32) last_dts;
+
+                       /*if PAFF, 2 pictures (eg poc) <=> 1 aggregated frame (eg sample), divide by 2*/
+                       if (is_paff) {
+                               cts /= 2;
+                               /*in some cases the poc is not on the top field - if that is the case, round up*/
+                               if (cts%dts_inc) {
+                                       cts = ((cts/dts_inc)+1)*dts_inc;
+                               }
+                       }
+
+                       /*B-frames offset*/
+                       cts += (u32) (max_total_delay*dts_inc);
+
+                       samp->CTS_Offset = (u32) (cts - samp->DTS);
+
+                       if (max_cts < samp->DTS + samp->CTS_Offset) {
+                               max_cts = samp->DTS + samp->CTS_Offset;
+                               last_cts_samp = i;
+                       }
+                       /*this should never happen, however some streams seem to do weird POC increases (cf sorenson streams, last 2 frames),
+                       this should hopefully take care of some bugs and ensure proper CTS...*/
+                       if ((s32)samp->CTS_Offset<0) {
+                               u32 j, k;
+                               samp->CTS_Offset = 0;
+                               gf_isom_modify_cts_offset(import->dest, track, i+1, samp->CTS_Offset);
+                               for (j=last_cts_samp; j<i; j++) {
+                                       GF_ISOSample *asamp = gf_isom_get_sample_info(import->dest, track, j+1, NULL, NULL);
+                                       for (k=j+1; k<=i; k++) {
+                                               GF_ISOSample *bsamp = gf_isom_get_sample_info(import->dest, track, k+1, NULL, NULL);
+                                               if (asamp->CTS_Offset+asamp->DTS==bsamp->CTS_Offset+bsamp->DTS) {
+                                                       max_cts += dts_inc;
+                                                       bsamp->CTS_Offset = (u32) (max_cts - bsamp->DTS);
+                                                       gf_isom_modify_cts_offset(import->dest, track, k+1, bsamp->CTS_Offset);
+                                               }
+                                               gf_isom_sample_del(&bsamp);
+                                       }
+                                       gf_isom_sample_del(&asamp);
+                               }
+                               max_cts = samp->DTS + samp->CTS_Offset;
+                       } else {
+                               gf_isom_modify_cts_offset(import->dest, track, i+1, samp->CTS_Offset);
+                       }
+                       gf_isom_sample_del(&samp);
+               }
+               /*and repack table*/
+               gf_isom_set_cts_packing(import->dest, track, 0);
+       } else {
+               gf_isom_remove_cts_info(import->dest, track);
+       }
+
+       gf_set_progress("Importing AVC-H264", (u32) cur_samp, cur_samp);
+
+       gf_isom_set_visual_info(import->dest, track, di, max_w, max_h);
+       hevccfg->nal_unit_size = size_length/8;
+
+       gf_isom_hevc_config_update(import->dest, track, 1, hevccfg);
+       gf_media_update_par(import->dest, track);
+       MP4T_RecomputeBitRate(import->dest, track);
+
+//     gf_isom_set_pl_indication(import->dest, GF_ISOM_PL_VISUAL, 0x15);
+       gf_isom_set_brand_info(import->dest, GF_ISOM_BRAND_ISO4, 1);
+       gf_isom_modify_alternate_brand(import->dest, GF_ISOM_BRAND_ISOM, 0);
+       gf_isom_modify_alternate_brand(import->dest, GF_4CC('h','v','c','1'), 1);
+
+       if (!vpss || !ppss || !spss) {
+               e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Import results: No SPS or PPS found in the bitstream ! Nothing imported\n");
+       } else {
+               if (nb_sp || nb_si) {
+                       gf_import_message(import, GF_OK, "AVC Import results: %d samples - Slices: %d I %d P %d B %d SP %d SI - %d SEI - %d IDR",
+                               cur_samp, nb_i, nb_p, nb_b, nb_sp, nb_si, nb_sei, nb_idr);
+               } else {
+                       gf_import_message(import, GF_OK, "AVC Import results: %d samples - Slices: %d I %d P %d B - %d SEI - %d IDR",
+                               cur_samp, nb_i, nb_p, nb_b, nb_sei, nb_idr);
+               }
+
+               if (max_total_delay>1) {
+                       gf_import_message(import, GF_OK, "Stream uses forward prediction - stream CTS offset: %d frames", max_total_delay);
+               }
+       }
+
+       if (use_opengop_gdr==2) {
+               gf_import_message(import, GF_OK, "OpenGOP detected - adjusting file brand");
+               gf_isom_modify_alternate_brand(import->dest, GF_4CC('i', 's', 'o', '6'), 1);
+       }
+
+       /*rewrite ESD*/
+       if (import->esd) {
+               if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig*) gf_odf_desc_new(GF_ODF_SLC_TAG);
+               import->esd->slConfig->predefined = 2;
+               import->esd->slConfig->timestampResolution = timescale;
+               if (import->esd->decoderConfig) gf_odf_desc_del((GF_Descriptor *)import->esd->decoderConfig);
+               import->esd->decoderConfig = gf_isom_get_decoder_config(import->dest, track, 1);
+               gf_isom_change_mpeg4_description(import->dest, track, 1, import->esd);
+       }
+
+exit:
+       if (sample_data) gf_bs_del(sample_data);
+       gf_odf_hevc_cfg_del(hevccfg);
+       gf_free(buffer);
+       gf_bs_del(bs);
+       fclose(mdia);
+       return e;
+}
+
+#endif /*GPAC_DISABLE_AV_PARSERS*/
+
+#ifndef GPAC_DISABLE_OGG
+
+#define OGG_BUFFER_SIZE 4096
+
+Bool OGG_ReadPage(FILE *f_in, ogg_sync_state *oy, ogg_page *oggpage)
+{
+       if (feof(f_in)) return 0;
+       while (ogg_sync_pageout(oy, oggpage ) != 1 ) {
+               char *buffer = ogg_sync_buffer(oy, OGG_BUFFER_SIZE);
+               u32 bytes = fread(buffer, sizeof(char), OGG_BUFFER_SIZE, f_in);
+               ogg_sync_wrote(oy, bytes);
+               if (feof(f_in)) return 1;
+       }
+       return 1;
+}
+
+static u32 get_ogg_serial_no_for_stream(char *fileName, u32 stream_num, Bool is_video)
+{
+       ogg_sync_state oy;
+       u32 track, serial_no;
+       ogg_page oggpage;
+       ogg_packet oggpacket;
+       ogg_stream_state os;
+       FILE *f_in;
+
+       /*means first one*/
+       if (!stream_num) return 0;
+
+       f_in = gf_f64_open(fileName, "rb");
+       if (!f_in) return 0;
+
+       track = 0;
+       serial_no = 0;
+       ogg_sync_init(&oy);
+       while (1) {
+               if (!OGG_ReadPage(f_in, &oy, &oggpage)) break;
+               if (!ogg_page_bos(&oggpage)) break;
+               track ++;
+               if (track != stream_num) continue;
+
+               serial_no = ogg_page_serialno(&oggpage);
+               ogg_stream_init(&os, serial_no);
+               ogg_stream_pagein(&os, &oggpage);
+               ogg_stream_packetpeek(&os, &oggpacket);
+
+               if (is_video && (oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "theora", 6)) {
+                       ogg_stream_clear(&os);
+                       break;
+               }
+               if (!is_video && (oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "vorbis", 6)) {
+                       ogg_stream_clear(&os);
+                       break;
+               }
+               ogg_stream_clear(&os);
+               serial_no = 0;
+       }
+       ogg_sync_clear(&oy);
+       fclose(f_in);
+       return serial_no;
+}
+
+GF_Err gf_import_ogg_video(GF_MediaImporter *import)
+{
+       GF_Err e;
+       ogg_sync_state oy;
+       u32 di, track;
+       u64 tot_size, done, duration;
+       u32 w, h, fps_num, fps_den, keyframe_freq_force, theora_kgs, flag, dts_inc, timescale;
+       Double FPS;
+       Bool destroy_esd, go;
+       u32 serial_no, sno, num_headers;
+       ogg_packet oggpacket;
+       ogg_page oggpage;
+       ogg_stream_state os;
+       oggpack_buffer opb;
+       GF_BitStream *bs;
+       FILE *f_in;
+       GF_ISOSample *samp;
+
+
+       dts_inc = 0;
+       /*assume audio or simple AV file*/
+       if (import->flags & GF_IMPORT_PROBE_ONLY) {
+               f_in = gf_f64_open(import->in_name, "rb");
+               if (!f_in) return GF_URL_ERROR;
+
+               import->nb_tracks = 0;
+               go = 1;
+               ogg_sync_init(&oy);
+               while (go) {
+                       if (!OGG_ReadPage(f_in, &oy, &oggpage)) break;
+
+                       if (!ogg_page_bos(&oggpage)) {
+                               go = 0;
+                               continue;
+                       }
+                       serial_no = ogg_page_serialno(&oggpage);
+                       ogg_stream_init(&os, serial_no);
+                       ogg_stream_pagein(&os, &oggpage);
+                       ogg_stream_packetpeek(&os, &oggpacket);
+
+                       import->tk_info[import->nb_tracks].track_num = import->nb_tracks+1;
+                       if ((oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "theora", 6)) {
+                               import->tk_info[import->nb_tracks].type = GF_ISOM_MEDIA_VISUAL;
+                               import->tk_info[import->nb_tracks].flags = GF_IMPORT_OVERRIDE_FPS;
+
+                               bs = gf_bs_new((char*)oggpacket.packet, oggpacket.bytes, GF_BITSTREAM_READ);
+                               gf_bs_read_int(bs, 80);
+                               import->tk_info[import->nb_tracks].video_info.width = gf_bs_read_u16(bs) << 4;
+                               import->tk_info[import->nb_tracks].video_info.height = gf_bs_read_u16(bs) << 4;
+                               gf_bs_read_int(bs, 64);
+                               fps_num = gf_bs_read_u32(bs);
+                               fps_den = gf_bs_read_u32(bs);
+                               gf_bs_del(bs);
+                               import->tk_info[import->nb_tracks].video_info.FPS = fps_num;
+                               import->tk_info[import->nb_tracks].video_info.FPS /= fps_den;
+                               import->tk_info[import->nb_tracks].media_type = GF_4CC('t','h','e','o');
+                       } else if ((oggpacket.bytes >= 7) && !strncmp((char *)&oggpacket.packet[1], "vorbis", 6)) {
+                               import->tk_info[import->nb_tracks].type = GF_ISOM_MEDIA_AUDIO;
+                               import->tk_info[import->nb_tracks].flags = 0;
+                       }
+                       ogg_stream_clear(&os);
+                       import->nb_tracks++;
+               }
+               ogg_sync_clear(&oy);
+               fclose(f_in);
+               return GF_OK;
+       }
+
+       if (import->flags & GF_IMPORT_USE_DATAREF) return gf_import_message(import, GF_NOT_SUPPORTED, "Cannot use data referencing with OGG files");
+
+       sno = get_ogg_serial_no_for_stream(import->in_name, import->trackID, 1);
+       /*not our stream*/
+       if (!sno && import->trackID) return GF_OK;
+
+       f_in = gf_f64_open(import->in_name, "rb");
+       if (!f_in) return gf_import_message(import, GF_URL_ERROR, "Opening file %s failed", import->in_name);
+
+       e = GF_OK;
+       done = 0;
+       gf_f64_seek(f_in, 0, SEEK_END);
+       tot_size = gf_f64_tell(f_in);
+       gf_f64_seek(f_in, 0, SEEK_SET);
+
+
+       destroy_esd = 0;
+       samp = gf_isom_sample_new();
+
+       /*avoids gcc warnings*/
        duration = 0;
        FPS = 0;
        num_headers = w = h = track = 0;
@@ -5395,6 +6093,9 @@ typedef struct
 #ifndef GPAC_DISABLE_AV_PARSERS
        GF_AVCConfig *avccfg;
        AVCState avc;
+
+       GF_HEVCConfig *hevccfg;
+       HEVCState hevc;
 #endif
        Bool force_next_au_start;
        Bool stream_setup;
@@ -5597,6 +6298,34 @@ void m2ts_rewrite_avc_sample(GF_MediaImporter *import, GF_TSImport *tsimp)
        gf_isom_sample_del(&samp);
 }
 
+static void hevc_cfg_add_nalu(GF_HEVCConfig *hevccfg, u8 nal_type, char *data, u32 data_len)
+{
+       u32 i, count;
+       GF_AVCConfigSlot *sl;
+       GF_HEVCParamArray *ar = NULL;
+       count = gf_list_count(hevccfg->param_array);
+       for (i=0; i<count; i++) {
+               ar = gf_list_get(hevccfg->param_array, i);
+               if (ar->type == nal_type) break;
+               ar = NULL;
+       }
+       if (!ar) {
+               GF_SAFEALLOC(ar, GF_HEVCParamArray);
+               ar->array_completeness = 1;
+               ar->type = nal_type;
+               ar->nalus = gf_list_new();
+       }
+       GF_SAFEALLOC(sl, GF_AVCConfigSlot);
+       if (data) {
+               sl->data = gf_malloc(sizeof(char)*data_len);
+               sl->size = data_len;
+               memcpy(sl->data, data, data_len);
+               gf_list_add(ar->nalus, ar);
+       } else {
+               ar->array_completeness = 0;
+       }
+}
+
 void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
 {
        GF_Err e;
@@ -5688,6 +6417,13 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        import->nb_tracks++;
                                        tsimp->nb_video++;
                                        break;
+                               case GF_M2TS_VIDEO_HEVC:
+                                       import->tk_info[idx].media_type = GF_4CC('h','e','v','c');
+                                       import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
+                                       import->tk_info[idx].lang = pes->lang;
+                                       import->nb_tracks++;
+                                       tsimp->nb_video++;
+                                       break;
                                case GF_M2TS_AUDIO_MPEG1:
                                        import->tk_info[idx].media_type = GF_4CC('M','P','G','1');
                                        import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
@@ -5813,6 +6549,12 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                oti = GPAC_OTI_VIDEO_AVC;
                                tsimp->avccfg = gf_odf_avc_cfg_new();
                                break;
+                       case GF_M2TS_VIDEO_HEVC:
+                               mtype = GF_ISOM_MEDIA_VISUAL;
+                               stype = GF_STREAM_VISUAL; 
+                               oti = GPAC_OTI_VIDEO_HEVC;
+                               tsimp->hevccfg = gf_odf_hevc_cfg_new();
+                               break;
                        case GF_M2TS_AUDIO_MPEG1:
                                mtype = GF_ISOM_MEDIA_AUDIO;
                                stype = GF_STREAM_AUDIO; 
@@ -5929,7 +6671,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
                                        is_subseq = 1;
                                case GF_AVC_NALU_SEQ_PARAM:
-                                       idx = AVC_ReadSeqInfo(pck->data+5, pck->data_len-5, &tsimp->avc, is_subseq, NULL);
+                                       idx = gf_media_avc_read_sps(pck->data+4, pck->data_len-4, &tsimp->avc, is_subseq, NULL);
 
                                        add_sps = 0;
                                        if (idx>=0) {
@@ -5965,7 +6707,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        }
                                        return;
                                case GF_AVC_NALU_PIC_PARAM:
-                                       idx = AVC_ReadPictParamSet(pck->data+5, pck->data_len-5, &tsimp->avc);
+                                       idx = gf_media_avc_read_pps(pck->data+4, pck->data_len-4, &tsimp->avc);
                                        if ((idx>=0) && (tsimp->avc.pps[idx].status==1)) {
                                                tsimp->avc.pps[idx].status = 2;
                                                slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
@@ -5987,9 +6729,96 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                case GF_AVC_NALU_SEI:
                                        break;
                                        if (tsimp->avc.sps_active_idx != -1) {
-                                               idx = AVC_ReformatSEI_NALU(pck->data+4, pck->data_len-4, &tsimp->avc);
+                                               idx = gf_media_avc_reformat_sei(pck->data+4, pck->data_len-4, &tsimp->avc);
+                                               if (idx>0) pck->data_len = idx+4;
+                                       }
+                                       break;
+                               }
+
+                               if (tsimp->force_next_au_start) {
+                                       is_au_start = 1;
+                                       tsimp->force_next_au_start = 0;
+                               }
+                       }
+
+                       /*avc data for the current sample is stored in annex-B, as we don't know the size of each nal
+                       when called back (depending on PES packetization, the end of the nal could be in following pes)*/
+                       else if (tsimp->hevccfg && !pck->data[0] && !pck->data[1]) {
+                               s32 idx;
+                               Bool add_sps, is_subseq = 0;
+                               u32 nal_type = (pck->data[4] & 0x7E) >> 1;
+
+                               switch (nal_type) {
+                               case GF_HEVC_NALU_SEQ_PARAM:
+                                       idx = gf_media_hevc_read_sps(pck->data+4, pck->data_len-4, &tsimp->hevc);
+                                       add_sps = 0;
+                                       if (idx>=0) {
+                                               if (is_subseq) {
+                                                       if ((tsimp->hevc.sps[idx].state & AVC_SUBSPS_PARSED) && !(tsimp->hevc.sps[idx].state & AVC_SUBSPS_DECLARED)) {
+                                                               tsimp->hevc.sps[idx].state |= AVC_SUBSPS_DECLARED;
+                                                               add_sps = 1;
+                                                       }
+                                               } else {
+                                                       if ((tsimp->hevc.sps[idx].state & AVC_SPS_PARSED) && !(tsimp->hevc.sps[idx].state & AVC_SPS_DECLARED)) {
+                                                               tsimp->hevc.sps[idx].state |= AVC_SPS_DECLARED;
+                                                               add_sps = 1;
+                                                       }
+                                               }
+                                               if (add_sps) {
+                                                       /*always store nalu size on 4 bytes*/
+                                                       tsimp->hevccfg->nal_unit_size = 4;
+                                                       tsimp->hevccfg->configurationVersion = 1;
+
+                                                       tsimp->hevccfg->configurationVersion = 1;
+                                                       tsimp->hevccfg->profile_space = tsimp->hevc.sps[idx].ptl.profile_space;
+                                                       tsimp->hevccfg->profile_idc = tsimp->hevc.sps[idx].ptl.profile_idc;
+                                                       tsimp->hevccfg->constraint_indicator_flags = 0;
+                                                       tsimp->hevccfg->level_idc = tsimp->hevc.sps[idx].ptl.level_idc;
+                                                       tsimp->hevccfg->profile_compatibility_indications = tsimp->hevc.sps[idx].ptl.profile_compatibility_flag;
+                                                       tsimp->hevccfg->chromaFormat = tsimp->hevc.sps[idx].chroma_format_idc;
+                                                       tsimp->hevccfg->luma_bit_depth = tsimp->hevc.sps[idx].bit_depth_luma;
+                                                       tsimp->hevccfg->chroma_bit_depth = tsimp->hevc.sps[idx].bit_depth_chroma;
+
+                                                       hevc_cfg_add_nalu(tsimp->hevccfg, nal_type, pck->data+4, pck->data_len-4);
+
+                                                       if (pck->stream->vid_w < tsimp->avc.sps[idx].width)
+                                                               pck->stream->vid_w = tsimp->avc.sps[idx].width;
+                                                       if (pck->stream->vid_h < tsimp->avc.sps[idx].height)
+                                                               pck->stream->vid_h = tsimp->avc.sps[idx].height;
+                                               }
+                                       }
+                                       return;
+                               case GF_HEVC_NALU_PIC_PARAM:
+                                       idx = gf_media_hevc_read_pps(pck->data+4, pck->data_len-4, &tsimp->hevc);
+                                       if ((idx>=0) && (tsimp->hevc.pps[idx].state==1)) {
+                                               tsimp->hevc.pps[idx].state = 2;
+                                               hevc_cfg_add_nalu(tsimp->hevccfg, nal_type, pck->data+4, pck->data_len-4);
+                                       }
+                                       return;
+                               case GF_HEVC_NALU_VID_PARAM:
+                                       idx = gf_media_hevc_read_vps(pck->data+4, pck->data_len-4, &tsimp->hevc);
+                                       if ((idx>=0) && (tsimp->hevc.vps[idx].state==1)) {
+                                               tsimp->hevc.vps[idx].state = 2;
+                                               tsimp->hevccfg->avgFrameRate = tsimp->hevc.vps[idx].rates[0].avg_pic_rate;
+                                               tsimp->hevccfg->constantFrameRate = tsimp->hevc.vps[idx].rates[0].constand_pic_rate_idc;
+                                               tsimp->hevccfg->numTemporalLayers = tsimp->hevc.vps[idx].max_sub_layer;
+                                               hevc_cfg_add_nalu(tsimp->hevccfg, nal_type, pck->data+4, pck->data_len-4);
+                                       }
+                                       return;
+                               /*remove*/
+                               case GF_HEVC_NALU_ACCESS_UNIT:
+                                       tsimp->force_next_au_start = 1;
+                                       return;
+                               case GF_HEVC_NALU_FILLER_DATA:
+                               case GF_HEVC_NALU_END_OF_SEQ:
+                               case GF_HEVC_NALU_END_OF_STREAM:
+                                       return;
+                               case GF_HEVC_NALU_SEI_PREFIX:
+/*TODO                                 if (tsimp->avc.sps_active_idx != -1) {
+                                               idx = gf_media_avc_reformat_sei(pck->data+4, pck->data_len-4, &tsimp->avc);
                                                if (idx>0) pck->data_len = idx+4;
                                        }
+*/
                                        break;
                                }
 
@@ -5998,6 +6827,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                        tsimp->force_next_au_start = 0;
                                }
                        }
+
                        if (!is_au_start) {
                                e = gf_isom_append_sample_data(import->dest, tsimp->track, (char*)pck->data, pck->data_len);
                                if (e) {
@@ -6028,6 +6858,7 @@ void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
                                case GF_M2TS_VIDEO_MPEG2: gf_import_message(import, GF_OK, "MPEG-2 Video import (TS PID %d)", pck->stream->pid); break;
                                case GF_M2TS_VIDEO_MPEG4: gf_import_message(import, GF_OK, "MPEG-4 Video import (TS PID %d)", pck->stream->pid); break;
                                case GF_M2TS_VIDEO_H264: gf_import_message(import, GF_OK, "MPEG-4 AVC/H264 Video import (TS PID %d)", pck->stream->pid); break;
+                               case GF_M2TS_VIDEO_HEVC: gf_import_message(import, GF_OK, "MPEG-H HEVC Video import (TS PID %d)", pck->stream->pid); break;
                                case GF_M2TS_AUDIO_MPEG1: gf_import_message(import, GF_OK, "MPEG-1 Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid); break;
                                case GF_M2TS_AUDIO_MPEG2: gf_import_message(import, GF_OK, "MPEG-2 Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid); break;
                                case GF_M2TS_AUDIO_AAC: gf_import_message(import, GF_OK, "MPEG-4 AAC Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid); break;
@@ -7086,7 +7917,11 @@ GF_Err gf_media_import(GF_MediaImporter *importer)
        if (!strnicmp(ext, ".h264", 5) || !strnicmp(ext, ".264", 4) || !strnicmp(ext, ".x264", 5)
                || !strnicmp(ext, ".h26L", 5) || !strnicmp(ext, ".26l", 4)
                || !stricmp(fmt, "AVC") || !stricmp(fmt, "H264") )
-               return gf_import_h264(importer);
+               return gf_import_avc_h264(importer);
+       /*HEVC video*/
+       if (!strnicmp(ext, ".hevc", 5) || !strnicmp(ext, ".hvc", 4) || !strnicmp(ext, ".265", 4)
+               || !stricmp(fmt, "HEVC") || !stricmp(fmt, "H265") )
+               return gf_import_hevc(importer);
        /*AC3*/
        if (!strnicmp(ext, ".ac3", 4) || !stricmp(fmt, "AC3") )
                return gf_import_ac3(importer);
@@ -7171,6 +8006,8 @@ GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level)
        switch (stype) {
        case GF_ISOM_SUBTYPE_AVC_H264:
        case GF_ISOM_SUBTYPE_AVC2_H264:
+       case GF_ISOM_SUBTYPE_AVC3_H264:
+       case GF_ISOM_SUBTYPE_AVC4_H264:
                break;
        default:
                return GF_OK;
index 67727ee36a15b8eeae18a446ea9e9eb112a18360..57ae337894bfdfb9ea98a28583a3ce17dabf43f9 100644 (file)
@@ -311,7 +311,7 @@ static void gf_mpd_parse_segment_base_generic(GF_MPD *mpd, GF_MPD_SegmentBase *s
        while ( (att = gf_list_enum(root->attributes, &i)) ) {
                if (!strcmp(att->name, "timescale")) seg->timescale = gf_mpd_parse_int(att->value);
                else if (!strcmp(att->name, "presentationTimeOffset")) seg->presentation_time_offset = gf_mpd_parse_long_int(att->value);
-               else if (!strcmp(att->name, "indexRange")) seg->index_range = gf_mpd_parse_int(att->value);
+               else if (!strcmp(att->name, "indexRange")) seg->index_range = gf_mpd_parse_byte_range(att->value);
                else if (!strcmp(att->name, "indexRangeExact")) seg->index_range_exact = gf_mpd_parse_bool(att->value);
        }
 
@@ -784,6 +784,7 @@ void gf_mpd_segment_base_free(void *_item)
        GF_MPD_SegmentBase *ptr = (GF_MPD_SegmentBase *)_item;
        if (ptr->initialization_segment) gf_mpd_url_free(ptr->initialization_segment);
        if (ptr->representation_index) gf_mpd_url_free(ptr->representation_index);
+       if (ptr->index_range) gf_free(ptr->index_range);
        gf_free(ptr);
 }
 
@@ -1343,7 +1344,9 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url,
                count2 = gf_list_count(prog->bitrates);
                for (j = 0; j<count2; j++) {
                        char *base_url;
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
                        Bool import_file = do_import;
+#endif
                        Bool is_aac = 0;
                        char *byte_range_media_file = NULL;
                        pe = gf_list_get(prog->bitrates, j);
@@ -1365,9 +1368,11 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url,
                                strncpy(pe->codecs, pe->codecs+1, len-1);
                                pe->codecs[len-2] = 0;
                        }
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
                        if (pe->bandwidth && pe->codecs && pe->width && pe->height) {
                                import_file = 0;
                        }
+#endif
 
                        /*get rid of level 0 aac*/
                        elt = gf_list_get(pe->element.playlist.elements, 0);
index 2a7b2c27b4193bdeef159041b578988bd34034d9..c401d7953b069689255e4cf2ddff4dddef95335c 100644 (file)
@@ -62,6 +62,7 @@ const char *gf_m2ts_get_stream_name(u32 streamType)
        case GF_M2TS_AUDIO_AAC: return "AAC Audio";
        case GF_M2TS_VIDEO_MPEG4: return "MPEG-4 Video";
        case GF_M2TS_VIDEO_H264: return "MPEG-4/H264 Video";
+       case GF_M2TS_VIDEO_HEVC: return "MPEG-H HEVC Video";
 
        case GF_M2TS_AUDIO_AC3: return "Dolby AC3 Audio";
        case GF_M2TS_AUDIO_DTS: return "Dolby DTS Audio";
@@ -109,7 +110,7 @@ static u32 gf_m2ts_reframe_reset(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool sam
        return 0;
 }
 
-static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
+static u32 gf_m2ts_reframe_nalu_video(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len, Bool is_hevc)
 {
        Bool au_start_in_pes=0;
        Bool prev_is_au_delim=0;
@@ -186,47 +187,94 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool
                        }
                        start_code_found = short_start_code ? 2 : 1;
 
-                       nal_type = pck.data[4] & 0x1F;
+                       if (is_hevc) {
+                               nal_type = (pck.data[4] & 0x7E) >> 1;
 
-                       /*check for SPS and update stream info*/
+                               /*check for SPS and update stream info*/
 #ifndef GPAC_DISABLE_AV_PARSERS
-                       if (!pes->vid_w && (nal_type==GF_AVC_NALU_SEQ_PARAM)) {
-                               AVCState avc;
-                               s32 idx;
-                               memset(&avc, 0, sizeof(AVCState));
-                               avc.sps_active_idx = -1;
-                               idx = AVC_ReadSeqInfo(data+5, sc_pos-5, &avc, 0, NULL);
-
-                               if (idx>=0) {
-                                       pes->vid_w = avc.sps[idx].width;
-                                       pes->vid_h = avc.sps[idx].height;
+                               if (!pes->vid_w && (nal_type==GF_HEVC_NALU_SEQ_PARAM)) {
+                                       HEVCState hevc;
+                                       s32 idx;
+                                       memset(&hevc, 0, sizeof(HEVCState));
+                                       hevc.sps_active_idx = -1;
+                                       idx = gf_media_hevc_read_sps(data+4, sc_pos-4, &hevc);
+
+                                       if (idx>=0) {
+                                               pes->vid_w = hevc.sps[idx].width;
+                                               pes->vid_h = hevc.sps[idx].height;
+                                       }
                                }
-                       }
 #endif
-                       /*check AU start type*/
-                       if (nal_type==GF_AVC_NALU_ACCESS_UNIT) {
-                               if (!prev_is_au_delim) {
-                                       if (au_start_in_pes) {
-                                               /*FIXME - we should check the AVC framerate to update the timing ...*/
-                                               pck.DTS += 3000;
-                                               pck.PTS += 3000;
-//                                             GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID%d: Two AVC AUs start in this PES packet - cannot recompute non-first AU timing\n", pes->pid));
+                               /*check AU start type*/
+                               if (nal_type==GF_HEVC_NALU_ACCESS_UNIT) {
+                                       if (!prev_is_au_delim) {
+                                               if (au_start_in_pes) {
+                                                       /*FIXME - we should check the AVC framerate to update the timing ...*/
+                                                       pck.DTS += 3000;
+                                                       pck.PTS += 3000;
+       //                                              GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID%d: Two AVC AUs start in this PES packet - cannot recompute non-first AU timing\n", pes->pid));
+                                               }
+                                               pck.flags = GF_M2TS_PES_PCK_AU_START;
+                                               force_new_au = 0;
+                                               au_start_in_pes = 1;
+                                               ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
+                                               prev_is_au_delim=1;
                                        }
-                                       pck.flags = GF_M2TS_PES_PCK_AU_START;
-                                       force_new_au = 0;
-                                       au_start_in_pes = 1;
+                               } else if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP)
+                                       || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)
+                               ) {
+                                       pck.flags = GF_M2TS_PES_PCK_RAP;
                                        ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
-                                       prev_is_au_delim=1;
+                                       prev_is_au_delim=0;
+                               } 
+                               else {
+                                       pck.flags = 0;
+                                       ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
+                                       prev_is_au_delim=0;
+                               }
+                       } else {
+                               nal_type = pck.data[4] & 0x1F;
+
+                               /*check for SPS and update stream info*/
+#ifndef GPAC_DISABLE_AV_PARSERS
+                               if (!pes->vid_w && (nal_type==GF_AVC_NALU_SEQ_PARAM)) {
+                                       AVCState avc;
+                                       s32 idx;
+                                       memset(&avc, 0, sizeof(AVCState));
+                                       avc.sps_active_idx = -1;
+                                       idx = gf_media_avc_read_sps(data+4, sc_pos-4, &avc, 0, NULL);
+
+                                       if (idx>=0) {
+                                               pes->vid_w = avc.sps[idx].width;
+                                               pes->vid_h = avc.sps[idx].height;
+                                       }
+                               }
+#endif
+                               /*check AU start type*/
+                               if (nal_type==GF_AVC_NALU_ACCESS_UNIT) {
+                                       if (!prev_is_au_delim) {
+                                               if (au_start_in_pes) {
+                                                       /*FIXME - we should check the AVC framerate to update the timing ...*/
+                                                       pck.DTS += 3000;
+                                                       pck.PTS += 3000;
+       //                                              GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID%d: Two AVC AUs start in this PES packet - cannot recompute non-first AU timing\n", pes->pid));
+                                               }
+                                               pck.flags = GF_M2TS_PES_PCK_AU_START;
+                                               force_new_au = 0;
+                                               au_start_in_pes = 1;
+                                               ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
+                                               prev_is_au_delim=1;
+                                       }
+                               } else if (nal_type==GF_AVC_NALU_IDR_SLICE) {
+                                       pck.flags = GF_M2TS_PES_PCK_RAP;
+                                       ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
+                                       prev_is_au_delim=0;
+                               } 
+                               else {
+                                       pck.flags = 0;
+                                       ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
+                                       prev_is_au_delim=0;
                                }
-                       } else if (nal_type==GF_AVC_NALU_IDR_SLICE) {
-                               pck.flags = GF_M2TS_PES_PCK_RAP;
-                               ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
-                               prev_is_au_delim=0;
-                       } 
-                       else {
-                               pck.flags = 0;
-                               ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck);
-                               prev_is_au_delim=0;
                        }
 
                        data += sc_pos;
@@ -243,8 +291,10 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool
        }
        /*we did not consume all data*/
        if (!start_code_found) {
+               u32 min_size = is_hevc ? 6 : 5;
                /*if not enough data to locate start code, store it*/
-               if (data_len<5) return data_len;
+               if (data_len < min_size ) 
+                       return data_len;
                /*otherwise this is the middle of a frame, let's dispatch it*/
        }
 
@@ -275,6 +325,16 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool
        return 0;
 }
 
+static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
+{
+       return gf_m2ts_reframe_nalu_video(ts, pes, same_pts, data, data_len, 0);
+}
+
+static u32 gf_m2ts_reframe_hevc(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
+{
+       return gf_m2ts_reframe_nalu_video(ts, pes, same_pts, data, data_len, 1);
+}
+
 static u32 gf_m2ts_reframe_mpeg_video(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len)
 {
        u32 sc_pos = 0;
@@ -1533,6 +1593,7 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF
                case GF_M2TS_VIDEO_MPEG4:
                case GF_M2TS_SYSTEMS_MPEG4_PES:
                case GF_M2TS_VIDEO_H264:
+               case GF_M2TS_VIDEO_HEVC:
                case GF_M2TS_AUDIO_AC3:
                case GF_M2TS_AUDIO_DTS:
                case GF_M2TS_SUBTITLE_DVB:
@@ -2478,6 +2539,9 @@ GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode)
                case GF_M2TS_VIDEO_H264:
                        pes->reframe = gf_m2ts_reframe_avc_h264;
                        break;
+               case GF_M2TS_VIDEO_HEVC:
+                       pes->reframe = gf_m2ts_reframe_hevc;
+                       break;
                case GF_M2TS_AUDIO_AAC:
                        pes->reframe = gf_m2ts_reframe_aac_adts;
                        break;
@@ -2686,8 +2750,9 @@ static u32 TSDemux_DemuxRun(void *_p)
                         gf_dm_sess_process(ts->dnload);         
                         gf_sleep(1);    
                 }
-        } else if (ts->file) {
+        } else if (ts->file || ts->ts_data_chunk) {
                u32 pos = 0;
+               GF_BitStream *ts_bs = NULL;
 
                if (ts->segment_switch) {
                        ts->segment_switch = 0;
@@ -2703,19 +2768,23 @@ static u32 TSDemux_DemuxRun(void *_p)
                                pos = 0;
                        }
                }
-               gf_f64_seek(ts->file, pos, SEEK_SET);
 
-restart_file:
-               gf_f64_seek(ts->file, ts->start_byterange, SEEK_SET);
+restart_stream:
+
+               if (ts->file)
+                       ts_bs = gf_bs_from_file(ts->file, GF_BITSTREAM_READ);
+               else
+                       ts_bs = gf_bs_new(ts->ts_data_chunk, ts->ts_data_chunk_size, GF_BITSTREAM_READ);
+
+               gf_bs_seek(ts_bs, ts->start_byterange);
 
-               while (ts->run_state && !feof(ts->file)) {
+               while (ts->run_state && gf_bs_available(ts_bs)) {
                        /*m2ts chunks by chunks*/
-                       size = fread(data, 1, 188, ts->file);
+                       size = gf_bs_read_data(ts_bs, data, 188);
                        if (!size && (ts->loop_demux == 1)) {
-                               gf_f64_seek(ts->file, pos, SEEK_SET);
+                               gf_bs_seek(ts_bs, pos);
                                GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TSDemux] Loop \n"));
-                gf_sleep(500);
-                               size = fread(data, 1, 188, ts->file);
+                               size = gf_bs_read_data(ts_bs, data, 188);
                        }
                        if (!size) break;
                        if (size != 188) {
@@ -2725,9 +2794,7 @@ restart_file:
                        gf_m2ts_process_data(ts, data, size);
 
                        ts->nb_pck++;
-                       //fprintf(stderr, "TS packet #%d\r", ts->nb_pck);
-
-                       if (ts->end_byterange && (gf_f64_tell(ts->file)>=ts->end_byterange))
+                       if (ts->end_byterange && (gf_bs_get_position(ts_bs) >= ts->end_byterange))
                                break;
 
                        //gf_sleep(0);
@@ -2737,13 +2804,13 @@ restart_file:
                                continue;
                        }
 
-            if(feof(ts->file) && ts->loop_demux == 1){
-                gf_f64_seek(ts->file, pos, SEEK_SET);
+            if (!gf_bs_available(ts_bs) && ts->loop_demux == 1){
+                gf_bs_seek(ts_bs, pos);
                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TSDemux] Loop \n"));
                                gf_sleep(3000);
             }
                }
-               if (feof(ts->file)) {
+               if (!gf_bs_available(ts_bs)) {
                        u32 i;
                        for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {
                                if (ts->ess[i]) {
@@ -2757,16 +2824,30 @@ restart_file:
                }
 
 next_segment_setup:
+               gf_bs_del(ts_bs);
+               ts_bs = NULL;
                if (ts->run_state && ts->query_next) {
                        const char *next_url = NULL;
                        ts->query_next(ts->query_udta, 0, &next_url, &ts->start_byterange, &ts->end_byterange);
                        if (next_url) {
-                               fclose(ts->file);
-                               ts->file = gf_f64_open(next_url, "rb");
                                gf_m2ts_set_segment_switch(ts);
 
-                               if (ts->file) goto restart_file;
-                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSDemux] Cannot open next file %s\n", next_url));
+                               if (!strncmp(next_url, "gmem://", 7)) {
+                                       u32 size;
+                                       void *mem_address;
+                                       if (sscanf(next_url, "gmem://%d@%p", &size, &mem_address) != 2) {
+                                               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSDemux] Cannot open next file %s\n", next_url));
+                                       } else {
+                                               ts->ts_data_chunk_size = size;
+                                               ts->ts_data_chunk = mem_address;
+                                               if (ts->ts_data_chunk_size) goto restart_stream;
+                                       }
+                               } else {
+                                       if (ts->file) fclose(ts->file);
+                                       ts->file = gf_f64_open(next_url, "rb");
+                                       if (ts->file) goto restart_stream;
+                                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TSDemux] Cannot open next file %s\n", next_url));
+                               }
                        }
                }
        }
@@ -3052,16 +3133,28 @@ static GF_Err TSDemux_SetupFile(GF_M2TS_Demuxer *ts, char *url)
                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[TSDemux] TS file already being processed: %s\n", url));
                return GF_IO_ERR;
        }
-
-       ts->file = gf_f64_open(url, "rb"); 
-       if (!ts->file) {
-               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[TSDemux] Could not open TS file: %s\n", url));                
-               return GF_IO_ERR;
-       }
        strcpy(ts->filename, url);
 
-       gf_f64_seek(ts->file, 0, SEEK_END);
-       ts->file_size = gf_f64_tell(ts->file);
+       if (!strncmp(url, "gmem://", 7)) {
+               u32 size;
+               void *mem_address;
+               if (sscanf(url, "gmem://%d@%p", &size, &mem_address) != 2)
+                       return GF_IO_ERR;
+               ts->ts_data_chunk_size = size;
+               ts->ts_data_chunk = mem_address;
+       } else {
+
+               ts->file = gf_f64_open(url, "rb"); 
+               if (!ts->file) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[TSDemux] Could not open TS file: %s\n", url));                
+                       return GF_IO_ERR;
+               }
+               strcpy(ts->filename, url);
+
+               gf_f64_seek(ts->file, 0, SEEK_END);
+               ts->file_size = gf_f64_tell(ts->file);
+
+       }
 
        /* reinitialization for seek */
        ts->end_range = ts->start_range = 0;
@@ -3131,6 +3224,7 @@ GF_Err TSDemux_CloseDemux(GF_M2TS_Demuxer *ts)
 
        if (ts->file) fclose(ts->file);
        ts->file = NULL;
+       ts->ts_data_chunk = NULL;
 
        return GF_OK;
 }
@@ -3155,7 +3249,25 @@ Bool gf_m2ts_probe_file(const char *fileName)
 {
        char buf[188];
        u32 count = 10;
-       FILE *t = gf_f64_open(fileName, "rb");
+       FILE *t;
+
+       if (!strncmp(fileName, "gmem://", 7)) {
+               u32 size;
+               u8 *mem_address;
+               if (sscanf(fileName, "gmem://%d@%p", &size, &mem_address) != 2) {
+                       return GF_URL_ERROR;
+               } 
+               while (size>188 && count) {
+                       if (mem_address[0] != 0x47)
+                               return 0;
+                       mem_address+=188;
+                       size-=188;
+                       count--;
+               }
+               return 1;
+       }
+
+       t = gf_f64_open(fileName, "rb");
        while (t && count) {
                u32 read = fread(buf, 1, 188, t);
                if (!read) {
@@ -3175,13 +3287,13 @@ Bool gf_m2ts_probe_file(const char *fileName)
 static void rewrite_pts_dts(unsigned char *ptr, u64 TS)
 {
        ptr[0] &= 0xf1;
-       ptr[0] |= (unsigned char)((TS&0x1c0000000)>>29);
-       ptr[1]  = (unsigned char)((TS&0x03fc00000)>>22);
+       ptr[0] |= (unsigned char)((TS&0x1c0000000ULL)>>29);
+       ptr[1]  = (unsigned char)((TS&0x03fc00000ULL)>>22);
        ptr[2] &= 0x1;
-       ptr[2] |= (unsigned char)((TS&0x0003f8000)>>14);
-       ptr[3]  = (unsigned char)((TS&0x000007f80)>>7);
+       ptr[2] |= (unsigned char)((TS&0x0003f8000ULL)>>14);
+       ptr[3]  = (unsigned char)((TS&0x000007f80ULL)>>7);
        ptr[4] &= 0x1;
-       ptr[4] |= (unsigned char)((TS&0x00000007f)<<1);
+       ptr[4] |= (unsigned char)((TS&0x00000007fULL)<<1);
 
        assert(((u64)(ptr[0]&0xe)<<29) + ((u64)ptr[1]<<22) + ((u64)(ptr[2]&0xfe)<<14) + ((u64)ptr[3]<<7) + ((ptr[4]&0xfe)>>1) == TS);
 }
@@ -3235,13 +3347,13 @@ GF_Err gf_m2ts_restamp(char *buffer, u32 size, s64 ts_shift, u8 *is_pes)
                                }
                                pck[11] = (unsigned char)(0xff&pcr_ext);
                        }
+                       /*add adaptation_field_length field*/
+                       adaptation_field_length++;
                }
                if (!is_pes[pid] || !(pck[1]&0x40)) {
                        done+=188;
                        continue;
                }
-               if (adaptation_field_length)
-                       adaptation_field_length++; /*add adaptation_field_length field*/
 
                pesh = &pck[4+adaptation_field_length];
 
index 8b4e181f44343a177678d890da00914948d0238b..3feedfb2d962f745cbd4590d00d78b37658b845e 100644 (file)
@@ -1960,7 +1960,10 @@ GF_Err gf_import_timed_text(GF_MediaImporter *import)
        u32 fmt;
        e = gf_text_guess_format(import->in_name, &fmt);
        if (e) return e;
-       if (!fmt) return GF_NOT_SUPPORTED;
+       if (!fmt) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[TTXT Import] Input %s does not look like a supported text format - ignoring\n", import->in_name));
+               return GF_NOT_SUPPORTED;
+       }
        if (import->flags & GF_IMPORT_PROBE_ONLY) {
                if (fmt==GF_TEXT_IMPORT_SUB) import->flags |= GF_IMPORT_OVERRIDE_FPS;
                return GF_OK;
index ea42ff4deb4a4daf7e21d4d0d6fdd7cf2645b9c0..70d668e72337204b1739f2aefbd377982321fc87 100644 (file)
@@ -791,6 +791,154 @@ exit:
        return e;
 }
 
+
+
+GF_EXPORT
+GF_HEVCConfig *gf_odf_hevc_cfg_new()
+{
+       GF_HEVCConfig *cfg;
+       GF_SAFEALLOC(cfg, GF_HEVCConfig);
+       if (!cfg) return NULL;
+       cfg->param_array = gf_list_new();
+       cfg->nal_unit_size = 4;
+       return cfg;
+}
+
+GF_EXPORT
+void gf_odf_hevc_cfg_del(GF_HEVCConfig *cfg)
+{
+       if (!cfg) return;
+       while (gf_list_count(cfg->param_array)) {
+               GF_HEVCParamArray *pa = (GF_HEVCParamArray*)gf_list_get(cfg->param_array, 0);
+               gf_list_rem(cfg->param_array, 0);
+
+               while (gf_list_count(pa->nalus)) {
+                       GF_AVCConfigSlot *n = (GF_AVCConfigSlot*)gf_list_get(pa->nalus, 0);
+                       gf_list_rem(pa->nalus, 0);
+                       if (n->data) gf_free(n->data);
+                       gf_free(n);
+               }
+               gf_free(pa);
+       }
+       gf_free(cfg);
+}
+
+GF_EXPORT
+GF_Err gf_odf_hevc_cfg_write_bs(GF_HEVCConfig *cfg, GF_BitStream *bs)
+{
+       u32 i, count;
+
+       gf_bs_write_int(bs, cfg->configurationVersion, 8);
+       gf_bs_write_int(bs, cfg->profile_space, 3);
+       gf_bs_write_int(bs, cfg->profile_idc, 5);
+       gf_bs_write_int(bs, cfg->constraint_indicator_flags, 16);
+       gf_bs_write_int(bs, cfg->level_idc, 8);
+       gf_bs_write_int(bs, cfg->profile_compatibility_indications, 32);
+       gf_bs_write_int(bs, 0xFF, 6);
+       gf_bs_write_int(bs, cfg->chromaFormat, 2);
+       gf_bs_write_int(bs, 0xFF, 5);
+       gf_bs_write_int(bs, cfg->luma_bit_depth-8, 3);
+       gf_bs_write_int(bs, 0xFF, 5);
+       gf_bs_write_int(bs, cfg->chroma_bit_depth-8, 3);
+       gf_bs_write_int(bs, cfg->avgFrameRate, 16);
+       gf_bs_write_int(bs, cfg->constantFrameRate, 2);
+       gf_bs_write_int(bs, cfg->numTemporalLayers, 3);
+       gf_bs_write_int(bs, 1, 1);
+       gf_bs_write_int(bs, cfg->nal_unit_size - 1, 2);
+
+       count = gf_list_count(cfg->param_array);
+       gf_bs_write_int(bs, count, 8);
+       for (i=0; i<count; i++) {
+               u32 nalucount, j;
+               GF_HEVCParamArray *ar = gf_list_get(cfg->param_array, i);
+               gf_bs_write_int(bs, ar->array_completeness, 1);
+               gf_bs_write_int(bs, 0, 1);
+               gf_bs_write_int(bs, ar->type, 6);
+               nalucount = gf_list_count(ar->nalus);
+               gf_bs_write_int(bs, nalucount, 16);
+               for (j=0; j<nalucount; j++) {
+                       GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ar->nalus, j);
+                       gf_bs_write_int(bs, sl->size, 16);
+                       gf_bs_write_data(bs, sl->data, sl->size);
+               }
+       }
+       return GF_OK;
+}
+
+GF_EXPORT
+GF_Err gf_odf_hevc_cfg_write(GF_HEVCConfig *cfg, char **outData, u32 *outSize)
+{
+       GF_Err e;
+       GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+       *outSize = 0;
+       *outData = NULL;
+       e = gf_odf_hevc_cfg_write_bs(cfg, bs);
+       if (e==GF_OK) 
+               gf_bs_get_content(bs, outData, outSize);
+
+       gf_bs_del(bs);
+       return e;
+}
+
+GF_EXPORT
+GF_HEVCConfig *gf_odf_hevc_cfg_read_bs(GF_BitStream *bs)
+{
+       u32 i, count;
+       GF_HEVCConfig *cfg = gf_odf_hevc_cfg_new();
+
+       cfg->configurationVersion = gf_bs_read_int(bs, 8);
+       cfg->profile_space = gf_bs_read_int(bs, 3);
+       cfg->profile_idc = gf_bs_read_int(bs, 5);
+       cfg->constraint_indicator_flags = gf_bs_read_int(bs, 16);
+       cfg->level_idc = gf_bs_read_int(bs, 8);
+       cfg->profile_compatibility_indications = gf_bs_read_int(bs, 32);
+       gf_bs_read_int(bs, 6);
+       cfg->chromaFormat = gf_bs_read_int(bs, 2);
+       gf_bs_read_int(bs, 5);
+       cfg->luma_bit_depth = 8 + gf_bs_read_int(bs, 3);
+       gf_bs_read_int(bs, 5);
+       cfg->chroma_bit_depth = 8 + gf_bs_read_int(bs, 3);
+       cfg->avgFrameRate = gf_bs_read_int(bs, 16);
+       cfg->constantFrameRate = gf_bs_read_int(bs, 2);
+       cfg->numTemporalLayers = gf_bs_read_int(bs, 3);
+       gf_bs_read_int(bs, 1);
+       cfg->nal_unit_size = 1 + gf_bs_read_int(bs, 2);
+
+       count = gf_bs_read_int(bs, 8);
+       for (i=0; i<count; i++) {
+               u32 nalucount, j;
+               GF_HEVCParamArray *ar;
+               GF_SAFEALLOC(ar, GF_HEVCParamArray);
+               ar->nalus = gf_list_new();
+               gf_list_add(cfg->param_array, ar);
+               
+               ar->array_completeness = gf_bs_read_int(bs, 1);
+               gf_bs_read_int(bs, 1);
+               ar->type = gf_bs_read_int(bs, 6);
+               nalucount = gf_bs_read_int(bs, 16);
+               for (j=0; j<nalucount; j++) {
+                       GF_AVCConfigSlot *sl;
+                       GF_SAFEALLOC(sl, GF_AVCConfigSlot );
+
+                       sl->size = gf_bs_read_int(bs, 16);
+
+                       sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
+                       gf_bs_read_data(bs, sl->data, sl->size);
+                       gf_list_add(ar->nalus, sl);
+               }
+       }
+       return cfg;
+}
+
+GF_EXPORT
+GF_HEVCConfig *gf_odf_hevc_cfg_read(char *dsi, u32 dsi_size)
+{
+       GF_BitStream *bs = gf_bs_new(dsi, dsi_size, GF_BITSTREAM_READ);
+       GF_HEVCConfig *cfg = gf_odf_hevc_cfg_read_bs(bs);
+       gf_bs_del(bs);
+       return cfg;
+}
+
 GF_EXPORT
 const char *gf_afx_get_type_description(u8 afx_code)
 {
index 5ceeb21c9ce4907700beca63691d40ab9c3b15e3..40a90382a72322beed627d7b927738aaab5655ab 100644 (file)
@@ -34,7 +34,7 @@
 #include <gpac/user.h>
 
 
-#ifndef GPAC_DISABLE_LOADER_BT
+#if !defined(GPAC_DISABLE_LOADER_BT) && !defined(GPAC_DISABLE_ZLIB)
 
 #include <gpac/mpeg4_odf.h>
 
@@ -1094,23 +1094,31 @@ u32 gf_bt_get_next_proto_id(GF_BTParser *parser)
 
 u32 gf_bt_get_def_id(GF_BTParser *parser, char *defName)
 {
-       GF_Node *n;
-       u32 ID;
+       GF_Node *n=NULL;
+       u32 ID=0;
        if (sscanf(defName, "N%u", &ID) == 1) {
-               ID ++;
-               n = gf_sg_find_node(parser->load->scene_graph, ID);
-               /*if an existing node use*/
-               if (n) {
-                       u32 id;
-                       u32 nID = gf_bt_get_next_node_id(parser);
-                       const char *name = gf_node_get_name_and_id(n, &id);
-                       gf_bt_report(parser, GF_OK, "changing node \"%s\" Binary ID from %d to %d", name, id -1, nID-1);
-                       gf_node_set_id(n, nID, name);
+               u32 k=1;
+               while (defName[k]) {
+                       if (strchr("0123456789", defName[k])==0) {
+                               ID = 0;
+                               break;
+                       }
+                       k++;
                }
-               if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
-       } else {
-               ID = gf_bt_get_next_node_id(parser);
-       }
+               if (ID) {
+                       ID ++;
+                       n = gf_sg_find_node(parser->load->scene_graph, ID);
+                       if (!n) {
+                               if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
+                               return ID;
+                       }
+               }
+       } 
+
+       ID = gf_bt_get_next_node_id(parser);
+       if (n) {
+               GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[BT Parsing] (line %d) Binary ID %d already assigned to %s - keeping internal ID %d", parser->line, gf_node_get_name(n), ID));
+       } 
        return ID;
 }
 
index a617c8307e6bf7a2a7456aa9d1fc4e5cb791e42d..a7b85fa8ef49fe52f3d48073ebf443c680f4cc6f 100644 (file)
@@ -607,19 +607,29 @@ static u32 xmt_get_next_node_id(GF_XMTParser *parser)
 }
 static u32 xmt_get_node_id(GF_XMTParser *parser, char *name)
 {
-       GF_Node *n;
-       u32 ID;
+       GF_Node *n = NULL;
+       u32 ID = 0;
        if (sscanf(name, "N%u", &ID) == 1) {
-               ID ++;
-               n = gf_sg_find_node(parser->load->scene_graph, ID);
-               if (n) {
-                       u32 nID = xmt_get_next_node_id(parser);
-                       xmt_report(parser, GF_OK, "WARNING: changing node \"%s\" ID from %d to %d", gf_node_get_name(n), gf_node_get_id(n)-1, nID-1);
-                       gf_node_set_id(n, nID, gf_node_get_name(n));
-               }
-               if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
-       } else {
-               ID = xmt_get_next_node_id(parser);
+               u32 k=1;
+               while (name[k]) {
+                       if (strchr("0123456789", name[k])==0) {
+                               ID = 0;
+                               break;
+                       }
+                       k++;
+               }
+               if (ID) {
+                       ID ++;
+                       n = gf_sg_find_node(parser->load->scene_graph, ID);
+                       if (!n) {
+                               if (parser->load->ctx && (parser->load->ctx->max_node_id<ID)) parser->load->ctx->max_node_id=ID;
+                               return ID;
+                       }
+               }
+       } 
+       ID = xmt_get_next_node_id(parser);
+       if (n) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[XMT Parsing] (line %d) Binary ID %s already assigned to %s - keeping internal ID %d\n", gf_xml_sax_get_line(parser->sax_parser), name, gf_node_get_name(n), ID));
        }
        return ID;
 }
index e2254fb51c7d90de98a229b44ba135f5b2bb6de9..9afe84e6eae0d97ed3448f9556b1764dc92bbbb1 100644 (file)
@@ -417,10 +417,16 @@ start:
        assert(fsize < 1<<31);
        GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[SceneEngine] Sending DIMS data - sizes: raw (%d)", buffer_len)); 
        if (compress_dims) {
+#ifndef GPAC_DISABLE_ZLIB
                dims_header |= GF_DIMS_UNIT_C;
                e = gf_gz_compress_payload(&buffer, buffer_len, &buffer_len);
                GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("/ compressed (%d)", buffer_len)); 
                if (e) goto exit;
+#else
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error: your version of GPAC was compile with no libz support. Abort."));
+               e = GF_NOT_SUPPORTED;
+               goto exit;
+#endif
        }
     GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n")); 
 
index 1b5b39bb23210412ae49856c1aa85f68b3a16774..46307e984c01f274ffdebf66111638d78c1e9fa6 100644 (file)
 #include <gpac/internal/swf_dev.h>
 #include <gpac/avparse.h>
 
-#include <zlib.h>
+#if !defined(GPAC_DISABLE_SWF_IMPORT) && !defined(GPAC_DISABLE_ZLIB)
 
-#ifndef GPAC_DISABLE_SWF_IMPORT
 
+#include <zlib.h>
 
 enum
 {
index 7b1cc04d4d38c26b63c816dceff79c4f7b3973fe..bf7cb498e4b1ea861df34dedcd0efd3fa7cdac8c 100644 (file)
@@ -472,7 +472,7 @@ static SMJS_FUNC_PROP_GET( dom_nodelist_getProperty)
        }
        return JS_TRUE;
 }
-static SMJS_FUNC_PROP_SET( dom_nodelist_setProperty)
+static SMJS_FUNC_PROP_SET_NOVP( dom_nodelist_setProperty)
 
        /*avoids gcc warning*/
        if (!obj) obj=NULL;
@@ -1405,7 +1405,7 @@ static SMJS_FUNC_PROP_GET( dom_document_getProperty )
        return JS_TRUE;
 }
 
-static SMJS_FUNC_PROP_SET(dom_document_setProperty)
+static SMJS_FUNC_PROP_SET_NOVP(dom_document_setProperty)
 
        u32 prop_id;
        GF_SceneGraph *sg = dom_get_doc(c, obj);
@@ -3445,10 +3445,11 @@ static SMJS_FUNC_PROP_GET( storage_getProperty)
        /*avoids gcc warning*/
        if (!id) id=0;
        if (!GF_JS_InstanceOf(c, obj, &dom_rt->storageClass, NULL) ) return JS_TRUE;
+       *vp = JSVAL_VOID;
        return JS_TRUE;
 }
 
-static SMJS_FUNC_PROP_SET( storage_setProperty)
+static SMJS_FUNC_PROP_SET_NOVP( storage_setProperty)
 
        /*avoids gcc warning*/
        if (!id) id=0;
@@ -3526,29 +3527,29 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec nodeProps[] = {
-                       {"nodeName",            0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"nodeValue",           1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"nodeType",            2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"parentNode",          3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"childNodes",          4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"firstChild",          5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"lastChild",           6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"previousSibling",     7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"nextSibling",         8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"attributes",          9,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"ownerDocument",       10,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"namespaceURI",        11,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"prefix",                      12,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"localName",           13,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"baseURI",                     14,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"textContent",         15,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
+                       SMJS_PROPERTY_SPEC("nodeName",          0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("nodeValue",         1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("nodeType",          2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("parentNode",                3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("childNodes",                4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("firstChild",                5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("lastChild",         6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("previousSibling",   7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("nextSibling",               8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("attributes",                9,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("ownerDocument",     10,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("namespaceURI",      11,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("prefix",                    12,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("localName",         13,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("baseURI",                   14,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("textContent",               15,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
                        /*elementTraversal interface*/
-                       {"firstElementChild",           16,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"lastElementChild",            17,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"previousElementSibling",      18,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"nextElementSibling",          19,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("firstElementChild",         16,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("lastElementChild",          17,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("previousElementSibling",    18,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("nextElementSibling",                19,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
 
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(c, global, 0, &dom_rt->domNodeClass, 0, 0, nodeProps, nodeFuncs, 0, 0);
                if (!dom_rt->domNodeClass._proto) {
@@ -3590,17 +3591,17 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                };
 
                JSPropertySpec documentProps[] = {
-                       {"doctype",                             1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"implementation",              2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"documentElement",             3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"inputEncoding",               4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"xmlEncoding",                 5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"xmlStandalone",               6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"xmlVersion",                  7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"strictErrorChecking", 8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"documentURI",                 9,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"domConfig",                   10,      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0},
+                       SMJS_PROPERTY_SPEC("doctype",                           1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("implementation",            2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("documentElement",           3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("inputEncoding",             4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("xmlEncoding",                       5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("xmlStandalone",             6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("xmlVersion",                        7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("strictErrorChecking",       8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("documentURI",                       9,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("domConfig",                 10,      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0),
                };
 
                GF_JS_InitClass(c, global, dom_rt->domNodeClass._proto, &dom_rt->domDocumentClass, 0, 0, documentProps, documentFuncs, 0, 0);
@@ -3633,9 +3634,9 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                };
 
                JSPropertySpec elementProps[] = {
-                       {"tagName",                             1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"schemaTypeInfo",              2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0},
+                       SMJS_PROPERTY_SPEC("tagName",                           1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("schemaTypeInfo",            2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0),
                };
                GF_JS_InitClass(c, global, dom_rt->domNodeClass._proto, &dom_rt->domElementClass, 0, 0, elementProps, elementFuncs, 0, 0);
                GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] element class initialized\n"));
@@ -3656,12 +3657,12 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec textProps[] = {
-                       {"data",                                                1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"length",                                              2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("data",                                              1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("length",                                            2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
                        /*text*/
-                       {"isElementContentWhitespace",  3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"wholeText",                                   4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0},
+                       SMJS_PROPERTY_SPEC("isElementContentWhitespace",        3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("wholeText",                                 4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0),
                };
                GF_JS_InitClass(c, global, dom_rt->domNodeClass._proto, &dom_rt->domTextClass, 0, 0, textProps, textFuncs, 0, 0);
                GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] text class initialized\n"));
@@ -3680,59 +3681,58 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec eventProps[] = {
-                       {"type",                         0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"target",                       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"currentTarget",        2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"eventPhase",           3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"bubbles",                      4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"cancelable",           5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"timeStamp",            6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"namespaceURI",         7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"defaultPrevented", 8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("type",                       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("target",                     1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("currentTarget",      2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("eventPhase",                 3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("bubbles",                    4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("cancelable",                 5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("timeStamp",          6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("namespaceURI",       7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("defaultPrevented", 8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
 
                        /*UIEvent*/
-                       {"detail",                      20,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("detail",                    20,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
                        /*text, connectionEvent*/
-                       {"data",                        25,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("data",                      25,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
                        /*MouseEvent*/
-                       {"screenX",                     30,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"screenY",                     31,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"clientX",                     32,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"clientY",                     33,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"button",                      34,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"relatedTarget",       35,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("screenX",                   30,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("screenY",                   31,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("clientX",                   32,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("clientY",                   33,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("button",                    34,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("relatedTarget",     35,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
                        /*wheelEvent*/
-                       {"wheelDelta",          36,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("wheelDelta",                36,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
 
                        /*keyboard*/
-                       {"keyIdentifier",       40,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"keyChar",                     41,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"charCode",            42,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("keyIdentifier",     40,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("keyChar",                   41,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("charCode",          42,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
 
                        /*progress*/
-                       {"lengthComputable",50,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"typeArg",                     51,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"loaded",                      52,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"total",                       53,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"bufferLevelValid",    54,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"bufferLevel",                 55,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"bufferRemainingTime", 56,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"status",                              57,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("lengthComputable",50,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("typeArg",                   51,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("loaded",                    52,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("total",                     53,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("bufferLevelValid",  54,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("bufferLevel",                       55,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("bufferRemainingTime",       56,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("status",                            57,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
 
                        /*used by vrml*/
-                       {"width",                       60,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"height",                      61,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"offset_x",            62,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"offset_y",            63,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"vp_width",            64,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"vp_height",           65,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"translation_x",       66,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"translation_y",       67,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"type3d",                      68,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"error",                       69,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-
-
-                       {0, 0, 0, 0, 0},
+                       SMJS_PROPERTY_SPEC("width",                     60,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("height",                    61,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("offset_x",          62,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("offset_y",          63,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("vp_width",          64,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("vp_height",         65,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("translation_x",     66,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("translation_y",     67,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("type3d",                    68,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("error",                     69,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0),
                };
                GF_JS_InitClass(c, global, 0, &dom_rt->domEventClass, 0, 0, eventProps, eventFuncs, 0, 0);
                GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] Event class initialized\n"));
@@ -3754,8 +3754,8 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec nodeListProps[] = {
-                       {"length",      0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("length",    0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(c, global, 0, &dom_rt->domNodeListClass, 0, 0, nodeListProps, nodeListFuncs, 0, 0);
                GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] nodeList class initialized\n"));
@@ -3763,13 +3763,13 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
 
        {
                JSPropertySpec xmlHTTPRequestClassProps[] = {
-                       {"onreadystatechange",  0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"readyState",                  1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"responseText",                2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"responseXML",                 3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"status",                              4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"statusText",                  5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("onreadystatechange",        0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("readyState",                        1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("responseText",              2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("responseXML",                       3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("status",                            4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("statusText",                        5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec xmlHTTPRequestClassFuncs[] = {
                        SMJS_FUNCTION_SPEC("open",                                      xml_http_open, 2),
@@ -3787,7 +3787,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
 
        {
                JSPropertySpec storageClassProps[] = {
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec storageClassFuncs[] = {
                        SMJS_FUNCTION_SPEC(0, 0, 0)
@@ -3810,14 +3810,14 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global)
                if (dcci && dcci->RootNode) {
 
                        JSPropertySpec DCCIClassProps[] = {
-                               {"value",                                                       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                               {"valueType",                                           1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                               {"propertyType",                                        2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                               {"readOnly",                                            3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                               {"DCCIMetadataInterfaceType",           4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                               {"DCCIMetadataInterface",                       5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                               {"version",                                                     6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                               {0, 0, 0, 0, 0}
+                               SMJS_PROPERTY_SPEC("value",                                                     0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                               SMJS_PROPERTY_SPEC("valueType",                                         1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                               SMJS_PROPERTY_SPEC("propertyType",                                      2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                               SMJS_PROPERTY_SPEC("readOnly",                                          3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                               SMJS_PROPERTY_SPEC("DCCIMetadataInterfaceType",         4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                               SMJS_PROPERTY_SPEC("DCCIMetadataInterface",                     5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                               SMJS_PROPERTY_SPEC("version",                                                   6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                               SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                        };
                        JSFunctionSpec DCCIClassFuncs[] = {
                                SMJS_FUNCTION_SPEC("hasProperty",                       dcci_has_property, 3),
index 1f3d7c7e4875b16e6273e083000fd59fa04e045b..ce87087addd1faa5ec5b3ad615b713fd79e180cd 100644 (file)
@@ -1523,8 +1523,8 @@ static JSBool svg_connection_close(JSContext *c, JSObject *obj, uintN argc, jsva
 }
 
 static JSPropertySpec connectionProps[] = {
-       {"connected",                   0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-       {0, 0, 0, 0, 0}
+       SMJS_PROPERTY_SPEC("connected",                 0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
 };
 static JSFunctionSpec connectionFuncs[] = {
        /*eventTarget interface*/
@@ -2149,9 +2149,9 @@ static void svg_init_js_api(GF_SceneGraph *scene)
        SMJS_SET_PRIVATE(scene->svg_js->js_ctx, scene->svg_js->global, scene);
        {
                JSPropertySpec globalClassProps[] = {
-                       {"connected",   0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"parent",              1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("connected", 0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("parent",            1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec globalClassFuncs[] = {
                        SMJS_FUNCTION_SPEC("createConnection", svg_connection_create, 0),
@@ -2180,9 +2180,8 @@ static void svg_init_js_api(GF_SceneGraph *scene)
 
                JSPropertySpec svgDocumentProps[] = {
                        /*in our implementation, defaultView is just an alias to the global Window object*/
-                       {"defaultView",                 0,      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("defaultView",                       0,      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSObject *doc_proto = dom_js_get_document_proto(scene->svg_js->js_ctx);
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, doc_proto, &svg_rt->svgDocument, 0, 0, svgDocumentProps, 0, 0, 0);
@@ -2248,21 +2247,21 @@ static void svg_init_js_api(GF_SceneGraph *scene)
 
                JSPropertySpec svgElementProps[] = {
                        /*svgElement interface*/
-                       {"id",                                          0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
+                       SMJS_PROPERTY_SPEC("id",                                                0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
                        /*svgSVGElement interface*/
-                       {"currentScale",                        5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"currentRotate",                       6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"currentTranslate",            7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"viewport",                            8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"currentTime",                         9,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
+                       SMJS_PROPERTY_SPEC("currentScale",                      5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("currentRotate",                     6,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("currentTranslate",          7,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("viewport",                          8,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("currentTime",                               9,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
                        /*timeControl interface*/
-                       {"isPaused",                            10,      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("isPaused",                          10,      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
                        /*old SVG1.1 stuff*/
-                       {"ownerSVGElement",                     11,             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
+                       SMJS_PROPERTY_SPEC("ownerSVGElement",                   11,             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
                        /*SVGElementInstance*/
-                       {"correspondingElement",        12, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {"correspondingUseElement",     13, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("correspondingElement",      12, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC("correspondingUseElement",   13, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSObject *elt_proto = dom_js_get_element_proto(scene->svg_js->js_ctx);
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, elt_proto, &svg_rt->svgElement, 0, 0, svgElementProps, svgElementFuncs, 0, 0);
@@ -2272,30 +2271,30 @@ static void svg_init_js_api(GF_SceneGraph *scene)
        /*RGBColor class*/
        {
                JSPropertySpec rgbClassProps[] = {
-                       {"red",         0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"green",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"blue",        2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("red",               0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("green",     1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("blue",      2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->rgbClass, 0, 0, rgbClassProps, 0, 0, 0);
        }
        /*SVGRect class*/
        {
                JSPropertySpec rectClassProps[] = {
-                       {"x",           0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"y",           1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"width",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"height",      3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("x",         0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("y",         1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("width",     2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("height",    3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->rectClass, 0, 0, rectClassProps, 0, 0, 0);
        }
        /*SVGPoint class*/
        {
                JSPropertySpec pointClassProps[] = {
-                       {"x",   0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"y",   1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("x", 0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("y", 1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->pointClass, 0, 0, pointClassProps, 0, 0, 0);
        }
@@ -2311,13 +2310,13 @@ static void svg_init_js_api(GF_SceneGraph *scene)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec matrixClassProps[] = {
-                       {"a",   0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"b",   1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"c",   2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"d",   3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"e",   4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"f",   5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("a", 0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("b", 1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("c", 2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("d", 3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("e", 4,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("f", 5,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->matrixClass, 0, 0, matrixClassProps, matrixClassFuncs, 0, 0);
        }
@@ -2334,8 +2333,8 @@ static void svg_init_js_api(GF_SceneGraph *scene)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec pathClassProps[] = {
-                       {"numberOfSegments",    0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("numberOfSegments",  0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->pathClass, 0, 0, pathClassProps, pathClassFuncs, 0, 0);
                JS_DefineProperty(scene->svg_js->js_ctx, svg_rt->pathClass._proto, "MOVE_TO", INT_TO_JSVAL(77), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
index 45a626261b93362ef86abc003e321ac3c9a9ba20..ffde778a1ca8062a32e80524094527f1be564cb6 100644 (file)
@@ -291,6 +291,7 @@ static void gf_sg_load_script_modules(GF_SceneGraph *sg)
                if (!ext) continue;
                gf_list_add(js_rt->extensions, ext);
        }
+       GF_LOG(GF_LOG_INFO, GF_LOG_SCRIPT, ("[ECMAScript] found %d JS extensions for %d modules\n", gf_list_count(js_rt->extensions), count));
 }
 
 static void gf_sg_unload_script_modules()
@@ -3119,17 +3120,17 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script)
 #else
        /*only used to debug JS_SETUP_CLASS at each of the numerous changes of JSAPI ............ */
        memset(&js_rt->SFNodeClass, 0, sizeof(js_rt->SFNodeClass));
-       js_rt->SFNodeClass.name = "SFNode";
-       js_rt->SFNodeClass.flags = JSCLASS_HAS_PRIVATE;
-       js_rt->SFNodeClass.addProperty = JS_PropertyStub;
-       js_rt->SFNodeClass.delProperty = JS_PropertyStub;
-       js_rt->SFNodeClass.getProperty = node_getProperty;
-       js_rt->SFNodeClass.setProperty = node_setProperty;
-       js_rt->SFNodeClass.enumerate = JS_EnumerateStub;
-       js_rt->SFNodeClass.resolve = JS_ResolveStub;
-       js_rt->SFNodeClass.convert = JS_ConvertStub;
-       js_rt->SFNodeClass.finalize = node_finalize;
-       js_rt->SFNodeClass.hasInstance = gf_sg_js_has_instance;
+       js_rt->SFNodeClass._class.name = "SFNode";
+       js_rt->SFNodeClass._class.flags = JSCLASS_HAS_PRIVATE;
+       js_rt->SFNodeClass._class.addProperty = JS_PropertyStub;
+       js_rt->SFNodeClass._class.delProperty = JS_PropertyStub;
+       js_rt->SFNodeClass._class.getProperty = node_getProperty;
+       js_rt->SFNodeClass._class.setProperty = node_setProperty;
+       js_rt->SFNodeClass._class.enumerate = JS_EnumerateStub;
+       js_rt->SFNodeClass._class.resolve = JS_ResolveStub;
+       js_rt->SFNodeClass._class.convert = JS_ConvertStub;
+       js_rt->SFNodeClass._class.finalize = node_finalize;
+       js_rt->SFNodeClass._class.hasInstance = gf_sg_js_has_instance;
 #endif
 
        JS_SETUP_CLASS(js_rt->SFVec2fClass , "SFVec2f", JSCLASS_HAS_PRIVATE,
@@ -3244,16 +3245,16 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script)
                        SMJS_FUNCTION_SPEC(0, 0, 0)
                };
                JSPropertySpec SFNodeProps[] = {
-                       {"__dummy",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("__dummy",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFNodeClass, SFNodeConstructor, 1, SFNodeProps, SFNodeMethods, 0, 0);
        }
        {
                JSPropertySpec SFVec2fProps[] = {
-                       {"x",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"y",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("x",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("y",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec SFVec2fMethods[] = {
                        SMJS_FUNCTION_SPEC("add",                       vec2f_add,      1),
@@ -3271,10 +3272,10 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script)
        }
        {
                JSPropertySpec SFVec3fProps[] = {
-                       {"x",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"y",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"z",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("x",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("y",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("z",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec SFVec3fMethods[] = {
                        SMJS_FUNCTION_SPEC("add",             vec3f_add,      1),
@@ -3293,11 +3294,11 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script)
        }
        {
                JSPropertySpec SFRotationProps[] = {
-                       {"xAxis",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"yAxis",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"zAxis",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"angle",   3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("xAxis",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("yAxis",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("zAxis",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("angle",   3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec SFRotationMethods[] = {
                        SMJS_FUNCTION_SPEC("getAxis",         rot_getAxis,      1),
@@ -3313,10 +3314,10 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script)
        }
        {
                JSPropertySpec SFColorProps[] = {
-                       {"r",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"g",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"b",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("r",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("g",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("b",       2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                JSFunctionSpec SFColorMethods[] = {
                        SMJS_FUNCTION_SPEC("setHSV",          color_setHSV,   3),
@@ -3328,20 +3329,20 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script)
        }
        {
                JSPropertySpec SFImageProps[] = {
-                       {"x",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"y",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"comp",    2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {"array",   3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
-                       {0, 0, 0, 0, 0}
+                       SMJS_PROPERTY_SPEC("x",       0,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("y",       1,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("comp",    2,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC("array",   3,       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0),
+                       SMJS_PROPERTY_SPEC(0, 0, 0, 0, 0)
                };
                GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFImageClass, SFImageConstructor, 0, SFImageProps, 0, 0, 0);
        }
 
        {
                JSPropertySpec MFArrayProp[] = {
-                       { "length", 0, JSPROP_PERMANENT | JSPROP_SHARED, array_getLength, array_setLength },
-                       { "assign", 1, JSPROP_PERMANENT | JSPROP_SHARED, array_getElement, array_setElement},
-                       { 0, 0, 0, 0, 0 }
+                       SMJS_PROPERTY_SPEC( "length", 0, JSPROP_PERMANENT | JSPROP_SHARED, array_getLength, array_setLength ),
+                       SMJS_PROPERTY_SPEC( "assign", 1, JSPROP_PERMANENT | JSPROP_SHARED, array_getElement, array_setElement),
+                       SMJS_PROPERTY_SPEC( 0, 0, 0, 0, 0 )
                };
                JSFunctionSpec MFArrayMethods[] = {
                        SMJS_FUNCTION_SPEC("toString",        field_toString,       0),
index f18a4332f58c9429fa1f8a2f8873c0776954a6c9..8c8f895000ef46f58d92f9f893d2c956525922bd 100644 (file)
@@ -669,8 +669,12 @@ static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable)
                                if ( LockCompositionUnit(codec, codec->last_unit_cts+1, &CU, &unit_size) == GF_OUT_OF_MEM)
                                        return GF_OK;
                                assert( CU );
+                               unit_size = 0;
                                e = mdec->ProcessData(mdec, NULL, 0, 0, CU->data, &unit_size, 0, 0);
-                               if (e==GF_OK) e = UnlockCompositionUnit(codec, CU, unit_size);
+                               if (e==GF_OK) {
+                                       e = UnlockCompositionUnit(codec, CU, unit_size);
+                                       if (unit_size) return GF_OK;
+                               }
                        }
                        gf_term_stop_codec(codec, 0);
                        if (codec->CB) gf_cm_set_eos(codec->CB);
@@ -939,7 +943,7 @@ drop:
                }
                Decoder_GetNextAU(codec, &ch, &AU);
                if (!ch || !AU) return GF_OK;
-               }
+       }
        return GF_OK;
 }
 
index 21d782d002a829b5f5ebeff5c2771efdfb3a14f0..a09dd2e1dcd84f00c311af94b33aa309628a27f4 100644 (file)
@@ -140,15 +140,23 @@ void gf_term_add_codec(GF_Terminal *term, GF_Codec *codec)
        cd->dec = codec;
        if (!cd->dec->Priority) 
                cd->dec->Priority = 1;
-
-       cap.CapCode = GF_CODEC_WANTS_THREAD;
-       cap.cap.valueInt = 0;
-       gf_codec_get_capability(codec, &cap);
-       threaded = cap.cap.valueInt;
+       
+       /*we force audio codecs to be threaded in free mode, so that we avoid waiting in the audio renderer if another decoder is locking the main mutex
+       this can happen when the audio decoder is running late*/
+       if (codec->type==GF_STREAM_AUDIO) {
+               threaded = 1;
+       } else {
+               cap.CapCode = GF_CODEC_WANTS_THREAD;
+               cap.cap.valueInt = 0;
+               gf_codec_get_capability(codec, &cap);
+               threaded = cap.cap.valueInt;
+       }
+       
        if (threaded) cd->flags |= GF_MM_CE_REQ_THREAD;
 
+
        if (term->flags & GF_TERM_MULTI_THREAD) {
-               if ((codec->type==0x04) || (codec->type==0x05)) threaded = 1;
+               if ((codec->type==GF_STREAM_AUDIO) || (codec->type==GF_STREAM_VISUAL)) threaded = 1;
        } else if (term->flags & GF_TERM_SINGLE_THREAD) {
                threaded = 0;
        }
index 3903b1524c52dca717816c278dd29bcefc007f08..910184821f39730faa9e0eff2c3318bb3c9ec061 100644 (file)
@@ -414,6 +414,7 @@ void gf_cm_resize(GF_CompositionMemory *cb, u32 newCapacity)
        if (!cb->no_allocation) {
                my_large_gf_free(cu->data);
                cu->data = (char*) my_large_alloc(newCapacity);
+               cu->dataLength = 0;
        } else {
                cu->data = NULL;
                if (cu->dataLength && cb->odm->raw_frame_sema) {
@@ -429,9 +430,12 @@ void gf_cm_resize(GF_CompositionMemory *cb, u32 newCapacity)
                } else {
                        cu->data = NULL;
                }
+               cu->dataLength = 0;
                cu = cu->next;
-       }
-
+       }       
+       
+       cb->UnitCount = 0;
+       cb->output = cb->input;
        gf_odm_lock(cb->odm, 0);
 }
 
index 3b56074fdbde0b5163621377061c18d73b8a0f3b..1ba90cbf82d6eea021f0627189c223dd36a5aac9 100644 (file)
@@ -82,7 +82,7 @@ static void term_on_connect(void *user_priv, GF_ClientService *service, LPNETCHA
                gf_term_service_media_event(service->owner, GF_EVENT_MEDIA_SETUP_DONE);
                if (err) {
                        char msg[5000];
-                       snprintf(msg, sizeof(msg), "Cannot open %s", service->url);
+                       snprintf(msg, sizeof(msg)-1, "Cannot open %s", service->url);
                        gf_term_message(term, service->url, msg, err);
 
                        gf_term_service_media_event(service->owner, GF_EVENT_ERROR);
index da429aac0baa2a166c534d96cf341c8445e24344..49eebf4e061b2e39c32815f0bedd783e99045c5d 100644 (file)
@@ -314,9 +314,23 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url
        }
 
        desc = odm->net_service->ifce->GetServiceDescriptor(odm->net_service->ifce, od_type, sub_url); 
-       if (odm->OD) return;
+
+       /*entry point is already setup (bad design in GPAC, happens with BIFS TS and DASH*/
+       if (odm->OD) {
+               if (!desc) return;
+               if (gf_list_count(odm->OD->ESDescriptors)) {
+                       gf_odf_desc_del(desc);
+                       return;
+               }
+               gf_odf_desc_del((GF_Descriptor *) odm->OD);
+               odm->OD=NULL;
+               odm->subscene->is_dynamic_scene = 0;
+       }
 
        if (!desc) {
+               if (odm->OD && !gf_list_count(odm->OD->ESDescriptors)) 
+                       return;
+
                /*if desc is NULL for a media, the media will be declared later by the service (gf_term_media_add)*/
                if (od_type != GF_MEDIA_OBJECT_SCENE) {
                        return;
index 64cfe1ff9c3478dbc9b00eec9ff2f64f5549629f..35409718f5bf69d8e9027d2e4055bfd592d9af42 100644 (file)
@@ -947,7 +947,6 @@ void gf_scene_register_extra_graph(GF_Scene *scene, GF_SceneGraph *extra_scene,
 }
 
 
-
 static void gf_scene_get_video_size(GF_MediaObject *mo, u32 *w, u32 *h)
 {
        u32 pixel_ar;
@@ -994,7 +993,7 @@ static void IS_UpdateVideoPos(GF_Scene *scene)
 
        if (scene->root_od->term->root_scene == scene) {
                //if (scene->graph_attached) gf_sc_set_scene(scene->root_od->term->compositor, NULL);
-               gf_sc_set_scene(scene->root_od->term->compositor, scene->graph);
+               //gf_sc_set_scene(scene->root_od->term->compositor, scene->graph);
        }
 }
 
@@ -1372,7 +1371,20 @@ void gf_scene_force_size(GF_Scene *scene, u32 width, u32 height)
        gf_sg_set_scene_size_info(scene->graph, width, height, gf_sg_use_pixel_metrics(scene->graph));
        
        if (scene->root_od->term->root_scene == scene) {
-               gf_sc_set_scene(scene->root_od->term->compositor, scene->graph);
+               GF_NetworkCommand com;
+
+               gf_sc_set_scene_size(scene->root_od->term->compositor, width, height, 1);
+
+               memset(&com, 0, sizeof(GF_NetworkCommand));
+               com.base.command_type = GF_NET_SERVICE_HAS_FORCED_VIDEO_SIZE;
+               gf_term_service_command(scene->root_od->net_service, &com);
+               if (com.par.width && com.par.height) {
+                       gf_sc_set_size(scene->root_od->term->compositor, com.par.width, com.par.height);
+               } else {
+                       /*need output resize*/
+                       gf_sc_set_scene(scene->root_od->term->compositor, scene->graph);
+                       gf_sc_set_size(scene->root_od->term->compositor, width, height);
+               }
        }
        else if (scene->root_od->parentscene && scene->root_od->parentscene->is_dynamic_scene) {
                gf_sg_set_scene_size_info(scene->root_od->parentscene->graph, width, height, gf_sg_use_pixel_metrics(scene->root_od->parentscene->graph));
index cb92a1b4892d392beb0cf2706b30ad97fbafea01..97afacbefbb74e586ca52c232911e625a9a0f638 100644 (file)
@@ -174,6 +174,9 @@ u32 gf_base16_decode(char *in, u32 inSize, char *out, u32 outSize)
        return j;
 }
 
+
+#ifndef GPAC_DISABLE_ZLIB
+
 #include <zlib.h>
 
 #define ZLIB_COMPRESS_SAFE     4
@@ -266,3 +269,5 @@ GF_Err gf_gz_decompress_payload(char *data, u32 data_len, char **uncompressed_da
        }
        return e;
 }
+
+#endif /*GPAC_DISABLE_ZLIB*/
index 7b08685a3e2d88c6a919f6f61d6f6f1dc06f2654..1e84ea402ab5615118c2f08e4c52d3d9cbe927aa 100644 (file)
@@ -156,6 +156,17 @@ struct __DownloadedCacheEntryStruct
        /*start and end range of the cache*/
        u64 range_start, range_end;
 
+       Bool continue_file;
+       Bool file_exists;
+
+       u32 previousRangeContentLength;
+
+       /**
+       * Set to 1 if file is not stored on disk
+       */
+       Bool memory_stored;
+       u32 mem_allocated;
+       u8 *mem_storage;
 };
 
 Bool delete_cache_files(void *cbck, char *item_name, char *item_path) {
@@ -362,7 +373,7 @@ static const char * default_cache_file_suffix = ".dat";
 
 static const char * cache_file_info_suffix = ".txt";
 
-DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char * cache_directory, const char * url , u64 start_range, u64 end_range)
+DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char * cache_directory, const char * url , u64 start_range, u64 end_range, Bool mem_storage)
 {
        char tmp[_CACHE_TMP_SIZE];
        u8 hash[_CACHE_HASH_SIZE];
@@ -408,14 +419,12 @@ DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char
                GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("gf_cache_create_entry:%d : OUT of memory !\n", __LINE__));
                return NULL;
        }
-       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK,
-               ("[CACHE] gf_cache_create_entry:%d, entry=%p\n", __LINE__, entry));
+       GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[CACHE] gf_cache_create_entry:%d, entry=%p\n", __LINE__, entry));
 
        entry->url = gf_strdup ( url );
        entry->hash = gf_strdup ( tmp );
 
-       /* Sizeof cache directory + hash + possible extension */
-       entry->cache_filename = gf_malloc ( strlen ( cache_directory ) + strlen(cache_file_prefix) + strlen(tmp) + _CACHE_MAX_EXTENSION_SIZE + 1);
+       entry->memory_stored = mem_storage;
 
        entry->cacheSize = 0;
        entry->contentLength = 0;
@@ -429,17 +438,26 @@ DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char
        entry->range_start = start_range;
        entry->range_end = end_range;
 
+#ifdef ENABLE_WRITE_MX
        {
                char name[1024];
-               snprintf(name, 1024, "CachedEntryWriteMx=%p, url=%s", (void*) entry, url);
-#ifdef ENABLE_WRITE_MX
+               snprintf(name, sizeof(name)-1, "CachedEntryWriteMx=%p, url=%s", (void*) entry, url);
                entry->write_mutex = gf_mx_new(name);
                assert( entry->write_mutex);
-#endif
        }
+#endif
+
        entry->deletableFilesOnDelete = 0;
        entry->write_session = NULL;
        entry->sessions = gf_list_new();
+
+       if (entry->memory_stored) {
+               entry->cache_filename = gf_malloc ( strlen ("gmem://") + 8 + strlen("@") + 16 + 1);
+       } else {
+               /* Sizeof cache directory + hash + possible extension */
+               entry->cache_filename = gf_malloc ( strlen ( cache_directory ) + strlen(cache_file_prefix) + strlen(tmp) + _CACHE_MAX_EXTENSION_SIZE + 1);
+       }
+
        if ( !entry->hash || !entry->url || !entry->cache_filename || !entry->sessions)
        {
                GF_Err err;
@@ -449,6 +467,13 @@ DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char
                assert ( err == GF_OK );
                return NULL;
        }
+
+       if (entry->memory_stored) {
+               sprintf(entry->cache_filename, "gmem://%d@%p", entry->contentLength, entry->mem_storage);
+               return entry;   
+       }
+
+
        tmp[0] = '\0';
        strcpy ( entry->cache_filename, cache_directory );
        strcat( entry->cache_filename, cache_file_prefix );
@@ -497,7 +522,13 @@ DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char
                        entry->flags |= CORRUPTED;
 
                keyValue = gf_cfg_get_key(entry->properties, CACHE_SECTION_NAME, CACHE_SECTION_NAME_RANGE);
-               if (keyValue) sscanf(keyValue, LLD"-"LLD, &entry->range_start, &entry->range_end);
+               if (keyValue) {
+                       u64 s, e;
+                       sscanf(keyValue, LLD"-"LLD, &s, &e);
+                       /*mark as corrupted if not same range (we don't support this for the time being ...*/
+                       if ((s!=entry->range_start) || (e!=entry->range_end))
+                               entry->flags |= CORRUPTED;
+               }
        }
        gf_cache_check_if_cache_file_is_corrupted(entry);
 
@@ -506,7 +537,11 @@ DownloadedCacheEntry gf_cache_create_entry ( GF_DownloadManager * dm, const char
 
 GF_Err gf_cache_set_content_length( const DownloadedCacheEntry entry, u32 length ) {
        CHECK_ENTRY;
-       entry->contentLength = length;
+       if (entry->continue_file) {
+               entry->contentLength = entry->previousRangeContentLength + length;
+       } else {
+               entry->contentLength = length;
+       }
        return GF_OK;
 }
 
@@ -557,10 +592,31 @@ GF_Err gf_cache_open_write_cache( const DownloadedCacheEntry entry, const GF_Dow
        gf_mx_p(entry->write_mutex);
 #endif
        entry->write_session = sess;
-       assert( ! entry->writeFilePtr);
-       GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK,
-               ("[CACHE] Opening cache file %s for write (%s)...\n", entry->cache_filename, entry->url));
-       entry->writeFilePtr = gf_f64_open(entry->cache_filename, "wb");
+       if (!entry->continue_file) {
+               assert( ! entry->writeFilePtr);
+
+               entry->written_in_cache = 0;
+       }
+       entry->flags &= ~CORRUPTED;
+
+
+       if (entry->memory_stored) {
+               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] Opening cache file %s for write (%s)...\n", entry->cache_filename, entry->url));
+               if (entry->mem_allocated <= entry->contentLength) {
+                       if (entry->contentLength) entry->mem_allocated = entry->contentLength;
+                       else if (!entry->mem_allocated) entry->mem_allocated = 1024;
+                       entry->mem_storage = gf_realloc(entry->mem_storage, sizeof(char)* (entry->mem_allocated + 2) );
+               }
+               if (!entry->mem_allocated) {
+                       GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[CACHE] Failed to create memory storage for file %s\n", entry->url));
+                       return GF_OUT_OF_MEM;
+               }
+               sprintf(entry->cache_filename, "gmem://%d@%p", entry->contentLength, entry->mem_storage);
+               return GF_OK;
+       }
+
+       GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] Opening cache file %s for write (%s)...\n", entry->cache_filename, entry->url));
+       entry->writeFilePtr = gf_f64_open(entry->cache_filename, entry->continue_file ? "a+b" : "wb");
        if (!entry->writeFilePtr) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK,
                        ("[CACHE] Error while opening cache file %s for writting.\n", entry->cache_filename));
@@ -570,7 +626,9 @@ GF_Err gf_cache_open_write_cache( const DownloadedCacheEntry entry, const GF_Dow
 #endif
                return GF_IO_ERR;
        }
-       entry->written_in_cache = 0;
+       entry->file_exists = 1;
+       if (entry->continue_file )
+               gf_f64_seek(entry->writeFilePtr, 0, SEEK_END);
        return GF_OK;
 }
 
@@ -578,10 +636,24 @@ GF_Err gf_cache_write_to_cache( const DownloadedCacheEntry entry, const GF_Downl
        u32 readen;
        GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[CACHE] gf_cache_write_to_cache:%d\n", __LINE__));
        CHECK_ENTRY;
-       if (!data || !entry->writeFilePtr || sess != entry->write_session) {
-               GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("Incorrect parameter : data=%p, entry->writeFilePtr=%p at "__FILE__, data, entry->writeFilePtr));
+
+       if (!data || (!entry->writeFilePtr && !entry->mem_storage) || sess != entry->write_session) {
+               GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("Incorrect parameter : data=%p, writeFilePtr=%p mem_storage=%p at "__FILE__, data, entry->writeFilePtr, entry->mem_storage));
                return GF_BAD_PARAM;
        }
+               
+       if (entry->memory_stored) {
+               if (entry->written_in_cache + size > entry->mem_allocated) {
+                       entry->mem_storage = gf_realloc(entry->mem_storage, (entry->mem_allocated+size+2));
+                       entry->mem_allocated += size;
+                       sprintf(entry->cache_filename, "gmem://%d@%p", entry->contentLength, entry->mem_storage);
+               }
+               memcpy(entry->mem_storage + entry->written_in_cache, data, size);
+               entry->written_in_cache += size;
+               memset(entry->mem_storage + entry->written_in_cache, 0, 2);
+               return GF_OK;
+       }
+
        readen = gf_fwrite(data, sizeof(char), size, entry->writeFilePtr);
        if (readen > 0)
                entry->written_in_cache+= readen;
@@ -671,7 +743,7 @@ GF_Err gf_cache_delete_entry ( const DownloadedCacheEntry entry )
                gf_mx_del(entry->write_mutex);
        }
 #endif
-       if (entry->deletableFilesOnDelete) {
+       if (entry->file_exists && entry->deletableFilesOnDelete) {
                GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] url %s cleanup, deleting %s...\n", entry->url, entry->cache_filename));
                if (GF_OK != gf_delete_file(entry->cache_filename))
                        GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[CACHE] gf_cache_delete_entry:%d, failed to delete file %s\n", __LINE__, entry->cache_filename));
@@ -738,6 +810,9 @@ GF_Err gf_cache_delete_entry ( const DownloadedCacheEntry entry )
                gf_list_del(entry->sessions);
                entry->sessions = NULL;
        }
+
+       if (entry->mem_storage) 
+               gf_free(entry->mem_storage);
        gf_free (entry);
        return GF_OK;
 }
@@ -757,17 +832,15 @@ Bool gf_cache_check_if_cache_file_is_corrupted(const DownloadedCacheEntry entry)
                        entry->contentLength = strtoul( keyValue, &endPtr, 10);
                        if (*endPtr!='\0' || entry->contentLength != entry->cacheSize) {
                                entry->flags |= CORRUPTED;
-                               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] gf_cache_create_entry:%d, cached file and cache info size mismatch.\n", __LINE__));
+                               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] gf_cache_create_entry:%d, Cache corrupted: file and cache info size mismatch.\n", __LINE__));
                        }
-               } else
+               } else {
                        entry->flags |= CORRUPTED;
-
+                       GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] gf_cache_create_entry:%d, CACHE is corrupted !\n", __LINE__));
+               }
        } else {
                entry->flags |= CORRUPTED;
        }
-       if (entry->flags & CORRUPTED)
-               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] gf_cache_create_entry:%d, CACHE is corrupted !\n", __LINE__));
-
        return entry->flags & CORRUPTED;
 }
 
@@ -832,3 +905,20 @@ FILE *gf_cache_get_file_pointer(const DownloadedCacheEntry entry)
        if (entry) return entry->writeFilePtr;
        return NULL;
 }
+
+
+void gf_cache_set_end_range(DownloadedCacheEntry entry, u64 range_end)
+{
+       entry->previousRangeContentLength = entry->contentLength;
+       entry->range_end = range_end;
+       entry->continue_file = 1;
+}
+
+Bool gf_cache_is_in_progress(const DownloadedCacheEntry entry)
+{
+       if (!entry) return 0;
+       if (entry->writeFilePtr) return 1;
+       if (entry->mem_storage && entry->written_in_cache && entry->contentLength && (entry->written_in_cache<entry->contentLength) ) 
+               return 1;
+       return 0;
+}
index c502d4f8da2caf3689e38e2c34ff2b715aa2a950..ebcbe30c3dfc64bf198d3c9a7dddb8906520f373 100644 (file)
@@ -207,7 +207,8 @@ GF_Config *gf_cfg_new(const char *filePath, const char* file_name)
        }
 
        if (gf_cfg_parse_config_file(tmp, filePath, file_name)){
-           gf_free( tmp );
+               gf_cfg_clear(tmp);
+               gf_free(tmp);
            tmp = NULL;
        }
        return tmp;
index bf8f1ffc5ff0eb9a5d2099db24dd881c7f13d79c..ccdde23ea4e3d59ef1a3f2c50918e4f4e4ddd41f 100644 (file)
@@ -108,6 +108,7 @@ struct __gf_download_session
     gf_user_credentials_struct * creds;
     char cookie[GF_MAX_PATH];
     DownloadedCacheEntry cache_entry;
+       Bool reused_cache_entry;
 
     GF_Socket *sock;
     u32 num_retry, status;
@@ -117,6 +118,9 @@ struct __gf_download_session
     u32 total_size, bytes_done, start_time, icy_metaint, icy_count, icy_bytes;
     u32 bytes_per_sec;
 
+       Bool is_range_continuation;
+       /*0: no cache reconfig before next GET request: 1: try to rematch the cache entry: 2: force to create a new cache entry (for byte-range cases*/
+       u32 needs_cache_reconfig;
     /* Range information if needed for the download (cf flag) */
     Bool needs_range;
     u64 range_start, range_end;
@@ -145,6 +149,7 @@ struct __gf_download_session
     /*callback for data reception - may not be NULL*/
     gf_dm_user_io user_proc;
     void *usr_cbk;
+       Bool reassigned;
 
     /*private extension*/
     void *ext;
@@ -241,6 +246,12 @@ GF_Err gf_cache_open_write_cache( const DownloadedCacheEntry entry, const GF_Dow
  */
 FILE *gf_cache_get_file_pointer(const DownloadedCacheEntry entry) ;
 
+/*modify end range when chaining byte-range requests*/
+void gf_cache_set_end_range(DownloadedCacheEntry entry, u64 range_end);
+
+/*returns 1 if cache is currently open for write*/
+Bool gf_cache_is_in_progress(const DownloadedCacheEntry entry);
+
 /**
  * Find a User's credentials for a given site
  */
@@ -455,8 +466,13 @@ DownloadedCacheEntry gf_dm_find_cached_entry_by_url(GF_DownloadSession * sess) {
         url = gf_cache_get_url(e);
         assert( url );
         if (strcmp(url, sess->orig_url)) continue;
-               if (sess->range_start != gf_cache_get_start_range(e)) continue;
-               if (sess->range_end != gf_cache_get_end_range(e)) continue;
+               if (sess->needs_cache_reconfig==2)
+                       continue;
+
+               if (! sess->is_range_continuation) {
+                       if (sess->range_start != gf_cache_get_start_range(e)) continue;
+                       if (sess->range_end != gf_cache_get_end_range(e)) continue;
+               }
                /*OK that's ours*/
                gf_mx_v( sess->dm->cache_mx );
                return e;
@@ -471,7 +487,7 @@ DownloadedCacheEntry gf_dm_find_cached_entry_by_url(GF_DownloadSession * sess) {
  * \param url The full URL
  * \return The DownloadedCacheEntry
  */
-DownloadedCacheEntry gf_cache_create_entry( GF_DownloadManager * dm, const char * cache_directory, const char * url, u64 start_range, u64 end_range);
+DownloadedCacheEntry gf_cache_create_entry( GF_DownloadManager * dm, const char * cache_directory, const char * url, u64 start_range, u64 end_range, Bool mem_storage);
 
 /*!
  * Removes a session for a DownloadedCacheEntry
@@ -528,13 +544,15 @@ void gf_dm_configure_cache(GF_DownloadSession *sess)
     gf_dm_remove_cache_entry_from_session(sess);
     entry = gf_dm_find_cached_entry_by_url(sess);
     if (!entry) {
-               entry = gf_cache_create_entry(sess->dm, sess->dm->cache_directory, sess->orig_url, sess->range_start, sess->range_end);
+               entry = gf_cache_create_entry(sess->dm, sess->dm->cache_directory, sess->orig_url, sess->range_start, sess->range_end, (sess->flags&GF_NETIO_SESSION_MEMORY_CACHE) ? 1 : 0);
         gf_mx_p( sess->dm->cache_mx );
         gf_list_add(sess->dm->cache_entries, entry);
         gf_mx_v( sess->dm->cache_mx );
+               sess->is_range_continuation = 0;
     }
     assert( entry );
     sess->cache_entry = entry;
+       sess->reused_cache_entry =      gf_cache_is_in_progress(entry);
     gf_cache_add_session_to_cache_entry(sess->cache_entry, sess);
     GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[CACHE] Cache setup to %p %s\n", sess, gf_cache_get_cache_filename(sess->cache_entry)));
 }
@@ -598,7 +616,7 @@ static void gf_dm_disconnect(GF_DownloadSession *sess, Bool force_close)
 {
     assert( sess );
     if (sess->status >= GF_NETIO_DISCONNECTED)
-       return;
+               return;
     GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Downloader] gf_dm_disconnect(%p)\n", sess ));
     if (sess->mx)
         gf_mx_p(sess->mx);
@@ -858,8 +876,8 @@ GF_Err gf_dm_get_url_info(const char * url, GF_URL_Info * info, const char * bas
     /* builds orig_url */
     /* We dont't want orig_url to contain user/passwords for security reasons or mismatch in cache hit */
     {
-        char port[7];
-        snprintf(port, 7, ":%d", info->port);
+        char port[8];
+        snprintf(port, sizeof(port)-1, ":%d", info->port);
         info->canonicalRepresentation = gf_malloc(strlen(info->protocol)+strlen(info->server_name)+1+strlen(port)+strlen(info->remotePath));
         strcpy(info->canonicalRepresentation, info->protocol);
         strcat(info->canonicalRepresentation, info->server_name);
@@ -878,13 +896,17 @@ GF_Err gf_dm_sess_setup_from_url(GF_DownloadSession *sess, const char *url)
        Bool socket_changed = 0;
     GF_Err e;
     GF_URL_Info info;
+
+       if (!url) return GF_BAD_PARAM;
+
     gf_dm_url_info_init(&info);
-    e = gf_dm_get_url_info(url, &info, sess->remote_path);
-       if (e) return e;
     
        if (!sess->sock) socket_changed = 1;
        else if (sess->status>GF_NETIO_DISCONNECTED) socket_changed = 1;
 
+    e = gf_dm_get_url_info(url, &info, sess->remote_path);
+       if (e) return e;
+
        if (sess->port != info.port) {
                socket_changed = 1;
                sess->port = info.port;
@@ -939,8 +961,7 @@ GF_Err gf_dm_sess_setup_from_url(GF_DownloadSession *sess, const char *url)
        if (sess->sock && !socket_changed) {
                sess->status = GF_NETIO_CONNECTED;
            sess->num_retry = SESSION_RETRY_COUNT;
-               /*this should be done when building HTTP GET request in case we have range directives*/
-               gf_dm_configure_cache(sess);
+               sess->needs_cache_reconfig = 1;
        } else {
                if (sess->sock) gf_sk_del(sess->sock);
                sess->sock = NULL;
@@ -1039,8 +1060,10 @@ GF_DownloadSession *gf_dm_sess_new(GF_DownloadManager *dm, const char *url, u32
 
 static GF_Err gf_dm_read_data(GF_DownloadSession *sess, char *data, u32 data_size, u32 *out_read)
 {
+#ifdef GPAC_HAS_SSL
     GF_Err e;
-    if (!sess)
+#endif
+       if (!sess)
         return GF_BAD_PARAM;
 #ifdef GPAC_HAS_SSL
     if (sess->ssl) {
@@ -1325,11 +1348,34 @@ const char *gf_dm_sess_mime_type(GF_DownloadSession *sess)
 }
 
 GF_EXPORT
-GF_Err gf_dm_sess_set_range(GF_DownloadSession *sess, u64 start_range, u64 end_range)
+GF_Err gf_dm_sess_set_range(GF_DownloadSession *sess, u64 start_range, u64 end_range, Bool discontinue_cache)
 {
        if (!sess) return GF_BAD_PARAM;
-       if (sess->cache_entry) return GF_BAD_PARAM;
-       if (sess->status != GF_NETIO_SETUP) return GF_BAD_PARAM;
+       if (sess->cache_entry) {
+               if (!discontinue_cache) {
+                       if (gf_cache_get_end_range(sess->cache_entry) + 1 != start_range) 
+                               return GF_NOT_SUPPORTED;
+               }
+               if (!sess->sock)
+                       return GF_BAD_PARAM;
+               if (sess->status != GF_NETIO_CONNECTED) {
+                       if (sess->status != GF_NETIO_DISCONNECTED) {
+                               return GF_BAD_PARAM;
+                       }
+               }
+               sess->status = GF_NETIO_CONNECTED;
+           sess->num_retry = SESSION_RETRY_COUNT;
+               if (!discontinue_cache) {
+                       gf_cache_set_end_range(sess->cache_entry, end_range);
+                       /*remember this in case we get disconnected*/
+                       sess->is_range_continuation = 1;
+               } else {
+                       sess->needs_cache_reconfig = 2;
+                       sess->reused_cache_entry = 0;
+               }
+       } else {
+               if (sess->status != GF_NETIO_SETUP) return GF_BAD_PARAM;
+       }
        sess->range_start = start_range;
        sess->range_end = end_range;
     sess->needs_range = 1;
@@ -1393,7 +1439,8 @@ GF_Err gf_dm_sess_process_headers(GF_DownloadSession *sess)
                 gf_sleep(16);
             break;
         case GF_NETIO_WAIT_FOR_REPLY:
-            gf_sleep(16);
+//            gf_sleep(16);
+              gf_sleep(1);
         case GF_NETIO_CONNECTED:
             sess->do_requests(sess);
             break;
@@ -1666,18 +1713,6 @@ static GFINLINE void gf_dm_data_received(GF_DownloadSession *sess, const char *d
         }
     }
 
-    if (sess->total_size && (sess->bytes_done == sess->total_size)) {
-        gf_dm_disconnect(sess, 0);
-        par.msg_type = GF_NETIO_DATA_TRANSFERED;
-        par.error = GF_OK;
-        gf_dm_sess_user_io(sess, &par);
-        if (sess->use_cache_file) {
-            gf_cache_close_write_cache(sess->cache_entry, sess, 1);
-            GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK,
-                   ("[CACHE] url %s saved as %s\n", gf_cache_get_url(sess->cache_entry), gf_cache_get_cache_filename(sess->cache_entry)));
-        }
-        return;
-    }
     /*update state if not done*/
     if (rcv) {
         runtime = gf_sys_clock() - sess->start_time;
@@ -1687,6 +1722,21 @@ static GFINLINE void gf_dm_data_received(GF_DownloadSession *sess, const char *d
             sess->bytes_per_sec = (1000 * sess->bytes_done) / runtime;
         }
     }
+
+       if (sess->total_size && (sess->bytes_done == sess->total_size)) {
+        gf_dm_disconnect(sess, 0);
+        par.msg_type = GF_NETIO_DATA_TRANSFERED;
+        par.error = GF_OK;
+
+               
+               gf_dm_sess_user_io(sess, &par);
+        if (sess->use_cache_file) {
+            gf_cache_close_write_cache(sess->cache_entry, sess, 1);
+            GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK,
+                   ("[CACHE] url %s saved as %s\n", gf_cache_get_url(sess->cache_entry), gf_cache_get_cache_filename(sess->cache_entry)));
+        }
+               GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP] url %s downloaded in %d ms (%d kbps)\n", gf_cache_get_url(sess->cache_entry), gf_sys_clock() - sess->start_time, 8*sess->bytes_per_sec/1024 ));
+    }
 }
 
 
@@ -1823,6 +1873,13 @@ static GF_Err http_send_headers(GF_DownloadSession *sess, char * sHTTP) {
     const char *param_string;
     Bool has_accept, has_connection, has_range, has_agent, has_language, send_profile, has_mime;
     assert (sess->status == GF_NETIO_CONNECTED);
+
+
+       if (sess->needs_cache_reconfig) {
+               gf_dm_configure_cache(sess);
+               sess->needs_cache_reconfig = 0;
+       }
+
     /*setup authentification*/
     strcpy(pass_buf, "");
     sess->creds = gf_find_user_credentials_for_site( sess->dm, sess->server_name );
@@ -2619,6 +2676,15 @@ exit:
 void http_do_requests(GF_DownloadSession *sess)
 {
     char sHTTP[GF_DOWNLOAD_BUFFER_SIZE];
+
+       if (sess->reused_cache_entry) {
+               if (!gf_cache_is_in_progress(sess->cache_entry)) {
+                       sess->status = GF_NETIO_DISCONNECTED;
+                       sess->reused_cache_entry = 0;
+               }
+               return;
+       }
+
     switch (sess->status) {
     case GF_NETIO_CONNECTED:
         http_send_headers(sess, sHTTP);
@@ -2627,6 +2693,21 @@ void http_do_requests(GF_DownloadSession *sess)
         wait_for_header_and_parse(sess, sHTTP);
         break;
     case GF_NETIO_DATA_EXCHANGE:
+               /*session has been reassigned, resend data retrieved in first GET reply to user but don't write to cache*/
+               if (sess->reassigned) {
+
+                       if (sess->icy_metaint > 0) {
+                               gf_icy_skip_data(sess, sess->icy_metaint, sess->init_data, sess->init_data_size);
+                       } else {
+                           GF_NETIO_Parameter par;
+                               par.msg_type = GF_NETIO_DATA_EXCHANGE;
+                               par.error = GF_OK;
+                               par.data = sess->init_data;
+                               par.size = sess->init_data_size;
+                               gf_dm_sess_user_io(sess, &par);
+                       }
+                       sess->reassigned = 0;
+               }
         http_parse_remaining_body(sess, sHTTP);
         break;
     }
@@ -2932,7 +3013,7 @@ GF_Err gf_dm_sess_reassign(GF_DownloadSession *sess, u32 flags, gf_dm_user_io us
        sess->flags = flags;
        sess->user_proc = user_io;
        sess->usr_cbk = cbk;
-
+       sess->reassigned = sess->init_data ? 1 : 0;
        sess->num_retry = SESSION_RETRY_COUNT;
 
        if (sess->status==GF_NETIO_DISCONNECTED)
index f6c57d1f2bb956f74a3cbba0d7fe09d884b58fd1..939d773ba1abfba205ee7d279b434ac16a222312 100644 (file)
@@ -547,7 +547,7 @@ static const u32 gf_crc_table[256] = {
 };
 
 GF_EXPORT
-u32 gf_crc_32(char *data, u32 len)
+u32 gf_crc_32(const char *data, u32 len)
 {
     register u32 i;
     u32 crc = 0xffffffff;
index 7c383fb3b8a64c870809571cdd778660706b2865..3813b0b7c37d995d12afedd2de1420836fa478a1 100644 (file)
@@ -309,7 +309,7 @@ int gettimeofday(struct timeval *tp, struct timezone *tzp)
 }
 
 
-#if 0
+#if _GPAC_UNUSED
 /*
        time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds 
        FILETIME in Win32 is from jan 1, 1601
@@ -406,7 +406,11 @@ GF_Err gf_move_file(const char *fileName, const char *newFileName)
        return (MoveFile(fileName, newFileName) == 0 ) ? GF_IO_ERR : GF_OK;
 #else
        /* success is == 0 */
-       return ( rename(fileName, newFileName) == 0) ? GF_OK : GF_IO_ERR;
+       char cmd[1024];
+       if (!fileName || !newFileName)
+               return GF_IO_ERR;
+       snprintf(cmd, sizeof(cmd)-1, "mv %s %s > /dev/null 2>&1", fileName, newFileName);
+       return ( system(cmd) == 0) ? GF_OK : GF_IO_ERR;
 #endif
 }
 
@@ -484,8 +488,13 @@ FILE *gf_temp_file_new()
        char tmp[MAX_PATH], t_file[100];
        FILE *res = tmpfile();
        if (res) return res;
+       {
+               u32 err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Win32] system failure for tmpfile(): %08x\n", err));
+       }
        /*tmpfile() may fail under vista ...*/
-       if (!GetEnvironmentVariable("TEMP",tmp,MAX_PATH)) return NULL;
+       if (!GetEnvironmentVariable("TEMP",tmp,MAX_PATH)) 
+               return NULL;
        sprintf(t_file, "\\gpac_%08x.tmp", (u32) tmp);
        strcat(tmp, t_file);
        return gf_f64_open(tmp, "w+b");
@@ -804,7 +813,13 @@ GF_EXPORT
 FILE *gf_f64_open(const char *file_name, const char *mode)
 {
 #if defined(WIN32)
-       return fopen(file_name, mode);
+       FILE *res = fopen(file_name, mode);
+       if (res) return res;
+       if (strchr(mode, 'w') || strchr(mode, 'a')) {
+               u32 err = GetLastError();
+               GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Win32] system failure for file opening of %s in mode %s: %08x\n", file_name, mode, err));
+       }
+       return NULL;
 #elif defined(GPAC_CONFIG_LINUX) && !defined(GPAC_ANDROID)
        return fopen64(file_name, mode);
 #elif (defined(GPAC_CONFIG_FREEBSD) || defined(GPAC_CONFIG_DARWIN))
@@ -1922,7 +1937,7 @@ GF_GlobalLock * gf_create_PID_file( const char * resourceName )
        {
                int sz = 100;
                char * buf = gf_malloc( sz );
-               sz = snprintf(buf, sz, "%ld\n", (long) getpid());
+               sz = snprintf(buf, sz-1, "%ld\n", (long) getpid());
                if (write(fd, buf, sz) != sz){
                        gf_free(buf);
                        goto exit;
index 9a1c990e1b2df0c1dd5bc6aefdd49d1fda6eac45..0f7119f11b45c4fdcd4f80adfaa5e8fdbb908a1f 100644 (file)
@@ -700,6 +700,7 @@ u32 gf_sema_notify(GF_Semaphore *sm, u32 NbRelease)
        return (u32) prevCount;
 }
 
+GF_EXPORT
 void gf_sema_wait(GF_Semaphore *sm)
 {
 #ifdef WIN32
index b78cdec1e1bf46d90fa7042921ab1293d8b73ffd..9711a864d02330b3a6b672203d940dd6a5f99fe2 100644 (file)
@@ -693,6 +693,16 @@ s32 gf_sha1_file( const char *path, u8 output[20] )
     GF_SHA1Context *ctx;
     u8 buf[1024];
 
+       if (!strncmp(path, "gmem://", 7)) {
+               u32 size;
+               u8 *mem_address;
+               if (sscanf(path, "gmem://%d@%p", &size, &mem_address) != 2) {
+                       return GF_IO_ERR;
+               } 
+               gf_sha1_csum(mem_address, size, output);
+               return 0;
+       }
+
     if( ( f = gf_f64_open( path, "rb" ) ) == NULL )
         return( 1 );
 
index 45d742d9c5b04d9a1e084ebbc82372b64c99f66a..09220d4506eb365a59af38b3f9b19264859e336b 100644 (file)
 
 #include <gpac/xml.h>
 #include <gpac/utf.h>
+
+#ifndef GPAC_DISABLE_ZLIB
 /*since 0.2.2, we use zlib for xmt/x3d reading to handle gz files*/
 #include <zlib.h>
 
 #if (defined(WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__)
 #pragma comment(lib, "zlib")
 #endif
+#else
+#define NO_GZIP
+#endif
 
 
 static GF_Err gf_xml_sax_parse_intern(GF_SAXParser *parser, char *current);
@@ -1178,6 +1183,40 @@ GF_Err gf_xml_sax_parse_file(GF_SAXParser *parser, const char *fileName, gf_xml_
 #endif
        unsigned char szLine[6];
 
+       parser->on_progress = OnProgress;
+
+       if (!strncmp(fileName, "gmem://", 7)) {
+               u32 size;
+               u8 *xml_mem_address;
+               if (sscanf(fileName, "gmem://%d@%p", &size, &xml_mem_address) != 2) {
+                       return GF_URL_ERROR;
+               } 
+               parser->file_size = size;
+
+               memcpy(szLine, xml_mem_address, 3);
+               szLine[4] = szLine[5] = 0;
+               e = gf_xml_sax_init(parser, szLine);
+               if (e) return e;
+               parser->file_pos = 4;
+               parser->elt_start_pos = 0;
+               parser->current_pos = 0;
+
+
+               e = gf_xml_sax_parse(parser, xml_mem_address+3);
+               if (parser->on_progress) parser->on_progress(parser->sax_cbck, parser->file_pos, parser->file_size);
+
+               parser->elt_start_pos = parser->elt_end_pos = 0;
+               parser->elt_name_start = parser->elt_name_end = 0;
+               parser->att_name_start = 0;
+               parser->current_pos = 0;
+               parser->line_size = 0;
+               parser->att_sep = 0;
+               parser->file_pos = 0;
+               parser->file_size = 0;
+               parser->line_size = 0;
+               return e;
+       } 
+
        /*check file exists and gets its size (zlib doesn't support SEEK_END)*/
        test = gf_f64_open(fileName, "rb");
        if (!test) return GF_URL_ERROR;
@@ -1186,7 +1225,6 @@ GF_Err gf_xml_sax_parse_file(GF_SAXParser *parser, const char *fileName, gf_xml_
        parser->file_size = (u32) gf_f64_tell(test);
        fclose(test);
 
-       parser->on_progress = OnProgress;
 
 #ifdef NO_GZIP
        parser->f_in = gf_f64_open(fileName, "rt");
@@ -1294,7 +1332,11 @@ GF_EXPORT
 char *gf_xml_sax_peek_node(GF_SAXParser *parser, char *att_name, char *att_value, char *substitute, char *get_attr, char *end_pattern, Bool *is_substitute)
 {
        u32 state, att_len, alloc_size;
+#ifdef NO_GZIP
+       u64 pos;
+#else
        z_off_t pos;
+#endif
        Bool from_buffer;
        Bool dobreak=0;
        char szLine1[XML_INPUT_SIZE+2], szLine2[XML_INPUT_SIZE+2], *szLine, *cur_line, *sep, *start, first_c, *result;