From: Alessio Treglia Date: Fri, 16 Nov 2012 12:06:41 +0000 (+0000) Subject: Imported Upstream version 0.5.0+svn4231~dfsg0 X-Git-Tag: archive/raspbian/1.0.1+dfsg1-4+rpi1~1^2~15^2~15 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=e8092b7c334ccc3e3fb9a0bbc2ef7b4c249b9aa3;p=gpac.git Imported Upstream version 0.5.0+svn4231~dfsg0 --- diff --git a/Makefile b/Makefile index 13b2533..a3bd4b4 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ all: version $(MAKE) -C modules all version: - @if [ -d ".svn" ]; then if which svnversion >/dev/null; then echo "#define GPAC_SVN_REVISION \"$(shell svnversion $(SRC_PATH) )\"" > $(SRC_PATH)/include/gpac/version.h ; else echo "No SVN Version found"; fi; fi + @if [ -d ".svn" ]; then if which svnversion >/dev/null; then echo "#define GPAC_SVN_REVISION \"$(shell svnversion $(SRC_PATH) )\"" > $(SRC_PATH)/include/gpac/revision.h ; else echo "No SVN Version found"; fi; fi lib: version $(MAKE) -C src all @@ -47,7 +47,7 @@ distclean: dep: depend # tar release (use 'make -k tar' on a checkouted tree) -FILE=gpac-$(shell grep "\#define GPAC_VERSION " include/gpac/tools.h | \ +FILE=gpac-$(shell grep "\#define GPAC_VERSION " include/gpac/version.h | \ cut -d "\"" -f 2 ) tar: @@ -160,8 +160,9 @@ deb: sed -i "s/.DEV/.DEV-r`svnversion \"$(SRC_PATH)\"`/" debian/changelog fakeroot debian/rules configure fakeroot debian/rules binary + rm -rf debian/ svn cleanup - svn revert debian/changelog + svn up endif help: @@ -184,7 +185,7 @@ ifeq ($(CONFIG_DARWIN),yes) @echo "dmg: creates DMG package file for OSX" endif ifeq ($(CONFIG_LINUX),yes) - @echo "dmg: creates DEB package file for debian based systems" + @echo "deb: creates DEB package file for debian based systems" endif @echo @echo "install-lib: install gpac library (dyn and static) and headers , and " diff --git a/applications/Makefile b/applications/Makefile index 16b0b7a..b2511e9 100644 --- a/applications/Makefile +++ b/applications/Makefile @@ -8,7 +8,7 @@ endif ifeq ($(DISABLE_ISOFF), no) APPDIRS+=mp4box -ifeq ($(DISABLE_M2TS), no) +ifeq ($(DISABLE_M2TS_MUX), no) APPDIRS+=mp42ts endif endif diff --git a/applications/generators/MPEG4/main.c b/applications/generators/MPEG4/main.c index 980ec6f..c940f06 100644 --- a/applications/generators/MPEG4/main.c +++ b/applications/generators/MPEG4/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / MPEG4 Scene Graph Generator sub-project @@ -35,8 +36,8 @@ #include -#define COPYRIGHT_SCENE "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Copyright (c) Jean Le Feuvre 2000-2005\n * All rights reserved\n *\n * This file is part of GPAC / Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" -#define COPYRIGHT_BIFS "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Copyright (c) Jean Le Feuvre 2000-2005\n * All rights reserved\n *\n * This file is part of GPAC / BIFS codec sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" +#define COPYRIGHT_SCENE "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Jean Le Feuvre\n * Copyright (c) Telecom ParisTech 2000-2012\n * All rights reserved\n *\n * This file is part of GPAC / Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" +#define COPYRIGHT_BIFS "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Jean Le Feuvre\n * Copyright (c) Telecom ParisTech 2000-2012\n * All rights reserved\n *\n * This file is part of GPAC / BIFS codec sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" static char *CurrentLine; @@ -48,7 +49,7 @@ void PrintUsage() "Template files MUST be fed in order\n" "\n" "Generated Files are directly updated in the GPAC distribution - do NOT try to change this\n\n" - "Written by Jean Le Feuvre - (c) 2000-2005\n" + "Written by Jean Le Feuvre - Copyright (c) Telecom ParisTech 2000-2012\n" ); } diff --git a/applications/generators/SVG/html.c b/applications/generators/SVG/html.c index 6e79378..8525f2c 100644 --- a/applications/generators/SVG/html.c +++ b/applications/generators/SVG/html.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project diff --git a/applications/generators/SVG/laser.c b/applications/generators/SVG/laser.c index 914594c..2986d9a 100644 --- a/applications/generators/SVG/laser.c +++ b/applications/generators/SVG/laser.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project diff --git a/applications/generators/SVG/main.c b/applications/generators/SVG/main.c index fa51fa1..7de0a23 100644 --- a/applications/generators/SVG/main.c +++ b/applications/generators/SVG/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project diff --git a/applications/generators/SVG/svggen.h b/applications/generators/SVG/svggen.h index 8913f31..fd74a60 100644 --- a/applications/generators/SVG/svggen.h +++ b/applications/generators/SVG/svggen.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project @@ -54,7 +55,7 @@ static u32 generation_mode = 3; #define RNGA_PREFIX "rnga" #define SVGA_PREFIX "svg" -#define COPYRIGHT "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Cyril Concolato - Jean Le Feuvre\n * Copyright (c)2004-200X ENST - All rights reserved\n *\n * This file is part of GPAC / SVG Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" +#define COPYRIGHT "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Cyril Concolato - Jean Le Feuvre\n * Copyright (c) Telecom ParisTech 2000-2012 - All rights reserved\n *\n * This file is part of GPAC / SVG Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" /* diff --git a/applications/generators/SVG/v1.c b/applications/generators/SVG/v1.c index 785866e..792a20d 100644 --- a/applications/generators/SVG/v1.c +++ b/applications/generators/SVG/v1.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project diff --git a/applications/generators/SVG/v2.c b/applications/generators/SVG/v2.c index 8c549e6..3497f1a 100644 --- a/applications/generators/SVG/v2.c +++ b/applications/generators/SVG/v2.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project diff --git a/applications/generators/SVG/v3.c b/applications/generators/SVG/v3.c index 3316889..0156844 100644 --- a/applications/generators/SVG/v3.c +++ b/applications/generators/SVG/v3.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004-2005 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph Generator sub-project diff --git a/applications/generators/X3D/main.c b/applications/generators/X3D/main.c index 22954ae..a2f9c40 100644 --- a/applications/generators/X3D/main.c +++ b/applications/generators/X3D/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / X3D Scene Graph Generator sub-project @@ -29,7 +30,7 @@ #include #include -#define COPYRIGHT "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Copyright (c) Jean Le Feuvre 2000-2005\n * All rights reserved\n *\n * This file is part of GPAC / X3D Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" +#define COPYRIGHT "/*\n * GPAC - Multimedia Framework C SDK\n *\n * Authors: Jean Le Feuvre\n * Copyright (c) Telecom ParisTech 2000-2012\n * All rights reserved\n *\n * This file is part of GPAC / X3D Scene Graph sub-project\n *\n * GPAC is free software; you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation; either version 2, or (at your option)\n * any later version.\n *\n * GPAC is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details. \n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; see the file COPYING. If not, write to\n * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n" static char *CurrentLine; diff --git a/applications/m3u82mpd/main.c b/applications/m3u82mpd/main.c index cb8c8e2..b64442f 100644 --- a/applications/m3u82mpd/main.c +++ b/applications/m3u82mpd/main.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) m3u8_local_name = url; is_local = 1; } else { - e = gf_dm_wget(url, m3u8_local_name); + e = gf_dm_wget(url, m3u8_local_name, 0, 0); if (e != GF_OK) return -1; } diff --git a/applications/mp42avi/Makefile b/applications/mp42avi/Makefile index 2226793..3dce49f 100644 --- a/applications/mp42avi/Makefile +++ b/applications/mp42avi/Makefile @@ -33,11 +33,6 @@ all: $(PROG) $(PROG): $(OBJS) $(CC) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/$(TARGET_BIN_DIR) -lgpac -lz - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(PROG) diff --git a/applications/mp42avi/main.c b/applications/mp42avi/main.c index dd31812..0089f0f 100644 --- a/applications/mp42avi/main.c +++ b/applications/mp42avi/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / command-line mp4 toolbox diff --git a/applications/mp42ts/Makefile b/applications/mp42ts/Makefile index f41ae96..a108db5 100644 --- a/applications/mp42ts/Makefile +++ b/applications/mp42ts/Makefile @@ -2,7 +2,7 @@ include ../../config.mak vpath %.c $(SRC_PATH)/applications/mp42ts -CFLAGS= $(OPTFLAGS) -DGPAC_HAVE_CONFIG_H -I"$(SRC_PATH)/include" +CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include" ifeq ($(DEBUGBUILD), yes) CFLAGS+=-g @@ -35,11 +35,6 @@ all: $(PROG) $(PROG): $(OBJS) $(CC) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKFLAGS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(PROG) diff --git a/applications/mp42ts/main.c b/applications/mp42ts/main.c index 64bd043..0eedc25 100644 --- a/applications/mp42ts/main.c +++ b/applications/mp42ts/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2000-200X + * Authors: Jean Le Feuvre, Cyril Concolato, Romain Bouqueau + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / mp4-to-ts (mp42ts) application @@ -28,7 +29,7 @@ #include #ifndef GPAC_DISABLE_STREAMING -#include +#include #endif #ifndef GPAC_DISABLE_SENG @@ -123,6 +124,8 @@ typedef struct u32 nb_real_streams; Bool real_time; GF_List *od_updates; + + Double last_ntp; } M2TSProgram; typedef struct @@ -360,6 +363,9 @@ static void fill_isom_es_ifce(M2TSProgram *prog, GF_ESInterface *ifce, GF_ISOFil if (dcd->decoderSpecificInfo && dcd->decoderSpecificInfo->dataLength) { switch (dcd->objectTypeIndication) { case GPAC_OTI_AUDIO_AAC_MPEG4: + case GPAC_OTI_AUDIO_AAC_MPEG2_MP: + case GPAC_OTI_AUDIO_AAC_MPEG2_LCP: + case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP: ifce->decoder_config = gf_malloc(sizeof(char)*dcd->decoderSpecificInfo->dataLength); ifce->decoder_config_size = dcd->decoderSpecificInfo->dataLength; memcpy(ifce->decoder_config, dcd->decoderSpecificInfo->data, dcd->decoderSpecificInfo->dataLength); @@ -390,6 +396,7 @@ static void fill_isom_es_ifce(M2TSProgram *prog, GF_ESInterface *ifce, GF_ISOFil } gf_bs_get_content(bs, (char **) &priv->dsi, &priv->dsi_size); 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*/ @@ -432,7 +439,7 @@ static void fill_isom_es_ifce(M2TSProgram *prog, GF_ESInterface *ifce, GF_ISOFil } #ifdef GPAC_DISABLE_ISOM_WRITE - fprintf(stdout, "Warning: GPAC was compiled without ISOM Write support, can't set SL Config!\n"); + fprintf(stderr, "Warning: GPAC was compiled without ISOM Write support, can't set SL Config!\n"); #else gf_isom_set_extraction_slc(mp4, track_num, 1, ifce->sl_config); #endif @@ -475,11 +482,20 @@ typedef struct GF_ESInterface *ifce; - Bool cat_dsi; + Bool cat_dsi, is_264; void *dsi_and_rap; + u32 avc_dsi_size; Bool use_carousel; u32 au_sn; + + s64 ts_offset; + Bool rtcp_init; + M2TSProgram *prog; + + u32 min_dts_inc; + u64 prev_cts; + u64 prev_dts; } GF_ESIRTP; static GF_Err rtp_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param) @@ -494,6 +510,31 @@ static GF_Err rtp_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param) switch (act_type) { case GF_ESI_INPUT_DATA_FLUSH: + /*flush rtcp channel*/ + while (1) { + Bool has_sr=0; + size = gf_rtp_read_rtcp(rtp->rtp_ch, buffer, 8000); + if (!size) break; + e = gf_rtp_decode_rtcp(rtp->rtp_ch, buffer, size, &has_sr); + + if (e == GF_EOS) ifce->caps |= GF_ESI_STREAM_IS_OVER; + + if (has_sr && !rtp->rtcp_init) { + Double time = rtp->rtp_ch->last_SR_NTP_sec; + time += ((Double)rtp->rtp_ch->last_SR_NTP_frac)/0xFFFFFFFF; + if (!rtp->prog->last_ntp) { + rtp->prog->last_ntp = time; + } + if (time >= rtp->prog->last_ntp) { + time -= rtp->prog->last_ntp; + } else { + time = 0; + } + rtp->ts_offset = rtp->rtp_ch->last_SR_rtp_time; + rtp->ts_offset -= (s64) (time * rtp->rtp_ch->TimeScale); + rtp->rtcp_init = 1; + } + } /*flush rtp channel*/ while (1) { size = gf_rtp_read_rtp(rtp->rtp_ch, buffer, 8000); @@ -502,25 +543,229 @@ static GF_Err rtp_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param) if (e) return e; gf_rtp_depacketizer_process(rtp->depacketizer, &hdr, buffer + PayloadStart, size - PayloadStart); } - /*flush rtcp channel*/ - while (1) { - size = gf_rtp_read_rtcp(rtp->rtp_ch, buffer, 8000); - if (!size) break; - e = gf_rtp_decode_rtcp(rtp->rtp_ch, buffer, size, NULL); - if (e == GF_EOS) ifce->caps |= GF_ESI_STREAM_IS_OVER; - } return GF_OK; case GF_ESI_INPUT_DESTROY: gf_rtp_depacketizer_del(rtp->depacketizer); if (rtp->dsi_and_rap) gf_free(rtp->dsi_and_rap); gf_rtp_del(rtp->rtp_ch); gf_free(rtp); + + if (ifce->decoder_config) { + gf_free(ifce->decoder_config); + ifce->decoder_config = NULL; + } ifce->input_udta = NULL; return GF_OK; } return GF_OK; } + +static void rtp_sl_packet_cbk(void *udta, char *payload, u32 size, GF_SLHeader *hdr, GF_Err e) +{ + GF_ESIRTP *rtp = (GF_ESIRTP*)udta; + + /*sync not found yet, cannot start (since we don't support PCR discontinuities yet ...)*/ + if (!rtp->rtcp_init) return; + + /*try to compute a DTS*/ + if (hdr->accessUnitStartFlag && !hdr->decodingTimeStampFlag) { + if (!rtp->prev_cts) { + rtp->prev_cts = rtp->prev_dts = hdr->compositionTimeStamp; + } + + if (hdr->compositionTimeStamp > rtp->prev_cts) { + u32 diff = (u32) (hdr->compositionTimeStamp - rtp->prev_cts); + if (!rtp->min_dts_inc || (rtp->min_dts_inc > diff)) { + rtp->min_dts_inc = diff; + rtp->prev_dts = hdr->compositionTimeStamp - diff; + } + } + hdr->decodingTimeStampFlag = 1; + hdr->decodingTimeStamp = rtp->prev_dts + rtp->min_dts_inc; + rtp->prev_dts += rtp->min_dts_inc; + if (hdr->compositionTimeStamp < hdr->decodingTimeStamp) { + hdr->decodingTimeStamp = hdr->compositionTimeStamp; + } + } + + rtp->pck.data = payload; + rtp->pck.data_len = size; + rtp->pck.dts = hdr->decodingTimeStamp + rtp->ts_offset; + rtp->pck.cts = hdr->compositionTimeStamp + rtp->ts_offset; + rtp->pck.flags = 0; + if (hdr->compositionTimeStampFlag) rtp->pck.flags |= GF_ESI_DATA_HAS_CTS; + if (hdr->decodingTimeStampFlag) rtp->pck.flags |= GF_ESI_DATA_HAS_DTS; + if (hdr->randomAccessPointFlag) rtp->pck.flags |= GF_ESI_DATA_AU_RAP; + if (hdr->accessUnitStartFlag) rtp->pck.flags |= GF_ESI_DATA_AU_START; + if (hdr->accessUnitEndFlag) rtp->pck.flags |= GF_ESI_DATA_AU_END; + + if (rtp->use_carousel) { + if ((hdr->AU_sequenceNumber==rtp->au_sn) && hdr->randomAccessPointFlag) rtp->pck.flags |= GF_ESI_DATA_REPEAT; + rtp->au_sn = hdr->AU_sequenceNumber; + } + + if (rtp->is_264) { + if (!payload) return; + + /*send a NALU delim: copy over NAL ref idc*/ + if (hdr->accessUnitStartFlag) { + char sc[6]; + sc[0] = sc[1] = sc[2] = 0; + sc[3] = 1; + sc[4] = (payload[4] & 0x60) | GF_AVC_NALU_ACCESS_UNIT; + sc[5] = 0xF0 /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/; + + rtp->pck.data = sc; + rtp->pck.data_len = 6; + rtp->ifce->output_ctrl(rtp->ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &rtp->pck); + + rtp->pck.flags &= ~GF_ESI_DATA_AU_START; + + /*since we don't inspect the RTP content, we can only concatenate SPS and PPS indicated in SDP*/ + if (hdr->randomAccessPointFlag && rtp->dsi_and_rap) { + rtp->pck.data = rtp->dsi_and_rap; + rtp->pck.data_len = rtp->avc_dsi_size; + + rtp->ifce->output_ctrl(rtp->ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &rtp->pck); + } + + rtp->pck.data = payload; + rtp->pck.data_len = size; + } + + rtp->ifce->output_ctrl(rtp->ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &rtp->pck); + } else { + if (rtp->cat_dsi && hdr->randomAccessPointFlag && hdr->accessUnitStartFlag) { + if (rtp->dsi_and_rap) gf_free(rtp->dsi_and_rap); + rtp->pck.data_len = size + rtp->depacketizer->sl_map.configSize; + rtp->dsi_and_rap = gf_malloc(sizeof(char)*(rtp->pck.data_len)); + memcpy(rtp->dsi_and_rap, rtp->depacketizer->sl_map.config, rtp->depacketizer->sl_map.configSize); + memcpy((char *) rtp->dsi_and_rap + rtp->depacketizer->sl_map.configSize, payload, size); + rtp->pck.data = rtp->dsi_and_rap; + } + rtp->ifce->output_ctrl(rtp->ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &rtp->pck); + } +} + +static void fill_rtp_es_ifce(GF_ESInterface *ifce, GF_SDPMedia *media, GF_SDPInfo *sdp, M2TSProgram *prog) +{ + u32 i; + GF_Err e; + GF_X_Attribute*att; + GF_ESIRTP *rtp; + GF_RTPMap*map; + GF_SDPConnection *conn; + GF_RTSPTransport trans; + + /*check connection*/ + conn = sdp->c_connection; + if (!conn) conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0); + + /*check payload type*/ + map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0); + GF_SAFEALLOC(rtp, GF_ESIRTP); + + memset(ifce, 0, sizeof(GF_ESInterface)); + rtp->rtp_ch = gf_rtp_new(); + i=0; + while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &i))) { + if (!stricmp(att->Name, "mpeg4-esid") && att->Value) ifce->stream_id = atoi(att->Value); + } + + memset(&trans, 0, sizeof(GF_RTSPTransport)); + trans.Profile = media->Profile; + trans.source = conn ? conn->host : sdp->o_address; + trans.IsUnicast = gf_sk_is_multicast_address(trans.source) ? 0 : 1; + if (!trans.IsUnicast) { + trans.port_first = media->PortNumber; + trans.port_last = media->PortNumber + 1; + trans.TTL = conn ? conn->TTL : 0; + } else { + trans.client_port_first = media->PortNumber; + trans.client_port_last = media->PortNumber + 1; + } + + if (gf_rtp_setup_transport(rtp->rtp_ch, &trans, NULL) != GF_OK) { + gf_rtp_del(rtp->rtp_ch); + fprintf(stderr, "Cannot initialize RTP transport\n"); + return; + } + /*setup depacketizer*/ + rtp->depacketizer = gf_rtp_depacketizer_new(media, rtp_sl_packet_cbk, rtp); + if (!rtp->depacketizer) { + gf_rtp_del(rtp->rtp_ch); + fprintf(stderr, "Cannot create RTP depacketizer\n"); + return; + } + /*setup channel*/ + gf_rtp_setup_payload(rtp->rtp_ch, map); + ifce->input_udta = rtp; + ifce->input_ctrl = rtp_input_ctrl; + rtp->ifce = ifce; + rtp->prog = prog; + + ifce->object_type_indication = rtp->depacketizer->sl_map.ObjectTypeIndication; + ifce->stream_type = rtp->depacketizer->sl_map.StreamType; + ifce->timescale = gf_rtp_get_clockrate(rtp->rtp_ch); + if (rtp->depacketizer->sl_map.config) { + switch (ifce->object_type_indication) { + case GPAC_OTI_VIDEO_MPEG4_PART2: + rtp->cat_dsi = 1; + break; + case GPAC_OTI_VIDEO_AVC: + rtp->is_264 = 1; + rtp->depacketizer->flags |= GF_RTP_AVC_USE_ANNEX_B; + { +#ifndef GPAC_DISABLE_AV_PARSERS + GF_AVCConfig *avccfg = gf_odf_avc_cfg_read(rtp->depacketizer->sl_map.config, rtp->depacketizer->sl_map.configSize); + if (avccfg) { + GF_AVCConfigSlot *slc; + u32 i; + GF_BitStream *bs; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + for (i=0; isequenceParameterSets);i++) { + slc = gf_list_get(avccfg->sequenceParameterSets, i); + gf_bs_write_u32(bs, 1); + gf_bs_write_data(bs, slc->data, slc->size); + } + for (i=0; ipictureParameterSets);i++) { + slc = gf_list_get(avccfg->pictureParameterSets, i); + gf_bs_write_u32(bs, 1); + gf_bs_write_data(bs, slc->data, slc->size); + } + gf_bs_get_content(bs, (char **) &rtp->dsi_and_rap, &rtp->avc_dsi_size); + gf_bs_del(bs); + } + gf_odf_avc_cfg_del(avccfg); #endif + } + break; + case GPAC_OTI_AUDIO_AAC_MPEG4: + ifce->decoder_config = gf_malloc(sizeof(char) * rtp->depacketizer->sl_map.configSize); + ifce->decoder_config_size = rtp->depacketizer->sl_map.configSize; + memcpy(ifce->decoder_config, rtp->depacketizer->sl_map.config, rtp->depacketizer->sl_map.configSize); + break; + } + } + if (rtp->depacketizer->sl_map.StreamStateIndication) { + rtp->use_carousel = 1; + rtp->au_sn=0; + } + + /*DTS signaling is only supported for MPEG-4 visual*/ + if (rtp->depacketizer->sl_map.DTSDeltaLength) ifce->caps |= GF_ESI_SIGNAL_DTS; + + gf_rtp_depacketizer_reset(rtp->depacketizer, 1); + e = gf_rtp_initialize(rtp->rtp_ch, 0x100000ul, 0, 0, 10, 200, NULL); + if (e!=GF_OK) { + gf_rtp_del(rtp->rtp_ch); + fprintf(stderr, "Cannot initialize RTP channel: %s\n", gf_error_to_string(e)); + return; + } + fprintf(stderr, "RTP interface initialized\n"); +} +#endif /*GPAC_DISABLE_STREAMING*/ static GF_Err void_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param) { @@ -918,7 +1163,7 @@ static Bool seng_output(void *param) case 'p': { char rad[GF_MAX_PATH]; - fprintf(stderr, "Enter output file name - \"std\" for stdout: "); + fprintf(stderr, "Enter output file name - \"std\" for stderr: "); if (1 > scanf("%s", rad)){ fprintf(stderr, "No outfile name has been entered, aborting.\n"); break; @@ -939,128 +1184,7 @@ static Bool seng_output(void *param) return e ? 1 : 0; } -#endif - - -#ifndef GPAC_DISABLE_STREAMING -static void rtp_sl_packet_cbk(void *udta, char *payload, u32 size, GF_SLHeader *hdr, GF_Err e) -{ - GF_ESIRTP *rtp = (GF_ESIRTP*)udta; - rtp->pck.data = payload; - rtp->pck.data_len = size; - rtp->pck.dts = hdr->decodingTimeStamp; - rtp->pck.cts = hdr->compositionTimeStamp; - rtp->pck.flags = 0; - if (hdr->compositionTimeStampFlag) rtp->pck.flags |= GF_ESI_DATA_HAS_CTS; - if (hdr->decodingTimeStampFlag) rtp->pck.flags |= GF_ESI_DATA_HAS_DTS; - if (hdr->randomAccessPointFlag) rtp->pck.flags |= GF_ESI_DATA_AU_RAP; - if (hdr->accessUnitStartFlag) rtp->pck.flags |= GF_ESI_DATA_AU_START; - if (hdr->accessUnitEndFlag) rtp->pck.flags |= GF_ESI_DATA_AU_END; - - if (rtp->use_carousel) { - if ((hdr->AU_sequenceNumber==rtp->au_sn) && hdr->randomAccessPointFlag) rtp->pck.flags |= GF_ESI_DATA_REPEAT; - rtp->au_sn = hdr->AU_sequenceNumber; - } - - if (rtp->cat_dsi && hdr->randomAccessPointFlag && hdr->accessUnitStartFlag) { - if (rtp->dsi_and_rap) gf_free(rtp->dsi_and_rap); - rtp->pck.data_len = size + rtp->depacketizer->sl_map.configSize; - rtp->dsi_and_rap = gf_malloc(sizeof(char)*(rtp->pck.data_len)); - memcpy(rtp->dsi_and_rap, rtp->depacketizer->sl_map.config, rtp->depacketizer->sl_map.configSize); - memcpy((char *) rtp->dsi_and_rap + rtp->depacketizer->sl_map.configSize, payload, size); - rtp->pck.data = rtp->dsi_and_rap; - } - - - rtp->ifce->output_ctrl(rtp->ifce, GF_ESI_OUTPUT_DATA_DISPATCH, &rtp->pck); -} - -static void fill_rtp_es_ifce(GF_ESInterface *ifce, GF_SDPMedia *media, GF_SDPInfo *sdp) -{ - u32 i; - GF_Err e; - GF_X_Attribute*att; - GF_ESIRTP *rtp; - GF_RTPMap*map; - GF_SDPConnection *conn; - GF_RTSPTransport trans; - - /*check connection*/ - conn = sdp->c_connection; - if (!conn) conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0); - - /*check payload type*/ - map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0); - GF_SAFEALLOC(rtp, GF_ESIRTP); - - memset(ifce, 0, sizeof(GF_ESInterface)); - rtp->rtp_ch = gf_rtp_new(); - i=0; - while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &i))) { - if (!stricmp(att->Name, "mpeg4-esid") && att->Value) ifce->stream_id = atoi(att->Value); - } - - memset(&trans, 0, sizeof(GF_RTSPTransport)); - trans.Profile = media->Profile; - trans.source = conn ? conn->host : sdp->o_address; - trans.IsUnicast = gf_sk_is_multicast_address(trans.source) ? 0 : 1; - if (!trans.IsUnicast) { - trans.port_first = media->PortNumber; - trans.port_last = media->PortNumber + 1; - trans.TTL = conn ? conn->TTL : 0; - } else { - trans.client_port_first = media->PortNumber; - trans.client_port_last = media->PortNumber + 1; - } - - if (gf_rtp_setup_transport(rtp->rtp_ch, &trans, NULL) != GF_OK) { - gf_rtp_del(rtp->rtp_ch); - fprintf(stderr, "Cannot initialize RTP transport\n"); - return; - } - /*setup depacketizer*/ - rtp->depacketizer = gf_rtp_depacketizer_new(media, rtp_sl_packet_cbk, rtp); - if (!rtp->depacketizer) { - gf_rtp_del(rtp->rtp_ch); - fprintf(stderr, "Cannot create RTP depacketizer\n"); - return; - } - /*setup channel*/ - gf_rtp_setup_payload(rtp->rtp_ch, map); - ifce->input_udta = rtp; - ifce->input_ctrl = rtp_input_ctrl; - rtp->ifce = ifce; - - ifce->object_type_indication = rtp->depacketizer->sl_map.ObjectTypeIndication; - ifce->stream_type = rtp->depacketizer->sl_map.StreamType; - ifce->timescale = gf_rtp_get_clockrate(rtp->rtp_ch); - if (rtp->depacketizer->sl_map.config) { - switch (ifce->object_type_indication) { - case GPAC_OTI_VIDEO_MPEG4_PART2: - rtp->cat_dsi = 1; - break; - } - } - if (rtp->depacketizer->sl_map.StreamStateIndication) { - rtp->use_carousel = 1; - rtp->au_sn=0; - } - - /*DTS signaling is only supported for MPEG-4 visual*/ - if (rtp->depacketizer->sl_map.DTSDeltaLength) ifce->caps |= GF_ESI_SIGNAL_DTS; - - gf_rtp_depacketizer_reset(rtp->depacketizer, 1); - e = gf_rtp_initialize(rtp->rtp_ch, 0x100000ul, 0, 0, 10, 200, NULL); - if (e!=GF_OK) { - gf_rtp_del(rtp->rtp_ch); - fprintf(stderr, "Cannot initialize RTP channel: %s\n", gf_error_to_string(e)); - return; - } - fprintf(stderr, "RTP interface initialized\n"); -} -#endif /*GPAC_DISABLE_STREAMING*/ -#ifndef GPAC_DISABLE_SENG void fill_seng_es_ifce(GF_ESInterface *ifce, u32 i, GF_SceneEngine *seng, u32 period) { GF_Err e = GF_OK; @@ -1300,7 +1424,7 @@ static Bool open_program(M2TSProgram *prog, char *src, u32 carousel_rate, u32 mp prog->nb_streams = gf_list_count(sdp->media_desc); for (i=0; inb_streams; i++) { GF_SDPMedia *media = gf_list_get(sdp->media_desc, i); - fill_rtp_es_ifce(&prog->streams[i], media, sdp); + fill_rtp_es_ifce(&prog->streams[i], media, sdp, prog); switch(prog->streams[i].stream_type) { case GF_STREAM_OD: case GF_STREAM_SCENE: @@ -1589,7 +1713,7 @@ static GFINLINE GF_Err parse_args(int argc, char **argv, u32 *mux_rate, u32 *car gf_sys_init(1); gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_DEBUG); #else - fprintf(stdout, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); + fprintf(stderr, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); #endif } else if (!strnicmp(arg, "-rate=", 6)) { if (rate_found) { @@ -1772,9 +1896,8 @@ error: return GF_BAD_PARAM; } -/* adapted from http://svn.assembla.com/svn/legend/segmenter/segmenter.c */ -static GF_Err write_manifest(char *manifest, char *segment_dir, u32 segment_duration, char *segment_prefix, char *http_prefix, - u32 first_segment, u32 last_segment, Bool end) { +static GF_Err write_manifest(char *manifest, char *segment_dir, u32 segment_duration, char *segment_prefix, char *http_prefix, u32 first_segment, u32 last_segment, Bool end) +{ FILE *manifest_fp; u32 i; char manifest_tmp_name[GF_MAX_PATH]; @@ -1810,7 +1933,7 @@ static GF_Err write_manifest(char *manifest, char *segment_dir, u32 segment_dura return GF_OK; } else { if (remove(manifest_name)) { - fprintf(stdout, "Error removing file %s\n", manifest_name); + fprintf(stderr, "Error removing file %s\n", manifest_name); return GF_IO_ERR; } else if (rename(tmp_manifest, manifest_name)) { fprintf(stderr, "Could not rename temporary m3u8 manifest file (%s) into %s\n", tmp_manifest, manifest_name); @@ -2016,7 +2139,7 @@ int main(int argc, char **argv) e = gf_sk_bind(audio_input_udp_sk, NULL, audio_input_port, (char *)audio_input_ip, audio_input_port, GF_SOCK_REUSE_PORT); } if (e) { - fprintf(stdout, "Error initializing UDP socket for %s:%d : %s\n", audio_input_ip, audio_input_port, gf_error_to_string(e)); + fprintf(stderr, "Error initializing UDP socket for %s:%d : %s\n", audio_input_ip, audio_input_port, gf_error_to_string(e)); goto exit; } gf_sk_set_buffer_size(audio_input_udp_sk, 0, UDP_BUFFER_SIZE); @@ -2223,8 +2346,8 @@ int main(int argc, char **argv) { u64 bits = muxer->tot_pck_sent*8*188; u32 dur_sec = gf_m2ts_get_ts_clock(muxer) / 1000; - fprintf(stdout, "Done muxing - %d sec - average rate %d kbps "LLD" packets written\n", dur_sec, (u32) (bits/dur_sec/1000), muxer->tot_pck_sent); - fprintf(stdout, "\tPadding: "LLD" packets - "LLD" PES padded bytes (%g kbps)\n", muxer->tot_pad_sent, muxer->tot_pes_pad_bytes, (Double) (muxer->tot_pes_pad_bytes*8.0/dur_sec/1000) ); + fprintf(stderr, "Done muxing - %d sec - average rate %d kbps "LLD" packets written\n", dur_sec, (u32) (bits/dur_sec/1000), muxer->tot_pck_sent); + fprintf(stderr, "\tPadding: "LLD" packets - "LLD" PES padded bytes (%g kbps)\n", muxer->tot_pad_sent, muxer->tot_pes_pad_bytes, (Double) (muxer->tot_pes_pad_bytes*8.0/dur_sec/1000) ); } exit: diff --git a/applications/mp42ts/mp42ts.h b/applications/mp42ts/mp42ts.h index 5ed59a1..3951be0 100644 --- a/applications/mp42ts/mp42ts.h +++ b/applications/mp42ts/mp42ts.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2000-200X + * Authors: Jean Le Feuvre, Cyril Concolato, Romain Bouqueau + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / mp42ts application diff --git a/applications/mp4box/Makefile b/applications/mp4box/Makefile index c82e22b..a248ab4 100644 --- a/applications/mp4box/Makefile +++ b/applications/mp4box/Makefile @@ -15,7 +15,10 @@ LDFLAGS+=-pg endif #common obj -OBJS= main.o filedump.o fileimport.o live.o +OBJS=main.o filedump.o fileimport.o +ifeq ($(DISABLE_STREAMING),no) +OBJS+=live.o +endif LINKFLAGS=-L../../bin/gcc -L../../extra_lib/lib/gcc @@ -59,11 +62,6 @@ all: $(PROG) $(PROG): $(OBJS) $(CC) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKFLAGS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(PROG) diff --git a/applications/mp4box/filedump.c b/applications/mp4box/filedump.c index e7289b8..147426e 100644 --- a/applications/mp4box/filedump.c +++ b/applications/mp4box/filedump.c @@ -1,12 +1,13 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / mp4box application * - * GPAC is gf_free software; you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. @@ -36,6 +37,9 @@ #ifndef GPAC_DISABLE_BIFS #include #endif +#ifndef GPAC_DISABLE_VRML +#include +#endif #include #include #include @@ -62,13 +66,13 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc void PrintLanguages() { u32 i=0; - fprintf(stdout, "Supported ISO 639 languages and codes:\n\n"); + fprintf(stderr, "Supported ISO 639 languages and codes:\n\n"); while (GF_ISO639_Lang[i]) { if (!GF_ISO639_Lang[i+2][0]) { i+=3; continue; } - fprintf(stdout, "%s (%s - %s)\n", GF_ISO639_Lang[i], GF_ISO639_Lang[i+1], GF_ISO639_Lang[i+2]); + fprintf(stderr, "%s (%s - %s)\n", GF_ISO639_Lang[i], GF_ISO639_Lang[i+1], GF_ISO639_Lang[i+2]); i+=3; } } @@ -113,7 +117,7 @@ GF_Err dump_cover_art(GF_ISOFile *file, char *inName) GF_Err e = gf_isom_apple_get_tag(file, GF_ISOM_ITUNE_COVER_ART, &tag, &tag_len); if (e!=GF_OK) { if (e==GF_URL_ERROR) { - fprintf(stdout, "No cover art found\n"); + fprintf(stderr, "No cover art found\n"); return GF_OK; } return e; @@ -171,6 +175,9 @@ GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log) load.fileName = file; load.ctx = ctx; load.swf_import_flags = swf_flags; + if (dump_mode == GF_SM_DUMP_SVG) { + load.swf_import_flags |= GF_SM_SWF_USE_SVG; + } load.swf_flatten_limit = swf_flatten_angle; ftype = get_file_type_by_ext(file); @@ -178,7 +185,7 @@ GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log) load.isom = gf_isom_open(file, GF_ISOM_OPEN_READ, NULL); if (!load.isom) { e = gf_isom_last_error(NULL); - fprintf(stdout, "Error opening file: %s\n", gf_error_to_string(e)); + fprintf(stderr, "Error opening file: %s\n", gf_error_to_string(e)); gf_sm_del(ctx); gf_sg_del(sg); return e; @@ -197,7 +204,7 @@ GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log) e = gf_isom_last_error(NULL); if (e) { - fprintf(stdout, "Error importing file: %s\n", gf_error_to_string(e)); + fprintf(stderr, "Error importing file: %s\n", gf_error_to_string(e)); gf_sm_del(ctx); gf_sg_del(sg); if (load.isom) gf_isom_delete(load.isom); @@ -224,16 +231,16 @@ GF_Err dump_file_text(char *file, char *inName, u32 dump_mode, Bool do_log) if (!e) { u32 count = gf_list_count(ctx->streams); if (count) - fprintf(stdout, "Scene loaded - dumping %d systems streams\n", count); + fprintf(stderr, "Scene loaded - dumping %d systems streams\n", count); else - fprintf(stdout, "Scene loaded - dumping root scene\n"); + fprintf(stderr, "Scene loaded - dumping root scene\n"); e = gf_sm_dump(ctx, inName, dump_mode); } gf_sm_del(ctx); gf_sg_del(sg); - if (e) fprintf(stdout, "Error loading scene: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Error loading scene: %s\n", gf_error_to_string(e)); if (load.isom) gf_isom_delete(load.isom); return e; } @@ -391,7 +398,7 @@ void dump_scene_stats(char *file, char *inName, u32 stat_level) if (get_file_type_by_ext(file) == 1) { load.isom = gf_isom_open(file, GF_ISOM_OPEN_READ, NULL); if (!load.isom) { - fprintf(stdout, "Cannot open file: %s\n", gf_error_to_string(gf_isom_last_error(NULL))); + fprintf(stderr, "Cannot open file: %s\n", gf_error_to_string(gf_isom_last_error(NULL))); gf_sm_del(ctx); gf_sg_del(scene_graph); return; @@ -409,11 +416,11 @@ void dump_scene_stats(char *file, char *inName, u32 stat_level) dump = gf_f64_open(szBuf, "wt"); close = 1; } else { - dump = stdout; + dump = stderr; close = 0; } - fprintf(stdout, "Analysing Scene\n"); + fprintf(stderr, "Analysing Scene\n"); fprintf(dump, "\n"); fprintf(dump, "\n"); @@ -483,12 +490,12 @@ exit: gf_sm_del(ctx); gf_sg_del(scene_graph); if (e) { - fprintf(stdout, "%s\n", gf_error_to_string(e)); + fprintf(stderr, "%s\n", gf_error_to_string(e)); } else { fprintf(dump, "\n"); } if (dump && close) fclose(dump); - fprintf(stdout, "done\n"); + fprintf(stderr, "done\n"); } #endif /*GPAC_DISABLE_SCENE_STATS*/ @@ -498,10 +505,10 @@ exit: static void PrintFixed(Fixed val, Bool add_space) { - if (add_space) fprintf(stdout, " "); - if (val==FIX_MIN) fprintf(stdout, "-I"); - else if (val==FIX_MAX) fprintf(stdout, "+I"); - else fprintf(stdout, "%g", FIX2FLT(val)); + if (add_space) fprintf(stderr, " "); + if (val==FIX_MIN) fprintf(stderr, "-I"); + else if (val==FIX_MAX) fprintf(stderr, "+I"); + else fprintf(stderr, "%g", FIX2FLT(val)); } static void PrintNodeSFField(u32 type, void *far_ptr) @@ -509,16 +516,16 @@ static void PrintNodeSFField(u32 type, void *far_ptr) if (!far_ptr) return; switch (type) { case GF_SG_VRML_SFBOOL: - fprintf(stdout, "%s", (*(SFBool *)far_ptr) ? "TRUE" : "FALSE"); + fprintf(stderr, "%s", (*(SFBool *)far_ptr) ? "TRUE" : "FALSE"); break; case GF_SG_VRML_SFINT32: - fprintf(stdout, "%d", (*(SFInt32 *)far_ptr)); + fprintf(stderr, "%d", (*(SFInt32 *)far_ptr)); break; case GF_SG_VRML_SFFLOAT: PrintFixed((*(SFFloat *)far_ptr), 0); break; case GF_SG_VRML_SFTIME: - fprintf(stdout, "%g", (*(SFTime *)far_ptr)); + fprintf(stderr, "%g", (*(SFTime *)far_ptr)); break; case GF_SG_VRML_SFVEC2F: PrintFixed(((SFVec2f *)far_ptr)->x, 0); @@ -542,9 +549,9 @@ static void PrintNodeSFField(u32 type, void *far_ptr) break; case GF_SG_VRML_SFSTRING: if (((SFString*)far_ptr)->buffer) - fprintf(stdout, "\"%s\"", ((SFString*)far_ptr)->buffer); + fprintf(stderr, "\"%s\"", ((SFString*)far_ptr)->buffer); else - fprintf(stdout, "NULL"); + fprintf(stderr, "NULL"); break; } } @@ -553,7 +560,7 @@ static void PrintNodeSFField(u32 type, void *far_ptr) void PrintNode(const char *name, u32 graph_type) { #ifdef GPAC_DISABLE_VRML - fprintf(stdout, "VRML/MPEG-4/X3D scene graph is disabled in this build of GPAC\n"); + fprintf(stderr, "VRML/MPEG-4/X3D scene graph is disabled in this build of GPAC\n"); return; #else const char *nname, *std_name; @@ -578,14 +585,14 @@ void PrintNode(const char *name, u32 graph_type) tag = 0; if (graph_type==2) { - fprintf(stdout, "SVG node printing is not supported\n"); + fprintf(stderr, "SVG node printing is not supported\n"); return; } else if (graph_type==1) { #ifndef GPAC_DISABLE_X3D tag = gf_node_x3d_type_by_class_name(name); std_name = "X3D"; #else - fprintf(stdout, "X3D node printing is not supported (X3D support disabled)\n"); + fprintf(stderr, "X3D node printing is not supported (X3D support disabled)\n"); return; #endif } else { @@ -593,7 +600,7 @@ void PrintNode(const char *name, u32 graph_type) std_name = "MPEG4"; } if (!tag) { - fprintf(stdout, "Unknown %s node %s\n", std_name, name); + fprintf(stderr, "Unknown %s node %s\n", std_name, name); return; } @@ -602,7 +609,7 @@ void PrintNode(const char *name, u32 graph_type) gf_node_register(node, NULL); nname = gf_node_get_class_name(node); if (!node) { - fprintf(stdout, "Node %s not supported in current built\n", nname); + fprintf(stderr, "Node %s not supported in current built\n", nname); return; } nbF = gf_node_get_field_count(node); @@ -610,10 +617,10 @@ void PrintNode(const char *name, u32 graph_type) if (is_nodefield) { u32 tfirst, tlast; if (gf_node_get_field_by_name(node, szField, &f) != GF_OK) { - fprintf(stdout, "Field %s is not a member of node %s\n", szField, name); + fprintf(stderr, "Field %s is not a member of node %s\n", szField, name); return; } - fprintf(stdout, "Allowed nodes in %s.%s:\n", name, szField); + fprintf(stderr, "Allowed nodes in %s.%s:\n", name, szField); if (graph_type==1) { tfirst = GF_NODE_RANGE_FIRST_X3D; tlast = GF_NODE_RANGE_LAST_X3D; @@ -627,7 +634,7 @@ void PrintNode(const char *name, u32 graph_type) if (gf_node_in_table_by_tag(i, f.NDTtype)) { const char *nname = gf_node_get_class_name(tmp); if (nname && strcmp(nname, "Unknown Node")) { - fprintf(stdout, "\t%s\n", nname); + fprintf(stderr, "\t%s\n", nname); } } gf_node_unregister(tmp, NULL); @@ -635,52 +642,52 @@ void PrintNode(const char *name, u32 graph_type) return; } - fprintf(stdout, "Node Syntax:\n%s {\n", nname); + fprintf(stderr, "Node Syntax:\n%s {\n", nname); for (i=0; icount; i++) { - if (i) fprintf(stdout, " "); + if (i) fprintf(stderr, " "); gf_sg_vrml_mf_get_item(f.far_ptr, f.fieldType, &ptr, i); PrintNodeSFField(sftype, ptr); } - fprintf(stdout, "]"); + fprintf(stderr, "]"); } #ifndef GPAC_DISABLE_BIFS if (gf_bifs_get_aq_info(node, i, &qt, &at, &bmin, &bmax, &nbBits)) { if (qt) { - fprintf(stdout, " #QP=%d", qt); - if (qt==13) fprintf(stdout, " NbBits=%d", nbBits); + fprintf(stderr, " #QP=%d", qt); + if (qt==13) fprintf(stderr, " NbBits=%d", nbBits); if (bmin && bmax) { - fprintf(stdout, " Bounds=["); + fprintf(stderr, " Bounds=["); PrintFixed(bmin, 0); - fprintf(stdout, ","); + fprintf(stderr, ","); PrintFixed(bmax, 0); - fprintf(stdout, "]"); + fprintf(stderr, "]"); } } } #endif /*GPAC_DISABLE_BIFS*/ - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } - fprintf(stdout, "}\n\n"); + fprintf(stderr, "}\n\n"); gf_node_unregister(node, NULL); gf_sg_del(sg); @@ -699,12 +706,12 @@ void PrintBuiltInNodes(u32 graph_type) start_tag = GF_NODE_RANGE_FIRST_X3D; end_tag = TAG_LastImplementedX3D; #else - fprintf(stdout, "X3D scene graph disabled in this build of GPAC\n"); + fprintf(stderr, "X3D scene graph disabled in this build of GPAC\n"); return; #endif } else if (graph_type==2) { #ifdef GPAC_DISABLE_SVG - fprintf(stdout, "SVG scene graph disabled in this build of GPAC\n"); + fprintf(stderr, "SVG scene graph disabled in this build of GPAC\n"); return; #else start_tag = GF_NODE_RANGE_FIRST_SVG; @@ -712,7 +719,7 @@ void PrintBuiltInNodes(u32 graph_type) #endif } else { #ifdef GPAC_DISABLE_VRML - fprintf(stdout, "VRML/MPEG-4 scene graph disabled in this build of GPAC\n"); + fprintf(stderr, "VRML/MPEG-4 scene graph disabled in this build of GPAC\n"); return; #else start_tag = GF_NODE_RANGE_FIRST_MPEG4; @@ -723,17 +730,17 @@ void PrintBuiltInNodes(u32 graph_type) sg = gf_sg_new(); if (graph_type==1) { - fprintf(stdout, "Available X3D nodes in this build (dumping):\n"); + fprintf(stderr, "Available X3D nodes in this build (dumping):\n"); } else if (graph_type==2) { - fprintf(stdout, "Available SVG nodes in this build (dumping and LASeR coding):\n"); + fprintf(stderr, "Available SVG nodes in this build (dumping and LASeR coding):\n"); } else { - fprintf(stdout, "Available MPEG-4 nodes in this build (encoding/decoding/dumping):\n"); + fprintf(stderr, "Available MPEG-4 nodes in this build (encoding/decoding/dumping):\n"); } for (i=start_tag; i\n"); @@ -807,7 +814,7 @@ void dump_file_rtp(GF_ISOFile *file, char *inName) } #endif -void dump_file_ts(GF_ISOFile *file, char *inName) +void dump_file_timestamps(GF_ISOFile *file, char *inName) { u32 i, j, k, count; Bool has_error; @@ -819,15 +826,16 @@ void dump_file_ts(GF_ISOFile *file, char *inName) strcat(szBuf, "_ts.txt"); dump = gf_f64_open(szBuf, "wt"); } else { - dump = stdout; + dump = stderr; } has_error = 0; for (i=0; i> 4; + quality_id = (ptr[2] & 0x0F); + temporal_id = (ptr[3] & 0xE0) >> 5; + fprintf(dump, "\" dependency_id=\"%d\" quality_id=\"%d\" temporal_id=\"%d", dependency_id, quality_id, temporal_id); + break; + case 30: fputs("SVCAggregator", dump); break; + case 31: + fputs("SVCExtractor", dump); + track_ref_index = (u8) ptr[4]; + data_offset = (ptr[6] << 12) + (ptr[7] << 8) + (ptr[8] << 4) + ptr[9]; + fprintf(dump, "\" track_ref_index=\"%d\" data_offset=\"%d", track_ref_index, data_offset); + break; + + default: + fputs("UNKNOWN", dump); break; + } + fputs("\"", dump); +} + +void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName) +{ + u32 i, count, track, nalh_size; + FILE *dump; +#ifndef GPAC_DISABLE_AV_PARSERS + GF_AVCConfig *avccfg, *svccfg; + GF_AVCConfigSlot *slc; +#endif + + if (inName) { + char szBuf[GF_MAX_PATH]; + strcpy(szBuf, inName); + sprintf(szBuf, "%s_%d_nalu.xml", inName, trackID); + dump = gf_f64_open(szBuf, "wt"); + } else { + dump = stderr; + } + track = gf_isom_get_track_by_id(file, trackID); + + count = gf_isom_get_sample_count(file, track); + + fprintf(dump, "\n", trackID, count); + +#ifndef GPAC_DISABLE_AV_PARSERS + avccfg = gf_isom_avc_config_get(file, track, 1); + svccfg = gf_isom_svc_config_get(file, track, 1); + fprintf(dump, " \n"); + +#define DUMP_ARRAY(arr, name)\ + if (arr) {\ + for (i=0; idata , svccfg ? 1 : 0);\ + fprintf(dump, ">\n");\ + }\ + }\ + + nalh_size = 0; + + if (avccfg) { + nalh_size = avccfg->nal_unit_size; + + DUMP_ARRAY(avccfg->sequenceParameterSets, "AVCSPSArray") + DUMP_ARRAY(avccfg->pictureParameterSets, "AVCPPSArray") + DUMP_ARRAY(avccfg->sequenceParameterSetExtensions, "AVCSPSExArray") + } + if (svccfg) { + if (!nalh_size) nalh_size = svccfg->nal_unit_size; + DUMP_ARRAY(svccfg->sequenceParameterSets, "SVCSPSArray") + DUMP_ARRAY(svccfg->pictureParameterSets, "SVCPPSArray") + } +#endif + fprintf(dump, " \n"); + + fprintf(dump, " \n"); + for (i=0; iDTS; + cts = dts + (s32) samp->CTS_Offset; + + fprintf(dump, " \n", i+1, dts, cts, samp->dataLength, samp->IsRAP); + if (cts\n"); + + idx = 1; + ptr = samp->data; + size = samp->dataLength; + while (size) { + u32 v = nalh_size; + nal_size = 0; + while (v) { + nal_size |= (u8) *ptr; + ptr++; + v-=1; + if (v) nal_size<<=8; + } + if (nalh_size + nal_size > size) { + fprintf(dump, " \n", idx, nal_size, size); + break; + } else { + fprintf(dump, " \n"); + } + idx++; + ptr+=nal_size; + size -= nal_size + nalh_size; + } + fprintf(dump, " \n"); + gf_isom_sample_del(&samp); + + fprintf(dump, "\n"); + gf_set_progress("Analysing Track NALUs", i+1, count); + } + fprintf(dump, " \n"); + fprintf(dump, "\n"); + + if (inName) fclose(dump); } #ifndef GPAC_DISABLE_ISOM_DUMP @@ -877,7 +1036,7 @@ void dump_file_ismacryp(GF_ISOFile *file, char *inName) strcat(szBuf, "_ismacryp.xml"); dump = gf_f64_open(szBuf, "wt"); } else { - dump = stdout; + dump = stderr; } fprintf(dump, "\n"); @@ -910,7 +1069,7 @@ void dump_timed_text_track(GF_ISOFile *file, u32 trackID, char *inName, Bool is_ track = gf_isom_get_track_by_id(file, trackID); if (!track) { - fprintf(stdout, "Cannot find track ID %d\n", trackID); + fprintf(stderr, "Cannot find track ID %d\n", trackID); return; } @@ -919,7 +1078,7 @@ void dump_timed_text_track(GF_ISOFile *file, u32 trackID, char *inName, Bool is_ case GF_ISOM_MEDIA_SUBT: break; default: - fprintf(stdout, "Track ID %d is not a 3GPP text track\n", trackID); + fprintf(stderr, "Track ID %d is not a 3GPP text track\n", trackID); return; } @@ -935,8 +1094,8 @@ void dump_timed_text_track(GF_ISOFile *file, u32 trackID, char *inName, Bool is_ e = gf_isom_text_dump(file, track, dump, dump_type); if (inName) fclose(dump); - if (e) fprintf(stdout, "Conversion failed (%s)\n", gf_error_to_string(e)); - else fprintf(stdout, "Conversion done\n"); + if (e) fprintf(stderr, "Conversion failed (%s)\n", gf_error_to_string(e)); + else fprintf(stderr, "Conversion done\n"); } #endif /*GPAC_DISABLE_ISOM_DUMP*/ @@ -958,7 +1117,7 @@ void DumpSDP(GF_ISOFile *file, char *inName) strcat(szBuf, "_sdp.txt"); dump = gf_f64_open(szBuf, "wt"); } else { - dump = stdout; + dump = stderr; fprintf(dump, "* File SDP content *\n\n"); } //get the movie SDP @@ -981,6 +1140,10 @@ void DumpSDP(GF_ISOFile *file, char *inName) static char *format_duration(u64 dur, u32 timescale, char *szDur) { u32 h, m, s, ms; + if ((dur==(u64) -1) || (dur==(u32) -1)) { + strcpy(szDur, "Unknown"); + return szDur; + } dur = (u64) (( ((Double) (s64) dur)/timescale)*1000); h = (u32) (dur / 3600000); m = (u32) (dur/ 60000) - h*60; @@ -1055,27 +1218,27 @@ static void DumpMetaItem(GF_ISOFile *file, Bool root_meta, u32 tk_num, char *nam count = gf_isom_get_meta_item_count(file, root_meta, tk_num); primary_id = gf_isom_get_meta_primary_item_id(file, root_meta, tk_num); - fprintf(stdout, "%s type: \"%s\" - %d resource item(s)\n", name, gf_4cc_to_str(brand), (count+(primary_id>0))); + fprintf(stderr, "%s type: \"%s\" - %d resource item(s)\n", name, gf_4cc_to_str(brand), (count+(primary_id>0))); switch (gf_isom_has_meta_xml(file, root_meta, tk_num)) { - case 1: fprintf(stdout, "Meta has XML resource\n"); break; - case 2: fprintf(stdout, "Meta has BinaryXML resource\n"); break; + case 1: fprintf(stderr, "Meta has XML resource\n"); break; + case 2: fprintf(stderr, "Meta has BinaryXML resource\n"); break; } if (primary_id) { - fprintf(stdout, "Primary Item - ID %d\n", primary_id); + fprintf(stderr, "Primary Item - ID %d\n", primary_id); } for (i=0; idecoderConfig->streamType); if (st) { - fprintf(stdout, "MPEG-4 Config%s%s Stream - ObjectTypeIndication 0x%02x\n", + fprintf(stderr, "MPEG-4 Config%s%s Stream - ObjectTypeIndication 0x%02x\n", full_dump ? "\n\t" : ": ", st, esd->decoderConfig->objectTypeIndication); } else { - fprintf(stdout, "MPEG-4 Config%sStream Type 0x%02x - ObjectTypeIndication 0x%02x\n", + fprintf(stderr, "MPEG-4 Config%sStream Type 0x%02x - ObjectTypeIndication 0x%02x\n", full_dump ? "\n\t" : ": ", esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication); } if (esd->decoderConfig->streamType==GF_STREAM_OD) @@ -1159,18 +1326,18 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) #ifndef GPAC_DISABLE_AV_PARSERS GF_M4VDecSpecInfo dsi; gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); - if (full_dump) fprintf(stdout, "\t"); + if (full_dump) fprintf(stderr, "\t"); w = dsi.width; h = dsi.height; - fprintf(stdout, "MPEG-4 Visual Size %d x %d - %s\n", w, h, gf_m4v_get_profile_name(dsi.VideoPL)); + fprintf(stderr, "MPEG-4 Visual Size %d x %d - %s\n", w, h, gf_m4v_get_profile_name(dsi.VideoPL)); if (dsi.par_den && dsi.par_num) { u32 tw, th; gf_isom_get_track_layout_info(file, trackNum, &tw, &th, NULL, NULL, NULL); - fprintf(stdout, "Pixel Aspect Ratio %d:%d - Indicated track size %d x %d\n", dsi.par_num, dsi.par_den, tw, th); + fprintf(stderr, "Pixel Aspect Ratio %d:%d - Indicated track size %d x %d\n", dsi.par_num, dsi.par_den, tw, th); } #else gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - fprintf(stdout, "MPEG-4 Visual Size %d x %d\n", w, h); + fprintf(stderr, "MPEG-4 Visual Size %d x %d\n", w, h); #endif } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) { @@ -1181,41 +1348,44 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) #endif gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - if (full_dump) fprintf(stdout, "\t"); - fprintf(stdout, "AVC/H264 Video - Visual Size %d x %d\n", w, h); + if (full_dump) fprintf(stderr, "\t"); + fprintf(stderr, "AVC/H264 Video - Visual Size %d x %d\n", w, h); #ifndef GPAC_DISABLE_AV_PARSERS avccfg = gf_isom_avc_config_get(file, trackNum, 1); svccfg = gf_isom_svc_config_get(file, trackNum, 1); if (!avccfg && !svccfg) { - fprintf(stdout, "\n\n\tNon-compliant AVC track: SPS/PPS not found in sample description\n"); + fprintf(stderr, "\n\n\tNon-compliant AVC track: SPS/PPS not found in sample description\n"); } else if (avccfg) { - fprintf(stdout, "\tAVC Info: %d SPS - %d PPS", gf_list_count(avccfg->sequenceParameterSets) , gf_list_count(avccfg->pictureParameterSets) ); - fprintf(stdout, " - Profile %s @ Level %g\n", gf_avc_get_profile_name(avccfg->AVCProfileIndication), ((Double)avccfg->AVCLevelIndication)/10.0 ); - fprintf(stdout, "\tNAL Unit length bits: %d\n", 8*avccfg->nal_unit_size); + fprintf(stderr, "\tAVC Info: %d SPS - %d PPS", gf_list_count(avccfg->sequenceParameterSets) , gf_list_count(avccfg->pictureParameterSets) ); + fprintf(stderr, " - Profile %s @ Level %g\n", gf_avc_get_profile_name(avccfg->AVCProfileIndication), ((Double)avccfg->AVCLevelIndication)/10.0 ); + fprintf(stderr, "\tNAL Unit length bits: %d\n", 8*avccfg->nal_unit_size); slc = gf_list_get(avccfg->sequenceParameterSets, 0); if (slc) { gf_avc_get_sps_info(slc->data, slc->size, NULL, NULL, NULL, &par_n, &par_d); if ((par_n>0) && (par_d>0)) { u32 tw, th; gf_isom_get_track_layout_info(file, trackNum, &tw, &th, NULL, NULL, NULL); - fprintf(stdout, "\tPixel Aspect Ratio %d:%d - Indicated track size %d x %d\n", par_n, par_d, tw, th); + fprintf(stderr, "\tPixel Aspect Ratio %d:%d - Indicated track size %d x %d\n", par_n, par_d, tw, th); } } + 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); + } gf_odf_avc_cfg_del(avccfg); } if (svccfg) { - fprintf(stdout, "\n\tSVC Info: %d SPS - %d PPS - Profile %s @ Level %g\n", gf_list_count(svccfg->sequenceParameterSets) , gf_list_count(svccfg->pictureParameterSets), gf_avc_get_profile_name(svccfg->AVCProfileIndication), ((Double)svccfg->AVCLevelIndication)/10.0 ); - fprintf(stdout, "\tSVC NAL Unit length bits: %d\n", 8*svccfg->nal_unit_size); + fprintf(stderr, "\n\tSVC Info: %d SPS - %d PPS - Profile %s @ Level %g\n", gf_list_count(svccfg->sequenceParameterSets) , gf_list_count(svccfg->pictureParameterSets), gf_avc_get_profile_name(svccfg->AVCProfileIndication), ((Double)svccfg->AVCLevelIndication)/10.0 ); + fprintf(stderr, "\tSVC NAL Unit length bits: %d\n", 8*svccfg->nal_unit_size); for (i=0; isequenceParameterSets); i++) { slc = gf_list_get(svccfg->sequenceParameterSets, i); if (slc) { u32 s_w, s_h, sps_id; gf_avc_get_sps_info(slc->data, slc->size, &sps_id, &s_w, &s_h, &par_n, &par_d); - fprintf(stdout, "\t\tSSPS ID %d - Visual Size %d x %d\n", sps_id, s_w, s_h); + fprintf(stderr, "\t\tSSPS ID %d - Visual Size %d x %d\n", sps_id, s_w, s_h); if ((par_n>0) && (par_d>0)) { u32 tw, th; gf_isom_get_track_layout_info(file, trackNum, &tw, &th, NULL, NULL, NULL); - fprintf(stdout, "\tPixel Aspect Ratio %d:%d - Indicated track size %d x %d\n", par_n, par_d, tw, th); + fprintf(stderr, "\tPixel Aspect Ratio %d:%d - Indicated track size %d x %d\n", par_n, par_d, tw, th); } } } @@ -1227,30 +1397,30 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_MEDIA_OGG) { char *szName; gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - if (full_dump) fprintf(stdout, "\t"); + if (full_dump) fprintf(stderr, "\t"); if (!strnicmp(&esd->decoderConfig->decoderSpecificInfo->data[3], "theora", 6)) szName = "Theora"; else szName = "Unknown"; - fprintf(stdout, "Ogg/%s video / GPAC Mux - Visual Size %d x %d\n", szName, w, h); + fprintf(stderr, "Ogg/%s video / GPAC Mux - Visual Size %d x %d\n", szName, w, h); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_IMAGE_JPEG) { gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - fprintf(stdout, "JPEG Stream - Visual Size %d x %d\n", w, h); + fprintf(stderr, "JPEG Stream - Visual Size %d x %d\n", w, h); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_IMAGE_PNG) { gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - fprintf(stdout, "PNG Stream - Visual Size %d x %d\n", w, h); + fprintf(stderr, "PNG Stream - Visual Size %d x %d\n", w, h); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_IMAGE_JPEG_2000) { gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - fprintf(stdout, "JPEG2000 Stream - Visual Size %d x %d\n", w, h); + fprintf(stderr, "JPEG2000 Stream - Visual Size %d x %d\n", w, h); } if (!w || !h) { gf_isom_get_visual_info(file, trackNum, 1, &w, &h); - if (full_dump) fprintf(stdout, "\t"); - fprintf(stdout, "Visual Size %d x %d\n", w, h); + if (full_dump) fprintf(stderr, "\t"); + fprintf(stderr, "Visual Size %d x %d\n", w, h); } if (gf_isom_get_rvc_config(file, trackNum, 1, &rvc_predef, NULL, NULL, NULL)==GF_OK) { - fprintf(stdout, "Has RVC signaled - Predefined configuration %d\n", rvc_predef); + fprintf(stderr, "Has RVC signaled - Predefined configuration %d\n", rvc_predef); } } else if (esd->decoderConfig->streamType==GF_STREAM_AUDIO) { @@ -1271,29 +1441,29 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) e = GF_NON_COMPLIANT_BITSTREAM; else e = gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &a_cfg); - if (full_dump) fprintf(stdout, "\t"); - if (e) fprintf(stdout, "Corrupted AAC Config\n"); + if (full_dump) fprintf(stderr, "\t"); + if (e) fprintf(stderr, "Corrupted AAC Config\n"); else { - fprintf(stdout, "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); - if (a_cfg.has_sbr) fprintf(stdout, " - SBR SampleRate %d", a_cfg.sbr_sr); - if (a_cfg.has_ps) fprintf(stdout, " - PS"); - fprintf(stdout, "\n"); + 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); + 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"); } #else - fprintf(stdout, "MPEG-2/4 Audio - %d Channels - SampleRate %d\n", nb_ch, sr); + fprintf(stderr, "MPEG-2/4 Audio - %d Channels - SampleRate %d\n", nb_ch, sr); #endif break; case GPAC_OTI_AUDIO_MPEG2_PART3: case GPAC_OTI_AUDIO_MPEG1: if (msub_type == GF_ISOM_SUBTYPE_MPEG4_CRYP) { - fprintf(stdout, "MPEG-1/2 Audio - %d Channels - SampleRate %d\n", nb_ch, sr); + fprintf(stderr, "MPEG-1/2 Audio - %d Channels - SampleRate %d\n", nb_ch, sr); } else { #ifndef GPAC_DISABLE_AV_PARSERS GF_ISOSample *samp = gf_isom_get_sample(file, trackNum, 1, &oti); if (samp) { oti = GF_4CC((u8)samp->data[0], (u8)samp->data[1], (u8)samp->data[2], (u8)samp->data[3]); - if (full_dump) fprintf(stdout, "\t"); - fprintf(stdout, "%s Audio - %d Channel(s) - SampleRate %d - Layer %d\n", + if (full_dump) fprintf(stderr, "\t"); + fprintf(stderr, "%s Audio - %d Channel(s) - SampleRate %d - Layer %d\n", gf_mp3_version_name(oti), gf_mp3_num_channels(oti), gf_mp3_sampling_rate(oti), @@ -1301,10 +1471,10 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) ); gf_isom_sample_del(&samp); } else { - fprintf(stdout, "\n\tError fetching sample: %s\n", gf_error_to_string(gf_isom_last_error(file)) ); + fprintf(stderr, "\n\tError fetching sample: %s\n", gf_error_to_string(gf_isom_last_error(file)) ); } #else - fprintf(stdout, "MPEG-1/2 Audio - %d Channels - SampleRate %d\n", nb_ch, sr); + fprintf(stderr, "MPEG-1/2 Audio - %d Channels - SampleRate %d\n", nb_ch, sr); #endif } break; @@ -1312,23 +1482,23 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) case GPAC_OTI_MEDIA_OGG: { char *szName; - if (full_dump) fprintf(stdout, "\t"); + if (full_dump) fprintf(stderr, "\t"); if (!strnicmp(&esd->decoderConfig->decoderSpecificInfo->data[3], "vorbis", 6)) szName = "Vorbis"; else if (!strnicmp(&esd->decoderConfig->decoderSpecificInfo->data[2], "Speex", 5)) szName = "Speex"; else if (!strnicmp(&esd->decoderConfig->decoderSpecificInfo->data[2], "Flac", 4)) szName = "Flac"; else szName = "Unknown"; - fprintf(stdout, "Ogg/%s audio / GPAC Mux - Sample Rate %d - %d channel(s)\n", szName, sr, nb_ch); + fprintf(stderr, "Ogg/%s audio / GPAC Mux - Sample Rate %d - %d channel(s)\n", szName, sr, nb_ch); } break; - case GPAC_OTI_AUDIO_EVRC_VOICE: fprintf(stdout, "EVRC Audio - Sample Rate 8000 - 1 channel\n"); break; - case GPAC_OTI_AUDIO_SMV_VOICE: fprintf(stdout, "SMV Audio - Sample Rate 8000 - 1 channel\n"); break; - case GPAC_OTI_AUDIO_13K_VOICE: fprintf(stdout, "QCELP Audio - Sample Rate 8000 - 1 channel\n"); break; + case GPAC_OTI_AUDIO_EVRC_VOICE: fprintf(stderr, "EVRC Audio - Sample Rate 8000 - 1 channel\n"); break; + case GPAC_OTI_AUDIO_SMV_VOICE: fprintf(stderr, "SMV Audio - Sample Rate 8000 - 1 channel\n"); break; + case GPAC_OTI_AUDIO_13K_VOICE: fprintf(stderr, "QCELP Audio - Sample Rate 8000 - 1 channel\n"); break; /*packetVideo hack for EVRC...*/ case 0xD1: if (esd->decoderConfig->decoderSpecificInfo && (esd->decoderConfig->decoderSpecificInfo->dataLength==8) && !strnicmp(esd->decoderConfig->decoderSpecificInfo->data, "pvmm", 4)) { - if (full_dump) fprintf(stdout, "\t"); - fprintf(stdout, "EVRC Audio (PacketVideo Mux) - Sample Rate 8000 - 1 channel\n"); + if (full_dump) fprintf(stderr, "\t"); + fprintf(stderr, "EVRC Audio (PacketVideo Mux) - Sample Rate 8000 - 1 channel\n"); } break; } @@ -1336,45 +1506,45 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) else if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { if (esd->decoderConfig->objectTypeIndication<=4) { GF_BIFSConfig *b_cfg = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication); - fprintf(stdout, "BIFS Scene description - %s stream\n", b_cfg->elementaryMasks ? "Animation" : "Command"); + fprintf(stderr, "BIFS Scene description - %s stream\n", b_cfg->elementaryMasks ? "Animation" : "Command"); if (full_dump && !b_cfg->elementaryMasks) { - fprintf(stdout, "\tWidth %d Height %d Pixel Metrics %s\n", b_cfg->pixelWidth, b_cfg->pixelHeight, b_cfg->pixelMetrics ? "yes" : "no"); + fprintf(stderr, "\tWidth %d Height %d Pixel Metrics %s\n", b_cfg->pixelWidth, b_cfg->pixelHeight, b_cfg->pixelMetrics ? "yes" : "no"); } gf_odf_desc_del((GF_Descriptor *)b_cfg); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_SCENE_AFX) { u8 tag = esd->decoderConfig->decoderSpecificInfo ? esd->decoderConfig->decoderSpecificInfo->data[0] : 0xFF; const char *afxtype = gf_afx_get_type_description(tag); - fprintf(stdout, "AFX Stream - type %s (%d)\n", afxtype, tag); + fprintf(stderr, "AFX Stream - type %s (%d)\n", afxtype, tag); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_FONT) { - fprintf(stdout, "Font Data stream\n"); + fprintf(stderr, "Font Data stream\n"); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_SCENE_LASER) { GF_LASERConfig l_cfg; gf_odf_get_laser_config(esd->decoderConfig->decoderSpecificInfo, &l_cfg); - fprintf(stdout, "LASER Stream - %s\n", l_cfg.newSceneIndicator ? "Full Scene" : "Scene Segment"); + fprintf(stderr, "LASER Stream - %s\n", l_cfg.newSceneIndicator ? "Full Scene" : "Scene Segment"); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_TEXT_MPEG4) { - fprintf(stdout, "MPEG-4 Streaming Text stream\n"); + fprintf(stderr, "MPEG-4 Streaming Text stream\n"); } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE) { - fprintf(stdout, "Synthetized Texture stream stream\n"); + fprintf(stderr, "Synthetized Texture stream stream\n"); } else { - fprintf(stdout, "Unknown Systems stream OTI %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "Unknown Systems stream OTI %d\n", esd->decoderConfig->objectTypeIndication); } } /*sync is only valid if we open all tracks to take care of default MP4 sync..*/ if (!full_dump) { if (!esd->OCRESID || (esd->OCRESID == esd->ESID)) - fprintf(stdout, "Self-synchronized\n"); + fprintf(stderr, "Self-synchronized\n"); else - fprintf(stdout, "Synchronized on stream %d\n", esd->OCRESID); + fprintf(stderr, "Synchronized on stream %d\n", esd->OCRESID); } else { - fprintf(stdout, "\tDecoding Buffer size %d - Average bitrate %d kbps - Max Bitrate %d kbps\n", esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate/1000, esd->decoderConfig->maxBitrate/1000); + fprintf(stderr, "\tDecoding Buffer size %d - Average bitrate %d kbps - Max Bitrate %d kbps\n", esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate/1000, esd->decoderConfig->maxBitrate/1000); if (esd->dependsOnESID) - fprintf(stdout, "\tDepends on stream %d for decoding\n", esd->dependsOnESID); + fprintf(stderr, "\tDepends on stream %d for decoding\n", esd->dependsOnESID); else - fprintf(stdout, "\tNo stream dependencies for decoding\n"); + fprintf(stderr, "\tNo stream dependencies for decoding\n"); - fprintf(stdout, "\tStreamPriority %d\n", esd->streamPriority); - if (esd->URLString) fprintf(stdout, "\tRemote Data Source %s\n", esd->URLString); + fprintf(stderr, "\tStreamPriority %d\n", esd->streamPriority); + if (esd->URLString) fprintf(stderr, "\tRemote Data Source %s\n", esd->URLString); } gf_odf_desc_del((GF_Descriptor *) esd); @@ -1387,44 +1557,44 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) if (gf_isom_is_ismacryp_media(file, trackNum, 1)) { gf_isom_get_ismacryp_info(file, trackNum, 1, NULL, &scheme_type, &version, &scheme_URI, &KMS_URI, &use_sel_enc, &IV_size, NULL); - fprintf(stdout, "\n*Encrypted stream - ISMA scheme %s (version %d)\n", gf_4cc_to_str(scheme_type), version); - if (scheme_URI) fprintf(stdout, "scheme location: %s\n", scheme_URI); + fprintf(stderr, "\n*Encrypted stream - ISMA scheme %s (version %d)\n", gf_4cc_to_str(scheme_type), version); + if (scheme_URI) fprintf(stderr, "scheme location: %s\n", scheme_URI); if (KMS_URI) { - if (!strnicmp(KMS_URI, "(key)", 5)) fprintf(stdout, "KMS location: key in file\n"); - else fprintf(stdout, "KMS location: %s\n", KMS_URI); + if (!strnicmp(KMS_URI, "(key)", 5)) fprintf(stderr, "KMS location: key in file\n"); + else fprintf(stderr, "KMS location: %s\n", KMS_URI); } - fprintf(stdout, "Selective Encryption: %s\n", use_sel_enc ? "Yes" : "No"); - if (IV_size) fprintf(stdout, "Initialization Vector size: %d bits\n", IV_size*8); + fprintf(stderr, "Selective Encryption: %s\n", use_sel_enc ? "Yes" : "No"); + if (IV_size) fprintf(stderr, "Initialization Vector size: %d bits\n", IV_size*8); } else if (gf_isom_is_omadrm_media(file, trackNum, 1)) { const char *textHdrs; u32 enc_type, hdr_len; u64 orig_len; - fprintf(stdout, "\n*Encrypted stream - OMA DRM\n"); + fprintf(stderr, "\n*Encrypted stream - OMA DRM\n"); gf_isom_get_omadrm_info(file, trackNum, 1, NULL, NULL, NULL, &scheme_URI, &KMS_URI, &textHdrs, &hdr_len, &orig_len, &enc_type, &use_sel_enc, &IV_size, NULL); - fprintf(stdout, "Rights Issuer: %s\n", KMS_URI); - fprintf(stdout, "Content ID: %s\n", scheme_URI); + fprintf(stderr, "Rights Issuer: %s\n", KMS_URI); + fprintf(stderr, "Content ID: %s\n", scheme_URI); if (textHdrs) { u32 i, offset; const char *start = textHdrs; - fprintf(stdout, "OMA Textual Headers:\n"); + fprintf(stderr, "OMA Textual Headers:\n"); i=offset=0; while (iacmod); - br = gf_ac3_get_bitrate(ac3->brcode); - lfe = ac3->lfon; + nb_ch = gf_ac3_get_channels(ac3->streams[0].acmod); + lfe = ac3->streams[0].lfon; + br = ac3->is_ec3 ? ac3->brcode : gf_ac3_get_bitrate(ac3->brcode); + is_ec3 = ac3->is_ec3; gf_free(ac3); } #endif - fprintf(stdout, "\tAC3 stream - Sample Rate %d - %d%s channel(s) - bitrate %d\n", sr, nb_ch, lfe ? ".1" : "", br); + fprintf(stderr, "\t%s stream - Sample Rate %d - %d%s channel(s) - bitrate %d\n", is_ec3 ? "EC-3" : "AC-3", sr, nb_ch, lfe ? ".1" : "", br); } else if (msub_type == GF_ISOM_SUBTYPE_3GP_SMV) { - fprintf(stdout, "\t3GPP SMV stream - Sample Rate %d - %d channel(s) %d bits per samples\n", sr, nb_ch, (u32) bps); + fprintf(stderr, "\t3GPP SMV stream - Sample Rate %d - %d channel(s) %d bits per samples\n", sr, nb_ch, (u32) bps); } else if (msub_type == GF_ISOM_SUBTYPE_3GP_DIMS) { u32 w, h; GF_DIMSDescription dims; gf_isom_get_visual_info(file, trackNum, 1, &w, &h); gf_isom_get_dims_description(file, trackNum, 1, &dims); - fprintf(stdout, "\t3GPP DIMS stream - size %d x %d - Profile %d - Level %d\n", w, h, dims.profile, dims.level); - fprintf(stdout, "\tpathComponents: %d - useFullRequestHost: %s\n", dims.pathComponents, dims.fullRequestHost ? "yes" : "no"); - fprintf(stdout, "\tstream type: %s - redundant: %s\n", dims.streamType ? "primary" : "secondary", (dims.containsRedundant==1) ? "main" : ((dims.containsRedundant==2) ? "redundant" : "main+redundant") ); - if (dims.textEncoding[0]) fprintf(stdout, "\ttext encoding %s\n", dims.textEncoding); - if (dims.contentEncoding[0]) fprintf(stdout, "\tcontent encoding %s\n", dims.contentEncoding); - if (dims.content_script_types) fprintf(stdout, "\tscript languages %s\n", dims.content_script_types); + fprintf(stderr, "\t3GPP DIMS stream - size %d x %d - Profile %d - Level %d\n", w, h, dims.profile, dims.level); + fprintf(stderr, "\tpathComponents: %d - useFullRequestHost: %s\n", dims.pathComponents, dims.fullRequestHost ? "yes" : "no"); + fprintf(stderr, "\tstream type: %s - redundant: %s\n", dims.streamType ? "primary" : "secondary", (dims.containsRedundant==1) ? "main" : ((dims.containsRedundant==2) ? "redundant" : "main+redundant") ); + if (dims.textEncoding[0]) fprintf(stderr, "\ttext encoding %s\n", dims.textEncoding); + if (dims.contentEncoding[0]) fprintf(stderr, "\tcontent encoding %s\n", dims.contentEncoding); + if (dims.content_script_types) fprintf(stderr, "\tscript languages %s\n", dims.content_script_types); } else if (mtype==GF_ISOM_MEDIA_HINT) { u32 refTrack; s32 i, refCount = gf_isom_get_reference_count(file, trackNum, GF_ISOM_REF_HINT); if (refCount) { - fprintf(stdout, "Streaming Hint Track for track%s ", (refCount>1) ? "s" :""); + fprintf(stderr, "Streaming Hint Track for track%s ", (refCount>1) ? "s" :""); for (i=0; icompressor_name, udesc->width, udesc->height); + fprintf(stderr, "Visual Track - Compressor \"%s\" - Resolution %d x %d\n", udesc->compressor_name, udesc->width, udesc->height); } else if (mtype==GF_ISOM_MEDIA_AUDIO) { - fprintf(stdout, "Audio Track - Sample Rate %d - %d channel(s)\n", udesc->samplerate, udesc->nb_channels); + fprintf(stderr, "Audio Track - Sample Rate %d - %d channel(s)\n", udesc->samplerate, udesc->nb_channels); } else { - fprintf(stdout, "Unknown media type\n"); + fprintf(stderr, "Unknown media type\n"); } - fprintf(stdout, "\tVendor code \"%s\" - Version %d - revision %d\n", gf_4cc_to_str(udesc->vendor_code), udesc->version, udesc->revision); + fprintf(stderr, "\tVendor code \"%s\" - Version %d - revision %d\n", gf_4cc_to_str(udesc->vendor_code), udesc->version, udesc->revision); if (udesc->extension_buf) { - fprintf(stdout, "\tCodec configuration data size: %d bytes\n", udesc->extension_buf_size); + fprintf(stderr, "\tCodec configuration data size: %d bytes\n", udesc->extension_buf_size); gf_free(udesc->extension_buf); } gf_free(udesc); } else { - fprintf(stdout, "Unknown track type\n"); + fprintf(stderr, "Unknown track type\n"); } } @@ -1534,29 +1706,29 @@ void DumpTrackInfo(GF_ISOFile *file, u32 trackID, Bool full_dump) gf_isom_get_track_switch_group_count(file, trackNum, &alt_group, &nb_groups); if (alt_group) { - fprintf(stdout, "Alternate Group ID %d\n", alt_group); + fprintf(stderr, "Alternate Group ID %d\n", alt_group); for (i=0; i= 1500) { rate /= 1000; max_rate /= 1000; - fprintf(stdout, "\tAverage rate %d kbps - Max Rate %d kbps\n", rate, max_rate); + fprintf(stderr, "\tAverage rate %d kbps - Max Rate %d kbps\n", rate, max_rate); } else { - fprintf(stdout, "\tAverage rate %d bps - Max Rate %d bps\n", rate, max_rate); + fprintf(stderr, "\tAverage rate %d bps - Max Rate %d bps\n", rate, max_rate); } { u32 dmin, dmax, davg, smin, smax, savg; gf_isom_get_chunks_infos(file, trackNum, &dmin, &davg, &dmax, &smin, &savg, &smax); - fprintf(stdout, "\tChunk durations: min %d ms - max %d ms - average %d ms\n", (1000*dmin)/ts, (1000*dmax)/ts, (1000*davg)/ts); - fprintf(stdout, "\tChunk sizes (bytes): min %d - max %d - average %d\n", smin, smax, savg); + fprintf(stderr, "\tChunk durations: min %d ms - max %d ms - average %d ms\n", (1000*dmin)/ts, (1000*dmax)/ts, (1000*davg)/ts); + fprintf(stderr, "\tChunk sizes (bytes): min %d - max %d - average %d\n", smin, smax, savg); } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); count = gf_isom_get_chapter_count(file, trackNum); if (count) { char szDur[20]; const char *name; u64 time; - fprintf(stdout, "\nChapters:\n"); + fprintf(stderr, "\nChapters:\n"); for (j=0; jtag == GF_ODF_IOD_TAG) { - fprintf(stdout, "File has root IOD (%d bytes)\n", desc_size); - fprintf(stdout, "Scene PL 0x%02x - Graphics PL 0x%02x - OD PL 0x%02x\n", iod->scene_profileAndLevel, iod->graphics_profileAndLevel, iod->OD_profileAndLevel); - fprintf(stdout, "Visual PL: %s (0x%02x)\n", gf_m4v_get_profile_name(iod->visual_profileAndLevel), iod->visual_profileAndLevel); - fprintf(stdout, "Audio PL: %s (0x%02x)\n", gf_m4a_get_profile_name(iod->audio_profileAndLevel), iod->audio_profileAndLevel); - //fprintf(stdout, "inline profiles included %s\n", iod->inlineProfileFlag ? "yes" : "no"); + fprintf(stderr, "File has root IOD (%d bytes)\n", desc_size); + fprintf(stderr, "Scene PL 0x%02x - Graphics PL 0x%02x - OD PL 0x%02x\n", iod->scene_profileAndLevel, iod->graphics_profileAndLevel, iod->OD_profileAndLevel); + fprintf(stderr, "Visual PL: %s (0x%02x)\n", gf_m4v_get_profile_name(iod->visual_profileAndLevel), iod->visual_profileAndLevel); + fprintf(stderr, "Audio PL: %s (0x%02x)\n", gf_m4a_get_profile_name(iod->audio_profileAndLevel), iod->audio_profileAndLevel); + //fprintf(stderr, "inline profiles included %s\n", iod->inlineProfileFlag ? "yes" : "no"); } else { - fprintf(stdout, "File has root OD (%d bytes)\n", desc_size); + fprintf(stderr, "File has root OD (%d bytes)\n", desc_size); } - if (!gf_list_count(iod->ESDescriptors)) fprintf(stdout, "No streams included in root OD\n"); + if (!gf_list_count(iod->ESDescriptors)) fprintf(stderr, "No streams included in root OD\n"); gf_odf_desc_del((GF_Descriptor *) iod); } else { - fprintf(stdout, "File has no MPEG4 IOD/OD\n"); + fprintf(stderr, "File has no MPEG4 IOD/OD\n"); } - if (gf_isom_is_JPEG2000(file)) fprintf(stdout, "File is JPEG 2000\n"); + if (gf_isom_is_JPEG2000(file)) fprintf(stderr, "File is JPEG 2000\n"); count = gf_isom_get_copyright_count(file); if (count) { const char *lang, *note; - fprintf(stdout, "\nCopyrights:\n"); + fprintf(stderr, "\nCopyrights:\n"); for (i=0; i>31) fprintf(stdout, "\tCover Art: PNG File\n"); - else fprintf(stdout, "\tCover Art: JPEG File\n"); + if (tag_len>>31) fprintf(stderr, "\tCover Art: PNG File\n"); + else fprintf(stderr, "\tCover Art: JPEG File\n"); } } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); for (i=0; i -typedef struct -{ - Bool start_indexing; - - /* For indexing the TS*/ - Double segment_duration; - Bool segment_at_rap; - u32 subsegs_per_segment; - char *seg_name; - char *seg_ext; - Bool use_url_template; - char *init_seg_name; - Bool single_segment; - - u32 segment_index; - - FILE *index_file; - char index_file_name[100]; - GF_BitStream *index_bs; - - char mpd_file_name[100]; - FILE *mpd_file; - /* temporary file to store the MPD segment description before writing the header */ - FILE *mpd_segs; - - u32 represantation_idx; - - u32 reference_pid; - GF_M2TS_PES *reference_stream; - - u32 nb_pes_in_segment; - /* earliest presentation time for the whole segment */ - u64 first_PTS; - - /* earliest presentation time for the subsegment being processed */ - u64 base_PTS; - /* byte offset for the start of subsegment being processed */ - u32 base_offset; - /* last presentation time for the subsegment being processed (before the next subsegment is started) */ - u64 last_PTS; - /* last decoding time for the subsegment being processed */ - u64 last_DTS; - /* byte offset for the last PES packet for the subsegment being processed */ - u32 last_offset; - - /* earliest presentation time for the previous subsegment */ - u64 prev_base_PTS; - /* byte offset for the start of the previous subsegment */ - u32 prev_base_offset; - /* last presentation time for the previous subsegment */ - u64 prev_last_PTS; - /* byte offset for the last PES packet for the previous subsegment */ - u32 prev_last_offset; - - /* indicates if the current subsegment contains a SAP and its SAP type*/ - u32 SAP_type; - /* indicates if the first PES in the current subsegment is a SAP*/ - Bool first_pes_sap; - /* Presentation time for the first RAP encountered in the subsegment */ - u64 first_SAP_PTS; - /* byte offset for the first RAP encountered in the subsegment */ - u32 first_SAP_offset; - u64 prev_last_SAP_PTS; - u32 prev_last_SAP_offset; - u64 last_SAP_PTS; - u32 last_SAP_offset; - - /*Interpolated PCR value for the pcrb*/ - u64 interpolated_pcr_value; - u64 last_pcr_value; - - /* information about the first PAT found in the subsegment */ - u32 last_pat_position; - u32 first_pat_position; - u32 prev_last_pat_position; - Bool first_pat_position_valid; - u32 pat_version; - - /* information about the first CAT found in the subsegment */ - u32 last_cat_position; - u32 first_cat_position; - u32 prev_last_cat_position; - Bool first_cat_position_valid; - u32 cat_version; - - /* information about the first PMT found in the subsegment */ - u32 last_pmt_position; - u32 first_pmt_position; - u32 prev_last_pmt_position; - Bool first_pmt_position_valid; - u32 pmt_version; - - /* information about the first PCR found in the subsegment */ - u32 last_pcr_position; - u32 first_pcr_position; - Bool first_pcr_position_valid; - u32 prev_last_pcr_position; - - //GF_List *sidxs; - GF_SegmentIndexBox *sidx; - - //GF_List *pcrbs; - GF_PcrInfoBox *pcrb; -} GF_M2TS_IndexingInfo; typedef struct { @@ -1915,202 +1990,9 @@ typedef struct u32 dump_pid; Bool has_seen_pat; - GF_M2TS_IndexingInfo index_info; - } GF_M2TS_Dump; -/* Initializes an SIDX */ -static GF_SegmentIndexBox *m2ts_sidx_new(u32 pid, u64 PTS, u64 position) -{ - GF_SegmentIndexBox *sidx = (GF_SegmentIndexBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SIDX); - sidx->reference_ID = pid; - /* timestamps in MPEG-2 are expressed in 90 kHz timescale */ - sidx->timescale = 90000; - /* first encountered PTS on the PID for this subsegment */ - sidx->earliest_presentation_time = PTS; - sidx->first_offset = position; - return sidx; -} - -static void m2ts_sidx_add_entry(GF_SegmentIndexBox *sidx, Bool ref_type, - u32 size, u32 duration, Bool first_is_SAP, u32 sap_type, u32 RAP_delta_time) -{ - GF_SIDXReference *ref; - sidx->nb_refs++; - sidx->refs = gf_realloc(sidx->refs, sidx->nb_refs*sizeof(GF_SIDXReference)); - ref = &(sidx->refs[sidx->nb_refs-1]); - ref->reference_type = ref_type; - ref->reference_size = size; - ref->subsegment_duration = duration; - ref->starts_with_SAP = first_is_SAP; - ref->SAP_type = sap_type; - ref->SAP_delta_time = (sap_type ? RAP_delta_time: 0); -} - -static void m2ts_pcrb_add_entry(GF_PcrInfoBox *pcrb, u64 interpolatedPCR) -{ - pcrb->subsegment_count++; - pcrb->pcr_values = gf_realloc(pcrb->pcr_values, pcrb->subsegment_count*sizeof(u64)); - - pcrb->pcr_values[pcrb->subsegment_count-1] = interpolatedPCR; -} - -static void m2ts_sidx_update_prev_entry_duration(GF_SegmentIndexBox *sidx, u32 duration) -{ - GF_SIDXReference *ref; - if (sidx->nb_refs == 0) return; - ref = &(sidx->refs[sidx->nb_refs-1]); - ref->subsegment_duration = duration; -} - -static void m2ts_sidx_finalize_size(GF_M2TS_IndexingInfo *index_info, u64 file_size) -{ - GF_SIDXReference *ref; - if (index_info->sidx->nb_refs == 0) return; - ref = &(index_info->sidx->refs[index_info->sidx->nb_refs-1]); - ref->reference_size = (u32)(file_size - index_info->prev_base_offset); - - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Subsegment: position-range ajdustment:%d-%d (%d bytes)\n", index_info->prev_base_offset, (u32)file_size, ref->reference_size)); -} - -static void m2ts_sidx_flush_entry(GF_M2TS_IndexingInfo *index_info) -{ - u32 size; - u32 duration, prev_duration; - u32 SAP_delta_time; - u32 SAP_offset; - - u32 end_offset; - - if (!index_info->sidx) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Segment: Reference PID: %d, EPTime: "LLU", Start Offset: %d bytes\n", index_info->reference_pid, index_info->base_PTS, index_info->base_offset)); - index_info->sidx = m2ts_sidx_new(index_info->reference_pid, index_info->base_PTS, index_info->base_offset); - } - - if (!index_info->pcrb) { - index_info->pcrb = (GF_PcrInfoBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_PCRB); - } - - /* determine the end of the current index */ - if (index_info->segment_at_rap) { - /*split at PAT*/ - end_offset = index_info->last_pat_position; - } else { - /* split at PES header */ - end_offset = index_info->last_offset; - } - - /* close the current index */ - size = (u32)(end_offset - index_info->base_offset); - duration = (u32)(index_info->last_PTS - index_info->base_PTS); - SAP_delta_time= (u32)(index_info->first_SAP_PTS - index_info->base_PTS); - SAP_offset = (u32)(index_info->first_SAP_offset - index_info->base_offset); - m2ts_sidx_add_entry(index_info->sidx, 0, size, duration, index_info->first_pes_sap, index_info->SAP_type, SAP_delta_time); - m2ts_pcrb_add_entry(index_info->pcrb, index_info->interpolated_pcr_value); - - /* adjust the previous index duration */ - if (index_info->sidx->nb_refs > 0 && (index_info->base_PTS < index_info->prev_last_PTS) ) { - prev_duration = (u32)(index_info->base_PTS-index_info->prev_base_PTS); - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" time-range adj.: %.03f-%.03f / %.03f sec.\n", - (index_info->prev_base_PTS - index_info->first_PTS)/90000.0, - (index_info->base_PTS - index_info->first_PTS)/90000.0, prev_duration/90000.0); - m2ts_sidx_update_prev_entry_duration(index_info->sidx, prev_duration)); - } - - /* Printing result */ - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Subsegment:")); - //time-range:position-range: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" %.03f-%0.3f / %.03f sec., %d-%d / %d bytes, ", - (index_info->base_PTS - index_info->first_PTS)/90000.0, - (index_info->last_PTS - index_info->first_PTS)/90000.0, duration/90000.0, - index_info->base_offset, end_offset, size)); - if (index_info->SAP_type) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("RAP @ %.03f sec. / %d bytes", (index_info->first_SAP_PTS - index_info->first_PTS)/90000.0, - SAP_offset)); - } - if (index_info->first_pat_position_valid) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PAT @ %d bytes", (u32)(index_info->first_pat_position - index_info->base_offset))); - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PAT")); - } - if (index_info->first_cat_position_valid) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", CAT @ %d bytes", (u32)(index_info->first_cat_position - index_info->base_offset))); - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No CAT")); - } - if (index_info->first_pmt_position_valid) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PMT @ %d bytes", (u32)(index_info->first_pmt_position - index_info->base_offset))); - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PMT")); - } - if (index_info->first_pcr_position_valid) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PCR @ %d bytes", (u32)(index_info->first_pcr_position - index_info->base_offset))); - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PCR")); - } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n")); - - /* save the current values for later adjustments */ - index_info->prev_last_SAP_PTS = index_info->last_SAP_PTS; - index_info->prev_last_SAP_offset = index_info->last_SAP_offset; - index_info->prev_last_PTS = index_info->last_PTS; - index_info->prev_last_offset = index_info->last_offset; - index_info->prev_base_PTS = index_info->base_PTS; - index_info->base_PTS = index_info->last_PTS; - index_info->prev_base_offset = index_info->base_offset; - index_info->prev_last_pat_position = index_info->last_pat_position; - index_info->prev_last_cat_position = index_info->last_cat_position; - index_info->prev_last_pmt_position = index_info->last_pmt_position; - index_info->prev_last_pcr_position = index_info->last_pcr_position; - - /* update the values for the new index*/ - index_info->base_offset = end_offset; - index_info->SAP_type = 0; - index_info->first_SAP_PTS = 0; - index_info->first_SAP_offset = 0; - index_info->first_pes_sap = 0; - index_info->nb_pes_in_segment = 0; - index_info->last_DTS = 0; - - if (index_info->last_pat_position >= index_info->base_offset) { - index_info->first_pat_position_valid = 1; - index_info->first_pat_position = index_info->last_pat_position; - } else { - index_info->first_pat_position_valid = 0; - index_info->first_pat_position = 0; - } - if (index_info->last_cat_position >= index_info->base_offset) { - index_info->first_cat_position_valid = 1; - index_info->first_cat_position = index_info->last_cat_position; - } else { - index_info->first_cat_position_valid = 0; - index_info->first_cat_position = 0; - } - if (index_info->last_pmt_position >= index_info->base_offset) { - index_info->first_pmt_position_valid = 1; - index_info->first_pmt_position = index_info->last_pmt_position; - } else { - index_info->first_pmt_position_valid = 0; - index_info->first_pmt_position = 0; - } - if (index_info->last_pcr_position >= index_info->base_offset) { - index_info->first_pcr_position_valid = 1; - index_info->first_pcr_position = index_info->last_pcr_position; - } else { - index_info->first_pcr_position_valid = 0; - index_info->first_pcr_position = 0; - } -} -static void m2ts_check_indexing(GF_M2TS_IndexingInfo *index_info) -{ - u32 delta_time = (u32)(index_info->last_PTS - index_info->base_PTS); - u32 segment_duration = (u32)(index_info->segment_duration*90000); - /* we need to create an SIDX entry when the duration of the previous entry is too big */ - if (delta_time >= segment_duration) { - m2ts_sidx_flush_entry(index_info); - } -} static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) { @@ -2118,29 +2000,14 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) GF_M2TS_Program *prog; GF_M2TS_PES_PCK *pck; GF_M2TS_Dump *dumper = (GF_M2TS_Dump *)ts->user; - GF_M2TS_IndexingInfo *index_info = &dumper->index_info; switch (evt_type) { case GF_M2TS_EVT_PAT_FOUND: - if (index_info->start_indexing) { - if (!index_info->first_pat_position_valid) { - index_info->first_pat_position_valid = 1; - index_info->first_pat_position = (ts->pck_number-1)*188; - } - index_info->last_pat_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, 0); } break; case GF_M2TS_EVT_PAT_UPDATE: - if (index_info->start_indexing) { - if (!index_info->first_pat_position_valid) { - index_info->first_pat_position_valid = 1; - index_info->first_pat_position = (ts->pck_number-1)*188; - } - index_info->last_pat_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, 0); } @@ -2149,50 +2016,22 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) /* WARNING: We detect the pat on a repetition, probably to ensure that we also have seen all the PMT To be checked */ dumper->has_seen_pat = 1; - if (index_info->start_indexing) { - if (!index_info->first_pat_position_valid) { - index_info->first_pat_position_valid = 1; - index_info->first_pat_position = (ts->pck_number-1)*188; - } - index_info->last_pat_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, 0); } -// fprintf(stdout, "Repeated PAT found - %d programs\n", gf_list_count(ts->programs) ); +// fprintf(stderr, "Repeated PAT found - %d programs\n", gf_list_count(ts->programs) ); break; case GF_M2TS_EVT_CAT_FOUND: - if (index_info->start_indexing) { - if (!index_info->first_cat_position_valid) { - index_info->first_cat_position_valid = 1; - index_info->first_cat_position = (ts->pck_number-1)*188; - } - index_info->last_cat_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, 0); } break; case GF_M2TS_EVT_CAT_UPDATE: - if (index_info->start_indexing) { - if (!index_info->first_cat_position_valid) { - index_info->first_cat_position_valid = 1; - index_info->first_cat_position = (ts->pck_number-1)*188; - } - index_info->last_cat_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, 0); } break; case GF_M2TS_EVT_CAT_REPEAT: - if (index_info->start_indexing) { - if (!index_info->first_cat_position_valid) { - index_info->first_cat_position_valid = 1; - index_info->first_cat_position = (ts->pck_number-1)*188; - } - index_info->last_cat_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, 0); } @@ -2201,13 +2040,7 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) prog = (GF_M2TS_Program*)par; if (gf_list_count(ts->programs)>1 && prog->number!=dumper->prog_number) break; - if (index_info->start_indexing) { - if (!index_info->first_pmt_position_valid) { - index_info->first_pmt_position_valid = 1; - index_info->first_pmt_position = (ts->pck_number-1)*188; - } - index_info->last_pmt_position = (ts->pck_number-1)*188; - } + count = gf_list_count(prog->streams); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Program number %d found - %d streams:\n", prog->number, count)); @@ -2222,11 +2055,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) if (pes->mpeg4_es_id) GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" - MPEG-4 ES ID %d", pes->mpeg4_es_id)); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n")); } - if (es->pid == prog->pcr_pid) { - /* we create indexing information on the stream used for carrying the PCR */ - index_info->reference_pid = prog->pcr_pid; - index_info->reference_stream = (GF_M2TS_PES *)es; - } } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, prog->pmt_pid); @@ -2236,13 +2064,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) prog = (GF_M2TS_Program*)par; if (gf_list_count(ts->programs)>1 && prog->number!=dumper->prog_number) break; - if (index_info->start_indexing) { - if (!index_info->first_pmt_position_valid) { - index_info->first_pmt_position_valid = 1; - index_info->first_pmt_position = (ts->pck_number-1)*188; - } - index_info->last_pmt_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, prog->pmt_pid); } @@ -2251,13 +2072,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) prog = (GF_M2TS_Program*)par; if (gf_list_count(ts->programs)>1 && prog->number!=dumper->prog_number) break; - if (index_info->start_indexing) { - if (!index_info->first_pmt_position_valid) { - index_info->first_pmt_position_valid = 1; - index_info->first_pmt_position = (ts->pck_number-1)*188; - } - index_info->last_pmt_position = (ts->pck_number-1)*188; - } if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\n", ts->pck_number, prog->pmt_pid); } @@ -2297,66 +2111,37 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) /*FIXME : not used GF_M2TS_Program *prog = pes->program; */ /* Interpolated PCR value for the TS packet containing the PES header start */ u64 interpolated_pcr_value = 0; - if (pes->last_pcr_value && pes->before_last_pcr_value && pes->last_pcr_value > pes->before_last_pcr_value) { + if (pes->last_pcr_value && pes->before_last_pcr_value_pck_number && pes->last_pcr_value > pes->before_last_pcr_value) { u32 delta_pcr_pck_num = pes->last_pcr_value_pck_number - pes->before_last_pcr_value_pck_number; u32 delta_pts_pcr_pck_num = pes->pes_start_packet_number - pes->last_pcr_value_pck_number; u64 delta_pcr_value = pes->last_pcr_value - pes->before_last_pcr_value; + if ((pes->pes_start_packet_number > pes->last_pcr_value_pck_number) + && (pes->last_pcr_value > pes->before_last_pcr_value)) { + + pes->last_pcr_value = pes->before_last_pcr_value; + } /* we can compute the interpolated pcr value for the packet containing the PES header */ interpolated_pcr_value = pes->last_pcr_value + (u64)((delta_pcr_value*delta_pts_pcr_pck_num*1.0)/delta_pcr_pck_num); - index_info->interpolated_pcr_value = interpolated_pcr_value; - index_info->last_pcr_value = pes->last_pcr_value; } if (dumper->timestamps_info_file) { + Double diff; fprintf(dumper->timestamps_info_file, "%u\t%d\t", pck->stream->pes_start_packet_number, pck->stream->pid); if (interpolated_pcr_value) fprintf(dumper->timestamps_info_file, "%f", interpolated_pcr_value/(300.0 * 90000)); fprintf(dumper->timestamps_info_file, "\t"); if (pck->DTS) fprintf(dumper->timestamps_info_file, "%f", (pck->DTS / 90000.0)); - fprintf(dumper->timestamps_info_file, "\t%f\t%d\t%d\n", pck->PTS / 90000.0, (pck->flags & GF_M2TS_PES_PCK_RAP ? 1 : 0), (pck->flags & GF_M2TS_PES_PCK_DISCONTINUITY ? 1 : 0)); - } - } - if (index_info->start_indexing) { - /* we process packets only for the given PID */ - if (pck->stream->pid != index_info->reference_pid) { - break; - } else { - if (index_info->last_DTS != pck->DTS) { - index_info->last_DTS = pck->DTS; - index_info->nb_pes_in_segment++; - } - - /* we store the fact that there is at least a RAP for the index - and we store the PTS of the first encountered RAP in the index*/ - if (pck->flags & GF_M2TS_PES_PCK_RAP) { - index_info->SAP_type = 1; - if (!index_info->first_SAP_PTS || (index_info->first_SAP_PTS > pck->PTS)) { - index_info->first_SAP_PTS = pck->PTS; - index_info->first_SAP_offset = (pck->stream->pes_start_packet_number-1)*188; - } - index_info->last_SAP_PTS = pck->PTS; - index_info->last_SAP_offset = (pck->stream->pes_start_packet_number-1)*188; - - if (index_info->nb_pes_in_segment==1) { - index_info->first_pes_sap = 1; - } - } - /* we need to know the earliest PTS value (RAP or not) in the index*/ - if (!index_info->base_PTS || (index_info->base_PTS > pck->PTS)) { - index_info->base_PTS = pck->PTS; - } - /* we need to know the earliest PTS value for the whole file (segment) */ - if (!index_info->first_PTS || (index_info->first_PTS > pck->PTS)) { - index_info->first_PTS = pck->PTS; - } - if (pck->PTS > index_info->last_PTS) { - /* we use the last PTS for first approximation of the duration */ - index_info->last_PTS = pck->PTS; - index_info->last_offset = (index_info->reference_stream->pes_start_packet_number-1)*188; + fprintf(dumper->timestamps_info_file, "\t%f\t%d\t%d", pck->PTS / 90000.0, (pck->flags & GF_M2TS_PES_PCK_RAP ? 1 : 0), (pck->flags & GF_M2TS_PES_PCK_DISCONTINUITY ? 1 : 0)); + if (interpolated_pcr_value) { + diff = (pck->DTS ? pck->DTS : pck->PTS) / 90000.0; + diff -= pes->last_pcr_value / (300.0 * 90000); + fprintf(dumper->timestamps_info_file, "\t%f\n", diff); + if (diff<0) fprintf(stderr, "Warning: detected PTS/DTS value less than current PCR of %g sec\n", diff); + } else { + fprintf(dumper->timestamps_info_file, "\t\n"); } - - m2ts_check_indexing(index_info); } } + if (dumper->has_seen_pat && dumper->pes_out && (dumper->dump_pid == pck->stream->pid)) { gf_fwrite(pck->data, pck->data_len, 1, dumper->pes_out); } @@ -2368,13 +2153,6 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) if (dumper->timestamps_info_file) { fprintf(dumper->timestamps_info_file, "%u\t%d\t%f\t\t\t\t%d\n", pck->stream->program->last_pcr_value_pck_number, pck->stream->pid, pck->PTS / (300*90000.0), (pck->flags & GF_M2TS_PES_PCK_DISCONTINUITY ? 1 : 0)); } - if (index_info->start_indexing) { - if (!index_info->first_pcr_position_valid) { - index_info->first_pcr_position_valid = 1; - index_info->first_pcr_position = (ts->pck_number-1)*188; - } - index_info->last_pcr_position = (ts->pck_number-1)*188; - } break; case GF_M2TS_EVT_SL_PCK: #if 0 @@ -2407,216 +2185,7 @@ static void on_m2ts_dump_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) } } -static void mpd_duration(Double duration, char *duration_string) -{ - u32 h, m; - Double s; - - h = (u32) (duration/3600); - m = (u32) (duration-h*60)/60; - s = (duration - h*3600 - m*60); - if (h) sprintf(duration_string, "PT%dH%dM%.2fS", h, m, s); - else if (m) sprintf(duration_string, "PT%dM%.2fS", m, s); - else if (s) sprintf(duration_string, "PT%.2fS", s); - else sprintf(duration_string, "PT0S"); -} - -static void mpd_start(GF_M2TS_IndexingInfo *index_info, Bool on_demand, const char *media_file_name, - Double file_duration, Bool split_seg_at_rap, u64 file_size, Double bufferTime) -{ - char duration_string[100]; - char buffer_string[100]; - u32 bandwidth, i; -#ifndef GPAC_DISABLE_MEDIA_IMPORT - GF_MediaImporter import; -#endif - char szCodecs[1000]; - u32 width, height, sample_rate, nb_channels, langCode; - GF_Err e; - FILE *mpd = index_info->mpd_file; - - /*get codecs*/ -#ifndef GPAC_DISABLE_MEDIA_IMPORT - memset(&import, 0, sizeof(GF_MediaImporter)); - import.trackID = 0; - import.flags = GF_IMPORT_PROBE_ONLY; - import.in_name = (char *)media_file_name; - e = gf_media_import(&import); -#else - fprintf(stdout, "Warning: generating MPD without media import support\n"); -#endif - strcpy(szCodecs, ""); - width = height = sample_rate = nb_channels = langCode = 0; - - - bandwidth = (u32) (file_size * 8 / file_duration); - mpd_duration(file_duration, duration_string); - mpd_duration(bufferTime, buffer_string); - - if (!index_info->represantation_idx) { - fprintf(mpd, "\n", (on_demand ? "static": "dynamic"), buffer_string); - fprintf(mpd, " \n"); - fprintf(mpd, " MPD for file %s generated with GPAC %s\n", media_file_name, GPAC_FULL_VERSION); - fprintf(mpd, " \n"); - fprintf(mpd, " \n", duration_string, buffer_string); - fprintf(mpd, " \n"); - } - - if (!e) { -#ifndef GPAC_DISABLE_MEDIA_IMPORT - for (i=0; i\n", import.tk_info[i].track_num); - } - else if (import.tk_info[i].type==GF_ISOM_MEDIA_AUDIO) { - if (!sample_rate) sample_rate = import.tk_info[i].audio_info.sample_rate; - if (!nb_channels) nb_channels = import.tk_info[i].audio_info.nb_channels; - fprintf(mpd, " \n", import.tk_info[i].track_num); - } - if (!langCode && import.tk_info[i].lang) langCode = import.tk_info[i].lang; - } -#endif - } - - fprintf(mpd, " represantation_idx+1, szCodecs); - if (width && height) fprintf(mpd, " width=\"%d\" height=\"%d\"", width, height); - if (sample_rate && nb_channels) fprintf(mpd, " sampleRate=\"%d\" numChannels=\"%d\"", sample_rate, nb_channels); - if (langCode) fprintf(mpd, " lang=\"%s\"", gf_4cc_to_str(langCode) ); - fprintf(mpd, " startWithRAP=\"%s\"", split_seg_at_rap ? "1" : "false"); - fprintf(mpd, " bandwidth=\"%d\"", bandwidth); - fprintf(mpd, ">\n"); - -} - -void mpd_end(FILE *mpd, Bool is_last_rep) -{ - fprintf(mpd, " \n"); - if (is_last_rep) { - fprintf(mpd, " \n"); - fprintf(mpd, " \n"); - fprintf(mpd, ""); - } -} - -static void write_mpd_segment_info(GF_M2TS_IndexingInfo *index_info, char *media_file_name) -{ - char *sep, SegName[GF_MAX_PATH]; - u32 i; - u64 start; - - if (!index_info->seg_name) { - fprintf(index_info->mpd_file, " %s\n", media_file_name); - } - - if (index_info->single_segment) { - fprintf(index_info->mpd_file, " \n"); - fprintf(index_info->mpd_file, " %s\n", index_info->index_file_name); - fprintf(index_info->mpd_file, " \n"); - return; - } - - if (index_info->seg_name) { - char *mfile = strrchr(media_file_name, '/'); - if (!mfile) mfile = strrchr(media_file_name, '\\'); - if (mfile) mfile += 1; - else mfile = media_file_name; - - if (strstr(index_info->seg_name, "%s")) { - sprintf(SegName, index_info->seg_name, mfile); - } else { - strcpy(SegName, index_info->seg_name); - } - sep = strrchr(SegName, '.'); - if (sep) sep[0] = 0; - } - - if (index_info->seg_name && index_info->use_url_template) { - fprintf(index_info->mpd_file, " \n", (u32) (1000*index_info->segment_duration), SegName, index_info->seg_ext); - } else { - fprintf(index_info->mpd_file, " \n", (u32) (1000*index_info->segment_duration)); - } - /* add startIndex for live scenarios */ - - if (index_info->init_seg_name) { - fprintf(index_info->mpd_file, " \n", index_info->init_seg_name); - } - - - fprintf(index_info->mpd_file, " %s\n", index_info->index_file_name); - - if (!index_info->seg_name) { - start=index_info->sidx->first_offset; - for (i=0; isidx->nb_refs; i++) { - GF_SIDXReference *ref = &index_info->sidx->refs[i]; - fprintf(index_info->mpd_file, " \n", start, start+ref->reference_size-1); - start += ref->reference_size; - } - } else { - FILE *src, *dst; - u64 pos, end; - src= gf_f64_open(media_file_name, "rb"); - start=index_info->sidx->first_offset; - for (i=0; isidx->nb_refs; i++) { - char szFile[GF_MAX_PATH], buf[4096]; - GF_SIDXReference *ref = &index_info->sidx->refs[i]; - - strcpy(szFile, SegName); - sprintf(buf, "%d", index_info->segment_index); - strcat(szFile, buf); - strcat(szFile, ".ts"); - - if (index_info->use_url_template!=2) { - dst = gf_f64_open(szFile, "wb"); - - gf_f64_seek(src, start, SEEK_SET); - pos = start; - end = start+ref->reference_size; - while (pos= end) { - to_read = (u32) (end-pos); - } - res = fread(buf, 1, to_read, src); - if (res==to_read) { - res = fwrite(buf, 1, to_read, dst); - } - if (res!=to_read) { - fprintf(stderr, "IO error while Extracting segment %03d / %03d\r", i+1, index_info->sidx->nb_refs); - break; - } - pos += res; - } - fclose(dst); - } - start += ref->reference_size; - index_info->segment_index++; - - if (!index_info->use_url_template) - fprintf(index_info->mpd_file, " \n", szFile); - - fprintf(stdout, "Extracting segment %03d / %03d\r", i+1, index_info->sidx->nb_refs); - } - fclose(src); - } -// fprintf(index_info->mpd_file, " \n", media_file_name, index_info->index_file_name); - if (index_info->seg_name && index_info->use_url_template) { - fprintf(index_info->mpd_file, " \n"); - } else { - fprintf(index_info->mpd_file, " \n"); - } -} - -void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num, - Double dash_duration, Bool seg_at_rap, u32 subseg_per_seg, - char *seg_name, char *seg_ext, Bool use_url_template, Bool single_segment, u32 representation_idx, Bool is_last_rep) +void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num) { char data[188]; GF_M2TS_Dump dumper; @@ -2633,51 +2202,13 @@ void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num, } ts = gf_m2ts_demux_new(); ts->on_event = on_m2ts_dump_event; + ts->notify_pes_timing = 1; memset(&dumper, 0, sizeof(GF_M2TS_Dump)); ts->user = &dumper; dumper.prog_number = prog_num; - - if (dash_duration) { - char *c, *f; - dumper.index_info.segment_duration = dash_duration; - dumper.index_info.segment_at_rap = seg_at_rap; - dumper.index_info.subsegs_per_segment = subseg_per_seg; - dumper.index_info.use_url_template = use_url_template; - dumper.index_info.init_seg_name = NULL; - dumper.index_info.single_segment = single_segment; - dumper.index_info.seg_name = seg_name; - dumper.index_info.seg_ext = seg_ext ? seg_ext : "ts"; - - c = strrchr(mpeg2ts_file, '.'); - if (c) *c = 0; - f = strrchr(mpeg2ts_file, '/'); - if (!f) f = strrchr(mpeg2ts_file, '\\'); - sprintf(dumper.index_info.index_file_name, "%s_index.%s", f ? f+1 : mpeg2ts_file, (seg_ext?seg_ext:"didx")); - if (c) *c = '.'; - - dumper.index_info.index_file = NULL; - dumper.index_info.index_bs = NULL; - if (dumper.index_info.use_url_template!=2) { -#ifndef GPAC_DISABLE_ISOM_FRAGMENTS - dumper.index_info.index_file = gf_f64_open(dumper.index_info.index_file_name, "wb"); - dumper.index_info.index_bs = gf_bs_from_file(dumper.index_info.index_file, GF_BITSTREAM_WRITE); - { - GF_SegmentTypeBox *styp = (GF_SegmentTypeBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_STYP); - styp->majorBrand = GF_4CC('r','i','s','x'); - styp->minorVersion = 0; - styp->altBrand = (u32*)gf_malloc(sizeof(u32)); - styp->altBrand[0] = styp->majorBrand; - styp->altCount = 1; - gf_isom_box_size((GF_Box *)styp); - gf_isom_box_write((GF_Box *)styp, dumper.index_info.index_bs); - gf_isom_box_del((GF_Box *)styp); - } -#endif - } - } /*PES dumping*/ - else if (out_name) { + if (out_name) { char *pid = strrchr(out_name, '#'); if (pid) { dumper.dump_pid = atoi(pid+1); @@ -2708,41 +2239,23 @@ void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num, gf_m2ts_process_data(ts, data, size); if (dumper.has_seen_pat) break; } + dumper.has_seen_pat = 1; - if (prog_num && !dash_duration) { + if (prog_num) { sprintf(dumper.timestamps_info_name, "%s_prog_%d_timestamps.txt", mpeg2ts_file, prog_num/*, mpeg2ts_file*/); dumper.timestamps_info_file = gf_f64_open(dumper.timestamps_info_name, "wt"); if (!dumper.timestamps_info_file) { fprintf(stderr, "Cannot open file %s\n", dumper.timestamps_info_name); return; } - fprintf(dumper.timestamps_info_file, "PCK#\tPID\tPCR\tDTS\tPTS\tRAP\tDiscontinuity\n"); + fprintf(dumper.timestamps_info_file, "PCK#\tPID\tPCR\tDTS\tPTS\tRAP\tDiscontinuity\tDTS-PCR Diff\n"); } gf_m2ts_reset_parsers(ts); gf_f64_seek(src, 0, SEEK_SET); fdone = 0; - if (dumper.index_info.segment_duration) { - char *sep; - dumper.index_info.start_indexing = 1; - fprintf(stderr, "Starting indexing ...\n"); - if (out_name) { - strcpy(dumper.index_info.mpd_file_name, out_name); - } else { - sep = strrchr(mpeg2ts_file, '/'); - if (!sep) sep = strrchr(mpeg2ts_file, '\\'); - strcpy(dumper.index_info.mpd_file_name, sep ? sep+1 : mpeg2ts_file); - sep = strrchr(dumper.index_info.mpd_file_name, '.'); - if (sep) sep[0] = 0; - strcat(dumper.index_info.mpd_file_name, ".mpd"); - } - if (!representation_idx) { - dumper.index_info.mpd_file = gf_f64_open(dumper.index_info.mpd_file_name, "wt"); - } else { - dumper.index_info.mpd_file = gf_f64_open(dumper.index_info.mpd_file_name, "a+t"); - } - dumper.index_info.represantation_idx = representation_idx; - } + + while (!feof(src)) { size = fread(data, 1, 188, src); if (size<188) break; @@ -2753,19 +2266,6 @@ void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num, gf_set_progress("MPEG-2 TS Parsing", fdone, fsize); } - if (dumper.index_info.segment_duration) { - u64 file_size; - /* flush SIDX entry for the last packets */ - m2ts_sidx_flush_entry(&dumper.index_info); - gf_f64_seek(src, 0, SEEK_END); - file_size = gf_f64_tell(src); - m2ts_sidx_finalize_size(&dumper.index_info, file_size); - fprintf(stderr, "Indexing done (1 sidx, %d entries).\n", dumper.index_info.sidx->nb_refs); - - mpd_start(&dumper.index_info, 1, mpeg2ts_file, (dumper.index_info.last_PTS-dumper.index_info.first_PTS)/90000.0, dumper.index_info.segment_at_rap, file_size, dumper.index_info.segment_duration/4); - write_mpd_segment_info(&dumper.index_info, mpeg2ts_file); - mpd_end(dumper.index_info.mpd_file, is_last_rep); - } fclose(src); gf_m2ts_demux_del(ts); @@ -2778,24 +2278,10 @@ void dump_mpeg2_ts(char *mpeg2ts_file, char *out_name, Bool prog_num, } #endif if (dumper.timestamps_info_file) fclose(dumper.timestamps_info_file); - if (dumper.index_info.sidx) { - gf_isom_box_size((GF_Box *)dumper.index_info.sidx); - if (dumper.index_info.index_bs) gf_isom_box_write((GF_Box *)dumper.index_info.sidx, dumper.index_info.index_bs); - gf_isom_box_del((GF_Box *)dumper.index_info.sidx); - } - - // ToDo: Should be configurable by some switch - if (dumper.index_info.pcrb) { - gf_isom_box_size((GF_Box *)dumper.index_info.pcrb); - if (dumper.index_info.index_bs) gf_isom_box_write((GF_Box *)dumper.index_info.pcrb, dumper.index_info.index_bs); - gf_isom_box_del((GF_Box *)dumper.index_info.pcrb); - } - if (dumper.index_info.mpd_file) fclose(dumper.index_info.mpd_file); - if (dumper.index_info.index_file) fclose(dumper.index_info.index_file); - if (dumper.index_info.index_bs) gf_bs_del(dumper.index_info.index_bs); } + #endif /*GPAC_DISABLE_MPEG2TS*/ diff --git a/applications/mp4box/fileimport.c b/applications/mp4box/fileimport.c index e7ccf03..e1976a8 100644 --- a/applications/mp4box/fileimport.c +++ b/applications/mp4box/fileimport.c @@ -1,12 +1,13 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / mp4box application * - * GPAC is gf_free software; you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. @@ -37,6 +38,10 @@ #ifndef GPAC_DISABLE_BIFS #include #endif +#ifndef GPAC_DISABLE_VRML +#include +#endif + #ifndef GPAC_DISABLE_ISOM_WRITE #include @@ -69,109 +74,118 @@ void convert_file_info(char *inName, u32 trackID) import.flags = GF_IMPORT_PROBE_ONLY; e = gf_media_import(&import); if (e) { - fprintf(stdout, "Error probing file %s: %s\n", inName, gf_error_to_string(e)); + fprintf(stderr, "Error probing file %s: %s\n", inName, gf_error_to_string(e)); return; } if (trackID) { - fprintf(stdout, "Import probing results for track %s#%d:\n", inName, trackID); + fprintf(stderr, "Import probing results for track %s#%d:\n", inName, trackID); } else { - fprintf(stdout, "Import probing results for %s:\n", inName); + fprintf(stderr, "Import probing results for %s:\n", inName); if (!import.nb_tracks) { - fprintf(stdout, "File has no selectable tracks\n"); + fprintf(stderr, "File has no selectable tracks\n"); return; } - fprintf(stdout, "File has %d tracks\n", import.nb_tracks); + fprintf(stderr, "File has %d tracks\n", import.nb_tracks); } found = 0; for (i=0; i> 16, import.tk_info[i].video_info.par & 0xFFFF); - fprintf(stdout, "\n"); + fprintf(stderr, "Source: %s %dx%d", gf_4cc_to_str(import.tk_info[i].media_type), import.tk_info[i].video_info.width, import.tk_info[i].video_info.height); + if (import.tk_info[i].video_info.FPS) fprintf(stderr, " @ %g FPS", import.tk_info[i].video_info.FPS); + if (import.tk_info[i].video_info.par) fprintf(stderr, " PAR: %d:%d", import.tk_info[i].video_info.par >> 16, import.tk_info[i].video_info.par & 0xFFFF); + fprintf(stderr, "\n"); } else if ((import.tk_info[i].type==GF_ISOM_MEDIA_AUDIO) && import.tk_info[i].audio_info.sample_rate) { - fprintf(stdout, "Source: %s - SampleRate %d - %d channels\n", gf_4cc_to_str(import.tk_info[i].media_type), import.tk_info[i].audio_info.sample_rate, import.tk_info[i].audio_info.nb_channels); + fprintf(stderr, "Source: %s - SampleRate %d - %d channels\n", gf_4cc_to_str(import.tk_info[i].media_type), import.tk_info[i].audio_info.sample_rate, import.tk_info[i].audio_info.nb_channels); } else { - fprintf(stdout, "Source: %s\n", gf_4cc_to_str(import.tk_info[i].media_type)); + fprintf(stderr, "Source: %s\n", gf_4cc_to_str(import.tk_info[i].media_type)); } - fprintf(stdout, "\nImport Capabilities:\n"); - if (import.tk_info[i].flags & GF_IMPORT_USE_DATAREF) fprintf(stdout, "\tCan use data referencing\n"); - if (import.tk_info[i].flags & GF_IMPORT_NO_FRAME_DROP) fprintf(stdout, "\tCan use fixed FPS import\n"); - if (import.tk_info[i].flags & GF_IMPORT_FORCE_PACKED) fprintf(stdout, "\tCan force packed bitstream import\n"); - if (import.tk_info[i].flags & GF_IMPORT_OVERRIDE_FPS) fprintf(stdout, "\tCan override source frame rate\n"); - if (import.tk_info[i].flags & (GF_IMPORT_SBR_IMPLICIT|GF_IMPORT_SBR_EXPLICIT)) fprintf(stdout, "\tCan use AAC-SBR signaling\n"); - if (import.tk_info[i].flags & (GF_IMPORT_PS_IMPLICIT|GF_IMPORT_PS_EXPLICIT)) fprintf(stdout, "\tCan use AAC-PS signaling\n"); - if (import.tk_info[i].flags & GF_IMPORT_FORCE_MPEG4) fprintf(stdout, "\tCan force MPEG-4 Systems signaling\n"); - if (import.tk_info[i].flags & GF_IMPORT_3GPP_AGGREGATION) fprintf(stdout, "\tCan use 3GPP frame aggregation\n"); - if (import.tk_info[i].flags & GF_IMPORT_NO_DURATION) fprintf(stdout, "\tCannot use duration-based import\n"); + fprintf(stderr, "\nImport Capabilities:\n"); + if (import.tk_info[i].flags & GF_IMPORT_USE_DATAREF) fprintf(stderr, "\tCan use data referencing\n"); + if (import.tk_info[i].flags & GF_IMPORT_NO_FRAME_DROP) fprintf(stderr, "\tCan use fixed FPS import\n"); + if (import.tk_info[i].flags & GF_IMPORT_FORCE_PACKED) fprintf(stderr, "\tCan force packed bitstream import\n"); + if (import.tk_info[i].flags & GF_IMPORT_OVERRIDE_FPS) fprintf(stderr, "\tCan override source frame rate\n"); + if (import.tk_info[i].flags & (GF_IMPORT_SBR_IMPLICIT|GF_IMPORT_SBR_EXPLICIT)) fprintf(stderr, "\tCan use AAC-SBR signaling\n"); + if (import.tk_info[i].flags & (GF_IMPORT_PS_IMPLICIT|GF_IMPORT_PS_EXPLICIT)) fprintf(stderr, "\tCan use AAC-PS signaling\n"); + if (import.tk_info[i].flags & GF_IMPORT_FORCE_MPEG4) fprintf(stderr, "\tCan force MPEG-4 Systems signaling\n"); + if (import.tk_info[i].flags & GF_IMPORT_3GPP_AGGREGATION) fprintf(stderr, "\tCan use 3GPP frame aggregation\n"); + if (import.tk_info[i].flags & GF_IMPORT_NO_DURATION) fprintf(stderr, "\tCannot use duration-based import\n"); found = 1; break; } - fprintf(stdout, "\n"); - if (!found && trackID) fprintf(stdout, "Cannot find track %d in file\n", trackID); + fprintf(stderr, "\n"); + if (!found && trackID) fprintf(stderr, "Cannot find track %d in file\n", trackID); } 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; + u32 track_id, i, timescale, track, stype, profile, level, new_timescale, rescale, svc_mode; s32 par_d, par_n, prog_id, delay; - s32 tw, th, tx, ty; - Bool do_audio, do_video, do_all, disable, track_layout, chap_ref, is_chap, keep_handler; - u32 group, handler, rvc_predefined; + s32 tw, th, tx, ty, txtw, txth, txtx, txty; + Bool do_audio, do_video, do_all, disable, track_layout, text_layout, chap_ref, is_chap, is_chap_file, keep_handler, negative_cts_offset; + u32 group, handler, rvc_predefined, check_track_for_svc; const char *szLan; GF_Err e; GF_MediaImporter import; - char *ext, szName[1000], *handler_name, *rvc_config; + char *ext, szName[1000], *handler_name, *rvc_config, *chapter_name; rvc_predefined = 0; + chapter_name = NULL; + new_timescale = 1; + rescale = 0; + text_layout = 0; + /*0: merge all + 1: split base and all SVC in two tracks + 2: split all base and SVC layers in dedicated tracks + */ + svc_mode = 0; memset(&import, 0, sizeof(GF_MediaImporter)); strcpy(szName, inName); ext = strrchr(inName, '.'); if (!ext) { - fprintf(stdout, "Unknown input file type\n"); + fprintf(stderr, "Unknown input file type\n"); return GF_BAD_PARAM; } - + is_chap_file = 0; handler = 0; disable = 0; chap_ref = 0; @@ -182,8 +196,9 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc group = 0; stype = 0; profile = level = 0; + negative_cts_offset = 0; - tw = th = tx = ty = 0; + tw = th = tx = ty = txtw = txth = txtx = txty = 0; par_d = par_n = -2; /*use ':' as separator, but beware DOS paths...*/ ext = strchr(szName, ':'); @@ -211,6 +226,12 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc } else force_fps = atof(ext+5); } + else if (!strnicmp(ext+1, "timescale=", 10)) { + new_timescale = atoi(ext+11); + } + else if (!strnicmp(ext+1, "rescale=", 8)) { + rescale = atoi(ext+9); + } else if (!stricmp(ext+1, "chap")) is_chap = 1; else if (!stricmp(ext+1, "dref")) import_flags |= GF_IMPORT_USE_DATAREF; else if (!stricmp(ext+1, "nodrop")) import_flags |= GF_IMPORT_NO_FRAME_DROP; @@ -246,7 +267,16 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc else if (!strnicmp(ext+1, "font=", 5)) import.fontName = gf_strdup(ext+6); else if (!strnicmp(ext+1, "size=", 5)) import.fontSize = atoi(ext+6); else if (!strnicmp(ext+1, "fmt=", 4)) import.streamFormat = gf_strdup(ext+5); - else if (!strnicmp(ext+1, "ext=", 4)) import.force_ext = gf_strdup(ext+5); + else if (!strnicmp(ext+1, "ext=", 4)) { + /*extensions begin with '.'*/ + if (*(ext+5) == '.') + import.force_ext = gf_strdup(ext+5); + else { + import.force_ext = gf_calloc(1+strlen(ext+5)+1, 1); + import.force_ext[0] = '.'; + strcat(import.force_ext+1, ext+5); + } + } else if (!strnicmp(ext+1, "disable", 7)) disable = 1; else if (!strnicmp(ext+1, "group=", 6)) { group = atoi(ext+7); @@ -263,11 +293,35 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc tx = ty = 0; } } + else if (!strnicmp(ext+1, "text_layout=", 12)) { + if ( sscanf(ext+13, "%dx%dx%dx%d", &txtw, &txth, &txtx, &txty)==4) { + text_layout = 1; + } else if ( sscanf(ext+8, "%dx%d", &txtw, &txth)==2) { + track_layout = 1; + txtx = txty = 0; + } + } else if (!strnicmp(ext+1, "stype=", 6)) { stype = GF_4CC(ext[7], ext[8], ext[9], ext[10]); } else if (!strnicmp(ext+1, "profile=", 8)) profile = atoi(ext+9); else if (!strnicmp(ext+1, "level=", 6)) level = atoi(ext+7); + else if (!strnicmp(ext+1, "chapter=", 8)) chapter_name = gf_strdup(ext+9); + else if (!strnicmp(ext+1, "chapfile=", 9)) { + chapter_name = gf_strdup(ext+10); + is_chap_file=1; + } + /*force all composition offsets to be positive*/ + else if (!strnicmp(ext+1, "negctts", 7)) negative_cts_offset = 1; + /*split SVC layers*/ + else if (!strnicmp(ext+1, "svcmode=", 8)) { + if (!stricmp(ext+9, "splitall")) + svc_mode = 2; + else if (!stricmp(ext+9, "splitbase")) + svc_mode = 1; + else if (!stricmp(ext+9, "merged")) + svc_mode = 0; + } /*unrecognized, assume name has colon in it*/ else { @@ -351,12 +405,21 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc if (!tw) tw = w; if (!th) th = h; if (ty==-1) ty = (h>(u32)th) ? h-th : 0; - import.twidth = tw; - import.theight = th; + import.text_width = tw; + import.text_height = th; } if (is_chap && chap_ref) import_flags |= GF_IMPORT_NO_TEXT_FLUSH; } + if (text_layout && txtw && txth) { + import.text_track_width = import.text_width ? import.text_width : txtw; + import.text_track_height = import.text_height ? import.text_height : txth; + import.text_width = txtw; + import.text_height = txth; + import.text_x = txtx; + import.text_y = txty; + } + check_track_for_svc = 0; import.dest = dest; import.video_fps = force_fps; @@ -385,7 +448,7 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc //u64 seg_dur = (-delay)*gf_isom_get_media_timescale(import.dest, i+1) / 1000; gf_isom_append_edit_segment(import.dest, i+1, tk_dur-to_skip, to_skip, GF_ISOM_EDIT_NORMAL); } else { - fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n"); + fprintf(stderr, "Warning: request negative delay longer than track duration - ignoring\n"); } } } @@ -426,6 +489,12 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc if (gf_isom_get_media_subtype(import.dest, i+1, 1)== GF_4CC( 'm', 'p', '4', 's' )) keep_sys_tracks = 1; + + 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) + check_track_for_svc = i+1; } } else { for (i=0; i1) { + gf_isom_set_media_timescale(import.dest, track, new_timescale, 0); + } + if (rescale>1) { + switch (gf_isom_get_media_type(import.dest, track)) { + case GF_ISOM_MEDIA_AUDIO: + fprintf(stderr, "Cannot force media timescale for audio media types - ignoring\n"); + break; + default: + gf_isom_set_media_timescale(import.dest, track, rescale, 1); + break; + } + } + if (rvc_config) { FILE *f = gf_f64_open(rvc_config, "rb"); if (f) { @@ -532,14 +615,39 @@ GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double forc } else if (rvc_predefined>0) { gf_isom_set_rvc_config(import.dest, track, 1, rvc_predefined, NULL, NULL, 0); } + + 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) + check_track_for_svc = track; + } + if (track_id) fprintf(stderr, "WARNING: Track ID %d not found in file\n", track_id); + else if (do_video) fprintf(stderr, "WARNING: Video track not found\n"); + else if (do_audio) fprintf(stderr, "WARNING: Audio track not found\n"); + } + + if (chapter_name) { + if (is_chap_file) { + e = gf_media_import_chapters(import.dest, chapter_name, 0); + } else { + e = gf_isom_add_chapter(import.dest, 0, 0, chapter_name); + } + } + + if (check_track_for_svc) { + if (svc_mode) { + e = gf_media_split_svc(import.dest, check_track_for_svc, (svc_mode==2) ? 1 : 0); + if (e) goto exit; + } else { + e = gf_media_merge_svc(import.dest, check_track_for_svc, 1); + if (e) goto exit; } - if (track_id) fprintf(stdout, "WARNING: Track ID %d not found in file\n", track_id); - else if (do_video) fprintf(stdout, "WARNING: Video track not found\n"); - else if (do_audio) fprintf(stdout, "WARNING: Audio track not found\n"); } exit: if (handler_name) gf_free(handler_name); + if (chapter_name ) gf_free(chapter_name ); if (import.fontName) gf_free(import.fontName); if (import.streamFormat) gf_free(import.streamFormat); if (import.force_ext) gf_free(import.force_ext); @@ -569,7 +677,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, { u32 i, count, nb_tk, needs_rap_sync, cur_file, conv_type, nb_tk_done, nb_samp, nb_done, di; Double max_dur, cur_file_time; - Bool do_add, all_duplicatable, size_exceeded, chunk_extraction, rap_split; + Bool do_add, all_duplicatable, size_exceeded, chunk_extraction, rap_split, split_until_end; GF_ISOFile *dest; GF_ISOSample *samp; GF_Err e; @@ -578,10 +686,16 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, Double chunk_start = (Double) chunk_start_time; chunk_extraction = (chunk_start>=0) ? 1 : 0; - + split_until_end = 0; rap_split = 0; if (split_size_kb==(u32) -1) rap_split = 1; if (split_dur==-1) rap_split = 1; + else if (split_dur==-2) { + split_size_kb = 0; + split_until_end = 1; + split_dur = 0; + } + if (rap_split) { split_size_kb = 0; split_dur = (double) GF_MAX_FLOAT; @@ -646,12 +760,12 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, case GF_ISOM_MEDIA_MPEGJ: case GF_ISOM_MEDIA_MPEG7: case GF_ISOM_MEDIA_FLASH: - fprintf(stdout, "WARNING: Track ID %d (type %s) not handled by spliter - skipping\n", gf_isom_get_track_id(mp4, i+1), gf_4cc_to_str(mtype)); + fprintf(stderr, "WARNING: Track ID %d (type %s) not handled by spliter - skipping\n", gf_isom_get_track_id(mp4, i+1), gf_4cc_to_str(mtype)); continue; default: /*for all other track types, only split if more than one sample*/ if (gf_isom_get_sample_count(mp4, i+1)==1) { - fprintf(stdout, "WARNING: Track ID %d (type %s) not handled by spliter - skipping\n", gf_isom_get_track_id(mp4, i+1), gf_4cc_to_str(mtype)); + fprintf(stderr, "WARNING: Track ID %d (type %s) not handled by spliter - skipping\n", gf_isom_get_track_id(mp4, i+1), gf_4cc_to_str(mtype)); continue; } tks[nb_tk].can_duplicate = 1; @@ -673,7 +787,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, if (tks[nb_tk].has_non_raps) { /*we don't support that*/ if (needs_rap_sync) { - fprintf(stdout, "More than one track has non-sync points - cannot split file\n"); + fprintf(stderr, "More than one track has non-sync points - cannot split file\n"); gf_free(tks); return GF_NOT_SUPPORTED; } @@ -683,24 +797,26 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, nb_tk++; } if (!nb_tk) { - fprintf(stdout, "No suitable tracks found for spliting file\n"); + fprintf(stderr, "No suitable tracks found for spliting file\n"); gf_free(tks); return GF_NOT_SUPPORTED; } if (chunk_start>=max_dur) { - fprintf(stdout, "Input file (%f) shorter than requested split start offset (%f)\n", max_dur, chunk_start); + fprintf(stderr, "Input file (%f) shorter than requested split start offset (%f)\n", max_dur, chunk_start); gf_free(tks); return GF_NOT_SUPPORTED; } - if (!rap_split && (max_dur<=split_dur)) { - fprintf(stdout, "Input file (%f) shorter than requested split duration (%f)\n", max_dur, split_dur); + if (split_until_end) { + split_dur = max_dur; + } else if (!rap_split && (max_dur<=split_dur)) { + fprintf(stderr, "Input file (%f) shorter than requested split duration (%f)\n", max_dur, split_dur); gf_free(tks); return GF_NOT_SUPPORTED; } if (needs_rap_sync) { tki = &tks[needs_rap_sync-1]; if ((gf_isom_get_sync_point_count(mp4, tki->tk)==1) && (chunk_start != 0.0f)) { - fprintf(stdout, "Not enough Random Access points in input file - cannot split\n"); + fprintf(stderr, "Not enough Random Access points in input file - cannot split\n"); gf_free(tks); return GF_NOT_SUPPORTED; } @@ -722,14 +838,14 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, } else { e = gf_isom_get_sample_for_media_time(mp4, tki->tk, (u64) (chunk_start*tki->time_scale), &di, GF_ISOM_SEARCH_SYNC_BACKWARD, &samp, &sample_num); if (e!=GF_OK) { - fprintf(stdout, "Cannot locate RAP in track ID %d for chunk extraction from %02.2f sec\n", gf_isom_get_track_id(mp4, tki->tk), chunk_start); + fprintf(stderr, "Cannot locate RAP in track ID %d for chunk extraction from %02.2f sec\n", gf_isom_get_track_id(mp4, tki->tk), chunk_start); gf_free(tks); return GF_NOT_SUPPORTED; } start = (Double) (s64) samp->DTS; start /= tki->time_scale; gf_isom_sample_del(&samp); - fprintf(stdout, "Adjusting chunk start time to previous random access at %02.2f sec\n", start); + fprintf(stderr, "Adjusting chunk start time to previous random access at %02.2f sec\n", start); split_dur += (chunk_start - start); chunk_start = start; } @@ -784,7 +900,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, e = gf_isom_clone_track(mp4, tki->tk, dest, 0, &tki->dst_tk); if (e) { - fprintf(stdout, "Error cloning track %d\n", tki->tk); + fprintf(stderr, "Error cloning track %d\n", tki->tk); goto err_exit; } /*use non-packet CTS offsets (faster add/remove)*/ @@ -868,7 +984,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, gf_set_progress("Splitting", nb_done, nb_samp); nb_done++; if (e) { - fprintf(stdout, "Error cloning track %d sample %d\n", tki->tk, tki->last_sample); + fprintf(stderr, "Error cloning track %d sample %d\n", tki->tk, tki->last_sample); goto err_exit; } @@ -956,12 +1072,12 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, } } if (file_split_dur == (Double) GF_MAX_FLOAT) { - fprintf(stdout, "Cannot split file (duration too small or size too small)\n"); + fprintf(stderr, "Cannot split file (duration too small or size too small)\n"); goto err_exit; } if (chunk_extraction) { if (adjust_split_end) { - fprintf(stdout, "Adjusting chunk end time to previous random access at %02.2f sec\n", chunk_start + last_rap_sample_time); + fprintf(stderr, "Adjusting chunk end time to previous random access at %02.2f sec\n", chunk_start + last_rap_sample_time); file_split_dur = last_rap_sample_time; sprintf(szFile, "%s_%d_%d%s", szName, (u32) chunk_start, (u32) (chunk_start+file_split_dur), ext); gf_isom_set_final_name(dest, szFile); @@ -971,7 +1087,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, /*don't split if eq to copy...*/ if (is_last && !cur_file && !chunk_start) { - fprintf(stdout, "Cannot split file (Not enough sync samples, duration too large or size too big)\n"); + fprintf(stderr, "Cannot split file (Not enough sync samples, duration too large or size too big)\n"); goto err_exit; } @@ -1046,9 +1162,9 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, } if (chunk_extraction) { - fprintf(stdout, "Extracting chunk %s - duration %02.2fs (%02.2fs->%02.2fs)\n", szFile, file_split_dur, chunk_start, (chunk_start+split_dur)); + fprintf(stderr, "Extracting chunk %s - duration %02.2fs (%02.2fs->%02.2fs)\n", szFile, file_split_dur, chunk_start, (chunk_start+split_dur)); } else { - fprintf(stdout, "Storing split-file %s - duration %02.2f seconds\n", szFile, file_split_dur); + fprintf(stderr, "Storing split-file %s - duration %02.2f seconds\n", szFile, file_split_dur); } /*repack CTSs*/ @@ -1072,7 +1188,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, new_track_dur = gf_isom_get_track_duration(dest, tki->dst_tk); count = gf_isom_get_edit_segment_count(mp4, tki->tk); if (count>2) { - fprintf(stdout, "Warning: %d edit segments - not supported while splitting (max 2) - ignoring extra\n", count); + fprintf(stderr, "Warning: %d edit segments - not supported while splitting (max 2) - ignoring extra\n", count); count=2; } for (j=0; jtk, j+1, &editTime, &segDur, &MediaTime, &mode); if (!j && (mode!=GF_ISOM_EDIT_EMPTY) ) { - fprintf(stdout, "Warning: Edit list doesn't look like a track delay scheme - ignoring\n"); + fprintf(stderr, "Warning: Edit list doesn't look like a track delay scheme - ignoring\n"); break; } if (mode==GF_ISOM_EDIT_NORMAL) { @@ -1123,7 +1239,7 @@ GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, gf_isom_clone_pl_indications(mp4, dest); e = gf_isom_close(dest); dest = NULL; - if (e) fprintf(stdout, "Error storing file %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Error storing file %s\n", gf_error_to_string(e)); if (is_last || chunk_extraction) break; cur_file++; } @@ -1134,23 +1250,39 @@ err_exit: return e; } -GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat); +GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat, Bool align_timelines); -GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat) +GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat, Bool align_timelines) { u32 i, j, count, nb_tracks, nb_samp, nb_done; GF_ISOFile *orig; GF_Err e; + char *opts, *multi_cat; Float ts_scale; Double dest_orig_dur; u32 dst_tk, tk_id, mtype; u64 insert_dts; + Bool is_isom; GF_ISOSample *samp; + Double aligned_to_DTS = 0; - if (strchr(fileName, '*')) return cat_multiple_files(dest, fileName, import_flags, force_fps, frames_per_sample, tmp_dir, force_cat); + if (strchr(fileName, '*')) return cat_multiple_files(dest, fileName, import_flags, force_fps, frames_per_sample, tmp_dir, force_cat, align_timelines); + + multi_cat = strchr(fileName, '+'); + if (multi_cat) { + multi_cat[0] = 0; + multi_cat = &multi_cat[1]; + } + opts = strchr(fileName, ':'); + if (opts && (opts[1]=='\\')) + opts = strchr(fileName, ':'); e = GF_OK; - if (!gf_isom_probe_file(fileName)) { + + /*if options are specified, reimport the file*/ + is_isom = opts ? 0 : gf_isom_probe_file(fileName); + + if (!is_isom || opts) { orig = gf_isom_open("temp", GF_ISOM_WRITE_EDIT, tmp_dir); e = import_file(orig, fileName, import_flags, force_fps, frames_per_sample); if (e) return e; @@ -1159,6 +1291,20 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou orig = gf_isom_open(fileName, GF_ISOM_OPEN_EDIT, tmp_dir); } + while (multi_cat) { + char *sep = strchr(multi_cat, '+'); + if (sep) sep[0] = 0; + + e = import_file(orig, multi_cat, import_flags, force_fps, frames_per_sample); + if (e) { + gf_isom_delete(orig); + return e; + } + if (!sep) break; + sep[0]=':'; + multi_cat = sep+1; + } + nb_samp = 0; nb_tracks = gf_isom_get_track_count(orig); for (i=0; iAVCLevelIndication!=avc_dst->AVCLevelIndication) { - fprintf(stdout, "Cannot concatenate files: Different AVC Level Indication between source (%d) and destination (%d)\n", avc_src->AVCLevelIndication, avc_dst->AVCLevelIndication); + fprintf(stderr, "Cannot concatenate files: Different AVC Level Indication between source (%d) and destination (%d)\n", avc_src->AVCLevelIndication, avc_dst->AVCLevelIndication); dst_tk = 0; } else if (avc_src->AVCProfileIndication!=avc_dst->AVCProfileIndication) { - fprintf(stdout, "Cannot concatenate files: Different AVC Profile Indication between source (%d) and destination (%d)\n", avc_src->AVCProfileIndication, avc_dst->AVCProfileIndication); + fprintf(stderr, "Cannot concatenate files: Different AVC Profile Indication between source (%d) and destination (%d)\n", avc_src->AVCProfileIndication, avc_dst->AVCProfileIndication); dst_tk = 0; } else { @@ -1287,6 +1443,7 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou } } if (!found) { + fprintf(stderr, "WARNING: Concatenating track ID %d with different SPS - result file might be broken\n", tk_id); gf_list_rem(avc_src->sequenceParameterSets, j); j--; gf_list_add(avc_dst->sequenceParameterSets, slc); @@ -1305,23 +1462,22 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou } } if (!found) { + fprintf(stderr, "WARNING: Concatenating track ID %d with different PPS - result file might be broken\n", tk_id); gf_list_rem(avc_src->pictureParameterSets, j); j--; gf_list_add(avc_dst->pictureParameterSets, slc); } } - gf_isom_avc_config_update(dest, dst_tk, 1, avc_dst); } - gf_odf_avc_cfg_del(avc_src); gf_odf_avc_cfg_del(avc_dst); } if (!dst_tk && force_cat) { dst_tk = gf_isom_get_track_by_id(dest, tk_id); - fprintf(stdout, "WARNING: Concatenating track ID %d even though sample descriptions do not match\n", tk_id); + fprintf(stderr, "WARNING: Concatenating track ID %d even though sample descriptions do not match\n", tk_id); } } @@ -1360,10 +1516,29 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou } /*looks like a new file*/ if (!dst_tk) { - fprintf(stdout, "No suitable destination track found - creating new one (type %s)\n", gf_4cc_to_str(mtype)); + 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); + + if (align_timelines) { + u32 max_timescale = 0; + u32 dst_timescale = 0; + u32 idx; + for (idx=0; idx1)) { + + if (align_timelines) { + insert_dts = (u64) (aligned_to_DTS * gf_isom_get_media_timescale(dest, dst_tk)); + } else if (use_ts_dur && (count>1)) { insert_dts = 2*gf_isom_get_sample_dts(dest, dst_tk, count) - gf_isom_get_sample_dts(dest, dst_tk, count-1); } else { insert_dts = dest_track_dur_before_cat; @@ -1431,6 +1608,12 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou } 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); + /*convert from orig to dst time scale*/ + rescale *= ts_scale; + /*get the first edit normal mode and add the new track dur*/ for (j=nb_edits; j>0; j--) { u64 editTime, segmentDuration, mediaTime; @@ -1438,14 +1621,18 @@ GF_Err cat_isomedia_file(GF_ISOFile *dest, char *fileName, u32 import_flags, Dou gf_isom_get_edit_segment(dest, dst_tk, j, &editTime, &segmentDuration, &mediaTime, &editMode); if (editMode==GF_ISOM_EDIT_NORMAL) { + Double prev_dur = (Double) (s64) dest_track_dur_before_cat; Double dur = (Double) (s64) gf_isom_get_media_duration(orig, i+1); - /*convert to dst time scale*/ - dur *= ts_scale; - /*convert to track time scale*/ - ts_scale = (Float) gf_isom_get_timescale(dest); - ts_scale /= (Float) gf_isom_get_media_timescale(dest, dst_tk); - dur *= ts_scale; + dur *= rescale; + prev_dur *= rescale; + + /*safety test: some files have broken edit lists. If no more than 2 entries, check that the segment duration + is less or equal to the movie duration*/ + if (prev_dur < segmentDuration) { + fprintf(stderr, "Warning: suspicious edit list entry found: duration %g sec but longest track duration before cat is %g - fixing it\n", (Double) (s64) segmentDuration/1000.0, prev_dur/1000); + segmentDuration = (u64) (s64) ( (Double) (s64) (dest_track_dur_before_cat - mediaTime) * rescale ); + } segmentDuration += (u64) (s64) dur; gf_isom_modify_edit_segment(dest, dst_tk, j, segmentDuration, mediaTime, editMode); @@ -1519,7 +1706,7 @@ typedef struct Double force_fps; u32 frames_per_sample; char *tmp_dir; - Bool force_cat; + Bool force_cat, align_timelines; } CATEnum; Bool cat_enumerate(void *cbk, char *szName, char *szPath) @@ -1535,12 +1722,12 @@ Bool cat_enumerate(void *cbk, char *szName, char *szPath) strcpy(szFileName, szName); strcat(szFileName, cat_enum->szOpt); - e = cat_isomedia_file(cat_enum->dest, szFileName, cat_enum->import_flags, cat_enum->force_fps, cat_enum->frames_per_sample, cat_enum->tmp_dir, cat_enum->force_cat); + e = cat_isomedia_file(cat_enum->dest, szFileName, cat_enum->import_flags, cat_enum->force_fps, cat_enum->frames_per_sample, cat_enum->tmp_dir, cat_enum->force_cat, cat_enum->align_timelines); if (e) return 1; return 0; } -GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat) +GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat, Bool align_timelines) { CATEnum cat_enum; char *sep; @@ -1551,6 +1738,7 @@ GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Do cat_enum.frames_per_sample = frames_per_sample; cat_enum.tmp_dir = tmp_dir; cat_enum.force_cat = force_cat; + cat_enum.align_timelines = align_timelines; strcpy(cat_enum.szPath, fileName); sep = strrchr(cat_enum.szPath, GF_PATH_SEPARATOR); @@ -1584,6 +1772,9 @@ GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Do GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *logs) { +#ifdef GPAC_DISABLE_SMGR + return GF_NOT_SUPPORTED; +#else GF_Err e; GF_SceneLoader load; GF_SceneManager *ctx; @@ -1604,7 +1795,7 @@ GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *log e = gf_sm_load_init(&load); if (e<0) { gf_sm_load_done(&load); - fprintf(stdout, "Cannot load context %s - %s\n", in, gf_error_to_string(e)); + fprintf(stderr, "Cannot load context %s - %s\n", in, gf_error_to_string(e)); goto err_exit; } e = gf_sm_load_run(&load); @@ -1612,7 +1803,7 @@ GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *log #ifndef GPAC_DISABLE_SCENE_STATS if (opts->auto_quant) { - fprintf(stdout, "Analysing Scene for Automatic Quantization\n"); + fprintf(stderr, "Analysing Scene for Automatic Quantization\n"); statsman = gf_sm_stats_new(); e = gf_sm_stats_for_scene(statsman, ctx); if (!e) { @@ -1620,24 +1811,24 @@ GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *log /*LASeR*/ if (opts->auto_quant==1) { if (opts->resolution > (s32)stats->frac_res_2d) { - fprintf(stdout, " Given resolution %d is (unnecessarily) too high, using %d instead.\n", opts->resolution, stats->frac_res_2d); + fprintf(stderr, " Given resolution %d is (unnecessarily) too high, using %d instead.\n", opts->resolution, stats->frac_res_2d); opts->resolution = stats->frac_res_2d; } else if (stats->int_res_2d + opts->resolution <= 0) { - fprintf(stdout, " Given resolution %d is too low, using %d instead.\n", opts->resolution, stats->int_res_2d - 1); + fprintf(stderr, " Given resolution %d is too low, using %d instead.\n", opts->resolution, stats->int_res_2d - 1); opts->resolution = 1 - stats->int_res_2d; } opts->coord_bits = stats->int_res_2d + opts->resolution; - fprintf(stdout, " Coordinates & Lengths encoded using "); - if (opts->resolution < 0) fprintf(stdout, "only the %d most significant bits (of %d).\n", opts->coord_bits, stats->int_res_2d); - else fprintf(stdout, "a %d.%d representation\n", stats->int_res_2d, opts->resolution); + fprintf(stderr, " Coordinates & Lengths encoded using "); + if (opts->resolution < 0) fprintf(stderr, "only the %d most significant bits (of %d).\n", opts->coord_bits, stats->int_res_2d); + else fprintf(stderr, "a %d.%d representation\n", stats->int_res_2d, opts->resolution); - fprintf(stdout, " Matrix Scale & Skew Coefficients "); + fprintf(stderr, " Matrix Scale & Skew Coefficients "); if (opts->coord_bits - 8 < stats->scale_int_res_2d) { opts->scale_bits = stats->scale_int_res_2d - opts->coord_bits + 8; - fprintf(stdout, "encoded using a %d.8 representation\n", stats->scale_int_res_2d); + fprintf(stderr, "encoded using a %d.8 representation\n", stats->scale_int_res_2d); } else { opts->scale_bits = 0; - fprintf(stdout, "encoded using a %d.8 representation\n", opts->coord_bits - 8); + fprintf(stderr, "encoded using a %d.8 representation\n", opts->coord_bits - 8); } } #ifndef GPAC_DISABLE_VRML @@ -1684,7 +1875,7 @@ GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *log #endif /*GPAC_DISABLE_SCENE_STATS*/ if (e<0) { - fprintf(stdout, "Error loading file %s\n", gf_error_to_string(e)); + fprintf(stderr, "Error loading file %s\n", gf_error_to_string(e)); goto err_exit; } else { gf_log_cbk prev_logs = NULL; @@ -1709,6 +1900,8 @@ err_exit: gf_sm_del(ctx); gf_sg_del(sg); return e; + +#endif /*GPAC_DISABLE_SMGR*/ } #endif /*GPAC_DISABLE_SCENE_ENCODER*/ @@ -1725,6 +1918,7 @@ static u32 GetNbBits(u32 MaxVal) return k; } +#ifndef GPAC_DISABLE_SMGR GF_Err EncodeBIFSChunk(GF_SceneManager *ctx, char *bifsOutputFile, GF_Err (*AUCallback)(GF_ISOSample *)) { GF_Err e; @@ -1815,15 +2009,15 @@ GF_Err EncodeBIFSChunk(GF_SceneManager *ctx, char *bifsOutputFile, GF_Err (*AUCa /*NO CHANGE TO BIFSC otherwise the generated update will not match the input context*/ nbb = GetNbBits(ctx->max_node_id); if (!bcfg->nodeIDbits) bcfg->nodeIDbits=nbb; - if (bcfg->nodeIDbitsnodeIDbitsmax_route_id); if (!bcfg->routeIDbits) bcfg->routeIDbits = nbb; - if (bcfg->routeIDbitsrouteIDbitsmax_proto_id); if (!bcfg->protoIDbits) bcfg->protoIDbits=nbb; - if (bcfg->protoIDbitsprotoIDbitscarousel_size = size; rtpch->carousel_ts = ts; rtpch->time_at_carousel_store = gf_sys_clock(); - fprintf(stdout, "\nStream %d: Storing new carousel TS "LLD", %d bytes\n", ESID, ts, size); + fprintf(stderr, "\nStream %d: Storing new carousel TS "LLD", %d bytes\n", ESID, ts, size); } /*send data*/ else { @@ -257,7 +258,7 @@ static void live_session_callback(void *calling_object, u16 ESID, char *data, u3 gf_rtp_streamer_send_au_with_sn(rtpch->rtp, data, size, ts, ts, rap, critical); - fprintf(stdout, "Stream %d: Sending update at TS "LLD", %d bytes - RAP %d - critical %d\n", ESID, ts, size, rap, critical); + fprintf(stderr, "Stream %d: Sending update at TS "LLD", %d bytes - RAP %d - critical %d\n", ESID, ts, size, rap, critical); rtpch->rap = rtpch->critical = 0; if (rtpch->manual_rtcp) gf_rtp_streamer_send_rtcp(rtpch->rtp, 0, 0); @@ -277,7 +278,7 @@ static void live_session_send_carousel(LiveSession *livesess, RTPChannel *ch) gf_rtp_streamer_send_au_with_sn(ch->rtp, ch->carousel_data, ch->carousel_size, ts, ts, 1, 0); ch->last_carousel_time = now - livesess->start_time; - fprintf(stdout, "Stream %d: Sending carousel at TS "LLD", %d bytes\n", ch->ESID, ts, ch->carousel_size); + fprintf(stderr, "Stream %d: Sending carousel at TS "LLD", %d bytes\n", ch->ESID, ts, ch->carousel_size); if (ch->manual_rtcp) { ts = ch->carousel_ts + ch->timescale * ( gf_sys_clock() - ch->init_time + ch->ts_delta)/1000; @@ -295,7 +296,7 @@ static void live_session_send_carousel(LiveSession *livesess, RTPChannel *ch) } gf_rtp_streamer_send_au_with_sn(ch->rtp, ch->carousel_data, ch->carousel_size, ts, ts, 1, 0); ch->last_carousel_time = now - livesess->start_time; - fprintf(stdout, "Stream %d: Sending carousel at TS "LLD" , %d bytes\n", ch->ESID, ts, ch->carousel_size); + fprintf(stderr, "Stream %d: Sending carousel at TS "LLD" , %d bytes\n", ch->ESID, ts, ch->carousel_size); if (ch->manual_rtcp) { ts = ch->carousel_ts + ch->timescale*(gf_sys_clock()-ch->init_time + ch->ts_delta)/1000; @@ -480,7 +481,7 @@ int live_session(int argc, char **argv) else if (!strnicmp(arg, "-tcp=", 5)) { sk_port = atoi(arg+5); udp = 0; } } if (!filename) { - fprintf(stdout, "Missing filename\n"); + fprintf(stderr, "Missing filename\n"); PrintLiveUsage(); return 1; } @@ -489,7 +490,7 @@ int live_session(int argc, char **argv) livesess.seng = gf_seng_init(&livesess, filename, load_type, NULL, (load_type == GF_SM_LOAD_DIMS) ? 1 : 0); if (!livesess.seng) { - fprintf(stdout, "Cannot create scene engine\n"); + fprintf(stderr, "Cannot create scene engine\n"); return 1; } if (livesess.streams) live_session_setup(&livesess, dst, dst_port, path_mtu, ttl, ifce_addr, sdp_name); @@ -520,7 +521,7 @@ int live_session(int argc, char **argv) sscanf(arg, "-rap=ESID=%u:%u", &id, &period); e = gf_seng_enable_aggregation(livesess.seng, id, 1); if (e) { - fprintf(stdout, "Cannot enable aggregation on stream %u: %s\n", id, gf_error_to_string(e)); + fprintf(stderr, "Cannot enable aggregation on stream %u: %s\n", id, gf_error_to_string(e)); goto exit; } } else { @@ -572,7 +573,7 @@ int live_session(int argc, char **argv) { GF_Err e; char szCom[8192]; - fprintf(stdout, "Enter command to send:\n"); + fprintf(stderr, "Enter command to send:\n"); szCom[0] = 0; if (1 > scanf("%[^\t\n]", szCom)){ fprintf(stderr, "No command entered properly, aborting.\n"); @@ -581,7 +582,7 @@ int live_session(int argc, char **argv) /*stdin flush bug*/ while (getchar()!='\n') {} e = gf_seng_encode_from_string(livesess.seng, 0, 0, szCom, live_session_callback); - if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Processing command failed: %s\n", gf_error_to_string(e)); e = gf_seng_aggregate_context(livesess.seng, 0); livesess.critical = 0; update_context = 1; @@ -593,7 +594,7 @@ int live_session(int argc, char **argv) { GF_Err e; char szCom[8192]; - fprintf(stdout, "Enter command to send:\n"); + fprintf(stderr, "Enter command to send:\n"); szCom[0] = 0; if (1 > scanf("%[^\t\n]", szCom)){ printf("No command entered properly, aborting.\n"); @@ -602,7 +603,7 @@ int live_session(int argc, char **argv) /*stdin flush bug*/ while (getchar()!='\n') {} e = gf_seng_encode_from_string(livesess.seng, 0, 1, szCom, live_session_callback); - if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Processing command failed: %s\n", gf_error_to_string(e)); livesess.critical = 0; e = gf_seng_aggregate_context(livesess.seng, 0); @@ -612,13 +613,13 @@ int live_session(int argc, char **argv) case 'p': { char rad[GF_MAX_PATH]; - fprintf(stdout, "Enter output file name - \"std\" for stdout: "); + fprintf(stderr, "Enter output file name - \"std\" for stderr: "); if (1 > scanf("%s", rad)){ fprintf(stderr, "No ouput file name entered, aborting.\n"); break; } e = gf_seng_save_context(livesess.seng, !strcmp(rad, "std") ? NULL : rad); - fprintf(stdout, "Dump done (%s)\n", gf_error_to_string(e)); + fprintf(stderr, "Dump done (%s)\n", gf_error_to_string(e)); } break; case 'F': @@ -637,7 +638,7 @@ int live_session(int argc, char **argv) if (mod_time != last_src_modif) { FILE *srcf; char flag_buf[201], *flag; - fprintf(stdout, "Update file modified - processing\n"); + fprintf(stderr, "Update file modified - processing\n"); last_src_modif = mod_time; srcf = gf_f64_open(src_name, "rt"); @@ -689,7 +690,7 @@ int live_session(int argc, char **argv) } e = gf_seng_encode_from_file(livesess.seng, es_id, aggregate_au ? 0 : 1, src_name, live_session_callback); - if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Processing command failed: %s\n", gf_error_to_string(e)); e = gf_seng_aggregate_context(livesess.seng, 0); update_context = no_rap ? 0 : 1; @@ -766,7 +767,7 @@ int live_session(int argc, char **argv) if (update_length) { e = gf_seng_encode_from_string(livesess.seng, es_id, aggregate_au ? 0 : 1, update_buffer, live_session_callback); - if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Processing command failed: %s\n", gf_error_to_string(e)); e = gf_seng_aggregate_context(livesess.seng, 0); update_context = 1; diff --git a/applications/mp4box/main.c b/applications/mp4box/main.c index 54e0e0e..2051753 100644 --- a/applications/mp4box/main.c +++ b/applications/mp4box/main.c @@ -1,12 +1,13 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / mp4box application * - * GPAC is gf_free software; you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. @@ -24,6 +25,7 @@ #include +#include #ifndef GPAC_DISABLE_SMGR #include @@ -35,6 +37,11 @@ #else +#if defined(WIN32) && !defined(_WIN32_WCE) +#include +#include +#endif + #include /*RTP packetizer flags*/ @@ -63,8 +70,8 @@ void convert_file_info(char *inName, u32 trackID); #ifndef GPAC_DISABLE_ISOM_WRITE GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample); -GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start, Bool adjust_split_end, char *outName, const char *tmpdir); -GF_Err cat_isomedia_file(GF_ISOFile *mp4, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat); +GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double interleaving_time, Double chunk_start, Bool adjust_split_end, char *outName, const char *tmpdir); +GF_Err cat_isomedia_file(GF_ISOFile *mp4, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat, Bool align_timelines); #if !defined(GPAC_DISABLE_SCENE_ENCODER) GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *logs); @@ -101,7 +108,8 @@ void dump_file_rtp(GF_ISOFile *file, char *inName); void DumpSDP(GF_ISOFile *file, char *inName); #endif -void dump_file_ts(GF_ISOFile *file, char *inName); +void dump_file_timestamps(GF_ISOFile *file, char *inName); +void dump_file_nal(GF_ISOFile *file, u32 trackID, char *inName); #ifndef GPAC_DISABLE_ISOM_DUMP void dump_file_ismacryp(GF_ISOFile *file, char *inName); @@ -115,9 +123,7 @@ void PrintLanguages(); const char *GetLanguageCode(char *lang); #ifndef GPAC_DISABLE_MPEG2TS -void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num, - Double dash_duration, Bool seg_at_rap, u32 subseg_per_seg, - char *seg_name, char *seg_ext, Bool use_url_template, Bool single_segment, u32 representation_idx, Bool last_rep); +void dump_mpeg2_ts(char *mpeg2ts_file, char *pes_out_name, Bool prog_num); #endif @@ -169,15 +175,15 @@ u32 nb_itunes_tags = sizeof(itags) / sizeof(itunes_tag); void PrintVersion() { - fprintf(stdout, "MP4Box - GPAC version " GPAC_FULL_VERSION "\n" - "GPAC Copyright: (c) Jean Le Feuvre 2000-2005\n\t\t(c) ENST 2005-200X\n" + fprintf(stderr, "MP4Box - GPAC version " GPAC_FULL_VERSION "\n" + "GPAC Copyright (c) Telecom ParisTech 2000-2012\n" "GPAC Configuration: " GPAC_CONFIGURATION "\n" "Features: %s\n", gpac_features()); } void PrintGeneralUsage() { - fprintf(stdout, "General Options:\n" + fprintf(stderr, "General Options:\n" #ifdef GPAC_MEMORY_TRACKING " -mem-track: enables memory tracker\n" #endif @@ -197,6 +203,7 @@ void PrintGeneralUsage() " * Note: By default input (MP4,3GP) file is overwritten\n" " -tmp dirname specifies directory for temporary file creation\n" " * Note: Default temp dir is OS-dependent\n" + " -write-buffer SIZE specifies write buffer in bytes for ISOBMF files\n" " -no-sys removes all MPEG-4 Systems info except IOD (profiles)\n" " * Note: Set by default whith '-add' and '-cat'\n" " -no-iod removes InitialObjectDescriptor from file\n" @@ -252,33 +259,67 @@ void PrintGeneralUsage() " -group-clean removes all group information from all tracks\n" " -group-single puts all tracks in a single group\n" " -ref id:XXXX:refID adds a reference of type 4CC from track ID to track refID\n" - "\n" - " -dash dur enables DASH-ing of the file with a segment duration of DUR\n" + "\n"); +} + +void PrintDASHUsage() +{ + fprintf(stderr, "DASH Options:\n" + " -dash dur enables DASH-ing of the file(s) with a segment duration of DUR ms\n" " Note: the duration of a fragment (subsegment) is set\n" - " using the interleaver (-inter) switch.\n" - " Note: You can specify -rap switch to split segments at RAP boundaries\n" - " Note: when single-segment is used, this specifies the duration of a subsegment\n" - " -subsegs-per-sidx N sets the number of subsegments to be written in each SIDX box\n" - " If 0, a single SIDX box is used per segment\n" - " If -1, no SIDX box is used\n" + " using the -frag switch.\n" + " 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" + " -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" " -rap segments begin with random access points\n" " Note: segment duration may not be exactly what asked by\n" - " \"-dash\" since raw video data is not modified\n" + " \"-dash\" since encoded video data is not modified\n" + " -frag-rap All fragments begin with random access points\n" + " Note: fragment duration may not be exactly what is asked by\n" + " \"-frag\" since encoded video data is not modified\n" " -segment-name name sets the segment name for generated segments\n" " If not set (default), segments are concatenated in output file\n" - " -segment-ext name sets the segment extension. Default is m4s\n" + " except in \"live\" profile where dash_%%s is used\n" + " -segment-ext name sets the segment extension. Default is m4s, \"null\" means no extension\n" + " -base-url string sets Base url at MPD level. Can be used several times.\n" + " -mpd-title string sets MPD title.\n" + " -mpd-source string sets MPD source.\n" + " -mpd-info-url string sets MPD info url.\n" + " -cprt string adds copyright string to MPD\n" + " -dash-live[=F] dur generates a live DASH session using dur segment duration, optionnally writing live context to F\n" + " MP4Box will run the live session until \'q\' is pressed or a fatal error occurs.\n" + " -dash-ctx FILE stores/restore DASH timing from FILE.\n" + " -dynamic uses dynamic MPD type instead of static.\n" + " -mpd-refresh TIME specifies MPD update time in seconds.\n" + " -time-shift TIME specifies MPD time shift buffer depth in seconds (default 0). Specify -1 to keep all files\n" + " -subdur DUR specifies maximum duration in ms of the input file to be dashed in LIVE or context mode.\n" + " NOTE: This does not change the segment duration: dashing stops once segments produced exceeded the duration.\n" + "\n" + "Advanced Options, should not be needed when using -dash-profile:\n" + " -subsegs-per-sidx N sets the number of subsegments to be written in each SIDX box\n" + " If 0, a single SIDX box is used per segment\n" + " If -1, no SIDX box is used\n" " -url-template uses SegmentTemplate instead of explicit sources in segments.\n" " Ignored if segments are stored in the output file.\n" - " -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" - " -dash-ctx FILE Stores/restore DASH timing from FILE.\n" + " -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" " -dash-ts-prog N program_number to be considered in case of an MPTS input file.\n" "\n"); } void PrintFormats() { - fprintf(stdout, "Suppported raw formats and file extensions:\n" + fprintf(stderr, "Suppported raw formats and file extensions:\n" " NHNT .media .nhnt .info\n" " NHML .nhml (opt: .media .info)\n" " MPEG-1-2 Video .m1v .m2v\n" @@ -313,14 +354,14 @@ void PrintFormats() " VRML .wrl .wrl.gz\n" " X3D-XML .x3d .x3d.gz\n" " X3D-VRML .x3dv .x3dv.gz\n" - " MacroMedia Flash .swf (very limitted import support only)\n" + " MacroMedia Flash .swf (very limited import support only)\n" "\n" ); } void PrintImportUsage() { - fprintf(stdout, "Importing Options\n" + fprintf(stderr, "Importing Options\n" "\nFile importing syntax:\n" " \"#video\" \"#audio\" base import for most AV files\n" " \"#trackID=ID\" track import for IsoMedia and other files\n" @@ -357,16 +398,27 @@ void PrintImportUsage() " \":stype=4CC\" forces the sample description type to a different value\n" " !! THIS MAY BREAK THE FILE WRITING !!\n" " \":chap\" specifies the track is a chapter track\n" + " \":chapter=NAME\" adds a single chapter (old nero format) with given name lasting the entire file\n" + " This command can be used in -cat as well\n" + " \":chapfile=file\" adds a chapter file (old nero format)\n" + " This command can be used in -cat as well\n" " \":layout=WxHxXxY\" specifies the track layout\n" " - if W (resp H) = 0, the max width (resp height) of\n" " the tracks in the file are used.\n" " - if Y=-1, the layout is moved to the bottom of the\n" " track area\n" " - X and Y can be omitted (:layout=WxH)\n" + " \":rescale=TS\" forces media timescale to TS !! changes the media duration\n" + " \":timescale=TS\" sets import timescale to TS\n" "\n" + " \":negctts\" uses negative CTS-DTS offsets (ISO4 brand)\n" " -add file add file tracks to (new) output file\n" " -cat file concatenates file samples to (new) output file\n" " * Note: creates tracks if needed\n" + " * Note: aligns initial timestamp of the file to be concatenated." + " * Note: new tracks can be imported before concatenation by specifying '+ADD_COMMAND'\n" + " where ADD_COMMAND is a regular -add syntax\n" + " -unalign-cat does not attempt to align timestamps of samples inbetween tracks\n" " -force-cat skips media configuration check when concatenating file\n" " !!! THIS MAY BREAK THE CONCATENATED TRACK(S) !!!\n" " -keep-sys keeps all MPEG-4 Systems info when using '-add' / 'cat'\n" @@ -399,7 +451,7 @@ void PrintImportUsage() void PrintEncodeUsage() { - fprintf(stdout, "MPEG-4 Scene Encoding Options\n" + fprintf(stderr, "MPEG-4 Scene Encoding Options\n" " -mp4 specify input file is for encoding.\n" " -def encode DEF names\n" " -sync time_in_ms forces BIFS sync sample generation every time_in_ms\n" @@ -427,7 +479,7 @@ void PrintEncodeUsage() void PrintEncryptUsage() { - fprintf(stdout, "ISMA Encryption/Decryption Options\n" + fprintf(stderr, "ISMA Encryption/Decryption Options\n" " -crypt drm_file crypts a specific track using ISMA AES CTR 128\n" " -decrypt [drm_file] decrypts a specific track using ISMA AES CTR 128\n" " * Note: drm_file can be omitted if keys are in file\n" @@ -464,7 +516,7 @@ void PrintEncryptUsage() void PrintHintUsage() { - fprintf(stdout, "Hinting Options\n" + fprintf(stderr, "Hinting Options\n" " -hint hints the file for RTP/RTSP\n" " -mtu size specifies RTP MTU (max size) in bytes. Default size is 1450\n" " * Note: this includes the RTP header (12 bytes)\n" @@ -496,7 +548,7 @@ void PrintHintUsage() } void PrintExtractUsage() { - fprintf(stdout, "Extracting Options\n" + fprintf(stderr, "Extracting Options\n" " -raw TrackID extracts track in raw format when supported\n" " -raws TrackID extract each track sample to a file\n" " * Note: \"TrackID:N\" extracts Nth sample\n" @@ -516,8 +568,9 @@ void PrintExtractUsage() } void PrintDumpUsage() { - fprintf(stdout, "Dumping Options\n" - " -std dumps to stdout instead of file\n" + fprintf(stderr, "Dumping Options\n" + " -stdb dumps/write to stdout and assumes stdout is opened in binary mode\n" + " -std dumps/write to stdout and try to reopen stdout in binary mode.\n" " -info [trackID] prints movie info / track info if trackID specified\n" " * Note: for non IsoMedia files, gets import options\n" " -bt scene to bt format - removes unknown MPEG4 nodes\n" @@ -529,6 +582,7 @@ void PrintDumpUsage() " -diso scene IsoMedia file boxes in XML output\n" " -drtp rtp hint samples structure to XML output\n" " -dts prints sample timing to text output\n" + " -dnal trackID prints NAL sample info of given track\n" " -sdp dumps SDP description of hinted file\n" " -dcr ISMACryp samples structure to XML output\n" " -dump-cover Extracts cover art\n" @@ -553,7 +607,7 @@ void PrintDumpUsage() void PrintMetaUsage() { - fprintf(stdout, "Meta handling Options\n" + fprintf(stderr, "Meta handling Options\n" " -set-meta args sets given meta type - syntax: \"ABCD[:tk=ID]\"\n" " * ABCD: four char meta type (NULL or 0 to remove meta)\n" " * [:tk=ID]: if not set use root (file) meta\n" @@ -582,7 +636,7 @@ void PrintMetaUsage() void PrintSWFUsage() { - fprintf(stdout, + fprintf(stderr, "SWF Importer Options\n" "\n" "MP4Box can import simple Macromedia Flash files (\".SWF\")\n" @@ -606,9 +660,10 @@ void PrintSWFUsage() void PrintUsage() { - fprintf (stdout, "MP4Box [option] input [option]\n" + fprintf (stderr, "MP4Box [option] input [option]\n" " -h general general options help\n" " -h hint hinting options help\n" + " -h dash DASH segmenter help\n" " -h import import options help\n" " -h encode encode options help\n" " -h meta meta handling options help\n" @@ -619,6 +674,7 @@ void PrintUsage() " -h format supported formats help\n" " -h rtp file streamer help\n" " -h live BIFS streamer help\n" + " -h all all options are printed\n" "\n" " -nodes lists supported MPEG4 nodes\n" " -node NodeName gets MPEG4 node syntax and QP info\n" @@ -633,6 +689,8 @@ void PrintUsage() " -v verbose mode\n" " -logs set log tools and levels, formatted as a ':'-separated list of toolX[:toolZ]@levelX\n" " -version gets build version\n" + " -- INPUT escape option if INPUT starts with - character\n" + "\n" ); } @@ -725,7 +783,7 @@ GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 /*skip emty tracks (mainly MPEG-4 interaction streams...*/ if (!gf_isom_get_sample_count(file, i+1)) continue; if (!gf_isom_is_track_enabled(file, i+1)) { - fprintf(stdout, "Track ID %d disabled - skipping hint\n", gf_isom_get_track_id(file, i+1) ); + fprintf(stderr, "Track ID %d disabled - skipping hint\n", gf_isom_get_track_id(file, i+1) ); continue; } @@ -793,7 +851,7 @@ GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 if (!hinter) { if (e) { - fprintf(stdout, "Cannot create hinter (%s)\n", gf_error_to_string(e)); + fprintf(stderr, "Cannot create hinter (%s)\n", gf_error_to_string(e)); if (!nb_done) return e; } continue; @@ -802,11 +860,11 @@ GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 tot_bw += bw; flags = gf_hinter_track_get_flags(hinter); gf_hinter_track_get_payload_name(hinter, szPayload); - fprintf(stdout, "Hinting track ID %d - Type \"%s:%s\" (%s) - BW %d kbps\n", gf_isom_get_track_id(file, i+1), gf_4cc_to_str(mtype), gf_4cc_to_str(mtype), szPayload, bw); - if (flags & GP_RTP_PCK_SYSTEMS_CAROUSEL) fprintf(stdout, "\tMPEG-4 Systems stream carousel enabled\n"); + fprintf(stderr, "Hinting track ID %d - Type \"%s:%s\" (%s) - BW %d kbps\n", gf_isom_get_track_id(file, i+1), gf_4cc_to_str(mtype), gf_4cc_to_str(mtype), szPayload, bw); + if (flags & GP_RTP_PCK_SYSTEMS_CAROUSEL) fprintf(stderr, "\tMPEG-4 Systems stream carousel enabled\n"); /* - if (flags & GP_RTP_PCK_FORCE_MPEG4) fprintf(stdout, "\tMPEG4 transport forced\n"); - if (flags & GP_RTP_PCK_USE_MULTI) fprintf(stdout, "\tRTP aggregation enabled\n"); + if (flags & GP_RTP_PCK_FORCE_MPEG4) fprintf(stderr, "\tMPEG4 transport forced\n"); + if (flags & GP_RTP_PCK_USE_MULTI) fprintf(stderr, "\tRTP aggregation enabled\n"); */ e = gf_hinter_track_process(hinter); @@ -814,7 +872,7 @@ GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 gf_hinter_track_del(hinter); if (e) { - fprintf(stdout, "Error while hinting (%s)\n", gf_error_to_string(e)); + fprintf(stderr, "Error while hinting (%s)\n", gf_error_to_string(e)); if (!nb_done) return e; } init_payt++; @@ -830,7 +888,7 @@ GF_Err HintFile(GF_ISOFile *file, u32 MTUSize, u32 max_ptime, u32 rtp_rate, u32 gf_hinter_finalize(file, iod_mode, tot_bw); if (!single_ocr) - fprintf(stdout, "Warning: at least 2 timelines found in the file\nThis may not be supported by servers/players\n\n"); + fprintf(stderr, "Warning: at least 2 timelines found in the file\nThis may not be supported by servers/players\n\n"); return GF_OK; } @@ -1144,7 +1202,7 @@ static Bool parse_tsel_args(TSELAction **__tsel_list, char *opts, u32 *nb_tsel_a } } else if (!strnicmp(szSlot, "trackID=", 8) || !strchr(szSlot, '=') ) { - __tsel_list = realloc(__tsel_list, sizeof(TSELAction) * (*nb_tsel_act + 1)); + __tsel_list = gf_realloc(__tsel_list, sizeof(TSELAction) * (*nb_tsel_act + 1)); tsel_list = *__tsel_list; tsel_act = &tsel_list[*nb_tsel_act]; @@ -1168,7 +1226,7 @@ static Bool parse_tsel_args(TSELAction **__tsel_list, char *opts, u32 *nb_tsel_a } -#define CHECK_NEXT_ARG if (i+1==(u32)argc) { fprintf(stdout, "Missing arg - please check usage\n"); MP4BOX_EXIT_WITH_CODE(1); } +#define CHECK_NEXT_ARG if (i+1==(u32)argc) { fprintf(stderr, "Missing arg - please check usage\n"); MP4BOX_EXIT_WITH_CODE(1); } typedef struct { @@ -1203,15 +1261,50 @@ enum }; #define MP4BOX_EXIT_WITH_CODE(__ret_code) \ - if (sdp_lines) free(sdp_lines); \ - if (metas) free(metas); \ - if (tracks) free(tracks); \ - if (tsel_acts) free(tsel_acts); \ - if (brand_add) free(brand_add); \ - if (brand_rem) free(brand_rem); \ - if (dash_inputs) free(dash_inputs); \ + if (mpd_base_urls) gf_free(mpd_base_urls); \ + if (sdp_lines) gf_free(sdp_lines); \ + if (metas) gf_free(metas); \ + if (tracks) gf_free(tracks); \ + if (tsel_acts) gf_free(tsel_acts); \ + if (brand_add) gf_free(brand_add); \ + if (brand_rem) gf_free(brand_rem); \ + if (dash_inputs) gf_free(dash_inputs); \ return __ret_code; \ + +GF_DashSegmenterInput *set_dash_input(GF_DashSegmenterInput *dash_inputs, char *name, u32 *nb_dash_inputs) +{ + GF_DashSegmenterInput *di; + char *sep = strchr(name, ':'); + if (sep && (sep[1]=='\\')) sep = strchr(sep+1, ':'); + + dash_inputs = gf_realloc(dash_inputs, sizeof(GF_DashSegmenterInput) * (*nb_dash_inputs + 1) ); + memset(&dash_inputs[*nb_dash_inputs], 0, sizeof(GF_DashSegmenterInput) ); + di = &dash_inputs[*nb_dash_inputs]; + (*nb_dash_inputs)++; + + if (sep) { + char *opts = sep+1; + sep[0] = 0; + while (opts) { + sep = strchr(opts, ':'); + if (sep) sep[0] = 0; + 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); + + if (!sep) break; + sep[0] = ':'; + opts = sep+1; + } + } + di->file_name = name; + if (!strlen(di->representationID)) sprintf(di->representationID, "%d", *nb_dash_inputs); + + return dash_inputs; +} + + int mp4boxMain(int argc, char **argv) { char outfile[5000]; @@ -1220,7 +1313,7 @@ int mp4boxMain(int argc, char **argv) GF_SMEncodeOptions opts; #endif SDPLine *sdp_lines = NULL; - Double InterleavingTime, split_duration, split_start, import_fps, dash_duration; + Double interleaving_time, split_duration, split_start, import_fps, dash_duration, dash_subduration; MetaAction *metas = NULL; TrackAction *tracks = NULL; TSELAction *tsel_acts = NULL; @@ -1228,11 +1321,17 @@ 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; + 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; 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_ts, do_saf, do_mpd, dump_m2ts, dump_cart, do_hash, verbose, force_cat, pack_wgt, single_group; - 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; + 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; + 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; + u32 nb_mpd_base_urls=0; +#ifndef GPAC_DISABLE_MPD + Bool do_mpd = 0; +#endif #ifndef GPAC_DISABLE_SCENE_ENCODER Bool chunk_mode=0; #endif @@ -1241,19 +1340,26 @@ int mp4boxMain(int argc, char **argv) u32 MTUSize = 1450; #endif GF_ISOFile *file; + u32 mpd_update_time = 0; Bool stream_rtp=0; Bool live_scene=0; Bool enable_mem_tracker = 0; Bool dump_iod=0; Bool daisy_chain_sidx=0; Bool single_segment=0; + Bool single_file=0; + GF_DashProfile dash_profile = GF_DASH_PROFILE_UNKNOWN; Bool use_url_template=0; - Bool seg_at_rap =0; + Bool seg_at_rap=0; + Bool frag_at_rap=0; Bool adjust_split_end = 0; - char **dash_inputs = NULL; + GF_DashSegmenterInput *dash_inputs = NULL; u32 nb_dash_inputs = 0; char *gf_logs = NULL; char *seg_ext = NULL; + const char *dash_title = NULL; + const char *dash_source = NULL; + const char *dash_more_info = NULL; if (argc < 2) { PrintUsage(); @@ -1264,21 +1370,26 @@ int mp4boxMain(int argc, char **argv) e = GF_OK; split_duration = 0.0; split_start = -1.0; - InterleavingTime = 0.5; - dash_duration = 0.0; + interleaving_time = 0.0; + dash_duration = dash_subduration = 0.0; import_fps = 0; import_flags = 0; split_size = 0; movie_time = 0; - FullInter = HintInter = encode = do_log = old_interleave = do_saf = do_mpd = do_hash = verbose = 0; + 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_ts = dump_m2ts = dump_cart = import_subtitle = force_cat = pack_wgt = 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; + /*align cat is the new default behaviour for -cat*/ + align_cat = 1; subsegs_per_sidx = 0; track_dump_type = 0; ismaCrypt = 0; + time_shift_depth = 0; file = NULL; itunes_tags = pes_dump = NULL; - seg_name = dash_ctx = NULL; + seg_name = dash_ctx_file = NULL; #ifndef GPAC_DISABLE_SCENE_ENCODER memset(&opts, 0, sizeof(opts)); @@ -1295,33 +1406,33 @@ int mp4boxMain(int argc, char **argv) #endif swf_flatten_angle = 0.0f; tmpdir = NULL; - + /*parse our args*/ for (i = 1; i < (u32) argc ; i++) { arg = argv[i]; - /*main file*/ -// if (isalnum(arg[0]) || (arg[0]=='/') || (arg[0]=='.') || (arg[0]=='\\') ) { - if (arg[0] != '-') { + /*input file(s)*/ + if ((arg[0] != '-') || !stricmp(arg, "--")) { + char *arg_val = arg; + if (!stricmp(arg, "--")) { + CHECK_NEXT_ARG + arg_val = argv[i+1]; + i++; + } if (argc < 3) { - fprintf(stdout, "Error - only one input file found as argument, please check usage\n"); + fprintf(stderr, "Error - only one input file found as argument, please check usage\n"); MP4BOX_EXIT_WITH_CODE(1); } else if (inName) { if (dash_duration) { if (!nb_dash_inputs) { - dash_inputs = realloc(dash_inputs, sizeof(char *) * (nb_dash_inputs+1) ); - dash_inputs[nb_dash_inputs] = inName; - nb_dash_inputs++; + dash_inputs = set_dash_input(dash_inputs, inName, &nb_dash_inputs); } - dash_inputs = realloc(dash_inputs, sizeof(char *) * (nb_dash_inputs+1) ); - - dash_inputs[nb_dash_inputs] = arg; - nb_dash_inputs++; + dash_inputs = set_dash_input(dash_inputs, arg_val, &nb_dash_inputs); } else { - fprintf(stdout, "Error - 2 input names specified, please check usage\n"); + fprintf(stderr, "Error - 2 input names specified, please check usage\n"); MP4BOX_EXIT_WITH_CODE(1); } } else { - inName = arg; + inName = arg_val; } } else if (!stricmp(arg, "-?")) { PrintUsage(); MP4BOX_EXIT_WITH_CODE(0); } @@ -1370,7 +1481,7 @@ int mp4boxMain(int argc, char **argv) if (strlen(argv[i+1])==5) trackID = 2; else trackID = 1 + atoi(argv[i+1] + 5); } - else { fprintf(stdout, "Usage: \"-aviraw video\" or \"-aviraw audio\"\n"); MP4BOX_EXIT_WITH_CODE(1); } + else { fprintf(stderr, "Usage: \"-aviraw video\" or \"-aviraw audio\"\n"); MP4BOX_EXIT_WITH_CODE(1); } track_dump_type = GF_EXPORT_AVI_NATIVE; i++; } @@ -1428,8 +1539,9 @@ int mp4boxMain(int argc, char **argv) #ifndef GPAC_DISABLE_SVG else if (!stricmp(arg, "-snode")) { CHECK_NEXT_ARG PrintNode(argv[i+1], 2); MP4BOX_EXIT_WITH_CODE(0); } else if (!stricmp(arg, "-snodes")) { PrintBuiltInNodes(2); MP4BOX_EXIT_WITH_CODE(0); } - else if (!stricmp(arg, "-std")) dump_std = 1; #endif + else if (!stricmp(arg, "-std")) dump_std = 2; + else if (!stricmp(arg, "-stdb")) dump_std = 1; #if !defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_SCENE_DUMP) else if (!stricmp(arg, "-bt")) dump_mode = 1 + GF_SM_DUMP_BT; @@ -1451,16 +1563,21 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-dmp4")) { dump_isom = 1; - fprintf(stdout, "WARNING: \"-dmp4\" is deprecated - use \"-diso\" option\n"); + fprintf(stderr, "WARNING: \"-dmp4\" is deprecated - use \"-diso\" option\n"); } else if (!stricmp(arg, "-drtp")) dump_rtp = 1; else if (!stricmp(arg, "-dts")) { - dump_ts = 1; + dump_timestamps = 1; if ( ((i+1<(u32) argc) && inName) || (i+2<(u32) argc) ) { if (argv[i+1][0] != '-') program_number = atoi(argv[i+1]); i++; } - } else if (!stricmp(arg, "-dcr")) dump_cr = 1; + } else if (!stricmp(arg, "-dnal")) { + CHECK_NEXT_ARG + dump_nal = atoi(argv[i+1]); + i++; + } + else if (!stricmp(arg, "-dcr")) dump_cr = 1; else if (!stricmp(arg, "-ttxt") || !stricmp(arg, "-srt")) { if ((i+1<(u32) argc) && (sscanf(argv[i+1], "%u", &trackID)==1)) { char szTk[20]; @@ -1471,7 +1588,7 @@ int mp4boxMain(int argc, char **argv) trackID = 0; } #ifdef GPAC_DISABLE_ISOM_WRITE - if (trackID) { fprintf(stdout, "Error: Read-Only version - subtitle conversion not available\n"); MP4BOX_EXIT_WITH_CODE(1); } + if (trackID) { fprintf(stderr, "Error: Read-Only version - subtitle conversion not available\n"); MP4BOX_EXIT_WITH_CODE(1); } #endif if (!stricmp(arg, "-ttxt")) dump_ttxt = 1; else dump_srt = 1; @@ -1514,33 +1631,41 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-tmp")) { CHECK_NEXT_ARG tmpdir = argv[i+1]; i++; } - else if (!stricmp(arg, "-cprt")) { CHECK_NEXT_ARG cprt = argv[i+1]; i++; open_edit = 1; } + else if (!stricmp(arg, "-write-buffer")) { + CHECK_NEXT_ARG + gf_isom_set_output_buffering(NULL, atoi(argv[i+1])); + i++; + } + else if (!stricmp(arg, "-cprt")) { CHECK_NEXT_ARG cprt = argv[i+1]; i++; if (!dash_duration) open_edit = 1; } else if (!stricmp(arg, "-chap")) { CHECK_NEXT_ARG chap_file = argv[i+1]; i++; open_edit = 1; } else if (!strcmp(arg, "-mem-track")) { #ifdef GPAC_MEMORY_TRACKING enable_mem_tracker = 1; #else - fprintf(stdout, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); + fprintf(stderr, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); #endif } else if (!strcmp(arg, "-strict-error")) { gf_log_set_strict_error(1); } else if (!stricmp(arg, "-inter") || !stricmp(arg, "-old-inter")) { CHECK_NEXT_ARG - InterleavingTime = atof(argv[i+1]) / 1000; + interleaving_time = atof(argv[i+1]) / 1000; open_edit = 1; needSave = 1; if (!stricmp(arg, "-old-inter")) old_interleave = 1; i++; } else if (!stricmp(arg, "-frag")) { CHECK_NEXT_ARG - InterleavingTime = atof(argv[i+1]) / 1000; + interleaving_time = atof(argv[i+1]) / 1000; needSave = 1; i++; Frag = 1; } else if (!stricmp(arg, "-dash")) { CHECK_NEXT_ARG dash_duration = atof(argv[i+1]) / 1000; - needSave = 1; + i++; + } else if (!stricmp(arg, "-subdur")) { + CHECK_NEXT_ARG + dash_subduration = atof(argv[i+1]) / 1000; i++; } else if (!stricmp(arg, "-dash-ts-prog")) { CHECK_NEXT_ARG @@ -1558,14 +1683,59 @@ int mp4boxMain(int argc, char **argv) CHECK_NEXT_ARG seg_ext = argv[i+1]; i++; - } else if (!stricmp(arg, "-dash-ctx")) { + } 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; + i++; + } + else if (!stricmp(arg, "-dynamic")) { dash_dynamic = 1; } + else if (!strnicmp(arg, "-dash-live", 10)) { + dash_dynamic = 1; + dash_live = 1; + if (arg[10]=='=') { + dash_ctx_file = arg+11; + } + CHECK_NEXT_ARG + dash_duration = atof(argv[i+1]) / 1000; + i++; + } + else if (!stricmp(arg, "-mpd-refresh")) { CHECK_NEXT_ARG mpd_update_time = atoi(argv[i+1]); i++; } + else if (!stricmp(arg, "-time-shift")) { + CHECK_NEXT_ARG + time_shift_depth = (u32) atoi(argv[i+1]); + i++; + } + else if (!stricmp(arg, "-mpd-title")) { CHECK_NEXT_ARG dash_title = argv[i+1]; i++; } + else if (!stricmp(arg, "-mpd-source")) { CHECK_NEXT_ARG dash_source = argv[i+1]; i++; } + else if (!stricmp(arg, "-mpd-info-url")) { CHECK_NEXT_ARG dash_more_info = argv[i+1]; i++; } + else if (!stricmp(arg, "-base-url")) { + CHECK_NEXT_ARG + dash_more_info = argv[i+1]; + mpd_base_urls = gf_realloc(mpd_base_urls, (nb_mpd_base_urls+1)*sizeof(char**)); + mpd_base_urls[nb_mpd_base_urls] = argv[i+1]; + nb_mpd_base_urls++; + i++; + } + + else if (!stricmp(arg, "-dash-ctx")) { CHECK_NEXT_ARG - dash_ctx = argv[i+1]; + dash_ctx_file = argv[i+1]; i++; } else if (!stricmp(arg, "-daisy-chain")) { daisy_chain_sidx = 1; } else if (!stricmp(arg, "-single-segment")) { single_segment = 1; + } else if (!stricmp(arg, "-single-file")) { + single_file = 1; + } else if (!stricmp(arg, "-dash-profile") || !stricmp(arg, "-profile")) { + CHECK_NEXT_ARG + if (!stricmp(argv[i+1], "live") || !stricmp(argv[i+1], "simple")) dash_profile = GF_DASH_PROFILE_LIVE; + else if (!stricmp(argv[i+1], "onDemand")) dash_profile = GF_DASH_PROFILE_ONDEMAND; + else if (!stricmp(argv[i+1], "main")) dash_profile = GF_DASH_PROFILE_MAIN; + else dash_profile = GF_DASH_PROFILE_FULL; + i++; } else if (!strnicmp(arg, "-url-template", 13)) { use_url_template = 1; if ((arg[13]=='=') && arg[14]) { @@ -1587,6 +1757,9 @@ int mp4boxMain(int argc, char **argv) hint_flags |= GP_RTP_PCK_SIGNAL_RAP; seg_at_rap=1; } + else if (!stricmp(arg, "-frag-rap")) { + frag_at_rap=1; + } else if (!stricmp(arg, "-ts")) hint_flags |= GP_RTP_PCK_SIGNAL_TS; else if (!stricmp(arg, "-size")) hint_flags |= GP_RTP_PCK_SIGNAL_SIZE; else if (!stricmp(arg, "-idx")) hint_flags |= GP_RTP_PCK_SIGNAL_AU_IDX; @@ -1617,7 +1790,7 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-add-sdp") || !stricmp(arg, "-sdp_ex")) { char *id; CHECK_NEXT_ARG - sdp_lines = realloc(sdp_lines, sizeof(SDPLine) * (nb_sdp_ex+1) ); + sdp_lines = gf_realloc(sdp_lines, sizeof(SDPLine) * (nb_sdp_ex+1) ); id = strchr(argv[i+1], ':'); if (id) { @@ -1654,8 +1827,8 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-new")) force_new = 1; else if (!stricmp(arg, "-add") || !stricmp(arg, "-import") || !stricmp(arg, "-convert")) { CHECK_NEXT_ARG - if (!stricmp(arg, "-import")) fprintf(stdout, "\tWARNING: \"-import\" is deprecated - use \"-add\"\n"); - else if (!stricmp(arg, "-convert")) fprintf(stdout, "\tWARNING: \"-convert\" is deprecated - use \"-add\"\n"); + if (!stricmp(arg, "-import")) fprintf(stderr, "\tWARNING: \"-import\" is deprecated - use \"-add\"\n"); + else if (!stricmp(arg, "-convert")) fprintf(stderr, "\tWARNING: \"-convert\" is deprecated - use \"-add\"\n"); nb_add++; i++; } @@ -1678,6 +1851,8 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-force-cat")) force_cat = 1; + else if (!stricmp(arg, "-align-cat")) align_cat = 1; + else if (!stricmp(arg, "-unalign-cat")) align_cat = 0; else if (!stricmp(arg, "-raw-cat")) { CHECK_NEXT_ARG raw_cat = argv[i+1]; @@ -1685,7 +1860,7 @@ int mp4boxMain(int argc, char **argv) } else if (!stricmp(arg, "-rem") || !stricmp(arg, "-disable") || !stricmp(arg, "-enable")) { CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); if (!stricmp(arg, "-enable")) tracks[nb_track_act].act_type = 6; else if (!stricmp(arg, "-disable")) tracks[nb_track_act].act_type = 7; @@ -1698,13 +1873,13 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-par")) { char szTK[20], *ext; CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); tracks[nb_track_act].act_type = 4; strcpy(szTK, argv[i+1]); ext = strchr(szTK, '='); if (!ext) { - fprintf(stdout, "Bad format for track par - expecting ID=PAR_NUM:PAR_DEN got %s\n", argv[i+1]); + fprintf(stderr, "Bad format for track par - expecting ID=PAR_NUM:PAR_DEN got %s\n", argv[i+1]); MP4BOX_EXIT_WITH_CODE(1); } if (!stricmp(ext+1, "none")) { @@ -1721,7 +1896,7 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-lang")) { char szTK[20], *ext; CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); tracks[nb_track_act].act_type = 1; tracks[nb_track_act].lang[3] = 0; @@ -1745,12 +1920,12 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-delay")) { char szTK[20], *ext; CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); strcpy(szTK, argv[i+1]); ext = strchr(szTK, '='); if (!ext) { - fprintf(stdout, "Bad format for track delay - expecting ID=DLAY got %s\n", argv[i+1]); + fprintf(stderr, "Bad format for track delay - expecting ID=DLAY got %s\n", argv[i+1]); MP4BOX_EXIT_WITH_CODE(1); } tracks[nb_track_act].act_type = 2; @@ -1764,19 +1939,19 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-ref")) { char *szTK, *ext; CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); szTK = argv[i+1]; ext = strchr(szTK, ':'); if (!ext) { - fprintf(stdout, "Bad format for track reference - expecting ID:XXXX:refID got %s\n", argv[i+1]); + fprintf(stderr, "Bad format for track reference - expecting ID:XXXX:refID got %s\n", argv[i+1]); MP4BOX_EXIT_WITH_CODE(1); } tracks[nb_track_act].act_type = 8; ext[0] = 0; tracks[nb_track_act].trackID = atoi(szTK); ext[0] = ':'; szTK = ext+1; ext = strchr(szTK, ':'); if (!ext) { - fprintf(stdout, "Bad format for track reference - expecting ID:XXXX:refID got %s\n", argv[i+1]); + fprintf(stderr, "Bad format for track reference - expecting ID:XXXX:refID got %s\n", argv[i+1]); MP4BOX_EXIT_WITH_CODE(1); } ext[0] = 0; @@ -1790,12 +1965,12 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-name")) { char szTK[GF_MAX_PATH], *ext; CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); strcpy(szTK, argv[i+1]); ext = strchr(szTK, '='); if (!ext) { - fprintf(stdout, "Bad format for track name - expecting ID=name got %s\n", argv[i+1]); + fprintf(stderr, "Bad format for track name - expecting ID=name got %s\n", argv[i+1]); MP4BOX_EXIT_WITH_CODE(1); } tracks[nb_track_act].act_type = 5; @@ -1836,12 +2011,14 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-mp4")) { encode = 1; open_edit = 1; } else if (!stricmp(arg, "-saf")) { do_saf = 1; } else if (!stricmp(arg, "-log")) { do_log = 1; } +#ifndef GPAC_DISABLE_MPD else if (!stricmp(arg, "-mpd")) { do_mpd = 1; CHECK_NEXT_ARG outName = argv[i+1]; i++; } +#endif #ifndef GPAC_DISABLE_SCENE_ENCODER else if (!stricmp(arg, "-def")) opts.flags |= GF_SM_ENCODE_USE_NAMES; @@ -1920,7 +2097,7 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-set-kms")) { char szTK[20], *ext; CHECK_NEXT_ARG - tracks = realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); + tracks = gf_realloc(tracks, sizeof(TrackAction) * (nb_track_act+1)); strncpy(szTK, argv[i+1], 19); ext = strchr(szTK, '='); @@ -1962,18 +2139,23 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-split-chunk") || !stricmp(arg, "-splitx") || !stricmp(arg, "-splitz")) { CHECK_NEXT_ARG if (!strstr(argv[i+1], ":")) { - fprintf(stdout, "Chunk extraction usage: \"-splitx start:end\" expressed in seconds\n"); + fprintf(stderr, "Chunk extraction usage: \"-splitx start:end\" expressed in seconds\n"); MP4BOX_EXIT_WITH_CODE(1); } - sscanf(argv[i+1], "%lf:%lf", &split_start, &split_duration); - split_duration -= split_start; + if (strstr(argv[i+1], "end")) { + sscanf(argv[i+1], "%lf:end", &split_start); + split_duration = -2; + } else { + sscanf(argv[i+1], "%lf:%lf", &split_start, &split_duration); + split_duration -= split_start; + } split_size = 0; if (!stricmp(arg, "-splitz")) adjust_split_end = 1; i++; } /*meta*/ else if (!stricmp(arg, "-set-meta")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 0; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -1982,7 +2164,7 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-add-item")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 1; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -1991,7 +2173,7 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-rem-item")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 2; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -2000,7 +2182,7 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-set-primary")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 3; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -2009,7 +2191,7 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-set-xml")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 4; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -2018,7 +2200,7 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-rem-xml")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 6; if (parse_meta_args(&metas[nb_meta_act], argv[i+1])) i++; @@ -2026,7 +2208,7 @@ int mp4boxMain(int argc, char **argv) open_edit = 1; } else if (!stricmp(arg, "-dump-xml")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 7; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -2034,7 +2216,7 @@ int mp4boxMain(int argc, char **argv) i++; } else if (!stricmp(arg, "-dump-item")) { - metas = realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); + metas = gf_realloc(metas, sizeof(MetaAction) * (nb_meta_act+1)); metas[nb_meta_act].act_type = 8; parse_meta_args(&metas[nb_meta_act], argv[i+1]); @@ -2044,7 +2226,7 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-group-add") || !stricmp(arg, "-group-rem-track") || !stricmp(arg, "-group-rem")) { tsel_acts[nb_tsel_acts].act_type = !stricmp(arg, "-group-rem") ? 2 : ( !stricmp(arg, "-group-rem-track") ? 1 : 0 ); if (parse_tsel_args(&tsel_acts, argv[i+1], &nb_tsel_acts)==0) { - fprintf(stdout, "Invalid group syntax - check usage\n"); + fprintf(stderr, "Invalid group syntax - check usage\n"); MP4BOX_EXIT_WITH_CODE(1); } open_edit=1; @@ -2081,7 +2263,7 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-ab")) { char *b = argv[i+1]; CHECK_NEXT_ARG - brand_add = realloc(brand_add, sizeof(u32) * (nb_alt_brand_add+1)); + brand_add = gf_realloc(brand_add, sizeof(u32) * (nb_alt_brand_add+1)); brand_add[nb_alt_brand_add] = GF_4CC(b[0], b[1], b[2], b[3]); nb_alt_brand_add++; @@ -2091,7 +2273,7 @@ int mp4boxMain(int argc, char **argv) else if (!stricmp(arg, "-rb")) { char *b = argv[i+1]; CHECK_NEXT_ARG - brand_rem = realloc(brand_rem, sizeof(u32) * (nb_alt_brand_rem+1)); + brand_rem = gf_realloc(brand_rem, sizeof(u32) * (nb_alt_brand_rem+1)); brand_rem[nb_alt_brand_rem] = GF_4CC(b[0], b[1], b[2], b[3]); nb_alt_brand_rem++; @@ -2107,6 +2289,7 @@ int mp4boxMain(int argc, char **argv) if (i+1== (u32) argc) PrintUsage(); else if (!strcmp(argv[i+1], "general")) PrintGeneralUsage(); else if (!strcmp(argv[i+1], "extract")) PrintExtractUsage(); + else if (!strcmp(argv[i+1], "dash")) PrintDASHUsage(); else if (!strcmp(argv[i+1], "dump")) PrintDumpUsage(); else if (!strcmp(argv[i+1], "import")) PrintImportUsage(); else if (!strcmp(argv[i+1], "format")) PrintFormats(); @@ -2122,6 +2305,7 @@ int mp4boxMain(int argc, char **argv) else if (!strcmp(argv[i+1], "all")) { PrintGeneralUsage(); PrintExtractUsage(); + PrintDASHUsage(); PrintDumpUsage(); PrintImportUsage(); PrintFormats(); @@ -2140,20 +2324,52 @@ int mp4boxMain(int argc, char **argv) } else if (!stricmp(arg, "-v")) verbose++; else if (!stricmp(arg, "-tag-list")) { - fprintf(stdout, "Supported iTunes tag modifiers:\n"); + fprintf(stderr, "Supported iTunes tag modifiers:\n"); for (i=0; i= to_copy) break; } fclose(fin); @@ -2216,13 +2432,14 @@ int mp4boxMain(int argc, char **argv) } } +#ifndef GPAC_DISABLE_MPD if (do_mpd) { Bool remote = 0; char *mpd_base_url = gf_strdup(inName); if (!strnicmp(inName, "http://", 7)) { - e = gf_dm_wget(inName, "tmp_main.m3u8"); + e = gf_dm_wget(inName, "tmp_main.m3u8", 0, 0); if (e != GF_OK) { - fprintf(stdout, "Cannot retrieve M3U8 (%s): %s\n", inName, gf_error_to_string(e)); + fprintf(stderr, "Cannot retrieve M3U8 (%s): %s\n", inName, gf_error_to_string(e)); gf_free(mpd_base_url); MP4BOX_EXIT_WITH_CODE(1); } @@ -2235,18 +2452,16 @@ int mp4boxMain(int argc, char **argv) //gf_delete_file("tmp_main.m3u8"); } if (e != GF_OK) { - fprintf(stdout, "Error converting M3U8 (%s) to MPD (%s): %s\n", inName, outName, gf_error_to_string(e)); + fprintf(stderr, "Error converting M3U8 (%s) to MPD (%s): %s\n", inName, outName, gf_error_to_string(e)); MP4BOX_EXIT_WITH_CODE(1); } else { - fprintf(stdout, "Done converting M3U8 (%s) to MPD (%s)\n", inName, outName); + fprintf(stderr, "Done converting M3U8 (%s) to MPD (%s)\n", inName, outName); MP4BOX_EXIT_WITH_CODE(0); } } - +#endif if (dash_duration && !nb_dash_inputs) { - dash_inputs = realloc(dash_inputs, sizeof(char *) * (nb_dash_inputs+1) ); - dash_inputs[nb_dash_inputs] = inName; - nb_dash_inputs++; + dash_inputs = set_dash_input(dash_inputs, inName, &nb_dash_inputs); } @@ -2274,7 +2489,7 @@ int mp4boxMain(int argc, char **argv) import.in_name = inName; e = gf_media_import(&import); if (e) { - fprintf(stdout, "Error importing %s: %s\n", inName, gf_error_to_string(e)); + fprintf(stderr, "Error importing %s: %s\n", inName, gf_error_to_string(e)); gf_isom_delete(file); gf_delete_file("ttxt_convert"); MP4BOX_EXIT_WITH_CODE(1); @@ -2290,12 +2505,12 @@ int mp4boxMain(int argc, char **argv) gf_isom_delete(file); gf_delete_file("ttxt_convert"); if (e) { - fprintf(stdout, "Error converting %s: %s\n", inName, gf_error_to_string(e)); + fprintf(stderr, "Error converting %s: %s\n", inName, gf_error_to_string(e)); MP4BOX_EXIT_WITH_CODE(1); } MP4BOX_EXIT_WITH_CODE(0); #else - fprintf(stdout, "Feature not supported\n"); + fprintf(stderr, "Feature not supported\n"); MP4BOX_EXIT_WITH_CODE(1); #endif } @@ -2322,14 +2537,14 @@ int mp4boxMain(int argc, char **argv) open_edit = 1; file = gf_isom_open(inName, open_mode, tmpdir); if (!file) { - fprintf(stdout, "Cannot open destination file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)) ); + fprintf(stderr, "Cannot open destination file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)) ); MP4BOX_EXIT_WITH_CODE(1); } 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); if (e) { - fprintf(stdout, "Error importing %s: %s\n", argv[i+1], gf_error_to_string(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); } @@ -2361,15 +2576,15 @@ int mp4boxMain(int argc, char **argv) open_edit = 1; file = gf_isom_open(inName, open_mode, tmpdir); if (!file) { - fprintf(stdout, "Cannot open destination file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)) ); + fprintf(stderr, "Cannot open destination file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL)) ); MP4BOX_EXIT_WITH_CODE(1); } } for (i=0; i<(u32)argc; i++) { if (!strcmp(argv[i], "-cat")) { - e = cat_isomedia_file(file, argv[i+1], import_flags, import_fps, agg_samples, tmpdir, force_cat); + e = cat_isomedia_file(file, argv[i+1], import_flags, import_fps, agg_samples, tmpdir, force_cat, align_cat); if (e) { - fprintf(stdout, "Error appending %s: %s\n", argv[i+1], gf_error_to_string(e)); + fprintf(stderr, "Error appending %s: %s\n", argv[i+1], gf_error_to_string(e)); gf_isom_delete(file); MP4BOX_EXIT_WITH_CODE(1); } @@ -2387,11 +2602,11 @@ int mp4boxMain(int argc, char **argv) #if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_MEDIA_IMPORT) else if (chunk_mode) { if (!inName) { - fprintf(stdout, "chunk encoding syntax: [-outctx outDump] -inctx inScene auFile\n"); + fprintf(stderr, "chunk encoding syntax: [-outctx outDump] -inctx inScene auFile\n"); MP4BOX_EXIT_WITH_CODE(1); } e = EncodeFileChunk(inName, outName ? outName : inName, input_ctx, output_ctx, tmpdir); - if (e) fprintf(stdout, "Error encoding chunk file %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Error encoding chunk file %s\n", gf_error_to_string(e)); MP4BOX_EXIT_WITH_CODE( e ? 1 : 0 ); } #endif @@ -2443,6 +2658,67 @@ int mp4boxMain(int argc, char **argv) } #endif + + if (dash_duration) { + char szMPD[GF_MAX_PATH], *sep; + GF_Config *dash_ctx = NULL; + gf_log_set_tool_level(GF_LOG_DASH, GF_LOG_INFO); + strcpy(outfile, outName ? outName : gf_url_get_resource_name(inName) ); + sep = strrchr(outfile, '.'); + if (sep) sep[0] = 0; + if (!outName) strcat(outfile, "_dash"); + strcpy(szMPD, outfile); + strcat(szMPD, ".mpd"); + + if (!dash_ctx_file && dash_live) { + dash_ctx = gf_cfg_new(NULL, NULL); + } else if (dash_ctx_file) { + if (force_new) + gf_delete_file(dash_ctx_file); + + dash_ctx = gf_cfg_force_new(NULL, dash_ctx_file); + } + + if (dash_profile==GF_DASH_PROFILE_UNKNOWN) + dash_profile = dash_dynamic ? GF_DASH_PROFILE_LIVE : GF_DASH_PROFILE_FULL; + + if (!dash_dynamic) { + time_shift_depth = 0; + mpd_update_time = 0; + } else if ((dash_profile>=GF_DASH_PROFILE_MAIN) && !use_url_template && !mpd_update_time) { + /*use a default MPD update of dash_duration sec*/ + mpd_update_time = (u32) (dash_subduration ? dash_subduration : dash_duration); + fprintf(stderr, "Using default MPD refresh of %d seconds\n", mpd_update_time); + } + + while (1) { + e = gf_dasher_segment_files(szMPD, dash_inputs, nb_dash_inputs, dash_profile, dash_title, dash_source, cprt, dash_more_info, + (const char **) mpd_base_urls, nb_mpd_base_urls, + use_url_template, single_segment, single_file, bitstream_switching_mode, + seg_at_rap, dash_duration, seg_name, seg_ext, + interleaving_time, subsegs_per_sidx, daisy_chain_sidx, frag_at_rap, tmpdir, + dash_ctx, dash_dynamic, mpd_update_time, time_shift_depth, dash_subduration); + if (e) break; + + if (dash_live) { + u32 sleep_for = gf_dasher_next_update_time(dash_ctx, mpd_update_time); + if (gf_prompt_has_input()) { + char c = (char) gf_prompt_get_char(); + if (c=='q') break; + } + fprintf(stderr, "sleep for %d ms\n", sleep_for); + gf_sleep(sleep_for); + } else { + break; + } + } + + if (dash_ctx) gf_cfg_del(dash_ctx); + + gf_sys_close(); + MP4BOX_EXIT_WITH_CODE( (e!=GF_OK) ? 1 : 0 ); + } + else if (!file #ifndef GPAC_DISABLE_MEDIA_EXPORT && !(track_dump_type & GF_EXPORT_AVI_NATIVE) @@ -2456,11 +2732,11 @@ int mp4boxMain(int argc, char **argv) } switch (get_file_type_by_ext(inName)) { case 1: - file = gf_isom_open(inName, (u8) (open_edit ? GF_ISOM_OPEN_EDIT : ( (dump_isom>0) ? GF_ISOM_OPEN_READ_DUMP : GF_ISOM_OPEN_READ) ), tmpdir); + file = gf_isom_open(inName, (u8) (open_edit ? GF_ISOM_OPEN_EDIT : ( ((dump_isom>0) || print_info) ? GF_ISOM_OPEN_READ_DUMP : GF_ISOM_OPEN_READ) ), tmpdir); if (!file && (gf_isom_last_error(NULL) == GF_ISOM_INCOMPLETE_FILE) && !open_edit) { u64 missing_bytes; e = gf_isom_open_progressive(inName, 0, 0, &file, &missing_bytes); - fprintf(stdout, "Truncated file - missing "LLD" bytes\n", missing_bytes); + fprintf(stderr, "Truncated file - missing "LLD" bytes\n", missing_bytes); } if (!file) { @@ -2470,7 +2746,7 @@ int mp4boxMain(int argc, char **argv) } if (!file) { - fprintf(stdout, "Error opening file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL))); + fprintf(stderr, "Error opening file %s: %s\n", inName, gf_error_to_string(gf_isom_last_error(NULL))); MP4BOX_EXIT_WITH_CODE(1); } } @@ -2508,7 +2784,7 @@ int mp4boxMain(int argc, char **argv) import.flags = GF_IMPORT_MPE_DEMUX; e = gf_media_import(&import); if (e) { - fprintf(stdout, "Error importing %s: %s\n", inName, gf_error_to_string(e)); + fprintf(stderr, "Error importing %s: %s\n", inName, gf_error_to_string(e)); gf_isom_delete(file); gf_delete_file("ttxt_convert"); MP4BOX_EXIT_WITH_CODE(1); @@ -2516,21 +2792,13 @@ int mp4boxMain(int argc, char **argv) } #endif /*GPAC_DISABLE_MEDIA_IMPORT*/ - if (dash_duration) { - if (subsegs_per_sidx<0) subsegs_per_sidx = 0; + if (dump_m2ts) { #ifndef GPAC_DISABLE_MPEG2TS - for (i=0; i2) { + if (dump_std) { + mdump.out_name = "std"; + } else if (outName) { + mdump.out_name = outName; + } else if (trackID>2) { sprintf(szFile, "%s_audio%d", outfile, trackID-1); + mdump.out_name = szFile; } else { sprintf(szFile, "%s_%s", outfile, (trackID==1) ? "video" : "audio"); + mdump.out_name = szFile; } - mdump.out_name = szFile; + e = gf_media_export(&mdump); if (e) goto err_exit; MP4BOX_EXIT_WITH_CODE(0); @@ -2616,8 +2890,12 @@ int mp4boxMain(int argc, char **argv) if (!HintIt && print_sdp) DumpSDP(file, dump_std ? NULL : outfile); #endif if (print_info) { - if (info_track_id) DumpTrackInfo(file, info_track_id, 1); - else DumpMovieInfo(file); + if (!file) { + fprintf(stderr, "Cannot print info on a non ISOM file (%s)\n", inName); + } else { + if (info_track_id) DumpTrackInfo(file, info_track_id, 1); + else DumpMovieInfo(file); + } } #ifndef GPAC_DISABLE_ISOM_DUMP if (dump_isom) dump_isom_xml(file, dump_std ? NULL : outfile); @@ -2628,14 +2906,16 @@ int mp4boxMain(int argc, char **argv) #endif #endif - if (dump_ts) dump_file_ts(file, dump_std ? NULL : outfile); + if (dump_timestamps) dump_file_timestamps(file, dump_std ? NULL : outfile); + if (dump_nal) dump_file_nal(file, dump_nal, dump_std ? NULL : outfile); + if (do_hash) { u8 hash[20]; e = gf_media_get_file_hash(inName, hash); if (e) goto err_exit; - fprintf(stdout, "File %s hash (SHA-1): ", inName); - for (i=0; i<20; i++) fprintf(stdout, "%02X", hash[i]); - fprintf(stdout, "\n"); + fprintf(stderr, "File %s hash (SHA-1): ", inName); + for (i=0; i<20; i++) fprintf(stderr, "%02X", hash[i]); + fprintf(stderr, "\n"); } if (dump_cart) dump_cover_art(file, outfile); if (dump_chap) dump_chapters(file, outfile); @@ -2643,7 +2923,7 @@ int mp4boxMain(int argc, char **argv) if (dump_iod) { GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor *)gf_isom_get_root_od(file); if (!iod) { - fprintf(stdout, "File %s has no IOD", inName); + fprintf(stderr, "File %s has no IOD", inName); } else { char szName[GF_MAX_PATH]; FILE *iodf; @@ -2652,7 +2932,7 @@ int mp4boxMain(int argc, char **argv) sprintf(szName, "%s.iod", outfile); iodf = gf_f64_open(szName, "wb"); if (!iodf) { - fprintf(stdout, "Cannot open destination %s\n", szName); + fprintf(stderr, "Cannot open destination %s\n", szName); } else { char *desc; u32 size; @@ -2661,7 +2941,7 @@ int mp4boxMain(int argc, char **argv) gf_fwrite(desc, 1, size, iodf); gf_free(desc); } else { - fprintf(stdout, "Error writing IOD %s\n", szName); + fprintf(stderr, "Error writing IOD %s\n", szName); } fclose(iodf); } @@ -2671,7 +2951,7 @@ int mp4boxMain(int argc, char **argv) #if !(definedGPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_MEDIA_IMPORT) if (split_duration || split_size) { - split_isomedia_file(file, split_duration, split_size, inName, InterleavingTime, split_start, adjust_split_end, outName, tmpdir); + split_isomedia_file(file, split_duration, split_size, inName, interleaving_time, split_start, adjust_split_end, outName, tmpdir); /*never save file when splitting is desired*/ open_edit = 0; needSave = 0; @@ -2745,14 +3025,14 @@ int mp4boxMain(int argc, char **argv) e = gf_isom_remove_meta_xml(file, meta->root_meta, tk); needSave = 1; } else { - fprintf(stdout, "No meta box in input file\n"); + fprintf(stderr, "No meta box in input file\n"); } break; case 8: if (gf_isom_get_meta_item_count(file, meta->root_meta, tk)) { e = gf_isom_extract_meta_item(file, meta->root_meta, tk, meta->item_id, strlen(meta->szPath) ? meta->szPath : NULL); } else { - fprintf(stdout, "No meta box in input file\n"); + fprintf(stderr, "No meta box in input file\n"); } break; #endif @@ -2760,7 +3040,7 @@ int mp4boxMain(int argc, char **argv) if (gf_isom_has_meta_xml(file, meta->root_meta, tk)) { e = gf_isom_extract_meta_xml(file, meta->root_meta, tk, meta->szPath, NULL); } else { - fprintf(stdout, "No meta box in input file\n"); + fprintf(stderr, "No meta box in input file\n"); } break; } @@ -2818,7 +3098,7 @@ int mp4boxMain(int argc, char **argv) if (remove_hint) { for (i=0; itrackID, gf_error_to_string(e)); + fprintf(stderr, "Error Removing track ID %d: %s\n", tka->trackID, gf_error_to_string(e)); } else { - fprintf(stdout, "Removing track ID %d\n", tka->trackID); + fprintf(stderr, "Removing track ID %d\n", tka->trackID); } needSave = 1; break; @@ -2997,7 +3277,7 @@ int mp4boxMain(int argc, char **argv) gf_isom_append_edit_segment(file, track, tk_dur-to_skip, media_time, GF_ISOM_EDIT_NORMAL); needSave = 1; } else { - fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n"); + fprintf(stderr, "Warning: request negative delay longer than track duration - ignoring\n"); } } } else if (gf_isom_get_edit_segment_count(file, track)) { @@ -3068,7 +3348,7 @@ int mp4boxMain(int argc, char **argv) } } if (itag==nb_itunes_tags) { - fprintf(stdout, "Invalid iTune tag format \"%s\" - ignoring\n", tags); + fprintf(stderr, "Invalid iTune tag format \"%s\" - ignoring\n", tags); tags = NULL; continue; } @@ -3076,7 +3356,7 @@ int mp4boxMain(int argc, char **argv) val = strchr(tags, '='); if (!val) { - fprintf(stdout, "Invalid iTune tag format \"%s\" (expecting '=') - ignoring\n", tags); + fprintf(stderr, "Invalid iTune tag format \"%s\" (expecting '=') - ignoring\n", tags); tags = NULL; continue; } @@ -3163,205 +3443,27 @@ int mp4boxMain(int argc, char **argv) needSave = 1; } - /*split file*/ - if (dash_duration) { - char szMPD[GF_MAX_PATH]; - char szInit[GF_MAX_PATH]; - GF_ISOFile *init_seg; - Bool sps_merge_failed = 0; - Double period_duration = 0; - - if (single_segment) { - fprintf(stdout, "DASH-ing file%s with single segment\nSubsegment duration %.3f - Fragment duration: %.3f secs\n", (nb_dash_inputs>1) ? "s" : "", dash_duration, InterleavingTime); - subsegs_per_sidx = 0; - seg_name = seg_ext = NULL; - } else { - if (!seg_ext) seg_ext = "m4s"; - fprintf(stdout, "DASH-ing file with %.3f secs segments - fragments: %.3f secs\n", dash_duration, InterleavingTime); - if (subsegs_per_sidx<0) fprintf(stdout, "No sidx used"); - else if (subsegs_per_sidx) fprintf(stdout, "%d subsegments per sidx", subsegs_per_sidx); - else fprintf(stdout, "Single sidx used"); - } - fprintf(stdout, "\n"); - if (seg_at_rap) fprintf(stdout, "Spliting segments at GOP boundaries\n"); - - strcpy(outfile, outName ? outName : inName); - while (outfile[strlen(outfile)-1] != '.') outfile[strlen(outfile)-1] = 0; - outfile[strlen(outfile)-1] = 0; - if (!outName) strcat(outfile, "_dash"); - - strcpy(szInit, outfile); - strcat(szInit, "_init.mp4"); - strcpy(szMPD, outfile); - strcat(szMPD, ".mpd"); - - init_seg = gf_isom_open(szInit, GF_ISOM_OPEN_WRITE, tmpdir); - for (i=0; isequenceParameterSets); k++) { - GF_AVCConfigSlot *slc = gf_list_get(avccfg2->sequenceParameterSets, k); - gf_avc_get_sps_info(slc->data, slc->size, &sps_id1, NULL, NULL, NULL, NULL); - for (l=0; lsequenceParameterSets); l++) { - GF_AVCConfigSlot *slc_orig = gf_list_get(avccfg1->sequenceParameterSets, l); - gf_avc_get_sps_info(slc_orig->data, slc_orig->size, &sps_id2, NULL, NULL, NULL, NULL); - if (sps_id2==sps_id1) { - do_merge = 0; - break; - } - } - } -#endif - /*no conflicts in SPS ids, merge all SPS in a single sample desc*/ - if (do_merge) { - while (gf_list_count(avccfg1->sequenceParameterSets)) { - GF_AVCConfigSlot *slc = gf_list_get(avccfg1->sequenceParameterSets, 0); - gf_list_rem(avccfg1->sequenceParameterSets, 0); - gf_list_add(avccfg2->sequenceParameterSets, slc); - } - while (gf_list_count(avccfg1->pictureParameterSets)) { - GF_AVCConfigSlot *slc = gf_list_get(avccfg1->pictureParameterSets, 0); - gf_list_rem(avccfg1->pictureParameterSets, 0); - gf_list_add(avccfg2->pictureParameterSets, slc); - } - gf_isom_avc_config_update(init_seg, track, 1, avccfg2); - } else { - sps_merge_failed = 1; - } - gf_odf_avc_cfg_del(avccfg1); - gf_odf_avc_cfg_del(avccfg2); - } - - /*cannot merge, clone*/ - if (!do_merge) - gf_isom_clone_sample_description(init_seg, track, in, j+1, 1, NULL, NULL, &outDescIndex); - } - } else { - gf_isom_clone_track(in, j+1, init_seg, 0, &track); - } - dur = (Double) gf_isom_get_track_duration(in, j+1); - dur /= gf_isom_get_timescale(in); - if (dur>period_duration) period_duration = dur; - } - - if (i) gf_isom_close(in); - } - if (sps_merge_failed) { - fprintf(stdout, "Couldnt merge AVC|H264 SPS from different files (same SPS ID used) - different sample descriptions will be used\n"); - } - if (!seg_name) use_url_template = 0; - - gf_media_mpd_start(szMPD, (char *)gf_isom_get_filename(file), use_url_template, single_segment, dash_ctx, init_seg, period_duration); - - for (i=0; i1) { - char *sep = strrchr(dash_inputs[i], '/'); - if (!sep) sep = strrchr(dash_inputs[i], '\\'); - if (sep) strcpy(outfile, sep+1); - else strcpy(outfile, dash_inputs[i]); - sep = strrchr(outfile, '.'); - if (sep) sep[0] = 0; - - if (seg_name) { - if (strstr(seg_name, "%s")) sprintf(szSegName, seg_name, outfile); - else strcpy(szSegName, seg_name); - segment_name = szSegName; - } - strcat(outfile, "_dash"); - } - if (nb_dash_inputs>1) { - fprintf(stdout, "DASHing file %s\n", dash_inputs[i]); - } -#ifndef GPAC_DISABLE_ISOM_FRAGMENTS - e = gf_media_fragment_file(in, outfile, szMPD, InterleavingTime, seg_at_rap ? 2 : 1, dash_duration, segment_name, seg_ext, subsegs_per_sidx, daisy_chain_sidx, use_url_template, single_segment, dash_ctx, init_seg, i+1); -#else - fprintf(stderr, "GPAC was compiled without fragment support\n"); - e = GF_NOT_SUPPORTED; -#endif - if (e) { - fprintf(stdout, "Error while DASH-ing file: %s\n", gf_error_to_string(e)); - break; - } - if (i) gf_isom_close(in); - } - /*close MPD*/ - gf_media_mpd_end(szMPD); - - /*if init segment shared, write to file*/ - if (nb_dash_inputs>1) { - gf_isom_close(init_seg); - } else { - gf_isom_delete(init_seg); - gf_delete_file(szInit); - } - - gf_isom_delete(file); - gf_sys_close(); - MP4BOX_EXIT_WITH_CODE( (e!=GF_OK) ? 1 : 0 ); #ifndef GPAC_DISABLE_ISOM_FRAGMENTS - } else if (Frag) { - if (!InterleavingTime) InterleavingTime = 0.5; - if (HintIt) fprintf(stdout, "Warning: cannot hint and fragment - ignoring hint\n"); - fprintf(stdout, "Fragmenting file (%.3f seconds fragments)\n", InterleavingTime); - e = gf_media_fragment_file(file, outfile, NULL, InterleavingTime, 0, 0, NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0); - if (e) fprintf(stdout, "Error while fragmenting file: %s\n", gf_error_to_string(e)); + if (Frag) { + if (!interleaving_time) interleaving_time = 0.5; + if (HintIt) fprintf(stderr, "Warning: cannot hint and fragment - ignoring hint\n"); + fprintf(stderr, "Fragmenting file (%.3f seconds fragments)\n", interleaving_time); + e = gf_media_fragment_file(file, outfile, interleaving_time); + if (e) fprintf(stderr, "Error while fragmenting file: %s\n", gf_error_to_string(e)); gf_isom_delete(file); if (!e && !outName && !force_new) { - if (remove(inName)) fprintf(stdout, "Error removing file %s\n", inName); - else if (rename(outfile, inName)) fprintf(stdout, "Error renaming file %s to %s\n", outfile, inName); + if (gf_delete_file(inName)) fprintf(stderr, "Error removing file %s\n", inName); + else if (gf_move_file(outfile, inName)) fprintf(stderr, "Error renaming file %s to %s\n", outfile, inName); } gf_sys_close(); MP4BOX_EXIT_WITH_CODE( (e!=GF_OK) ? 1 : 0 ); -#endif } - +#endif + #ifndef GPAC_DISABLE_ISOM_HINTING if (HintIt) { if (force_ocr) SetupClockReferences(file); - fprintf(stdout, "Hinting file with Path-MTU %d Bytes\n", MTUSize); + fprintf(stderr, "Hinting file with Path-MTU %d Bytes\n", MTUSize); MTUSize -= 12; e = HintFile(file, MTUSize, max_ptime, rtp_rate, hint_flags, HintCopy, HintInter, regular_iod, single_group); if (e) goto err_exit; @@ -3373,14 +3475,14 @@ int mp4boxMain(int argc, char **argv) /*full interleave (sample-based) if just hinted*/ if (FullInter) { e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_TIGHT); - } else if (!InterleavingTime) { + } else if (!interleaving_time) { e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_STREAMABLE); needSave = 1; } else if (do_flat) { e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_FLAT); needSave = 1; } else { - e = gf_isom_make_interleave(file, InterleavingTime); + e = gf_isom_make_interleave(file, interleaving_time); if (!e && !old_interleave) e = gf_isom_set_storage_mode(file, GF_ISOM_STORE_DRIFT_INTERLEAVED); } if (e) goto err_exit; @@ -3426,7 +3528,7 @@ int mp4boxMain(int argc, char **argv) e = gf_media_import_chapters(file, chap_file, import_fps); needSave = 1; #else - fprintf(stdout, "Warning: GPAC compiled without Media Import, chapters can't be imported\n"); + fprintf(stderr, "Warning: GPAC compiled without Media Import, chapters can't be imported\n"); e = GF_NOT_SUPPORTED; #endif if (e) goto err_exit; @@ -3448,23 +3550,23 @@ int mp4boxMain(int argc, char **argv) if (!encode && !force_new) gf_isom_set_final_name(file, outfile); if (needSave) { if (outName) { - fprintf(stdout, "Saving to %s: ", outfile); + fprintf(stderr, "Saving to %s: ", outfile); gf_isom_set_final_name(file, outfile); } else if (encode || pack_file) { - fprintf(stdout, "Saving to %s: ", gf_isom_get_filename(file) ); + fprintf(stderr, "Saving to %s: ", gf_isom_get_filename(file) ); } else { - fprintf(stdout, "Saving %s: ", inName); + fprintf(stderr, "Saving %s: ", inName); } - if (HintIt && FullInter) fprintf(stdout, "Hinted file - Full Interleaving\n"); - else if (FullInter) fprintf(stdout, "Full Interleaving\n"); - else if (do_flat || !InterleavingTime) fprintf(stdout, "Flat storage\n"); - else fprintf(stdout, "%.3f secs Interleaving%s\n", InterleavingTime, old_interleave ? " - no drift control" : ""); + if (HintIt && FullInter) fprintf(stderr, "Hinted file - Full Interleaving\n"); + else if (FullInter) fprintf(stderr, "Full Interleaving\n"); + else if (do_flat || !interleaving_time) fprintf(stderr, "Flat storage\n"); + else fprintf(stderr, "%.3f secs Interleaving%s\n", interleaving_time, old_interleave ? " - no drift control" : ""); e = gf_isom_close(file); if (!e && !outName && !encode && !force_new && !pack_file) { - if (remove(inName)) fprintf(stdout, "Error removing file %s\n", inName); - else if (rename(outfile, inName)) fprintf(stdout, "Error renaming file %s to %s\n", outfile, inName); + if (gf_delete_file(inName)) fprintf(stderr, "Error removing file %s\n", inName); + else if (gf_move_file(outfile, inName)) fprintf(stderr, "Error renaming file %s to %s\n", outfile, inName); } } else { gf_isom_delete(file); @@ -3472,20 +3574,20 @@ int mp4boxMain(int argc, char **argv) /*close libgpac*/ gf_sys_close(); - if (e) fprintf(stdout, "Error: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Error: %s\n", gf_error_to_string(e)); MP4BOX_EXIT_WITH_CODE( (e!=GF_OK) ? 1 : 0 ); #else /*close libgpac*/ gf_sys_close(); gf_isom_delete(file); - fprintf(stdout, "Error: Read-only version of MP4Box.\n"); + fprintf(stderr, "Error: Read-only version of MP4Box.\n"); MP4BOX_EXIT_WITH_CODE(1); #endif err_exit: /*close libgpac*/ gf_sys_close(); if (file) gf_isom_delete(file); - fprintf(stdout, "\n\tError: %s\n", gf_error_to_string(e)); + fprintf(stderr, "\n\tError: %s\n", gf_error_to_string(e)); MP4BOX_EXIT_WITH_CODE(1); } diff --git a/applications/mp4client/Makefile b/applications/mp4client/Makefile index 0cdc8d9..00d37e4 100644 --- a/applications/mp4client/Makefile +++ b/applications/mp4client/Makefile @@ -38,9 +38,6 @@ all: $(PROG) MP4Client$(EXE): $(OBJS) $(CC) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/gcc -lgpac $(LINKLIBS) -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - clean: rm -f $(OBJS) ../../bin/gcc/$(PROG) diff --git a/applications/mp4client/extract.c b/applications/mp4client/extract.c index 9ff1009..9556a9d 100644 --- a/applications/mp4client/extract.c +++ b/applications/mp4client/extract.c @@ -1,13 +1,13 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / command-line client * - * GPAC is gf_free software; you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. @@ -65,7 +65,7 @@ typedef struct tagBITMAPINFOHEADER{ extern Bool is_connected; extern GF_Terminal *term; -extern u32 Duration; +extern u64 Duration; extern GF_Err last_error; static GFINLINE u8 colmask(s32 a, s32 n) @@ -215,6 +215,7 @@ void write_bmp(GF_VideoSurface *fb, char *rad_name, u32 img_num) void write_png(GF_VideoSurface *fb, char *rad_name, u32 img_num) { +#ifndef GPAC_DISABLE_AV_PARSERS char str[GF_MAX_PATH]; FILE *fout; u32 dst_size; @@ -246,6 +247,7 @@ void write_png(GF_VideoSurface *fb, char *rad_name, u32 img_num) } gf_free(dst); +#endif //GPAC_DISABLE_AV_PARSERS } @@ -340,8 +342,8 @@ void dump_depth (GF_Terminal *term, char *rad_name, u32 dump_type, u32 frameNum, /*lock it*/ e = gf_sc_get_screen_buffer(term->compositor, &fb, 1); - if (e) fprintf(stdout, "Error grabbing depth buffer: %s\n", gf_error_to_string(e)); - else fprintf(stdout, "OK\n"); + if (e) fprintf(stderr, "Error grabbing depth buffer: %s\n", gf_error_to_string(e)); + else fprintf(stderr, "OK\n"); /*export frame*/ switch (dump_type) { case 1: @@ -409,7 +411,7 @@ void dump_depth (GF_Terminal *term, char *rad_name, u32 dump_type, u32 frameNum, } #ifndef GPAC_DISABLE_AVILIB if (AVI_write_frame(avi_out, conv_buf, fb.height*fb.width*3, 1) <0) - printf("Error writing frame\n"); + fprintf(stderr, "Error writing frame\n"); #endif break; case 2: @@ -444,7 +446,7 @@ void dump_frame(GF_Terminal *term, char *rad_name, u32 dump_type, u32 frameNum, if (dump_type==5 || dump_type==6) e = gf_sc_get_screen_buffer(term->compositor, &fb, 2); else if (dump_type== 9 || dump_type==10) e = gf_sc_get_screen_buffer(term->compositor, &fb, 3); else e = gf_sc_get_screen_buffer(term->compositor, &fb, 0); - if (e) fprintf(stdout, "Error grabbing frame buffer: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Error grabbing frame buffer: %s\n", gf_error_to_string(e)); /*export frame*/ switch (dump_type) { @@ -549,10 +551,10 @@ void dump_frame(GF_Terminal *term, char *rad_name, u32 dump_type, u32 frameNum, #ifndef GPAC_DISABLE_AVILIB if (dump_type!=5 && dump_type!= 10) { if (AVI_write_frame(avi_out, conv_buf, out_size, 1) <0) - printf("Error writing frame\n"); + fprintf(stderr, "Error writing frame\n"); } else { if (AVI_write_frame(avi_out, conv_buf, out_size, 1) <0) - printf("Error writing frame\n"); + fprintf(stderr, "Error writing frame\n"); } #endif break; @@ -594,7 +596,7 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa prev = strrchr(szPath, '.'); if (prev) prev[0] = 0; - fprintf(stdout, "Opening URL %s\n", url); + fprintf(stderr, "Opening URL %s\n", url); /*connect in pause mode*/ gf_term_connect_from_time(term, url, 0, 1); @@ -612,14 +614,14 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa gf_term_process_flush(term); } #ifndef GPAC_USE_TINYGL - printf("not tinygl\n"); + fprintf(stderr, "not tinygl\n"); e = gf_sc_get_screen_buffer(term->compositor, &fb, 0); #else - printf("tinygl\n"); + fprintf(stderr, "tinygl\n"); e = gf_sc_get_screen_buffer(term->compositor, &fb, 1); #endif if (e != GF_OK) { - fprintf(stdout, "Error grabbing screen buffer: %s\n", gf_error_to_string(e)); + fprintf(stderr, "Error grabbing screen buffer: %s\n", gf_error_to_string(e)); return 0; } width = fb.width; @@ -635,7 +637,7 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa /*we work in RGB24, and we must make sure the pitch is %4*/ if ((width*3)%4) { - fprintf(stdout, "Adjusting width (%d) to have a stride multiple of 4\n", width); + fprintf(stderr, "Adjusting width (%d) to have a stride multiple of 4\n", width); while ((width*3)%4) width--; gf_term_set_size(term, width, height); @@ -649,10 +651,11 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa if (dump_mode==1 || dump_mode==5 || dump_mode==8 || dump_mode==10) { #ifdef GPAC_DISABLE_AVILIB - fprintf(stdout, "AVILib is disabled in this build of GPAC\n"); + fprintf(stderr, "AVILib is disabled in this build of GPAC\n"); return 0; #else - u32 time, prev_time, nb_frames, dump_dur; + u32 time, prev_time, nb_frames; + u64 dump_dur; char *conv_buf; avi_t *avi_out = NULL; avi_t *depth_avi_out = NULL; @@ -662,14 +665,14 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa strcat(szPath, ".avi"); avi_out = AVI_open_output_file(szPath); if (!avi_out) { - fprintf(stdout, "Error creating AVI file %s\n", szPath); + fprintf(stderr, "Error creating AVI file %s\n", szPath); return 1; } if (dump_mode==8) { strcat(szPath_depth, "_depth.avi"); depth_avi_out = AVI_open_output_file(szPath_depth); if (!depth_avi_out) { - fprintf(stdout, "Error creating AVI file %s\n", szPath); + fprintf(stderr, "Error creating AVI file %s\n", szPath); return 1; } } @@ -685,7 +688,7 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa dump_dur = times[0] ? times[0] : Duration; } if (!dump_dur) { - fprintf(stdout, "Warning: file has no duration, defaulting to 1 sec\n"); + fprintf(stderr, "Warning: file has no duration, defaulting to 1 sec\n"); dump_dur = 1000; } @@ -701,7 +704,7 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa while ((gf_term_get_option(term, GF_OPT_PLAY_STATE) == GF_STATE_STEP_PAUSE)) { gf_term_process_flush(term); } - fprintf(stdout, "Dumping %02d/100 %% - time %.02f sec\r", (u32) ((100.0*prev_time)/dump_dur), prev_time/1000.0 ); + fprintf(stderr, "Dumping %02d/100 %% - time %.02f sec\r", (u32) ((100.0*prev_time)/dump_dur), prev_time/1000.0 ); if (dump_mode==8) { /*we'll dump both buffers at once*/ @@ -719,14 +722,14 @@ Bool dump_file(char *url, u32 dump_mode, Double fps, u32 width, u32 height, Floa prev_time = time; if (gf_prompt_has_input() && (gf_prompt_get_char()=='q')) { - fprintf(stdout, "Aborting dump\n"); + fprintf(stderr, "Aborting dump\n"); break; } } AVI_close(avi_out); if (dump_mode==8) AVI_close(depth_avi_out); gf_free(conv_buf); - fprintf(stdout, "AVI Extraction 100/100\n"); + fprintf(stderr, "AVI Extraction 100/100\n"); #endif /*GPAC_DISABLE_AVILIB*/ } else { if (times[0]) gf_term_step_clocks(term, times[0]); diff --git a/applications/mp4client/main.c b/applications/mp4client/main.c index a2d0ec0..caa330b 100644 --- a/applications/mp4client/main.c +++ b/applications/mp4client/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / command-line client @@ -34,6 +35,9 @@ /*ISO 639 languages*/ #include +#include + + #ifndef WIN32 #include #include @@ -123,7 +127,7 @@ void hide_shell(u32 cmd_type) void PrintUsage() { - fprintf(stdout, "Usage MP4Client [options] [filename]\n" + fprintf(stderr, "Usage MP4Client [options] [filename]\n" "\t-c fileName: user-defined configuration file. Also works with -cfg\n" #ifdef GPAC_MEMORY_TRACKING "\t-mem-track: enables memory tracker\n" @@ -163,6 +167,9 @@ void PrintUsage() "\t \"audio\" : Audio renderer and mixers\n" #ifdef GPAC_MEMORY_TRACKING "\t \"mem\" : GPAC memory tracker\n" +#endif +#ifndef GPAC_DISABLE_DASH_CLIENT + "\t \"dash\" : HTTP streaming logs\n" #endif "\t \"module\" : GPAC modules debugging\n" "\t \"mutex\" : mutex\n" @@ -224,7 +231,7 @@ void PrintUsage() void PrintHelp() { - fprintf(stdout, "MP4Client command keys:\n" + fprintf(stderr, "MP4Client command keys:\n" "\tq: quit\n" "\tX: kill\n" "\to: connect to the specified URL\n" @@ -270,7 +277,7 @@ void PrintHelp() "\tE: forces reload of GPAC configuration\n" "\n" "\tR: toggles run-time info display in window title bar on/off\n" - "\tF: toggle displaying of FPS in stdout on/off\n" + "\tF: toggle displaying of FPS in stderr on/off\n" "\tg: print GPAC allocated memory\n" "\th: print this message\n" "\n" @@ -297,7 +304,7 @@ static void PrintTime(u64 time) m = (u32) (time / 1000 / 60 - h*60); s = (u32) (time / 1000 - h*3600 - m*60); ms = (u32) (time - (h*3600 + m*60 + s) * 1000); - fprintf(stdout, "%02d:%02d:%02d.%03d", h, m, s, ms); + fprintf(stderr, "%02d:%02d:%02d.%03d", h, m, s, ms); } @@ -325,7 +332,7 @@ static void UpdateRTInfo(const char *legend) } if (display_rti==2) { - fprintf(stdout, "%s\r", szMsg); + fprintf(stderr, "%s\r", szMsg); } else { GF_Event evt; evt.type = GF_EVENT_SET_CAPTION; @@ -436,7 +443,7 @@ int getch(){ static const char * read_line_input(char * line, int maxSize, Bool showContent){ char read; int i = 0; - if (fflush( stdout )) + if (fflush( stderr )) perror("Failed to flush buffer %s"); do { line[i] = '\0'; @@ -445,14 +452,14 @@ static const char * read_line_input(char * line, int maxSize, Bool showContent){ read = getch(); if (read == 8 || read == 127){ if (i > 0){ - fprintf(stdout, "\b \b"); + fprintf(stderr, "\b \b"); i--; } } else if (read > 32){ - fputc(showContent ? read : '*', stdout); + fputc(showContent ? read : '*', stderr); line[i++] = read; } - fflush(stdout); + fflush(stderr); } while (read != '\n'); if (!read) return 0; @@ -564,10 +571,10 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt) gf_term_set_option(term, GF_OPT_FULLSCREEN, !gf_term_get_option(term, GF_OPT_FULLSCREEN)); break; case GF_KEY_F: - if (evt->key.flags & GF_KEY_MOD_CTRL) fprintf(stdout, "Rendering rate: %f FPS\n", gf_term_get_framerate(term, 0)); + if (evt->key.flags & GF_KEY_MOD_CTRL) fprintf(stderr, "Rendering rate: %f FPS\n", gf_term_get_framerate(term, 0)); break; case GF_KEY_T: - if (evt->key.flags & GF_KEY_MOD_CTRL) fprintf(stdout, "Scene Time: %f \n", gf_term_get_time_in_ms(term)/1000.0); + if (evt->key.flags & GF_KEY_MOD_CTRL) fprintf(stderr, "Scene Time: %f \n", gf_term_get_time_in_ms(term)/1000.0); break; case GF_KEY_D: if (evt->key.flags & GF_KEY_MOD_CTRL) gf_term_set_option(term, GF_OPT_DRAW_MODE, (gf_term_get_option(term, GF_OPT_DRAW_MODE)==GF_DRAW_MODE_DEFER) ? GF_DRAW_MODE_IMMEDIATE : GF_DRAW_MODE_DEFER ); @@ -591,16 +598,16 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt) case GF_KEY_P: if (evt->key.flags & GF_KEY_MOD_CTRL && is_connected) { Bool is_pause = gf_term_get_option(term, GF_OPT_PLAY_STATE); - fprintf(stdout, "[Status: %s]\n", is_pause ? "Playing" : "Paused"); + fprintf(stderr, "[Status: %s]\n", is_pause ? "Playing" : "Paused"); gf_term_set_option(term, GF_OPT_PLAY_STATE, (gf_term_get_option(term, GF_OPT_PLAY_STATE)==GF_STATE_PAUSED) ? GF_STATE_PLAYING : GF_STATE_PAUSED); } break; case GF_KEY_S: if ((evt->key.flags & GF_KEY_MOD_CTRL) && is_connected) { gf_term_set_option(term, GF_OPT_PLAY_STATE, GF_STATE_STEP_PAUSE); - fprintf(stdout, "Step time: "); + fprintf(stderr, "Step time: "); PrintTime(gf_term_get_time_in_ms(term)); - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } break; case GF_KEY_B: @@ -629,9 +636,9 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt) case GF_EVENT_CONNECT: if (evt->connect.is_connected) { is_connected = 1; - fprintf(stdout, "Service Connected\n"); + fprintf(stderr, "Service Connected\n"); } else if (is_connected) { - fprintf(stdout, "Service %s\n", is_connected ? "Disconnected" : "Connection Failed"); + fprintf(stderr, "Service %s\n", is_connected ? "Disconnected" : "Connection Failed"); is_connected = 0; Duration = 0; } @@ -704,16 +711,16 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt) } break; case GF_EVENT_NAVIGATE_INFO: - if (evt->navigate.to_url) fprintf(stdout, "Go to URL: \"%s\"\r", evt->navigate.to_url); + if (evt->navigate.to_url) fprintf(stderr, "Go to URL: \"%s\"\r", evt->navigate.to_url); break; case GF_EVENT_NAVIGATE: if (gf_term_is_supported_url(term, evt->navigate.to_url, 1, no_mime_check)) { strcpy(the_url, evt->navigate.to_url); - fprintf(stdout, "Navigating to URL %s\n", the_url); + fprintf(stderr, "Navigating to URL %s\n", the_url); gf_term_navigate_to(term, evt->navigate.to_url); return 1; } else { - fprintf(stdout, "Navigation destination not supported\nGo to URL: %s\n", evt->navigate.to_url); + fprintf(stderr, "Navigation destination not supported\nGo to URL: %s\n", evt->navigate.to_url); } break; case GF_EVENT_SET_CAPTION: @@ -727,15 +734,15 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt) assert( evt->auth.password); assert( evt->auth.site_url); while ((!strlen(evt->auth.user) || !strlen(evt->auth.password)) && (maxTries--) >= 0){ - fprintf(stdout, "**** Authorization required for site %s ****\n", evt->auth.site_url); - fprintf(stdout, "login : "); + fprintf(stderr, "**** Authorization required for site %s ****\n", evt->auth.site_url); + fprintf(stderr, "login : "); read_line_input(evt->auth.user, 50, 1); - fprintf(stdout, "\npassword: "); + fprintf(stderr, "\npassword: "); read_line_input(evt->auth.password, 50, 0); - printf("*********\n"); + fprintf(stderr, "*********\n"); } if (maxTries < 0){ - printf("**** No User or password has been filled, aborting ***\n"); + fprintf(stderr, "**** No User or password has been filled, aborting ***\n"); return 0; } return 1; @@ -749,12 +756,12 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt) void list_modules(GF_ModuleManager *modules) { u32 i; - fprintf(stdout, "\rAvailable modules:\n"); + fprintf(stderr, "\rAvailable modules:\n"); for (i=0; i #endif @@ -922,7 +953,7 @@ int main (int argc, char **argv) #ifdef GPAC_MEMORY_TRACKING enable_mem_tracker = 1; #else - fprintf(stdout, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); + fprintf(stderr, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); #endif } else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")) { @@ -939,7 +970,7 @@ int main (int argc, char **argv) cfg_file = gf_cfg_init(the_cfg, NULL); if (!cfg_file) { - fprintf(stdout, "Error: Configuration File not found\n"); + fprintf(stderr, "Error: Configuration File not found\n"); return 1; } /*if logs are specified, use them*/ @@ -1056,27 +1087,12 @@ int main (int argc, char **argv) #ifdef GPAC_MEMORY_TRACKING enable_mem_tracker = 1; #else - fprintf(stdout, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); + fprintf(stderr, "WARNING - GPAC not compiled with Memory Tracker - ignoring \"-mem-track\"\n"); #endif } else if (!strcmp(arg, "-loop")) loop_at_end = 1; else if (!strcmp(arg, "-opt")) { - char *sep, *sep2, szSec[1024], szKey[1024], szVal[1024]; - sep = strchr(argv[i+1], ':'); - if (sep) { - sep[0] = 0; - strcpy(szSec, argv[i+1]); - sep[0] = ':'; sep ++; - sep2 = strchr(sep, '='); - if (sep2) { - sep2[0] = 0; - strcpy(szKey, sep); - strcpy(szVal, sep2+1); - sep2[0] = '='; - if (!stricmp(szVal, "null")) szVal[0]=0; - gf_cfg_set_key(cfg_file, szSec, szKey, szVal[0] ? szVal : NULL); - } - } + set_cfg_option(argv[i+1]); i++; } else if (!stricmp(arg, "-views")) { @@ -1093,11 +1109,11 @@ int main (int argc, char **argv) PrintUsage(); return 1; } else { - fprintf(stdout, "Unrecognized option %s - skipping\n", arg); + fprintf(stderr, "Unrecognized option %s - skipping\n", arg); } } if (dump_mode && !url_arg ) { - fprintf(stdout, "Missing argument for dump\n"); + fprintf(stderr, "Missing argument for dump\n"); PrintUsage(); if (logfile) fclose(logfile); return 1; @@ -1137,21 +1153,21 @@ int main (int argc, char **argv) init_h = forced_height; } - fprintf(stdout, "Loading modules\n"); + fprintf(stderr, "Loading modules\n"); str = gf_cfg_get_key(cfg_file, "General", "ModulesDirectory"); assert( str ); user.modules = gf_modules_new((const unsigned char *) str, cfg_file); if (user.modules) i = gf_modules_get_count(user.modules); if (!i || !user.modules) { - fprintf(stdout, "Error: no modules found in %s - exiting\n", str); + fprintf(stderr, "Error: no modules found in %s - exiting\n", str); if (user.modules) gf_modules_del(user.modules); gf_cfg_del(cfg_file); gf_sys_close(); if (logfile) fclose(logfile); return 1; } - fprintf(stdout, "Modules Found (%d in dir %s)\n", i, str); + fprintf(stderr, "Modules Found (%d in dir %s)\n", i, str); user.config = cfg_file; user.EventProc = GPAC_EventProc; @@ -1163,11 +1179,11 @@ int main (int argc, char **argv) if (threading_flags & (GF_TERM_NO_DECODER_THREAD|GF_TERM_NO_COMPOSITOR_THREAD) ) term_step = 1; - fprintf(stdout, "Loading GPAC Terminal\n"); + fprintf(stderr, "Loading GPAC Terminal\n"); i = gf_sys_clock(); term = gf_term_new(&user); if (!term) { - fprintf(stdout, "\nInit error - check you have at least one video out and one rasterizer...\nFound modules:\n"); + fprintf(stderr, "\nInit error - check you have at least one video out and one rasterizer...\nFound modules:\n"); list_modules(user.modules); gf_modules_del(user.modules); gf_cfg_del(cfg_file); @@ -1175,7 +1191,7 @@ int main (int argc, char **argv) if (logfile) fclose(logfile); return 1; } - fprintf(stdout, "Terminal Loaded in %d ms\n", gf_sys_clock()-i); + fprintf(stderr, "Terminal Loaded in %d ms\n", gf_sys_clock()-i); if (dump_mode) { // gf_term_set_option(term, GF_OPT_VISIBLE, 0); @@ -1183,10 +1199,10 @@ int main (int argc, char **argv) } else { /*check video output*/ str = gf_cfg_get_key(cfg_file, "Video", "DriverName"); - if (!strcmp(str, "Raw Video Output")) fprintf(stdout, "WARNING: using raw output video (memory only) - no display used\n"); + if (!strcmp(str, "Raw Video Output")) fprintf(stderr, "WARNING: using raw output video (memory only) - no display used\n"); /*check audio output*/ str = gf_cfg_get_key(cfg_file, "Audio", "DriverName"); - if (!str || !strcmp(str, "No Audio Output Available")) fprintf(stdout, "WARNING: no audio output available - make sure no other program is locking the sound card\n"); + if (!str || !strcmp(str, "No Audio Output Available")) fprintf(stderr, "WARNING: no audio output available - make sure no other program is locking the sound card\n"); str = gf_cfg_get_key(cfg_file, "General", "NoMIMETypeFetch"); no_mime_check = (str && !stricmp(str, "yes")) ? 1 : 0; @@ -1195,7 +1211,7 @@ int main (int argc, char **argv) str = gf_cfg_get_key(cfg_file, "HTTPProxy", "Enabled"); if (str && !strcmp(str, "yes")) { str = gf_cfg_get_key(cfg_file, "HTTPProxy", "Name"); - if (str) fprintf(stdout, "HTTP Proxy %s enabled\n", str); + if (str) fprintf(stderr, "HTTP Proxy %s enabled\n", str); } if (rti_file) { @@ -1226,28 +1242,42 @@ int main (int argc, char **argv) strcpy(the_url, url_arg); ext = strrchr(the_url, '.'); - if (ext && strncmp("http:", the_url, 5) && (!stricmp(ext, ".m3u") || !stricmp(ext, ".pls"))) { - fprintf(stdout, "Opening Playlist %s\n", the_url); - playlist = gf_f64_open(the_url, "rt"); + if (ext && (!stricmp(ext, ".m3u") || !stricmp(ext, ".pls"))) { + GF_Err e = GF_OK; + fprintf(stderr, "Opening Playlist %s\n", the_url); + + strcpy(pl_path, the_url); + /*this is not clean, we need to have a plugin handle playlist for ourselves*/ + if (!strncmp("http:", the_url, 5)) { + GF_DownloadSession *sess = gf_dm_sess_new(term->downloader, the_url, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e); + if (sess) { + e = gf_dm_sess_process(sess); + if (!e) strcpy(the_url, gf_dm_sess_get_cache_name(sess)); + gf_dm_sess_del(sess); + } + } + + playlist = e ? NULL : gf_f64_open(the_url, "rt"); readonly_playlist = 1; if (playlist) { - strcpy(pl_path, the_url); if (1 > fscanf(playlist, "%s", the_url)) fprintf(stderr, "Cannot read any URL from playlist\n"); else { - fprintf(stdout, "Opening URL %s\n", the_url); + fprintf(stderr, "Opening URL %s\n", the_url); gf_term_connect_with_path(term, the_url, pl_path); } } else { - fprintf(stdout, "Hit 'h' for help\n\n"); + if (e) + fprintf(stderr, "Failed to open playlist %s: %s\n", the_url, gf_error_to_string(e) ); + fprintf(stderr, "Hit 'h' for help\n\n"); } } else { - fprintf(stdout, "Opening URL %s\n", the_url); - if (pause_at_first) fprintf(stdout, "[Status: Paused]\n"); + fprintf(stderr, "Opening URL %s\n", the_url); + if (pause_at_first) fprintf(stderr, "[Status: Paused]\n"); gf_term_connect_from_time(term, the_url, 0, pause_at_first); } } else { - fprintf(stdout, "Hit 'h' for help\n\n"); + fprintf(stderr, "Hit 'h' for help\n\n"); str = gf_cfg_get_key(cfg_file, "General", "StartupFile"); if (str) { strcpy(the_url, "MP4Client "GPAC_FULL_VERSION); @@ -1317,7 +1347,7 @@ force_input: case 'o': startup_file = 0; gf_term_disconnect(term); - fprintf(stdout, "Enter the absolute URL\n"); + fprintf(stderr, "Enter the absolute URL\n"); if (1 > scanf("%s", the_url)){ fprintf(stderr, "Cannot read absolute URL, aborting\n"); break; @@ -1327,7 +1357,7 @@ force_input: break; case 'O': gf_term_disconnect(term); - fprintf(stdout, "Enter the absolute URL to the playlist\n"); + fprintf(stderr, "Enter the absolute URL to the playlist\n"); if (1 > scanf("%s", the_url)){ fprintf(stderr, "Cannot read the absolute URL, aborting.\n"); break; @@ -1339,7 +1369,7 @@ force_input: fclose( playlist); break; } - fprintf(stdout, "Opening URL %s\n", the_url); + fprintf(stderr, "Opening URL %s\n", the_url); gf_term_connect(term, the_url); } break; @@ -1355,10 +1385,10 @@ force_input: res = fscanf(playlist, "%s", the_url); } if (res == EOF) { - fprintf(stdout, "No more items - exiting\n"); + fprintf(stderr, "No more items - exiting\n"); Run = 0; } else { - fprintf(stdout, "Opening URL %s\n", the_url); + fprintf(stderr, "Opening URL %s\n", the_url); gf_term_connect_with_path(term, the_url, pl_path); } } @@ -1378,7 +1408,7 @@ force_input: } count--; } - fprintf(stdout, "Opening URL %s\n", the_url); + fprintf(stderr, "Opening URL %s\n", the_url); gf_term_connect(term, the_url); } break; @@ -1394,32 +1424,32 @@ force_input: case 'p': if (is_connected) { Bool is_pause = gf_term_get_option(term, GF_OPT_PLAY_STATE); - fprintf(stdout, "[Status: %s]\n", is_pause ? "Playing" : "Paused"); + fprintf(stderr, "[Status: %s]\n", is_pause ? "Playing" : "Paused"); gf_term_set_option(term, GF_OPT_PLAY_STATE, is_pause ? GF_STATE_PLAYING : GF_STATE_PAUSED); } break; case 's': if (is_connected) { gf_term_set_option(term, GF_OPT_PLAY_STATE, GF_STATE_STEP_PAUSE); - fprintf(stdout, "Step time: "); + fprintf(stderr, "Step time: "); PrintTime(gf_term_get_time_in_ms(term)); - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } break; case 'z': case 'T': if (!CanSeek || (Duration<=2000)) { - fprintf(stdout, "scene not seekable\n"); + fprintf(stderr, "scene not seekable\n"); } else { Double res; s32 seekTo; - fprintf(stdout, "Duration: "); + fprintf(stderr, "Duration: "); PrintTime(Duration); res = gf_term_get_time_in_ms(term); if (c=='z') { res *= 100; res /= (s64)Duration; - fprintf(stdout, " (current %.2f %%)\nEnter Seek percentage:\n", res); + fprintf(stderr, " (current %.2f %%)\nEnter Seek percentage:\n", res); if (scanf("%d", &seekTo) == 1) { if (seekTo > 100) seekTo = 100; res = (Double)(s64)Duration; res /= 100; res *= seekTo; @@ -1427,9 +1457,9 @@ force_input: } } else { u32 r, h, m, s; - fprintf(stdout, " - Current Time: "); + fprintf(stderr, " - Current Time: "); PrintTime((u64) res); - fprintf(stdout, "\nEnter seek time (Format: s, m:s or h:m:s):\n"); + fprintf(stderr, "\nEnter seek time (Format: s, m:s or h:m:s):\n"); h = m = s = 0; r =scanf("%d:%d:%d", &h, &m, &s); if (r==2) { s = m; m = h; h = 0; } @@ -1446,11 +1476,11 @@ force_input: case 't': { if (is_connected) { - fprintf(stdout, "Current Time: "); + fprintf(stderr, "Current Time: "); PrintTime(gf_term_get_time_in_ms(term)); - fprintf(stdout, " - Duration: "); + fprintf(stderr, " - Duration: "); PrintTime(Duration); - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } } break; @@ -1464,8 +1494,8 @@ force_input: if (is_connected) { u32 ID; do { - fprintf(stdout, "Enter OD ID (0 for main OD): "); - fflush(stdout); + fprintf(stderr, "Enter OD ID (0 for main OD): "); + fflush(stderr); } while( 1 > scanf("%ud", &ID)); ViewOD(term, ID, (u32)-1); } @@ -1474,8 +1504,8 @@ force_input: if (is_connected) { u32 num; do { - fprintf(stdout, "Enter OD number (0 for main OD): "); - fflush(stdout); + fprintf(stderr, "Enter OD number (0 for main OD): "); + fflush(stderr); } while( 1 > scanf("%ud", &num)); ViewOD(term, (u32)-1, num); } @@ -1508,8 +1538,8 @@ force_input: Bool xml_dump, std_out; radname[0] = 0; do { - fprintf(stdout, "Enter Inline OD ID if any or 0 : "); - fflush(stdout); + fprintf(stderr, "Enter Inline OD ID if any or 0 : "); + fflush(stderr); } while( 1 > scanf("%ud", &odid)); if (odid) { GF_ObjectManager *root_odm = gf_term_get_root_object(term); @@ -1525,8 +1555,8 @@ force_input: } } do{ - fprintf(stdout, "Enter file radical name (+\'.x\' for XML dumping) - \"std\" for stdout: "); - fflush(stdout); + fprintf(stderr, "Enter file radical name (+\'.x\' for XML dumping) - \"std\" for stderr: "); + fflush(stderr); } while( 1 > scanf("%s", radname)); sExt = strrchr(radname, '.'); xml_dump = 0; @@ -1536,7 +1566,7 @@ force_input: } std_out = strnicmp(radname, "std", 3) ? 0 : 1; e = gf_term_dump_scene(term, std_out ? NULL : radname, NULL, xml_dump, 0, odm); - fprintf(stdout, "Dump done (%s)\n", gf_error_to_string(e)); + fprintf(stderr, "Dump done (%s)\n", gf_error_to_string(e)); } break; @@ -1547,7 +1577,7 @@ force_input: { Bool use_3d = !gf_term_get_option(term, GF_OPT_USE_OPENGL); if (gf_term_set_option(term, GF_OPT_USE_OPENGL, use_3d)==GF_OK) { - fprintf(stdout, "Using %s for 2D drawing\n", use_3d ? "OpenGL" : "2D rasterizer"); + fprintf(stderr, "Using %s for 2D drawing\n", use_3d ? "OpenGL" : "2D rasterizer"); } } break; @@ -1555,7 +1585,7 @@ force_input: { Bool opt = gf_term_get_option(term, GF_OPT_STRESS_MODE); opt = !opt; - fprintf(stdout, "Turning stress mode %s\n", opt ? "on" : "off"); + fprintf(stderr, "Turning stress mode %s\n", opt ? "on" : "off"); gf_term_set_option(term, GF_OPT_STRESS_MODE, opt); } break; @@ -1568,21 +1598,21 @@ force_input: switch (gf_term_get_option(term, GF_OPT_MEDIA_CACHE)) { case GF_MEDIA_CACHE_DISABLED: gf_term_set_option(term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_ENABLED); break; case GF_MEDIA_CACHE_ENABLED: gf_term_set_option(term, GF_OPT_MEDIA_CACHE, GF_MEDIA_CACHE_DISABLED); break; - case GF_MEDIA_CACHE_RUNNING: fprintf(stdout, "Streaming Cache is running - please stop it first\n"); continue; + case GF_MEDIA_CACHE_RUNNING: fprintf(stderr, "Streaming Cache is running - please stop it first\n"); continue; } switch (gf_term_get_option(term, GF_OPT_MEDIA_CACHE)) { - case GF_MEDIA_CACHE_ENABLED: fprintf(stdout, "Streaming Cache Enabled\n"); break; - case GF_MEDIA_CACHE_DISABLED: fprintf(stdout, "Streaming Cache Disabled\n"); break; - case GF_MEDIA_CACHE_RUNNING: fprintf(stdout, "Streaming Cache Running\n"); break; + case GF_MEDIA_CACHE_ENABLED: fprintf(stderr, "Streaming Cache Enabled\n"); break; + case GF_MEDIA_CACHE_DISABLED: fprintf(stderr, "Streaming Cache Disabled\n"); break; + case GF_MEDIA_CACHE_RUNNING: fprintf(stderr, "Streaming Cache Running\n"); break; } break; case 'S': case 'A': if (gf_term_get_option(term, GF_OPT_MEDIA_CACHE)==GF_MEDIA_CACHE_RUNNING) { gf_term_set_option(term, GF_OPT_MEDIA_CACHE, (c=='S') ? GF_MEDIA_CACHE_DISABLED : GF_MEDIA_CACHE_DISCARD); - fprintf(stdout, "Streaming Cache stopped\n"); + fprintf(stderr, "Streaming Cache stopped\n"); } else { - fprintf(stdout, "Streaming Cache not running\n"); + fprintf(stderr, "Streaming Cache not running\n"); } break; case 'R': @@ -1599,7 +1629,7 @@ force_input: { GF_Err e; char szCom[8192]; - fprintf(stdout, "Enter command to send:\n"); + fprintf(stderr, "Enter command to send:\n"); fflush(stdin); szCom[0] = 0; if (1 > scanf("%[^\t\n]", szCom)){ @@ -1607,7 +1637,7 @@ force_input: break; } e = gf_term_scene_update(term, NULL, szCom); - if (e) fprintf(stdout, "Processing command failed: %s\n", gf_error_to_string(e)); + if (e) fprintf(stderr, "Processing command failed: %s\n", gf_error_to_string(e)); } break; @@ -1615,7 +1645,7 @@ force_input: { char szLog[1024], *cur_logs; cur_logs = gf_log_get_tools_levels(); - fprintf(stdout, "Enter new log level (current tools %s):\n", cur_logs); + fprintf(stderr, "Enter new log level (current tools %s):\n", cur_logs); gf_free(cur_logs); if (scanf("%s", szLog) < 1) { fprintf(stderr, "Cannot read new log level, aborting.\n"); @@ -1629,14 +1659,14 @@ force_input: { GF_SystemRTInfo rti; gf_sys_get_rti(rti_update_time_ms, &rti, 0); - fprintf(stdout, "GPAC allocated memory "LLD"\n", rti.gpac_memory); + fprintf(stderr, "GPAC allocated memory "LLD"\n", rti.gpac_memory); } break; case 'M': { u32 size; do { - fprintf(stdout, "Enter new video cache memory in kBytes (current %ud):\n", gf_term_get_option(term, GF_OPT_VIDEO_CACHE_SIZE)); + fprintf(stderr, "Enter new video cache memory in kBytes (current %ud):\n", gf_term_get_option(term, GF_OPT_VIDEO_CACHE_SIZE)); } while (1 > scanf("%ud", &size)); gf_term_set_option(term, GF_OPT_VIDEO_CACHE_SIZE, size); } @@ -1650,6 +1680,20 @@ force_input: switch_bench(); break; + case 'Y': + { + char szOpt[8192]; + fprintf(stderr, "Enter option to set (Section:Name=Value):\n"); + fflush(stdin); + szOpt[0] = 0; + if (1 > scanf("%[^\t\n]", szOpt)){ + fprintf(stderr, "Cannot read option\n"); + break; + } + set_cfg_option(szOpt); + } + break; + /*extract to PNG*/ case 'Z': { @@ -1660,7 +1704,7 @@ force_input: nb_pass = 1; nb_views = gf_term_get_option(term, GF_OPT_NUM_STEREO_VIEWS); if (nb_views>1) { - fprintf(stdout, "Auto-stereo mode detected - type number of view to dump (0 is main output, 1 to %d offscreen view, %d for all offscreen, %d for all offscreen and main)\n", nb_views, nb_views+1, nb_views+2); + fprintf(stderr, "Auto-stereo mode detected - type number of view to dump (0 is main output, 1 to %d offscreen view, %d for all offscreen, %d for all offscreen and main)\n", nb_views, nb_views+1, nb_views+2); if (scanf("%d", &offscreen_view) != 1) { offscreen_view = 0; } @@ -1684,32 +1728,34 @@ force_input: } offscreen_view++; if (e) { - fprintf(stdout, "Error dumping screen buffer %s\n", gf_error_to_string(e) ); + fprintf(stderr, "Error dumping screen buffer %s\n", gf_error_to_string(e) ); nb_pass = 0; } else { +#ifndef GPAC_DISABLE_AV_PARSERS u32 dst_size = fb.width*fb.height*4; char *dst = (char*)gf_malloc(sizeof(char)*dst_size); e = gf_img_png_enc(fb.video_buffer, fb.width, fb.height, fb.pitch_y, fb.pixel_format, dst, &dst_size); if (e) { - fprintf(stdout, "Error encoding PNG %s\n", gf_error_to_string(e) ); + fprintf(stderr, "Error encoding PNG %s\n", gf_error_to_string(e) ); nb_pass = 0; } else { FILE *png = gf_f64_open(szFileName, "wb"); if (!png) { - fprintf(stdout, "Error writing file %s\n", szFileName); + fprintf(stderr, "Error writing file %s\n", szFileName); nb_pass = 0; } else { gf_fwrite(dst, dst_size, 1, png); fclose(png); - fprintf(stdout, "Dump to %s\n", szFileName); + fprintf(stderr, "Dump to %s\n", szFileName); } } if (dst) gf_free(dst); gf_term_release_screen_buffer(term, &fb); +#endif //GPAC_DISABLE_AV_PARSERS } } - fprintf(stdout, "Done: %s\n", szFileName); + fprintf(stderr, "Done: %s\n", szFileName); } break; @@ -1725,12 +1771,12 @@ force_input: gf_term_disconnect(term); if (rti_file) UpdateRTInfo("Disconnected\n"); - fprintf(stdout, "Deleting terminal... "); + fprintf(stderr, "Deleting terminal... "); if (playlist) fclose(playlist); gf_term_del(term); - fprintf(stdout, "done (in %d ms)\n", gf_sys_clock() - i); + fprintf(stderr, "done (in %d ms)\n", gf_sys_clock() - i); - fprintf(stdout, "GPAC cleanup ...\n"); + fprintf(stderr, "GPAC cleanup ...\n"); gf_modules_del(user.modules); gf_cfg_del(cfg_file); @@ -1753,12 +1799,12 @@ void PrintWorldInfo(GF_Terminal *term) descs = gf_list_new(); title = gf_term_get_world_info(term, NULL, descs); if (!title && !gf_list_count(descs)) { - fprintf(stdout, "No World Info available\n"); + fprintf(stderr, "No World Info available\n"); } else { - fprintf(stdout, "\t%s\n", title ? title : "No title available"); + fprintf(stderr, "\t%s\n", title ? title : "No title available"); for (i=0; iServiceID) fprintf(stdout, "Service ID %d ", odi.od->ServiceID); + fprintf(stderr, "%s", szIndent); + fprintf(stderr, "#%d %s - ", num, root_name); + if (odi.od->ServiceID) fprintf(stderr, "Service ID %d ", odi.od->ServiceID); if (odi.media_url) { - fprintf(stdout, "%s\n", odi.media_url); + fprintf(stderr, "%s\n", odi.media_url); } else { - fprintf(stdout, "OD ID %d\n", odi.od->objectDescriptorID); + fprintf(stderr, "OD ID %d\n", odi.od->objectDescriptorID); } szIndent[indent]=' '; @@ -1820,16 +1866,16 @@ void PrintODList(GF_Terminal *term, GF_ObjectManager *root_odm, u32 num, u32 ind PrintODList(term, odm, num, indent, "EXTERNPROTO Library"); break; default: - fprintf(stdout, "%s", szIndent); - fprintf(stdout, "#%d - ", num); + fprintf(stderr, "%s", szIndent); + fprintf(stderr, "#%d - ", num); if (odi.media_url) { - fprintf(stdout, "%s", odi.media_url); + fprintf(stderr, "%s", odi.media_url); } else { - fprintf(stdout, "ID %d", odi.od->objectDescriptorID); + fprintf(stderr, "ID %d", odi.od->objectDescriptorID); } - fprintf(stdout, " - %s", (odi.od_type==GF_STREAM_VISUAL) ? "Video" : (odi.od_type==GF_STREAM_AUDIO) ? "Audio" : "Systems"); - if (odi.od && odi.od->ServiceID) fprintf(stdout, " - Service ID %d", odi.od->ServiceID); - fprintf(stdout, "\n"); + fprintf(stderr, " - %s", (odi.od_type==GF_STREAM_VISUAL) ? "Video" : (odi.od_type==GF_STREAM_AUDIO) ? "Audio" : "Systems"); + if (odi.od && odi.od->ServiceID) fprintf(stderr, " - Service ID %d", odi.od->ServiceID); + fprintf(stderr, "\n"); break; } } @@ -1863,70 +1909,70 @@ void ViewOD(GF_Terminal *term, u32 OD_ID, u32 number) } } if (!odm) { - if (number == (u32)-1) fprintf(stdout, "cannot find OD with ID %d\n", OD_ID); - else fprintf(stdout, "cannot find OD with number %d\n", number); + if (number == (u32)-1) fprintf(stderr, "cannot find OD with ID %d\n", OD_ID); + else fprintf(stderr, "cannot find OD with number %d\n", number); return; } if (!odi.od) { - if (number == (u32)-1) fprintf(stdout, "Object %d not attached yet\n", OD_ID); - else fprintf(stdout, "Object #%d not attached yet\n", number); + if (number == (u32)-1) fprintf(stderr, "Object %d not attached yet\n", OD_ID); + else fprintf(stderr, "Object #%d not attached yet\n", number); return; } if (!odi.od) { - fprintf(stdout, "Service not attached\n"); + fprintf(stderr, "Service not attached\n"); return; } if (odi.od->tag==GF_ODF_IOD_TAG) { - fprintf(stdout, "InitialObjectDescriptor %d\n", odi.od->objectDescriptorID); - fprintf(stdout, "Profiles and Levels: Scene %x - Graphics %x - Visual %x - Audio %x - OD %x\n", + fprintf(stderr, "InitialObjectDescriptor %d\n", odi.od->objectDescriptorID); + fprintf(stderr, "Profiles and Levels: Scene %x - Graphics %x - Visual %x - Audio %x - OD %x\n", odi.scene_pl, odi.graphics_pl, odi.visual_pl, odi.audio_pl, odi.OD_pl); - fprintf(stdout, "Inline Profile Flag %d\n", odi.inline_pl); + fprintf(stderr, "Inline Profile Flag %d\n", odi.inline_pl); } else { - fprintf(stdout, "ObjectDescriptor %d\n", odi.od->objectDescriptorID); + fprintf(stderr, "ObjectDescriptor %d\n", odi.od->objectDescriptorID); } - fprintf(stdout, "Object Duration: "); + fprintf(stderr, "Object Duration: "); if (odi.duration) { PrintTime((u32) (odi.duration*1000)); } else { - fprintf(stdout, "unknown"); + fprintf(stderr, "unknown"); } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); if (odi.owns_service) { - fprintf(stdout, "Service Handler: %s\n", odi.service_handler); - fprintf(stdout, "Service URL: %s\n", odi.service_url); + fprintf(stderr, "Service Handler: %s\n", odi.service_handler); + fprintf(stderr, "Service URL: %s\n", odi.service_url); } if (odi.codec_name) { Float avg_dec_time; switch (odi.od_type) { case GF_STREAM_VISUAL: - fprintf(stdout, "Video Object: Width %d - Height %d\r\n", odi.width, odi.height); - fprintf(stdout, "Media Codec: %s\n", odi.codec_name); - if (odi.par) fprintf(stdout, "Pixel Aspect Ratio: %d:%d\n", (odi.par>>16)&0xFF, (odi.par)&0xFF); + fprintf(stderr, "Video Object: Width %d - Height %d\r\n", odi.width, odi.height); + fprintf(stderr, "Media Codec: %s\n", odi.codec_name); + if (odi.par) fprintf(stderr, "Pixel Aspect Ratio: %d:%d\n", (odi.par>>16)&0xFF, (odi.par)&0xFF); break; case GF_STREAM_AUDIO: - fprintf(stdout, "Audio Object: Sample Rate %d - %d channels\r\n", odi.sample_rate, odi.num_channels); - fprintf(stdout, "Media Codec: %s\n", odi.codec_name); + fprintf(stderr, "Audio Object: Sample Rate %d - %d channels\r\n", odi.sample_rate, odi.num_channels); + fprintf(stderr, "Media Codec: %s\n", odi.codec_name); break; case GF_STREAM_SCENE: case GF_STREAM_PRIVATE_SCENE: if (odi.width && odi.height) { - fprintf(stdout, "Scene Description - Width %d - Height %d\n", odi.width, odi.height); + fprintf(stderr, "Scene Description - Width %d - Height %d\n", odi.width, odi.height); } else { - fprintf(stdout, "Scene Description - no size specified\n"); + fprintf(stderr, "Scene Description - no size specified\n"); } - fprintf(stdout, "Scene Codec: %s\n", odi.codec_name); + fprintf(stderr, "Scene Codec: %s\n", odi.codec_name); break; case GF_STREAM_TEXT: if (odi.width && odi.height) { - fprintf(stdout, "Text Object: Width %d - Height %d\n", odi.width, odi.height); + fprintf(stderr, "Text Object: Width %d - Height %d\n", odi.width, odi.height); } else { - fprintf(stdout, "Text Object: No size specified\n"); + fprintf(stderr, "Text Object: No size specified\n"); } - fprintf(stdout, "Text Codec %s\n", odi.codec_name); + fprintf(stderr, "Text Codec %s\n", odi.codec_name); break; } @@ -1935,65 +1981,65 @@ void ViewOD(GF_Terminal *term, u32 OD_ID, u32 number) avg_dec_time = (Float) odi.total_dec_time; avg_dec_time /= odi.nb_dec_frames; } - fprintf(stdout, "\tBitrate over last second: %d kbps\n\tMax bitrate over one second: %d kbps\n\tAverage Decoding Time %.2f ms (%d max)\n\tTotal decoded frames %d\n", + fprintf(stderr, "\tBitrate over last second: %d kbps\n\tMax bitrate over one second: %d kbps\n\tAverage Decoding Time %.2f ms (%d max)\n\tTotal decoded frames %d\n", (u32) odi.avg_bitrate/1024, odi.max_bitrate/1024, avg_dec_time, odi.max_dec_time, odi.nb_dec_frames); } - if (odi.protection) fprintf(stdout, "Encrypted Media%s\n", (odi.protection==2) ? " NOT UNLOCKED" : ""); + if (odi.protection) fprintf(stderr, "Encrypted Media%s\n", (odi.protection==2) ? " NOT UNLOCKED" : ""); count = gf_list_count(odi.od->ESDescriptors); - fprintf(stdout, "%d streams in OD\n", count); + fprintf(stderr, "%d streams in OD\n", count); for (i=0; iESDescriptors, i); - fprintf(stdout, "\nStream ID %d - Clock ID %d\n", esd->ESID, esd->OCRESID); - if (esd->dependsOnESID) fprintf(stdout, "\tDepends on Stream ID %d for decoding\n", esd->dependsOnESID); + fprintf(stderr, "\nStream ID %d - Clock ID %d\n", esd->ESID, esd->OCRESID); + if (esd->dependsOnESID) fprintf(stderr, "\tDepends on Stream ID %d for decoding\n", esd->dependsOnESID); switch (esd->decoderConfig->streamType) { case GF_STREAM_OD: - fprintf(stdout, "\tOD Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tOD Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_OCR: - fprintf(stdout, "\tOCR Stream\n"); + fprintf(stderr, "\tOCR Stream\n"); break; case GF_STREAM_SCENE: - fprintf(stdout, "\tScene Description Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tScene Description Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_VISUAL: - fprintf(stdout, "\tVisual Stream - media type: %s", gf_esd_get_textual_description(esd)); + fprintf(stderr, "\tVisual Stream - media type: %s", gf_esd_get_textual_description(esd)); break; case GF_STREAM_AUDIO: - fprintf(stdout, "\tAudio Stream - media type: %s", gf_esd_get_textual_description(esd)); + fprintf(stderr, "\tAudio Stream - media type: %s", gf_esd_get_textual_description(esd)); break; case GF_STREAM_MPEG7: - fprintf(stdout, "\tMPEG-7 Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tMPEG-7 Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_IPMP: - fprintf(stdout, "\tIPMP Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tIPMP Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_OCI: - fprintf(stdout, "\tOCI Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tOCI Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_MPEGJ: - fprintf(stdout, "\tMPEGJ Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tMPEGJ Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_INTERACT: - fprintf(stdout, "\tUser Interaction Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tUser Interaction Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; case GF_STREAM_TEXT: - fprintf(stdout, "\tStreaming Text Stream - version %d\n", esd->decoderConfig->objectTypeIndication); + fprintf(stderr, "\tStreaming Text Stream - version %d\n", esd->decoderConfig->objectTypeIndication); break; default: - fprintf(stdout, "\tUnknown Stream\n"); + fprintf(stderr, "\tUnknown Stream\n"); break; } - fprintf(stdout, "\tBuffer Size %d\n\tAverage Bitrate %d bps\n\tMaximum Bitrate %d bps\n", esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate, esd->decoderConfig->maxBitrate); + fprintf(stderr, "\tBuffer Size %d\n\tAverage Bitrate %d bps\n\tMaximum Bitrate %d bps\n", esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate, esd->decoderConfig->maxBitrate); if (esd->slConfig->predefined==SLPredef_SkipSL) { - fprintf(stdout, "\tNot using MPEG-4 Synchronization Layer\n"); + fprintf(stderr, "\tNot using MPEG-4 Synchronization Layer\n"); } else { - fprintf(stdout, "\tStream Clock Resolution %d\n", esd->slConfig->timestampResolution); + fprintf(stderr, "\tStream Clock Resolution %d\n", esd->slConfig->timestampResolution); } - if (esd->URLString) fprintf(stdout, "\tStream Location: %s\n", esd->URLString); + if (esd->URLString) fprintf(stderr, "\tStream Location: %s\n", esd->URLString); /*check language*/ if (esd->langDesc) { @@ -2015,31 +2061,31 @@ void ViewOD(GF_Terminal *term, u32 OD_ID, u32 number) i+=3; } } - fprintf(stdout, "\tStream Language: %s\n", szLang); + fprintf(stderr, "\tStream Language: %s\n", szLang); } } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); /*check OCI (not everything interests us) - FIXME: support for unicode*/ count = gf_list_count(odi.od->OCIDescriptors); if (count) { - fprintf(stdout, "%d Object Content Information descriptors in OD\n", count); + fprintf(stderr, "%d Object Content Information descriptors in OD\n", count); for (i=0; iOCIDescriptors, i); switch (desc->tag) { case GF_ODF_SEGMENT_TAG: { GF_Segment *sd = (GF_Segment *) desc; - fprintf(stdout, "Segment Descriptor: Name: %s - start time %g sec - duration %g sec\n", sd->SegmentName, sd->startTime, sd->Duration); + fprintf(stderr, "Segment Descriptor: Name: %s - start time %g sec - duration %g sec\n", sd->SegmentName, sd->startTime, sd->Duration); } break; case GF_ODF_CC_NAME_TAG: { GF_CC_Name *ccn = (GF_CC_Name *)desc; - fprintf(stdout, "Content Creators:\n"); + fprintf(stderr, "Content Creators:\n"); for (j=0; jContentCreators); j++) { GF_ContentCreatorInfo *ci = (GF_ContentCreatorInfo *) gf_list_get(ccn->ContentCreators, j); if (!ci->isUTF8) continue; - fprintf(stdout, "\t%s\n", ci->contentCreatorName); + fprintf(stderr, "\t%s\n", ci->contentCreatorName); } } break; @@ -2047,69 +2093,69 @@ void ViewOD(GF_Terminal *term, u32 OD_ID, u32 number) case GF_ODF_SHORT_TEXT_TAG: { GF_ShortTextual *std = (GF_ShortTextual *)desc; - fprintf(stdout, "Description:\n\tEvent: %s\n\t%s\n", std->eventName, std->eventText); + fprintf(stderr, "Description:\n\tEvent: %s\n\t%s\n", std->eventName, std->eventText); } break; default: break; } } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } switch (odi.status) { - case 0: fprintf(stdout, "Stopped - "); break; - case 1: fprintf(stdout, "Playing - "); break; - case 2: fprintf(stdout, "Paused - "); break; - case 3: fprintf(stdout, "Not setup yet\n"); return; - default: fprintf(stdout, "Setup Failed\n"); return; - } - if (odi.buffer>=0) fprintf(stdout, "Buffer: %d ms - ", odi.buffer); - else fprintf(stdout, "Not buffering - "); - fprintf(stdout, "Clock drift: %d ms\n", odi.clock_drift); - if (odi.db_unit_count) fprintf(stdout, "%d AU in DB\n", odi.db_unit_count); - if (odi.cb_max_count) fprintf(stdout, "Composition Buffer: %d CU (%d max)\n", odi.cb_unit_count, odi.cb_max_count); - fprintf(stdout, "\n"); + case 0: fprintf(stderr, "Stopped - "); break; + case 1: fprintf(stderr, "Playing - "); break; + case 2: fprintf(stderr, "Paused - "); break; + case 3: fprintf(stderr, "Not setup yet\n"); return; + default: fprintf(stderr, "Setup Failed\n"); return; + } + if (odi.buffer>=0) fprintf(stderr, "Buffer: %d ms - ", odi.buffer); + else fprintf(stderr, "Not buffering - "); + fprintf(stderr, "Clock drift: %d ms\n", odi.clock_drift); + if (odi.db_unit_count) fprintf(stderr, "%d AU in DB\n", odi.db_unit_count); + if (odi.cb_max_count) fprintf(stderr, "Composition Buffer: %d CU (%d max)\n", odi.cb_unit_count, odi.cb_max_count); + fprintf(stderr, "\n"); if (odi.owns_service) { const char *url; u32 done, total, bps; d_enum = 0; while (gf_term_get_download_info(term, odm, &d_enum, &url, NULL, &done, &total, &bps)) { - if (d_enum==1) fprintf(stdout, "Current Downloads in service:\n"); + if (d_enum==1) fprintf(stderr, "Current Downloads in service:\n"); if (done && total) { - fprintf(stdout, "%s: %d / %d bytes (%.2f %%) - %.2f kBps\n", url, done, total, (100.0f*done)/total, ((Float)bps)/1024.0f); + fprintf(stderr, "%s: %d / %d bytes (%.2f %%) - %.2f kBps\n", url, done, total, (100.0f*done)/total, ((Float)bps)/1024.0f); } else { - fprintf(stdout, "%s: %.2f kbps\n", url, ((Float)8*bps)/1024.0f); + fprintf(stderr, "%s: %.2f kbps\n", url, ((Float)8*bps)/1024.0f); } } - if (!d_enum) fprintf(stdout, "No Downloads in service\n"); - fprintf(stdout, "\n"); + if (!d_enum) fprintf(stderr, "No Downloads in service\n"); + fprintf(stderr, "\n"); } d_enum = 0; while (gf_term_get_channel_net_info(term, odm, &d_enum, &id, &com, &e)) { if (e) continue; if (!com.bw_down && !com.bw_up) continue; - fprintf(stdout, "Stream ID %d statistics:\n", id); + fprintf(stderr, "Stream ID %d statistics:\n", id); if (com.multiplex_port) { - fprintf(stdout, "\tMultiplex Port %d - multiplex ID %d\n", com.multiplex_port, com.port); + fprintf(stderr, "\tMultiplex Port %d - multiplex ID %d\n", com.multiplex_port, com.port); } else { - fprintf(stdout, "\tPort %d\n", com.port); + fprintf(stderr, "\tPort %d\n", com.port); } - fprintf(stdout, "\tPacket Loss Percentage: %.4f\n", com.pck_loss_percentage); - fprintf(stdout, "\tDown Bandwidth: %d bps\n", com.bw_down); - if (com.bw_up) fprintf(stdout, "\tUp Bandwidth: %d bps\n", com.bw_up); + fprintf(stderr, "\tPacket Loss Percentage: %.4f\n", com.pck_loss_percentage); + fprintf(stderr, "\tDown Bandwidth: %d bps\n", com.bw_down); + if (com.bw_up) fprintf(stderr, "\tUp Bandwidth: %d bps\n", com.bw_up); if (com.ctrl_port) { if (com.multiplex_port) { - fprintf(stdout, "\tControl Multiplex Port: %d - Control Multiplex ID %d\n", com.multiplex_port, com.ctrl_port); + fprintf(stderr, "\tControl Multiplex Port: %d - Control Multiplex ID %d\n", com.multiplex_port, com.ctrl_port); } else { - fprintf(stdout, "\tControl Port: %d\n", com.ctrl_port); + fprintf(stderr, "\tControl Port: %d\n", com.ctrl_port); } - fprintf(stdout, "\tDown Bandwidth: %d bps\n", com.ctrl_bw_down); - fprintf(stdout, "\tUp Bandwidth: %d bps\n", com.ctrl_bw_up); + fprintf(stderr, "\tDown Bandwidth: %d bps\n", com.ctrl_bw_down); + fprintf(stderr, "\tUp Bandwidth: %d bps\n", com.ctrl_bw_up); } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } } @@ -2120,22 +2166,22 @@ void PrintODTiming(GF_Terminal *term, GF_ObjectManager *odm) if (gf_term_get_object_info(term, odm, &odi) != GF_OK) return; if (!odi.od) { - fprintf(stdout, "Service not attached\n"); + fprintf(stderr, "Service not attached\n"); return; } - fprintf(stdout, "OD %d: ", odi.od->objectDescriptorID); + fprintf(stderr, "OD %d: ", odi.od->objectDescriptorID); switch (odi.status) { - case 1: fprintf(stdout, "Playing - "); break; - case 2: fprintf(stdout, "Paused - "); break; - default: fprintf(stdout, "Stopped - "); break; - } - if (odi.buffer>=0) fprintf(stdout, "Buffer: %d ms - ", odi.buffer); - else fprintf(stdout, "Not buffering - "); - fprintf(stdout, "Clock drift: %d ms", odi.clock_drift); - fprintf(stdout, " - time: "); + case 1: fprintf(stderr, "Playing - "); break; + case 2: fprintf(stderr, "Paused - "); break; + default: fprintf(stderr, "Stopped - "); break; + } + if (odi.buffer>=0) fprintf(stderr, "Buffer: %d ms - ", odi.buffer); + else fprintf(stderr, "Not buffering - "); + fprintf(stderr, "Clock drift: %d ms", odi.clock_drift); + fprintf(stderr, " - time: "); PrintTime((u32) (odi.current_time*1000)); - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } void PrintODBuffer(GF_Terminal *term, GF_ObjectManager *odm) @@ -2146,24 +2192,24 @@ void PrintODBuffer(GF_Terminal *term, GF_ObjectManager *odm) if (gf_term_get_object_info(term, odm, &odi) != GF_OK) return; if (!odi.od) { - fprintf(stdout, "Service not attached\n"); + fprintf(stderr, "Service not attached\n"); return; } - fprintf(stdout, "OD %d: ", odi.od->objectDescriptorID); + fprintf(stderr, "OD %d: ", odi.od->objectDescriptorID); switch (odi.status) { - case 1: fprintf(stdout, "Playing"); break; - case 2: fprintf(stdout, "Paused"); break; - default: fprintf(stdout, "Stopped"); break; + case 1: fprintf(stderr, "Playing"); break; + case 2: fprintf(stderr, "Paused"); break; + default: fprintf(stderr, "Stopped"); break; } - if (odi.buffer>=0) fprintf(stdout, " - Buffer: %d ms", odi.buffer); - if (odi.db_unit_count) fprintf(stdout, " - DB: %d AU", odi.db_unit_count); - if (odi.cb_max_count) fprintf(stdout, " - CB: %d/%d CUs", odi.cb_unit_count, odi.cb_max_count); + if (odi.buffer>=0) fprintf(stderr, " - Buffer: %d ms", odi.buffer); + if (odi.db_unit_count) fprintf(stderr, " - DB: %d AU", odi.db_unit_count); + if (odi.cb_max_count) fprintf(stderr, " - CB: %d/%d CUs", odi.cb_unit_count, odi.cb_max_count); - fprintf(stdout, "\n * %d decoded frames - %d dropped frames\n", odi.nb_dec_frames, odi.nb_droped); + fprintf(stderr, "\n * %d decoded frames - %d dropped frames\n", odi.nb_dec_frames, odi.nb_droped); avg_dec_time = 0; if (odi.nb_dec_frames) { avg_dec_time = (Float) odi.total_dec_time; avg_dec_time /= odi.nb_dec_frames; } - fprintf(stdout, " * Avg Bitrate %d kbps (%d max) - Avg Decoding Time %.2f ms (%d max)\n", + fprintf(stderr, " * Avg Bitrate %d kbps (%d max) - Avg Decoding Time %.2f ms (%d max)\n", (u32) odi.avg_bitrate/1024, odi.max_bitrate/1024, avg_dec_time, odi.max_dec_time); } @@ -2187,7 +2233,7 @@ void ViewODs(GF_Terminal *term, Bool show_timing) PrintODBuffer(term, odm); } } - fprintf(stdout, "\n"); + fprintf(stderr, "\n"); } @@ -2197,14 +2243,14 @@ void PrintGPACConfig() char szName[200]; char *secName = NULL; - fprintf(stdout, "Enter section name (\"*\" for complete dump):\n"); + fprintf(stderr, "Enter section name (\"*\" for complete dump):\n"); if (1 > scanf("%s", szName)){ fprintf(stderr, "No section name, aborting.\n"); return; } if (strcmp(szName, "*")) secName = szName; - fprintf(stdout, "\n\n*** GPAC Configuration ***\n\n"); + fprintf(stderr, "\n\n*** GPAC Configuration ***\n\n"); cfg_count = gf_cfg_get_section_count(cfg_file); for (i=0; i.depend + +distclean: clean + rm -f Makefile.bak .depend + + + +# include dependency files if they exist +# +ifneq ($(wildcard .depend),) +include .depend +endif diff --git a/applications/ts2hds/f4m.c b/applications/ts2hds/f4m.c new file mode 100644 index 0000000..b09aa49 --- /dev/null +++ b/applications/ts2hds/f4m.c @@ -0,0 +1,141 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Author: Romain Bouqueau + * Copyright (c) Romain Bouqueau 2012- + * All rights reserved + * + * Note: this development was kindly sponsorized by Vizion'R (http://vizionr.com) + * + * This file is part of GPAC / TS to HDS (ts2hds) application + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "ts2hds.h" + +#include + +#define ADOBE_INLINED_BOOTSTRAP + +struct __tag_adobe_stream +{ + FILE *f; + const char *id; + const char *base_url; + u32 bitrate; +}; + +struct __tag_adobe_multirate +{ + FILE *f; + const char *id; + const char *base_url; + GF_List *streams; +}; + +AdobeMultirate *adobe_alloc_multirate_manifest(char *id) +{ + AdobeMultirate *am = gf_calloc(1, sizeof(AdobeMultirate)); + char filename[GF_MAX_PATH]; + + //default init + am->base_url = "http://localhost/hds/tmp"; + am->id = id; + sprintf(filename, "%s.f4m", am->id); + am->f = fopen(filename, "wt"); + if (!am->f) { + fprintf(stderr, "Couldn't create Adobe multirate manifest file: %s\n", filename); + assert(0); + gf_free(am); + return NULL; + } + am->streams = gf_list_new(); + + //create a fake stream + { + AdobeStream *as = gf_calloc(1, sizeof(AdobeStream)); + as->id = "HD"; + as->bitrate = 100; + gf_list_add(am->streams, as); + } + + return am; +} + +void adobe_free_multirate_manifest(AdobeMultirate *am) +{ + u32 i; + + if (am->f) + fclose(am->f); + + for (i=0; istreams); i++) { + AdobeStream *as = gf_list_get(am->streams, i); + assert(as); + //TODO: base_url and id may be stored as gf_strdup in the future + gf_list_rem(am->streams, i); + gf_free(as); + } + gf_list_del(am->streams); + + gf_free(am); +} + +GF_Err adobe_gen_multirate_manifest(AdobeMultirate* am, char *bootstrap, size_t bootstrap_size) +{ + u32 i; +#ifdef ADOBE_INLINED_BOOTSTRAP + char bootstrap64[GF_MAX_PATH]; + u32 bootstrap64_len; +#endif + + fprintf(am->f, "\n"); + fprintf(am->f, "\n"); + fprintf(am->f, "%s\n", am->id); + fprintf(am->f, "%s\n", am->base_url); + fprintf(am->f, "live\n"); + + assert(am->streams); + for (i=0; istreams); i++) { + AdobeStream *as = gf_list_get(am->streams, i); + assert(as); +#ifdef ADOBE_INLINED_BOOTSTRAP + fprintf(am->f, "\n", as->id, as->bitrate); + bootstrap64_len = gf_base64_encode(bootstrap, bootstrap_size, bootstrap64, GF_MAX_PATH); + fwrite(bootstrap64, bootstrap64_len, 1, am->f); + if (bootstrap64_len >= GF_MAX_PATH) { + fprintf(stderr, "Bootstrap may have been truncated for stream %s_%d.\n", as->id, as->bitrate); + assert(0); + } + fprintf(am->f, "\n\n"); +#else + fprintf(am->f, "\n", as->id, as->bitrate, as->id, as->bitrate); + { + char filename[GF_MAX_PATH]; + FILE *bstfile; + sprintf(filename, "%s_%d.bootstrap", as->id, as->bitrate); + bstfile = fopen(filename, "wb"); + gf_fwrite(bootstrap, bootstrap_size, 1, bstfile); + fclose(bstfile); + } +#endif + fprintf(am->f, "\n", am->id, as->id, as->bitrate, as->bitrate, as->id, as->bitrate); + } + fprintf(am->f, "\n"); + + return GF_OK; +} diff --git a/applications/ts2hds/f4v.c b/applications/ts2hds/f4v.c new file mode 100644 index 0000000..f49284b --- /dev/null +++ b/applications/ts2hds/f4v.c @@ -0,0 +1,185 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Author: Romain Bouqueau + * Copyright (c) Romain Bouqueau 2012- + * All rights reserved + * + * Note: this development was kindly sponsorized by Vizion'R (http://vizionr.com) + * + * This file is part of GPAC / TS to HDS (ts2hds) application + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "ts2hds.h" + +//we need to write Adobe custom boxes +#include + +GF_Err adobize_segment(GF_ISOFile *isom_file, AdobeHDSCtx *ctx) +{ + GF_Err e; + GF_BitStream *bs; + + GF_AdobeFragRandomAccessBox *afra = (GF_AdobeFragRandomAccessBox*) afra_New(); + GF_AfraEntry *ae = (GF_AfraEntry*) gf_calloc(1, sizeof(GF_AfraEntry)); + GF_AdobeBootstrapInfoBox *abst = (GF_AdobeBootstrapInfoBox*) abst_New(); + GF_AdobeSegmentRunTableBox *asrt = (GF_AdobeSegmentRunTableBox*) asrt_New(); + GF_AdobeSegmentRunEntry *asre = (GF_AdobeSegmentRunEntry*) gf_calloc(1, sizeof(GF_AdobeSegmentRunEntry)); + GF_AdobeFragmentRunTableBox *afrt = (GF_AdobeFragmentRunTableBox*) afrt_New(); + GF_AdobeFragmentRunEntry *afre = (GF_AdobeFragmentRunEntry*) gf_calloc(1, sizeof(GF_AdobeFragmentRunEntry)); + + u64 init_seg_time = ctx->curr_time; + u32 seg_duration = (u32)gf_isom_get_duration(isom_file); + + //update context + ctx->curr_time += seg_duration; + + //Adobe specific boxes + //Random Access + afra->type = GF_4CC('a', 'f', 'r', 'a'); + afra->version = 0; + afra->flags = 0; + afra->long_ids = 1; + afra->long_offsets = 1; + afra->global_entries = 0; + afra->time_scale = gf_isom_get_timescale(isom_file); + + afra->entry_count = 1; + ae->time = init_seg_time; + ae->offset = 31663; + gf_list_add(afra->local_access_entries, ae); + + afra->global_entries = 0; + afra->global_entry_count = 0; + + e = gf_list_add(isom_file->TopBoxes, afra); + if (e) { + fprintf(stderr, "Impossible to write AFRA box: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + + //Bootstrap Info + abst->type = GF_4CC('a', 'b', 's', 't'); + abst->version = 0; + abst->flags = 0; + abst->bootstrapinfo_version = 1; + abst->profile = 0; + abst->live = 1; + abst->update = 0; + abst->time_scale = gf_isom_get_timescale(isom_file); + abst->current_media_time = init_seg_time+seg_duration; + abst->smpte_time_code_offset = 0; + + abst->movie_identifier = NULL; + abst->drm_data = NULL; + abst->meta_data = NULL; + + abst->server_entry_count = 0; + abst->quality_entry_count = 0; + + abst->segment_run_table_count = 1; + { + //Segment Run + asrt->type = GF_4CC('a', 's', 'r', 't'); + asrt->version = 0; + asrt->flags = 0; + asrt->segment_run_entry_count = 1; + { + asre->first_segment = 1; + asre->fragment_per_segment = 1; + } + e = gf_list_add(asrt->segment_run_entry_table, asre); + if (e) { + fprintf(stderr, "Impossible to write ASR Entry: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + } + e = gf_list_add(abst->segment_run_table_entries, asrt); + if (e) { + fprintf(stderr, "Impossible to write ASRT box: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + + abst->fragment_run_table_count = 1; + { + //Fragment Run + afrt->type = GF_4CC('a', 'f', 'r', 't'); + afrt->version = 0; + afrt->flags = 0; + afrt->timescale = 1000; + afrt->fragment_run_entry_count = 1; + { + afre->first_fragment = 1; + afre->first_fragment_timestamp = 0; + afre->fragment_duration = seg_duration; + } + e = gf_list_add(afrt->fragment_run_entry_table, afre); + if (e) { + fprintf(stderr, "Impossible to write AFR Entry: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + } + e = gf_list_add(abst->fragment_run_table_entries, afrt); + if (e) { + fprintf(stderr, "Impossible to write AFRT box: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + + e = gf_list_add(isom_file->TopBoxes, abst); + if (e) { + fprintf(stderr, "Impossible to write ABST box: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + + e = abst_Size((GF_Box*)abst); + if (e) { + fprintf(stderr, "Impossible to compute ABST box size: %s\n", gf_error_to_string(e)); + assert(0); + return e; + } + ctx->bootstrap_size = (size_t)abst->size; + ctx->bootstrap = gf_malloc(ctx->bootstrap_size); + bs = gf_bs_new(ctx->bootstrap, ctx->bootstrap_size, GF_BITSTREAM_WRITE); + e = abst_Write((GF_Box*)abst, bs); + if (e) { + fprintf(stderr, "Impossible to code the ABST box: %s\n", gf_error_to_string(e)); + assert(0); + gf_bs_del(bs); + return e; + } + gf_bs_del(bs); + + //set brands as reversed engineered from f4v files + /*e = gf_isom_reset_alt_brands(isom_file); + if (e) { + fprintf(stderr, "Warning: couldn't reset ISOM brands: %s\n", gf_error_to_string(e)); + assert(0); + }*/ + gf_isom_set_brand_info(isom_file, GF_4CC('f','4','v',' '), 1); + gf_isom_modify_alternate_brand(isom_file, GF_4CC('i','s','o','m'), 1); + gf_isom_modify_alternate_brand(isom_file, GF_4CC('m','p','4','2'), 1); + gf_isom_modify_alternate_brand(isom_file, GF_4CC('m','4','v',' '), 1); + + return GF_OK; +} \ No newline at end of file diff --git a/applications/ts2hds/main.c b/applications/ts2hds/main.c new file mode 100644 index 0000000..0e98a52 --- /dev/null +++ b/applications/ts2hds/main.c @@ -0,0 +1,304 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Author: Romain Bouqueau + * Copyright (c) Romain Bouqueau 2012- + * All rights reserved + * + * Note: this development was kindly sponsorized by Vizion'R (http://vizionr.com) + * + * This file is part of GPAC / TS to HDS (ts2hds) application + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "ts2hds.h" + +//FIXME: test only +//#include +//#include + +#ifdef WIN32 +#define strnicmp _strnicmp +#endif + +#define CHECK_NEXT_ARG if (i+1==(u32)argc) { fprintf(stderr, "Missing arg - please check usage\n"); exit(1); } + +#ifdef GPAC_DISABLE_ISOM + +#error "Cannot compile TS2HDS if GPAC is not built with ISO File Format support" + +#endif + + +static GFINLINE void usage(const char * progname) +{ + fprintf(stderr, "USAGE: %s -i input -o output\n" + "\n" +#ifdef GPAC_MEMORY_TRACKING + "\t-mem-track: enables memory tracker\n" +#endif + ); +} + + +/*parse TS2HDS arguments*/ +static GFINLINE GF_Err parse_args(int argc, char **argv, char **input, char **output, u64 *curr_time, u32 *segnum) +{ + Bool input_found=0, output_found=0; + char *arg = NULL, *error_msg = "no argument found"; + s32 i; + + for (i=1; isize = bootstrap[2]*256+bootstrap[3]; + assert(abst->size + +//f4m +typedef struct __tag_adobe_stream AdobeStream; +typedef struct __tag_adobe_multirate AdobeMultirate; +AdobeMultirate *adobe_alloc_multirate_manifest(char *id); +void adobe_free_multirate_manifest(AdobeMultirate *am); +GF_Err adobe_gen_multirate_manifest(AdobeMultirate* am, char *bootstrap, size_t bootstrap_size); + +//context +typedef struct +{ + u64 curr_time; + u32 segnum; + char *bootstrap; + size_t bootstrap_size; + AdobeMultirate *multirate_manifest; +} AdobeHDSCtx; + +//f4v +GF_Err adobize_segment(GF_ISOFile *isom_file, AdobeHDSCtx *ctx); diff --git a/applications/udptsseg/Makefile b/applications/udptsseg/Makefile index f7f7bf2..cfcadb1 100644 --- a/applications/udptsseg/Makefile +++ b/applications/udptsseg/Makefile @@ -55,11 +55,6 @@ all: $(PROG) $(PROG): $(OBJS) $(CC) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKFLAGS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(PROG) diff --git a/applications/udptsseg/main.c b/applications/udptsseg/main.c index b372b65..9825bff 100644 --- a/applications/udptsseg/main.c +++ b/applications/udptsseg/main.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * -* Copyright (c) ENST 2000-200X + * Authors: Cyril COncolato, Romain Bouqueau + * Copyright (c) Telecom ParisTech 2008-2012 * All rights reserved * * This file is part of GPAC / udp TS segmenter (udptsseg) application diff --git a/bin/smartphone 2003 (armv4)/release/install/archive.bat b/bin/smartphone 2003 (armv4)/release/install/archive.bat index f91f14d..7ec194b 100644 --- a/bin/smartphone 2003 (armv4)/release/install/archive.bat +++ b/bin/smartphone 2003 (armv4)/release/install/archive.bat @@ -2,7 +2,8 @@ set OLDDIR=%CD% cd /d %~dp0 for /f "delims=" %%a in ('svnversion ') do set gpac_revision=%%a +set gpac_version="0.5.1-DEV-r%gpac_revision%" -zip "GPAC_0.5.0-r%gpac_revision%_WindowsMobile.zip" ../*.dll ../*.exe ../*.plg +zip "GPAC_%gpac_version%_WindowsMobile.zip" ../*.dll ../*.exe ../*.plg cd /d %OLDDIR% diff --git a/bin/smartphone 2003 (armv4)/release/install/build_installer.bat b/bin/smartphone 2003 (armv4)/release/install/build_installer.bat index 8591a04..ad3dcad 100644 --- a/bin/smartphone 2003 (armv4)/release/install/build_installer.bat +++ b/bin/smartphone 2003 (armv4)/release/install/build_installer.bat @@ -3,8 +3,10 @@ cd /d %~dp0 for /f "delims=" %%a in ('svnversion') do set gpac_revision=%%a +set gpac_version="0.5.1-DEV-r%gpac_revision%" + ECHO [Version] > gpaccab.inf -ECHO Provider = "GPAC 0.5.0-r%gpac_revision%" >> gpaccab.inf +ECHO Provider = "GPAC %gpac_version%" >> gpaccab.inf type gpac.inf >> gpaccab.inf CabWiz gpaccab.inf @@ -12,7 +14,7 @@ CabWiz gpaccab.inf ECHO off ECHO [CEAppManager]> gpac.ini -ECHO Version = 0.5.0-r%gpac_revision%>> gpac.ini +ECHO Version = %gpac_version%>> gpac.ini ECHO Component = GPAC for Windows Mobile>> gpac.ini ECHO [GPAC for Windows Mobile]>> gpac.ini ECHO Description = GPAC MPEG-4 Player>> gpac.ini @@ -24,7 +26,7 @@ ECHO CabFiles = gpaccab.cab >> gpac.ini ECHO on ezsetup -l english -i gpac.ini -r readme.txt -e ../../../../COPYING -o gpac.exe -rename gpac.exe "GPAC_0.5.0-r%gpac_revision%_WindowsMobile.exe" +rename gpac.exe "GPAC_%gpac_version%_WindowsMobile.exe" DEL gpaccab.cab DEL gpaccab.inf DEL gpac.ini diff --git a/bin/smartphone 2003 (armv4)/release/install/gpac.inf b/bin/smartphone 2003 (armv4)/release/install/gpac.inf index 5879e32..0bce1e0 100644 --- a/bin/smartphone 2003 (armv4)/release/install/gpac.inf +++ b/bin/smartphone 2003 (armv4)/release/install/gpac.inf @@ -1,5 +1,4 @@ ;[Version] -;Provider = "GPAC 0.5.0" Signature = "$Windows NT$" CESignature = "$Windows CE$" diff --git a/bin/smartphone 2003 (armv4)/release/install/readme.txt b/bin/smartphone 2003 (armv4)/release/install/readme.txt index 46dd627..08442c1 100644 --- a/bin/smartphone 2003 (armv4)/release/install/readme.txt +++ b/bin/smartphone 2003 (armv4)/release/install/readme.txt @@ -1,4 +1,4 @@ -This will install GPAC version 0.5.0 for ARM PocketPC/SmartPhones 2003 Platforms +This will install GPAC for ARM PocketPC/SmartPhones 2003 Platforms GPAC is an open source MPEG-4 framework developped by ENST and available at: http://gpac.sourceforge.net diff --git a/bin/win32/release/nsis_install/gpac_installer.nsi b/bin/win32/release/nsis_install/gpac_installer.nsi index 65437e9..d9645da 100644 --- a/bin/win32/release/nsis_install/gpac_installer.nsi +++ b/bin/win32/release/nsis_install/gpac_installer.nsi @@ -1,6 +1,6 @@ ;-------------------------------- ;General -!define GPAC_VERSION 0.5.0 +!define GPAC_VERSION 0.5.1-DEV !include default.out !define GPAC_ROOT ..\..\..\.. diff --git a/configure b/configure index 2da22e1..e3220ac 100755 --- a/configure +++ b/configure @@ -1,7 +1,9 @@ #!/bin/sh # -# GPAC MPEG-4 SDK configure script (c) 2003-2005 Jean Le Feuvre (c) 2005-20XX Telecom ParisTech -# inspired from ffmpeg configure by Fabrice Bellard (c) 2000-2002 +# GPAC configure script +# (c) 2003-2012 Telecom ParisTech +# Authors: Jean Le Feuvre, Romain Bouqueau +# #set -v @@ -15,7 +17,7 @@ else fi -#thanks to ffmpeg for this +#remember the ./configure command line for v in "$@"; do r="${v#*=}" l="${v%$r}" @@ -56,6 +58,7 @@ debuginfo="no" sdl_path="" sdl_local="no" sdl_static="no" +verbose="no" xulsdk_path="/usr/lib/xulrunner/sdk/include" xul_flags="" libdir="lib" @@ -108,6 +111,7 @@ has_joystick="no" has_xul="no" enable_joystick="no" static_mp4box="no" +disable_core_tools="no" disable_3d="no" disable_svg="no" disable_vrml="no" @@ -136,8 +140,11 @@ disable_loader_isoff="no" disable_loader_bt="no" disable_loader_xmt="no" disable_od_dump="no" +disable_od_parse="no" disable_isom_dump="no" disable_mcrypt="no" +disable_mpd="no" +disable_dash="no" disable_isoff="no" disable_isoff_write="no" disable_isoff_frag="no" @@ -146,7 +153,7 @@ disable_isoff_frag="no" disable_streaming="no" disable_player="no" disable_scenegraph="no" -disable_dvbx="no" +disable_dvbx="yes" disable_vobsub="no" disable_ttxt="no" enable_depth_compositor="no" @@ -193,6 +200,7 @@ GPAC configuration options: --prefix=PREFIX install in PREFIX [$prefix] --mandir=DIR man documentation in DIR [PREFIX/man] + --verbose enable verbose building [$verbose] --source-path=PATH path of source code [$source_path] --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix] --cc =CC use C compiler CC [$cc] @@ -276,7 +284,7 @@ Configuration options for libgpac - all options can be enabled with --enable-opt --disable-isoff-hint disable ISO File Format hinting --disable-isoff-frag disable fragments in ISO File Format --disable-streaming disable RTP/RTSP/SDP - --disable-dvb disable DVB-specific tools (MPE, FEC, DSM-CC) + --disable-dvbx disable DVB-specific tools (MPE, FEC, DSM-CC) --disable-vobsub disable VobSub support --disable-sman disable scene manager --disable-ttxt disable TTXT (3GPP / MPEG-4 Timed Text) support @@ -334,6 +342,8 @@ for opt do ;; --enable-pic) want_pic="yes"; ;; + --verbose) verbose="yes"; + ;; esac done @@ -646,14 +656,9 @@ fi if test "$has_zlib" = "no" ; then if $cc -o $TMPO $TMPC -I"$local_inc/zlib" -L$local_lib -lz 2> /dev/null ; then has_zlib="local" - else - echo "error: zlib not found on system or in local libs" - exit 1 fi fi - - #check dlopen cat > $TMPC << EOF #include @@ -664,16 +669,13 @@ if $cc -o $TMPE $TMPC > /dev/null 2>&1 ; then dlopen="yes" elif $cc -o $TMPE $TMPC $LDFLAGS -ldl > /dev/null 2>&1 ; then GPAC_SH_FLAGS="$GPAC_SH_FLAGS -ldl" -else - if test "$win32" = "no"; then - echo "error: dlopen not found on system" - exit 1 - fi fi #look for spidermonkey JS support +mozjs_pkgcfg="no" + #spidermonkey test for new API if test "$has_js" = "no" ; then @@ -692,11 +694,19 @@ EOF else #try pkg-config if $pkg_config --exists mozilla-js 2> /dev/null ; then - js_flags=`$pkg_config --cflags mozilla-js` - js_lib_pkg=`$pkg_config --libs mozilla-js` + mozjs_pkgcfg="mozilla-js" + elif $pkg_config --exists mozjs 2> /dev/null ; then + mozjs_pkgcfg="mozjs" + elif $pkg_config --exists mozjs185 2> /dev/null ; then + mozjs_pkgcfg="mozjs185" + fi + + if test $mozjs_pkgcfg != "no" ; then + js_flags=`$pkg_config --cflags $mozjs_pkgcfg` + js_lib_pkg=`$pkg_config --libs $mozjs_pkgcfg` if $cc -o $TMPO $TMPC $js_flags $js_lib_pkg $LDFLAGS -lpthread 2> /dev/null ; then has_js="system" - js_lib=`$pkg_config --libs mozilla-js` + js_lib=`$pkg_config --libs $mozjs_pkgcfg` fi #try firefox folders (starting at ubuntu 11.10, no pkg-config) elif ls -d /usr/lib/firefox* > /dev/null 2>&1 ; then @@ -787,11 +797,19 @@ EOF #dc added end else if $pkg_config --exists mozilla-js 2> /dev/null ; then - js_flags=`$pkg_config --cflags mozilla-js` - js_lib_pkg=`$pkg_config --libs mozilla-js` + mozjs_pkgcfg="mozilla-js" + elif $pkg_config --exists mozjs 2> /dev/null ; then + mozjs_pkgcfg="mozjs" + elif $pkg_config --exists mozjs185 2> /dev/null ; then + mozjs_pkgcfg="mozjs185" + fi + + if test mozjs_pkgcfg != "no" ; then + js_flags=`$pkg_config --cflags $mozjs_pkgcfg` + js_lib_pkg=`$pkg_config --libs $mozjs_pkgcfg` if $cc -o $TMPO $TMPC $js_flags $js_lib_pkg $LDFLAGS -lpthread 2> /dev/null ; then has_js="system" - js_lib=`$pkg_config --libs mozilla-js` + js_lib=`$pkg_config --libs $mozjs_pkgcfg` fi fi if test "$has_js" = "no" ; then @@ -844,7 +862,20 @@ cat > $TMPC << EOF int main( void ) { JSObject *obj; JS_GetPrivate(obj); } EOF if $cc -o $TMPO $TMPC $js_flags $LDFLAGS $js_lib 2> /dev/null ; then - js_flags="-DUSE_FFDEV_12 $js_flags" + +cat > $TMPC << EOF +#include +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 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 + js_flags="-DUSE_FFDEV_15 $js_flags" + else + js_flags="-DUSE_FFDEV_14 $js_flags" + fi else cat > $TMPC << EOF #include @@ -962,15 +993,15 @@ if test "$cross_prefix" = "" ; then if $cc $CFLAGS_DIR -o $TMPO $TMPC $ft_cflags $ft_lflags $LDFLAGS 2> /dev/null ; then has_ft="system" else - ft_cflags="`freetype-config --cflags`" - ft_lflags="`freetype-config --libs`" + ft_cflags="`freetype-config --cflags 2> /dev/null`" + ft_lflags="`freetype-config --libs 2> /dev/null`" if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags $LDFLAGS 2> /dev/null ; then has_ft="system" fi fi fi if test "$has_ft" = "no" ; then - if test "`which freetype-config`" != ""; then + if test "`which freetype-config 2> /dev/null`" != ""; then ft_cflags="-I$local_inc/freetype" ft_lflags="-L$local_lib -lfreetype" if $cc -o $TMPO $TMPC $ft_cflags $ft_lflags 2> /dev/null ; then @@ -1017,7 +1048,7 @@ if test "$cross_prefix" = "" ; then if cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -ljpeg 2> /dev/null ; then has_jpeg="system" fi - elif test "`which $prefix/bin/jpeg-config`" != ""; then + elif test "`which $prefix/bin/jpeg-config 2> /dev/null`" != ""; then jpeg_cflags="`$prefix/bin/jpeg-config --cflags`" jpeg_lflags="`$prefix/bin/jpeg-config --libs`" if $cc -o $TMPO $TMPC $jpeg_cflags $jpeg_lflags $LDFLAGS 2> /dev/null ; then @@ -1698,7 +1729,7 @@ for opt do --enable-pulseaudio=*) has_pulseaudio="yes" ;; - --disable-all) has_pulseaudio="no"; has_alsa="no"; 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_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_ttxt="yes"; disable_saf="yes"; disable_smgr="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-3d) disable_3d="yes" @@ -1807,6 +1838,10 @@ for opt do ;; --enable-od-dump) disable_od_dump="no" ;; + --disable-od-parse) disable_od_parse="yes" + ;; + --enable-od-parse) disable_od_parse="no" + ;; --disable-isom-dump) disable_isom_dump="yes" ;; --enable-isom-dump) disable_isom_dump="no" @@ -1863,12 +1898,39 @@ for opt do ;; --enable-smgr) disable_smgr="no" ;; - + --disable-mpd) disable_mpd="yes" + ;; + --enable-mpd) disable_mpd="no" + ;; + --disable-dash) disable_dash="yes" + ;; + --enable-dash) disable_dash="no" + ;; + --disable-core) disable_core_tools="yes" + ;; + --enable-core) disable_core_tools="no" + ;; esac done +if test "$disable_core_tools" = "no"; then + if test "$has_zlib" = "no" ; then + echo "error: zlib not found on system or in local libs" + exit 1 + fi + if test "$dlopen" = "no"; then + if test "$win32" = "no"; then + echo "error: dlopen not found on system" + exit 1 + fi + fi +else +GPAC_SH_FLAGS="" +has_ssl="no" +fi + #look for OpenGL support or for TinyGL support LINK3D="" INCL3D="" @@ -1958,8 +2020,10 @@ if test "$has_xul" = "no" ; then #xulrunner directories are sometimes included through js/xul/ff packages if test ! "$has_js" = "no" -a ! "$has_js" = "local" ; then if $cc -o $TMPO $TMPCPP $js_flags $js_lib_pkg $LDFLAGS 2> /dev/null ; then - xul_flags=`$pkg_config --cflags mozilla-js` - has_xul="$has_js" + if test "$mozjs_pkgcfg" != "no" ; then + xul_flags=`$pkg_config --cflags $mozjs_pkgcfg` + has_xul="$has_js" + fi fi fi fi @@ -2093,12 +2157,15 @@ if test "$cpu" = "sh4"; then fi fi +if test "$disable_player" = "yes" ; then +disable_scenegraph="yes" +fi + if test "$disable_scenegraph" = "yes" ; then disable_3d="yes" disable_svg="yes" disable_vrml="yes" disable_x3d="yes" -disable_od="no" disable_bifs="yes" disable_bifs_enc="yes" disable_laser="yes" @@ -2113,6 +2180,23 @@ disable_loader_bt="yes" disable_loader_xmt="yes" disable_streaming="yes" disable_player="yes" +disable_smgr="yes" +has_js="no" +fi + +if test "$disable_mpd" = "yes"; then +disable_dash="yes" +fi + +if test "$disable_od_parse" = "yes" ; then +disable_loader_isoff="yes" +disable_loader_bt="yes" +disable_loader_xmt="yes" +fi + +if test "$disable_parsers" = "yes" ; then +has_jpeg="no" +has_png="no" fi #prepare for config.h writing @@ -2122,22 +2206,24 @@ echo "#ifndef GF_CONFIG_H" >> $TMPH echo "#define GF_CONFIG_H" >> $TMPH echo "#define GPAC_CONFIGURATION \"$GPAC_CONFIGURATION\"" >> $TMPH -version="`grep '#define GPAC_VERSION ' \"$source_path/include/gpac/tools.h\" | cut -d '"' -f 2`" -version_major=`grep '#define GPAC_VERSION_MAJOR ' $source_path/include/gpac/tools.h | sed -e 's/.*\([0-9]\)\+$/\1/'` -version_minor=`grep '#define GPAC_VERSION_MINOR ' $source_path/include/gpac/tools.h | sed -e 's/.*\([0-9]\)\+$/\1/'` -version_micro=`grep '#define GPAC_VERSION_MICRO ' $source_path/include/gpac/tools.h | sed -e 's/.*\([0-9]\)\+$/\1/'` +version="`grep '#define GPAC_VERSION ' \"$source_path/include/gpac/version.h\" | cut -d '"' -f 2`" +version_major=`grep '#define GPAC_VERSION_MAJOR ' $source_path/include/gpac/version.h | sed -e 's/.*\([0-9]\)\+$/\1/'` +version_minor=`grep '#define GPAC_VERSION_MINOR ' $source_path/include/gpac/version.h | sed -e 's/.*\([0-9]\)\+$/\1/'` +version_micro=`grep '#define GPAC_VERSION_MICRO ' $source_path/include/gpac/version.h | sed -e 's/.*\([0-9]\)\+$/\1/'` soname_version="${version_major}.${version_minor}.${version_micro}" if [ -d ".svn" ]; then - if which svnversion >/dev/null + if which svnversion 2>/dev/null then revision="`svnversion \"$source_path\"`" - echo "#define GPAC_SVN_REVISION \"$revision\"" > $source_path/include/gpac/version.h + echo "#define GPAC_SVN_REVISION \"$revision\"" > $source_path/include/gpac/revision.h else echo "Cannot find SVN revision" fi else - echo "#define GPAC_SVN_REVISION \"4065\"" > $source_path/include/gpac/version.h + if [ ! -e "$source_path/include/gpac/revision.h" ]; then + echo "#define GPAC_SVN_REVISION \"4065\"" > $source_path/include/gpac/revision.h + fi fi echo "" @@ -2182,6 +2268,10 @@ disable_svg="yes" echo "Scene Manager disabled" echo "#define GPAC_DISABLE_SMGR" >> $TMPH fi +if test "$disable_core_tools" = "yes" ; then + echo "Core tools disabled" + echo "#define GPAC_DISABLE_CORE_TOOLS" >> $TMPH +fi if test "$disable_svg" = "yes" ; then echo "SVG disabled" echo "#define GPAC_DISABLE_SVG" >> $TMPH @@ -2199,6 +2289,10 @@ if test "$disable_od" = "yes" ; then echo "OD Full support disabled" echo "#define GPAC_MINIMAL_ODF" >> $TMPH fi +if test "$disable_od_parse" = "yes" ; then + echo "OD Parsing disabled" + echo "#define GPAC_DISABLE_OD_PARSE" >> $TMPH +fi if test "$disable_bifs" = "yes" ; then echo "BIFS coder disabled" echo "#define GPAC_DISABLE_BIFS" >> $TMPH @@ -2315,10 +2409,10 @@ if test "$disable_streaming" = "yes" ; then echo "RTP/RTSP/SDP streaming disabled" echo "#define GPAC_DISABLE_STREAMING" >> $TMPH fi -if test "$disable_dvbx" = "yes" ; then +if test "$disable_dvbx" = "no" ; then echo "DVB MPE and DSM-CC disabled" - echo "#define GPAC_DISABLE_MPE" >> $TMPH - echo "#define GPAC_DISABLE_DSMCC" >> $TMPH + echo "#define GPAC_ENABLE_MPE" >> $TMPH + echo "#define GPAC_ENABLE_DSMCC" >> $TMPH fi if test "$disable_vobsub" = "yes" ; then echo "VobSub disabled" @@ -2334,6 +2428,15 @@ if test "$enable_depth_compositor" = "yes" ; then echo "#define GF_SR_USE_DEPTH" >> $TMPH fi +if test "$disable_mpd" = "yes" ; then + echo "HLS and DASH Manifest Disabled" +fi + +if test "$disable_dash" = "yes" ; then + echo "Adaptive HTTP Streaming Client disabled" + echo "#define GPAC_DISABLE_DASH_CLIENT" >> $TMPH +fi + echo "" echo "** Detected libraries **" @@ -2474,11 +2577,21 @@ echo "moddir_path=$prefix/$libdir/gpac" >> config.mak echo "mandir=$mandir" >> config.mak echo "tinygl_target_bin_dir=$target_bin_dir" >> config.mak echo "MAKE=$make" >> config.mak + +if test "$verbose" = "yes" ; then echo "CC=$cc_naked" >> config.mak echo "AR=$ar" >> config.mak echo "RANLIB=$ranlib" >> config.mak echo "STRIP=$strip" >> config.mak +else +echo "CC=@$cc_naked" >> config.mak +echo "AR=@$ar" >> config.mak +echo "RANLIB=@$ranlib" >> config.mak +echo "STRIP=@$strip" >> config.mak +fi echo "INSTALL=$install" >> config.mak +echo "LIBTOOL=libtool" >> config.mak + echo "INSTFLAGS=$instflags" >> config.mak echo "OPTFLAGS=$CFLAGS" >> config.mak echo "CPPFLAGS=$CPPFLAGS" >> config.mak @@ -2643,15 +2756,21 @@ echo "DISABLE_ISOFF_HINT=$disable_isoff_hint" >> config.mak echo "DISABLE_VOBSUB=$disable_vobsub" >> config.mak echo "DISABLE_TTXT=$disable_ttxt" >> config.mak echo "DISABLE_SMGR=$disable_smgr" >> config.mak +echo "DISABLE_AV_PARSERS=$disable_parsers" >> config.mak +echo "DISABLE_MEDIA_IMPORT=$disable_import" >> config.mak +echo "DISABLE_MEDIA_EXPORT=$disable_export" >> config.mak +echo "DISABLE_MPD=$disable_mpd" >> config.mak +echo "DISABLE_DASH_CLIENT=$disable_dash" >> config.mak +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 if test "$disable_parsers" = "yes" ; then disable_m2ts_mux="yes" fi -if test "$disable_m2ts_mux" = "yes" -o "$disable_m2ts" = "yes" ; then - echo "DISABLE_M2TS=yes" >> config.mak -else - echo "DISABLE_M2TS=no" >> config.mak -fi +echo "DISABLE_M2TS_MUX=$disable_m2ts_mux" >> config.mak +echo "DISABLE_M2TS=$disable_m2ts" >> config.mak echo "GPAC_USE_TINYGL=$has_tinygl" >> config.mak @@ -2882,13 +3001,29 @@ if [ ! -d "./bin/gcc/temp" ] ; then mkdir ./bin/gcc/temp fi + echo '%.opic : %.c' >> config.mak +if test "$verbose" = "no" ; then +echo ' @echo " CC $<"' >> config.mak +fi echo ' $(CC) $(CFLAGS) $(PIC_CFLAGS) -c $< -o $@' >> config.mak +echo '%.o : %.c' >> config.mak +if test "$verbose" = "no" ; then +echo ' @echo " CC $<"' >> config.mak +fi +echo ' $(CC) $(CFLAGS) -c -o $@ $<' >> config.mak + +echo '%.o: %.cpp' >> config.mak +if test "$verbose" = "no" ; then +echo ' @echo " CC $<"' >> config.mak +fi +echo ' $(CXX) $(CFLAGS) -c -o $@ $<' >> config.mak + #pkg-config echo "prefix=$prefix" > gpac.pc echo "exec_prefix=\${prefix}" >> gpac.pc -echo "libdir=\${exec_prefix}/lib" >> gpac.pc +echo "libdir=\${exec_prefix}/$libdir" >> gpac.pc echo "includedir=\${exec_prefix}/include" >> gpac.pc echo "" >> gpac.pc echo "Name: gpac" >> gpac.pc diff --git a/doc/configuration.html b/doc/configuration.html index 019f6c6..1062baf 100644 Binary files a/doc/configuration.html and b/doc/configuration.html differ diff --git a/extra_lib/include/avcap/Connector.h b/extra_lib/include/avcap/Connector.h index cc318a7..94b390a 100644 --- a/extra_lib/include/avcap/Connector.h +++ b/extra_lib/include/avcap/Connector.h @@ -31,7 +31,11 @@ #ifdef AVCAP_LINUX # include -# include +# ifdef AVCAP_HAVE_V4L2 +# include +# else +# include +# endif #endif #include diff --git a/extra_lib/include/avcap/FormatManager.h b/extra_lib/include/avcap/FormatManager.h index b111c26..04bf1ce 100644 --- a/extra_lib/include/avcap/FormatManager.h +++ b/extra_lib/include/avcap/FormatManager.h @@ -37,7 +37,11 @@ #ifdef AVCAP_LINUX # include -# include +# ifdef AVCAP_HAVE_V4L2 +# include +# else +# include +# endif #endif // AVCAP_LINUX #ifdef _WIN32 diff --git a/extra_lib/include/avcap/linux/V4L1_Connector.h b/extra_lib/include/avcap/linux/V4L1_Connector.h index 827b5eb..db4e825 100644 --- a/extra_lib/include/avcap/linux/V4L1_Connector.h +++ b/extra_lib/include/avcap/linux/V4L1_Connector.h @@ -26,13 +26,18 @@ #define V4L1_CONNECTOR_H_ #include -#include #include #include #include "Connector.h" +#ifdef AVCAP_HAVE_V4L2 +#include +#else +#include +#endif + namespace avcap { // forward declaration diff --git a/extra_lib/include/avcap/linux/V4L1_ConnectorManager.h b/extra_lib/include/avcap/linux/V4L1_ConnectorManager.h index f771b67..4b211b6 100644 --- a/extra_lib/include/avcap/linux/V4L1_ConnectorManager.h +++ b/extra_lib/include/avcap/linux/V4L1_ConnectorManager.h @@ -25,11 +25,16 @@ #ifndef V4L1_CONNECTORMANAGER_H_ #define V4L1_CONNECTORMANAGER_H_ -#include #include #include "ConnectorManager.h" +#ifdef AVCAP_HAVE_V4L2 +#include +#else +#include +#endif + namespace avcap { class V4L1_DeviceDescriptor; diff --git a/extra_lib/include/avcap/linux/V4L2_Connector.h b/extra_lib/include/avcap/linux/V4L2_Connector.h index 3927bf2..469d4ef 100644 --- a/extra_lib/include/avcap/linux/V4L2_Connector.h +++ b/extra_lib/include/avcap/linux/V4L2_Connector.h @@ -26,13 +26,18 @@ #define V4L2_CONNECTOR_H_ #include -#include #include #include #include "Connector.h" +#ifdef AVCAP_HAVE_V4L2 +#include +#else +#include +#endif + namespace avcap { // forward declaration diff --git a/extra_lib/include/avcap/linux/V4L2_ControlBase.h b/extra_lib/include/avcap/linux/V4L2_ControlBase.h index 806574c..f8efb75 100644 --- a/extra_lib/include/avcap/linux/V4L2_ControlBase.h +++ b/extra_lib/include/avcap/linux/V4L2_ControlBase.h @@ -26,7 +26,16 @@ #include #include + +#if !defined(_MSC_VER) && !defined(USE_PREBUILD_LIBS) +# include "avcap-config.h" +#endif + +#ifdef AVCAP_HAVE_V4L2 +#include +#else #include +#endif namespace avcap { diff --git a/extra_lib/include/avcap/linux/V4L2_Tuner.h b/extra_lib/include/avcap/linux/V4L2_Tuner.h index 043acb4..1dcdf6d 100644 --- a/extra_lib/include/avcap/linux/V4L2_Tuner.h +++ b/extra_lib/include/avcap/linux/V4L2_Tuner.h @@ -26,11 +26,15 @@ #define V4L2_TUNER_H_ #include -#include #include #include #include "Tuner_avcap.h" +#ifdef AVCAP_HAVE_V4L2 +#include +#else +#include +#endif namespace avcap { diff --git a/extra_lib/include/libavcodec/avcodec.h b/extra_lib/include/libavcodec/avcodec.h index 594da5f..0b3a19a 100644 --- a/extra_lib/include/libavcodec/avcodec.h +++ b/extra_lib/include/libavcodec/avcodec.h @@ -22,33 +22,64 @@ #define AVCODEC_AVCODEC_H /** - * @file libavcodec/avcodec.h + * @file * external API header */ #include +#include "libavutil/samplefmt.h" #include "libavutil/avutil.h" +#include "libavutil/cpu.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/audioconvert.h" + +#include "libavcodec/version.h" +/** + * @defgroup libavc Encoding/Decoding Library + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + * + */ -#define LIBAVCODEC_VERSION_MAJOR 52 -#define LIBAVCODEC_VERSION_MINOR 29 -#define LIBAVCODEC_VERSION_MICRO 0 - -#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ - LIBAVCODEC_VERSION_MINOR, \ - LIBAVCODEC_VERSION_MICRO) -#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ - LIBAVCODEC_VERSION_MINOR, \ - LIBAVCODEC_VERSION_MICRO) -#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT - -#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ -#define AV_NOPTS_VALUE INT64_C(0x8000000000000000) -#define AV_TIME_BASE 1000000 -#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE} /** - * Identifies the syntax and semantics of the bitstream. + * Identify the syntax and semantics of the bitstream. * The principle is roughly: * Two decoders with the same ID can decode the same streams. * Two encoders with the same ID can encode compatible streams. @@ -57,359 +88,454 @@ * * If you add a codec ID to this list, add it so that * 1. no value of a existing codec ID changes (that would break ABI), - * 2. it is as close as possible to similar codecs. + * 2. Give it a value which when taken as ASCII is recognized uniquely by a human as this specific codec. + * This ensures that 2 forks can independently add AVCodecIDs without producing conflicts. + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. */ -enum CodecID { - CODEC_ID_NONE, +enum AVCodecID { + AV_CODEC_ID_NONE, /* video codecs */ - CODEC_ID_MPEG1VIDEO, - CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding - CODEC_ID_MPEG2VIDEO_XVMC, - CODEC_ID_H261, - CODEC_ID_H263, - CODEC_ID_RV10, - CODEC_ID_RV20, - CODEC_ID_MJPEG, - CODEC_ID_MJPEGB, - CODEC_ID_LJPEG, - CODEC_ID_SP5X, - CODEC_ID_JPEGLS, - CODEC_ID_MPEG4, - CODEC_ID_RAWVIDEO, - CODEC_ID_MSMPEG4V1, - CODEC_ID_MSMPEG4V2, - CODEC_ID_MSMPEG4V3, - CODEC_ID_WMV1, - CODEC_ID_WMV2, - CODEC_ID_H263P, - CODEC_ID_H263I, - CODEC_ID_FLV1, - CODEC_ID_SVQ1, - CODEC_ID_SVQ3, - CODEC_ID_DVVIDEO, - CODEC_ID_HUFFYUV, - CODEC_ID_CYUV, - CODEC_ID_H264, - CODEC_ID_INDEO3, - CODEC_ID_VP3, - CODEC_ID_THEORA, - CODEC_ID_ASV1, - CODEC_ID_ASV2, - CODEC_ID_FFV1, - CODEC_ID_4XM, - CODEC_ID_VCR1, - CODEC_ID_CLJR, - CODEC_ID_MDEC, - CODEC_ID_ROQ, - CODEC_ID_INTERPLAY_VIDEO, - CODEC_ID_XAN_WC3, - CODEC_ID_XAN_WC4, - CODEC_ID_RPZA, - CODEC_ID_CINEPAK, - CODEC_ID_WS_VQA, - CODEC_ID_MSRLE, - CODEC_ID_MSVIDEO1, - CODEC_ID_IDCIN, - CODEC_ID_8BPS, - CODEC_ID_SMC, - CODEC_ID_FLIC, - CODEC_ID_TRUEMOTION1, - CODEC_ID_VMDVIDEO, - CODEC_ID_MSZH, - CODEC_ID_ZLIB, - CODEC_ID_QTRLE, - CODEC_ID_SNOW, - CODEC_ID_TSCC, - CODEC_ID_ULTI, - CODEC_ID_QDRAW, - CODEC_ID_VIXL, - CODEC_ID_QPEG, - CODEC_ID_XVID, - CODEC_ID_PNG, - CODEC_ID_PPM, - CODEC_ID_PBM, - CODEC_ID_PGM, - CODEC_ID_PGMYUV, - CODEC_ID_PAM, - CODEC_ID_FFVHUFF, - CODEC_ID_RV30, - CODEC_ID_RV40, - CODEC_ID_VC1, - CODEC_ID_WMV3, - CODEC_ID_LOCO, - CODEC_ID_WNV1, - CODEC_ID_AASC, - CODEC_ID_INDEO2, - CODEC_ID_FRAPS, - CODEC_ID_TRUEMOTION2, - CODEC_ID_BMP, - CODEC_ID_CSCD, - CODEC_ID_MMVIDEO, - CODEC_ID_ZMBV, - CODEC_ID_AVS, - CODEC_ID_SMACKVIDEO, - CODEC_ID_NUV, - CODEC_ID_KMVC, - CODEC_ID_FLASHSV, - CODEC_ID_CAVS, - CODEC_ID_JPEG2000, - CODEC_ID_VMNC, - CODEC_ID_VP5, - CODEC_ID_VP6, - CODEC_ID_VP6F, - CODEC_ID_TARGA, - CODEC_ID_DSICINVIDEO, - CODEC_ID_TIERTEXSEQVIDEO, - CODEC_ID_TIFF, - CODEC_ID_GIF, - CODEC_ID_FFH264, - CODEC_ID_DXA, - CODEC_ID_DNXHD, - CODEC_ID_THP, - CODEC_ID_SGI, - CODEC_ID_C93, - CODEC_ID_BETHSOFTVID, - CODEC_ID_PTX, - CODEC_ID_TXD, - CODEC_ID_VP6A, - CODEC_ID_AMV, - CODEC_ID_VB, - CODEC_ID_PCX, - CODEC_ID_SUNRAST, - CODEC_ID_INDEO4, - CODEC_ID_INDEO5, - CODEC_ID_MIMIC, - CODEC_ID_RL2, - CODEC_ID_8SVX_EXP, - CODEC_ID_8SVX_FIB, - CODEC_ID_ESCAPE124, - CODEC_ID_DIRAC, - CODEC_ID_BFI, - CODEC_ID_CMV, - CODEC_ID_MOTIONPIXELS, - CODEC_ID_TGV, - CODEC_ID_TGQ, - CODEC_ID_TQI, - CODEC_ID_AURA, - CODEC_ID_AURA2, - CODEC_ID_V210X, - CODEC_ID_TMV, - CODEC_ID_V210, + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_MPEG2VIDEO_XVMC, + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, + AV_CODEC_ID_IFF_BYTERUN1, + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_Y41P = MKBETAG('Y','4','1','P'), + AV_CODEC_ID_ESCAPE130 = MKBETAG('E','1','3','0'), + AV_CODEC_ID_EXR = MKBETAG('0','E','X','R'), + AV_CODEC_ID_AVRP = MKBETAG('A','V','R','P'), + + AV_CODEC_ID_G2M = MKBETAG( 0 ,'G','2','M'), + AV_CODEC_ID_AVUI = MKBETAG('A','V','U','I'), + AV_CODEC_ID_AYUV = MKBETAG('A','Y','U','V'), + AV_CODEC_ID_TARGA_Y216 = MKBETAG('T','2','1','6'), + AV_CODEC_ID_V308 = MKBETAG('V','3','0','8'), + AV_CODEC_ID_V408 = MKBETAG('V','4','0','8'), + AV_CODEC_ID_YUV4 = MKBETAG('Y','U','V','4'), + AV_CODEC_ID_SANM = MKBETAG('S','A','N','M'), + AV_CODEC_ID_PAF_VIDEO = MKBETAG('P','A','F','V'), + AV_CODEC_ID_AVRN = MKBETAG('A','V','R','n'), + AV_CODEC_ID_CPIA = MKBETAG('C','P','I','A'), + AV_CODEC_ID_XFACE = MKBETAG('X','F','A','C'), /* various PCM "codecs" */ - CODEC_ID_PCM_S16LE= 0x10000, - CODEC_ID_PCM_S16BE, - CODEC_ID_PCM_U16LE, - CODEC_ID_PCM_U16BE, - CODEC_ID_PCM_S8, - CODEC_ID_PCM_U8, - CODEC_ID_PCM_MULAW, - CODEC_ID_PCM_ALAW, - CODEC_ID_PCM_S32LE, - CODEC_ID_PCM_S32BE, - CODEC_ID_PCM_U32LE, - CODEC_ID_PCM_U32BE, - CODEC_ID_PCM_S24LE, - CODEC_ID_PCM_S24BE, - CODEC_ID_PCM_U24LE, - CODEC_ID_PCM_U24BE, - CODEC_ID_PCM_S24DAUD, - CODEC_ID_PCM_ZORK, - CODEC_ID_PCM_S16LE_PLANAR, - CODEC_ID_PCM_DVD, - CODEC_ID_PCM_F32BE, - CODEC_ID_PCM_F32LE, - CODEC_ID_PCM_F64BE, - CODEC_ID_PCM_F64LE, + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, /* various ADPCM codecs */ - CODEC_ID_ADPCM_IMA_QT= 0x11000, - CODEC_ID_ADPCM_IMA_WAV, - CODEC_ID_ADPCM_IMA_DK3, - CODEC_ID_ADPCM_IMA_DK4, - CODEC_ID_ADPCM_IMA_WS, - CODEC_ID_ADPCM_IMA_SMJPEG, - CODEC_ID_ADPCM_MS, - CODEC_ID_ADPCM_4XM, - CODEC_ID_ADPCM_XA, - CODEC_ID_ADPCM_ADX, - CODEC_ID_ADPCM_EA, - CODEC_ID_ADPCM_G726, - CODEC_ID_ADPCM_CT, - CODEC_ID_ADPCM_SWF, - CODEC_ID_ADPCM_YAMAHA, - CODEC_ID_ADPCM_SBPRO_4, - CODEC_ID_ADPCM_SBPRO_3, - CODEC_ID_ADPCM_SBPRO_2, - CODEC_ID_ADPCM_THP, - CODEC_ID_ADPCM_IMA_AMV, - CODEC_ID_ADPCM_EA_R1, - CODEC_ID_ADPCM_EA_R3, - CODEC_ID_ADPCM_EA_R2, - CODEC_ID_ADPCM_IMA_EA_SEAD, - CODEC_ID_ADPCM_IMA_EA_EACS, - CODEC_ID_ADPCM_EA_XAS, - CODEC_ID_ADPCM_EA_MAXIS_XA, - CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_VIMA = MKBETAG('V','I','M','A'), /* AMR */ - CODEC_ID_AMR_NB= 0x12000, - CODEC_ID_AMR_WB, + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, /* RealAudio codecs*/ - CODEC_ID_RA_144= 0x13000, - CODEC_ID_RA_288, + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, /* various DPCM codecs */ - CODEC_ID_ROQ_DPCM= 0x14000, - CODEC_ID_INTERPLAY_DPCM, - CODEC_ID_XAN_DPCM, - CODEC_ID_SOL_DPCM, + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, /* audio codecs */ - CODEC_ID_MP2= 0x15000, - CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 - CODEC_ID_AAC, - CODEC_ID_AC3, - CODEC_ID_DTS, - CODEC_ID_VORBIS, - CODEC_ID_DVAUDIO, - CODEC_ID_WMAV1, - CODEC_ID_WMAV2, - CODEC_ID_MACE3, - CODEC_ID_MACE6, - CODEC_ID_VMDAUDIO, - CODEC_ID_SONIC, - CODEC_ID_SONIC_LS, - CODEC_ID_FLAC, - CODEC_ID_MP3ADU, - CODEC_ID_MP3ON4, - CODEC_ID_SHORTEN, - CODEC_ID_ALAC, - CODEC_ID_WESTWOOD_SND1, - CODEC_ID_GSM, ///< as in Berlin toast format - CODEC_ID_QDM2, - CODEC_ID_COOK, - CODEC_ID_TRUESPEECH, - CODEC_ID_TTA, - CODEC_ID_SMACKAUDIO, - CODEC_ID_QCELP, - CODEC_ID_WAVPACK, - CODEC_ID_DSICINAUDIO, - CODEC_ID_IMC, - CODEC_ID_MUSEPACK7, - CODEC_ID_MLP, - CODEC_ID_GSM_MS, /* as found in WAV */ - CODEC_ID_ATRAC3, - CODEC_ID_VOXWARE, - CODEC_ID_APE, - CODEC_ID_NELLYMOSER, - CODEC_ID_MUSEPACK8, - CODEC_ID_SPEEX, - CODEC_ID_WMAVOICE, - CODEC_ID_WMAPRO, - CODEC_ID_WMALOSSLESS, - CODEC_ID_ATRAC3P, - CODEC_ID_EAC3, - CODEC_ID_SIPR, - CODEC_ID_MP1, - CODEC_ID_TWINVQ, - CODEC_ID_TRUEHD, - CODEC_ID_MP4ALS, + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_VOXWARE, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS_DEPRECATED, + AV_CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), + AV_CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), + AV_CODEC_ID_SONIC = MKBETAG('S','O','N','C'), + AV_CODEC_ID_SONIC_LS = MKBETAG('S','O','N','L'), + AV_CODEC_ID_PAF_AUDIO = MKBETAG('P','A','F','A'), + AV_CODEC_ID_OPUS = MKBETAG('O','P','U','S'), + AV_CODEC_ID_TAK = MKBETAG('t','B','a','K'), /* subtitle codecs */ - CODEC_ID_DVD_SUBTITLE= 0x17000, - CODEC_ID_DVB_SUBTITLE, - CODEC_ID_TEXT, ///< raw UTF-8 text - CODEC_ID_XSUB, - CODEC_ID_SSA, - CODEC_ID_MOV_TEXT, + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + AV_CODEC_ID_MICRODVD = MKBETAG('m','D','V','D'), + AV_CODEC_ID_EIA_608 = MKBETAG('c','6','0','8'), + AV_CODEC_ID_JACOSUB = MKBETAG('J','S','U','B'), + AV_CODEC_ID_SAMI = MKBETAG('S','A','M','I'), + AV_CODEC_ID_REALTEXT = MKBETAG('R','T','X','T'), + AV_CODEC_ID_SUBVIEWER = MKBETAG('S','u','b','V'), + AV_CODEC_ID_SUBRIP = MKBETAG('S','R','i','p'), + AV_CODEC_ID_WEBVTT = MKBETAG('W','V','T','T'), /* other specific kind of codecs (generally used for attachments) */ - CODEC_ID_TTF= 0x18000, + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + AV_CODEC_ID_BINTEXT = MKBETAG('B','T','X','T'), + AV_CODEC_ID_XBIN = MKBETAG('X','B','I','N'), + AV_CODEC_ID_IDF = MKBETAG( 0 ,'I','D','F'), + AV_CODEC_ID_OTF = MKBETAG( 0 ,'O','T','F'), - CODEC_ID_PROBE= 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it - CODEC_ID_MPEG2TS= 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS * stream (only used by libavformat) */ -}; + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. -enum CodecType { - CODEC_TYPE_UNKNOWN = -1, - CODEC_TYPE_VIDEO, - CODEC_TYPE_AUDIO, - CODEC_TYPE_DATA, - CODEC_TYPE_SUBTITLE, - CODEC_TYPE_ATTACHMENT, - CODEC_TYPE_NB +#if FF_API_CODEC_ID +#include "old_codec_ids.h" +#endif }; +#if FF_API_CODEC_ID +#define CodecID AVCodecID +#endif + /** - * all in native-endian format + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_get_descriptor() */ -enum SampleFormat { - SAMPLE_FMT_NONE = -1, - SAMPLE_FMT_U8, ///< unsigned 8 bits - SAMPLE_FMT_S16, ///< signed 16 bits - SAMPLE_FMT_S32, ///< signed 32 bits - SAMPLE_FMT_FLT, ///< float - SAMPLE_FMT_DBL, ///< double - SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if dynamically linking to libavcodec -}; +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; +} AVCodecDescriptor; -/* Audio channel masks */ -#define CH_FRONT_LEFT 0x00000001 -#define CH_FRONT_RIGHT 0x00000002 -#define CH_FRONT_CENTER 0x00000004 -#define CH_LOW_FREQUENCY 0x00000008 -#define CH_BACK_LEFT 0x00000010 -#define CH_BACK_RIGHT 0x00000020 -#define CH_FRONT_LEFT_OF_CENTER 0x00000040 -#define CH_FRONT_RIGHT_OF_CENTER 0x00000080 -#define CH_BACK_CENTER 0x00000100 -#define CH_SIDE_LEFT 0x00000200 -#define CH_SIDE_RIGHT 0x00000400 -#define CH_TOP_CENTER 0x00000800 -#define CH_TOP_FRONT_LEFT 0x00001000 -#define CH_TOP_FRONT_CENTER 0x00002000 -#define CH_TOP_FRONT_RIGHT 0x00004000 -#define CH_TOP_BACK_LEFT 0x00008000 -#define CH_TOP_BACK_CENTER 0x00010000 -#define CH_TOP_BACK_RIGHT 0x00020000 -#define CH_STEREO_LEFT 0x20000000 ///< Stereo downmix. -#define CH_STEREO_RIGHT 0x40000000 ///< See CH_STEREO_LEFT. - -/* Audio channel convenience macros */ -#define CH_LAYOUT_MONO (CH_FRONT_CENTER) -#define CH_LAYOUT_STEREO (CH_FRONT_LEFT|CH_FRONT_RIGHT) -#define CH_LAYOUT_2_1 (CH_LAYOUT_STEREO|CH_BACK_CENTER) -#define CH_LAYOUT_SURROUND (CH_LAYOUT_STEREO|CH_FRONT_CENTER) -#define CH_LAYOUT_4POINT0 (CH_LAYOUT_SURROUND|CH_BACK_CENTER) -#define CH_LAYOUT_2_2 (CH_LAYOUT_STEREO|CH_SIDE_LEFT|CH_SIDE_RIGHT) -#define CH_LAYOUT_QUAD (CH_LAYOUT_STEREO|CH_BACK_LEFT|CH_BACK_RIGHT) -#define CH_LAYOUT_5POINT0 (CH_LAYOUT_SURROUND|CH_SIDE_LEFT|CH_SIDE_RIGHT) -#define CH_LAYOUT_5POINT1 (CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY) -#define CH_LAYOUT_5POINT0_BACK (CH_LAYOUT_SURROUND|CH_BACK_LEFT|CH_BACK_RIGHT) -#define CH_LAYOUT_5POINT1_BACK (CH_LAYOUT_5POINT0_BACK|CH_LOW_FREQUENCY) -#define CH_LAYOUT_7POINT1 (CH_LAYOUT_5POINT1|CH_BACK_LEFT|CH_BACK_RIGHT) -#define CH_LAYOUT_7POINT1_WIDE (CH_LAYOUT_5POINT1_BACK|\ - CH_FRONT_LEFT_OF_CENTER|CH_FRONT_RIGHT_OF_CENTER) -#define CH_LAYOUT_STEREO_DOWNMIX (CH_STEREO_LEFT|CH_STEREO_RIGHT) +/** + * Codec uses only intra compression. + * Video codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +#if FF_API_OLD_DECODE_AUDIO /* in bytes */ #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio +#endif /** + * @ingroup lavc_decoding * Required number of additionally allocated bytes at the end of the input bitstream for decoding. * This is mainly needed because some optimized bitstream readers read * 32 or 64 bit at once and could read over the end.
* Note: If the first 23 bits of the additional bytes are not 0, then damaged * MPEG bitstreams could cause overread and segfault. */ -#define FF_INPUT_BUFFER_PADDING_SIZE 8 +#define FF_INPUT_BUFFER_PADDING_SIZE 16 /** + * @ingroup lavc_encoding * minimum encoding buffer size * Used to avoid some checks during header writing. */ @@ -417,6 +543,7 @@ enum SampleFormat { /** + * @ingroup lavc_encoding * motion estimation type. */ enum Motion_Est_ID { @@ -432,52 +559,58 @@ enum Motion_Est_ID { ME_TESA, ///< transformed exhaustive search algorithm }; +/** + * @ingroup lavc_decoding + */ enum AVDiscard{ /* We leave some space between them for extensions (drop some * keyframes for intra-only or drop just some bidir frames). */ - AVDISCARD_NONE =-16, ///< discard nothing - AVDISCARD_DEFAULT= 0, ///< discard useless packets like 0 size packets in avi - AVDISCARD_NONREF = 8, ///< discard all non reference - AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames - AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes - AVDISCARD_ALL = 48, ///< discard all + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all }; enum AVColorPrimaries{ - AVCOL_PRI_BT709 =1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B - AVCOL_PRI_UNSPECIFIED=2, - AVCOL_PRI_BT470M =4, - AVCOL_PRI_BT470BG =5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM - AVCOL_PRI_SMPTE170M =6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC - AVCOL_PRI_SMPTE240M =7, ///< functionally identical to above - AVCOL_PRI_FILM =8, - AVCOL_PRI_NB , ///< Not part of ABI + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_BT470M = 4, + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above + AVCOL_PRI_FILM = 8, + AVCOL_PRI_NB , ///< Not part of ABI }; enum AVColorTransferCharacteristic{ - AVCOL_TRC_BT709 =1, ///< also ITU-R BT1361 - AVCOL_TRC_UNSPECIFIED=2, - AVCOL_TRC_GAMMA22 =4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM - AVCOL_TRC_GAMMA28 =5, ///< also ITU-R BT470BG - AVCOL_TRC_NB , ///< Not part of ABI + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_NB , ///< Not part of ABI }; enum AVColorSpace{ - AVCOL_SPC_RGB =0, - AVCOL_SPC_BT709 =1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B - AVCOL_SPC_UNSPECIFIED=2, - AVCOL_SPC_FCC =4, - AVCOL_SPC_BT470BG =5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 - AVCOL_SPC_SMPTE170M =6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above - AVCOL_SPC_SMPTE240M =7, - AVCOL_SPC_NB , ///< Not part of ABI + AVCOL_SPC_RGB = 0, + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_FCC = 4, + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, + AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_NB , ///< Not part of ABI }; +#define AVCOL_SPC_YCGCO AVCOL_SPC_YCOCG enum AVColorRange{ - AVCOL_RANGE_UNSPECIFIED=0, - AVCOL_RANGE_MPEG =1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges - AVCOL_RANGE_JPEG =2, ///< the normal 2^n-1 "JPEG" YUV ranges - AVCOL_RANGE_NB , ///< Not part of ABI + AVCOL_RANGE_UNSPECIFIED = 0, + AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + AVCOL_RANGE_NB , ///< Not part of ABI }; /** @@ -486,16 +619,32 @@ enum AVColorRange{ * X X 5 6 X 0 is undefined/unknown position */ enum AVChromaLocation{ - AVCHROMA_LOC_UNSPECIFIED=0, - AVCHROMA_LOC_LEFT =1, ///< mpeg2/4, h264 default - AVCHROMA_LOC_CENTER =2, ///< mpeg1, jpeg, h263 - AVCHROMA_LOC_TOPLEFT =3, ///< DV - AVCHROMA_LOC_TOP =4, - AVCHROMA_LOC_BOTTOMLEFT =5, - AVCHROMA_LOC_BOTTOM =6, - AVCHROMA_LOC_NB , ///< Not part of ABI + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< mpeg2/4, h264 default + AVCHROMA_LOC_CENTER = 2, ///< mpeg1, jpeg, h263 + AVCHROMA_LOC_TOPLEFT = 3, ///< DV + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB , ///< Not part of ABI +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI }; +/** + * @ingroup lavc_encoding + */ typedef struct RcOverride{ int start_frame; int end_frame; @@ -515,7 +664,6 @@ typedef struct RcOverride{ #define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. #define CODEC_FLAG_GMC 0x0020 ///< Use GMC. #define CODEC_FLAG_MV0 0x0040 ///< Always try a MB with MV=<0,0>. -#define CODEC_FLAG_PART 0x0080 ///< Use data partitioning. /** * The parent program guarantees that the input for B-frames containing * streams is not written to for at least s->max_b_frames+1 frames, if @@ -524,7 +672,6 @@ typedef struct RcOverride{ #define CODEC_FLAG_INPUT_PRESERVED 0x0100 #define CODEC_FLAG_PASS1 0x0200 ///< Use internal 2pass ratecontrol in first pass mode. #define CODEC_FLAG_PASS2 0x0400 ///< Use internal 2pass ratecontrol in second pass mode. -#define CODEC_FLAG_EXTERN_HUFF 0x1000 ///< Use external Huffman table (for MJPEG). #define CODEC_FLAG_GRAY 0x2000 ///< Only decode/encode grayscale. #define CODEC_FLAG_EMU_EDGE 0x4000 ///< Don't draw edges. #define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding. @@ -533,39 +680,25 @@ typedef struct RcOverride{ #define CODEC_FLAG_NORMALIZE_AQP 0x00020000 ///< Normalize adaptive quantization. #define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< Use interlaced DCT. #define CODEC_FLAG_LOW_DELAY 0x00080000 ///< Force low delay. -#define CODEC_FLAG_ALT_SCAN 0x00100000 ///< Use alternate scan. #define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< Place global headers in extradata instead of every keyframe. #define CODEC_FLAG_BITEXACT 0x00800000 ///< Use only bitexact stuff (except (I)DCT). /* Fx : Flag for h263+ extra options */ #define CODEC_FLAG_AC_PRED 0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction -#define CODEC_FLAG_H263P_UMV 0x02000000 ///< unlimited motion vector -#define CODEC_FLAG_CBP_RD 0x04000000 ///< Use rate distortion optimization for cbp. -#define CODEC_FLAG_QP_RD 0x08000000 ///< Use rate distortion optimization for qp selectioon. -#define CODEC_FLAG_H263P_AIV 0x00000008 ///< H.263 alternative inter VLC -#define CODEC_FLAG_OBMC 0x00000001 ///< OBMC #define CODEC_FLAG_LOOP_FILTER 0x00000800 ///< loop filter -#define CODEC_FLAG_H263P_SLICE_STRUCT 0x10000000 #define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation -#define CODEC_FLAG_SVCD_SCAN_OFFSET 0x40000000 ///< Will reserve space for SVCD scan offset user data. #define CODEC_FLAG_CLOSED_GOP 0x80000000 #define CODEC_FLAG2_FAST 0x00000001 ///< Allow non spec compliant speedup tricks. -#define CODEC_FLAG2_STRICT_GOP 0x00000002 ///< Strictly enforce GOP size. #define CODEC_FLAG2_NO_OUTPUT 0x00000004 ///< Skip bitstream encoding. #define CODEC_FLAG2_LOCAL_HEADER 0x00000008 ///< Place global headers at every keyframe instead of in extradata. -#define CODEC_FLAG2_BPYRAMID 0x00000010 ///< H.264 allow B-frames to be used as references. -#define CODEC_FLAG2_WPRED 0x00000020 ///< H.264 weighted biprediction for B-frames -#define CODEC_FLAG2_MIXED_REFS 0x00000040 ///< H.264 one reference per partition, as opposed to one reference per macroblock -#define CODEC_FLAG2_8X8DCT 0x00000080 ///< H.264 high profile 8x8 transform -#define CODEC_FLAG2_FASTPSKIP 0x00000100 ///< H.264 fast pskip -#define CODEC_FLAG2_AUD 0x00000200 ///< H.264 access unit delimiters -#define CODEC_FLAG2_BRDO 0x00000400 ///< B-frame rate-distortion optimization -#define CODEC_FLAG2_INTRA_VLC 0x00000800 ///< Use MPEG-2 intra VLC table. -#define CODEC_FLAG2_MEMC_ONLY 0x00001000 ///< Only do ME/MC (I frames -> ref, P frame -> ME+MC). -#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. +#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. DEPRECATED!!!! +#if FF_API_MPV_GLOBAL_OPTS +#define CODEC_FLAG_CBP_RD 0x04000000 ///< Use rate distortion optimization for cbp. +#define CODEC_FLAG_QP_RD 0x08000000 ///< Use rate distortion optimization for qp selectioon. +#define CODEC_FLAG2_STRICT_GOP 0x00000002 ///< Strictly enforce GOP size. #define CODEC_FLAG2_SKIP_RD 0x00004000 ///< RD optimal MB level residual skipping +#endif #define CODEC_FLAG2_CHUNKS 0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries. -#define CODEC_FLAG2_NON_LINEAR_QUANT 0x00010000 ///< Use MPEG-2 nonlinear quantizer. -#define CODEC_FLAG2_BIT_RESERVOIR 0x00020000 ///< Use a bit reservoir when encoding if possible +#define CODEC_FLAG2_SHOW_ALL 0x00400000 ///< Show all frames before the first keyframe /* Unsupported options : * Syntax Arithmetic coding (SAC) @@ -576,18 +709,36 @@ typedef struct RcOverride{ #define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 ///< Decoder can use draw_horiz_band callback. /** - * Codec uses get_buffer() for allocating buffers. - * direct rendering method 1 + * Codec uses get_buffer() for allocating buffers and supports custom allocators. + * If not set, it might not use get_buffer() at all or use operations that + * assume the buffer was allocated by avcodec_default_get_buffer. */ #define CODEC_CAP_DR1 0x0002 -/* If 'parse_only' field is true, then avcodec_parse_frame() can be used. */ -#define CODEC_CAP_PARSE_ONLY 0x0004 #define CODEC_CAP_TRUNCATED 0x0008 /* Codec can export data for HW decoding (XvMC). */ #define CODEC_CAP_HWACCEL 0x0010 /** - * Codec has a nonzero delay and needs to be fed with NULL at the end to get the delayed data. - * If this is not set, the codec is guaranteed to never be fed with NULL data. + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. */ #define CODEC_CAP_DELAY 0x0020 /** @@ -599,6 +750,61 @@ typedef struct RcOverride{ * Codec can export data for HW decoding (VDPAU). */ #define CODEC_CAP_HWACCEL_VDPAU 0x0080 +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carring such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define CODEC_CAP_SUBFRAMES 0x0100 +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define CODEC_CAP_EXPERIMENTAL 0x0200 +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define CODEC_CAP_CHANNEL_CONF 0x0400 + +/** + * Codec is able to deal with negative linesizes + */ +#define CODEC_CAP_NEG_LINESIZES 0x0800 + +/** + * Codec supports frame-level multithreading. + */ +#define CODEC_CAP_FRAME_THREADS 0x1000 +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define CODEC_CAP_SLICE_THREADS 0x2000 +/** + * Codec supports changed parameters at any point. + */ +#define CODEC_CAP_PARAM_CHANGE 0x4000 +/** + * Codec supports avctx->thread_count == 0 (auto). + */ +#define CODEC_CAP_AUTO_THREADS 0x8000 +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000 +/** + * Codec is intra only. + */ +#define CODEC_CAP_INTRA_ONLY 0x40000000 +/** + * Codec is lossless. + */ +#define CODEC_CAP_LOSSLESS 0x80000000 //The following defines may change, don't expect compatibility if you use them. #define MB_TYPE_INTRA4x4 0x0001 @@ -653,256 +859,91 @@ typedef struct AVPanScan{ int16_t position[3][2]; }AVPanScan; -#define FF_COMMON_FRAME \ - /**\ - * pointer to the picture planes.\ - * This might be different from the first allocated byte\ - * - encoding: \ - * - decoding: \ - */\ - uint8_t *data[4];\ - int linesize[4];\ - /**\ - * pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer.\ - * This isn't used by libavcodec unless the default get/release_buffer() is used.\ - * - encoding: \ - * - decoding: \ - */\ - uint8_t *base[4];\ - /**\ - * 1 -> keyframe, 0-> not\ - * - encoding: Set by libavcodec.\ - * - decoding: Set by libavcodec.\ - */\ - int key_frame;\ -\ - /**\ - * Picture type of the frame, see ?_TYPE below.\ - * - encoding: Set by libavcodec. for coded_picture (and set by user for input).\ - * - decoding: Set by libavcodec.\ - */\ - int pict_type;\ -\ - /**\ - * presentation timestamp in time_base units (time when frame should be shown to user)\ - * If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed.\ - * - encoding: MUST be set by user.\ - * - decoding: Set by libavcodec.\ - */\ - int64_t pts;\ -\ - /**\ - * picture number in bitstream order\ - * - encoding: set by\ - * - decoding: Set by libavcodec.\ - */\ - int coded_picture_number;\ - /**\ - * picture number in display order\ - * - encoding: set by\ - * - decoding: Set by libavcodec.\ - */\ - int display_picture_number;\ -\ - /**\ - * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) \ - * - encoding: Set by libavcodec. for coded_picture (and set by user for input).\ - * - decoding: Set by libavcodec.\ - */\ - int quality; \ -\ - /**\ - * buffer age (1->was last buffer and dint change, 2->..., ...).\ - * Set to INT_MAX if the buffer has not been used yet.\ - * - encoding: unused\ - * - decoding: MUST be set by get_buffer().\ - */\ - int age;\ -\ - /**\ - * is this picture used as reference\ - * The values for this are the same as the MpegEncContext.picture_structure\ - * variable, that is 1->top field, 2->bottom field, 3->frame/both fields.\ - * Set to 4 for delayed, non-reference frames.\ - * - encoding: unused\ - * - decoding: Set by libavcodec. (before get_buffer() call)).\ - */\ - int reference;\ -\ - /**\ - * QP table\ - * - encoding: unused\ - * - decoding: Set by libavcodec.\ - */\ - int8_t *qscale_table;\ - /**\ - * QP store stride\ - * - encoding: unused\ - * - decoding: Set by libavcodec.\ - */\ - int qstride;\ -\ - /**\ - * mbskip_table[mb]>=1 if MB didn't change\ - * stride= mb_width = (width+15)>>4\ - * - encoding: unused\ - * - decoding: Set by libavcodec.\ - */\ - uint8_t *mbskip_table;\ -\ - /**\ - * motion vector table\ - * @code\ - * example:\ - * int mv_sample_log2= 4 - motion_subsample_log2;\ - * int mb_width= (width+15)>>4;\ - * int mv_stride= (mb_width << mv_sample_log2) + 1;\ - * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y];\ - * @endcode\ - * - encoding: Set by user.\ - * - decoding: Set by libavcodec.\ - */\ - int16_t (*motion_val[2])[2];\ -\ - /**\ - * macroblock type table\ - * mb_type_base + mb_width + 2\ - * - encoding: Set by user.\ - * - decoding: Set by libavcodec.\ - */\ - uint32_t *mb_type;\ -\ - /**\ - * log2 of the size of the block which a single vector in motion_val represents: \ - * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2)\ - * - encoding: unused\ - * - decoding: Set by libavcodec.\ - */\ - uint8_t motion_subsample_log2;\ -\ - /**\ - * for some private data of the user\ - * - encoding: unused\ - * - decoding: Set by user.\ - */\ - void *opaque;\ -\ - /**\ - * error\ - * - encoding: Set by libavcodec. if flags&CODEC_FLAG_PSNR.\ - * - decoding: unused\ - */\ - uint64_t error[4];\ -\ - /**\ - * type of the buffer (to keep track of who has to deallocate data[*])\ - * - encoding: Set by the one who allocates it.\ - * - decoding: Set by the one who allocates it.\ - * Note: User allocated (direct rendering) & internal buffers cannot coexist currently.\ - */\ - int type;\ - \ - /**\ - * When decoding, this signals how much the picture must be delayed.\ - * extra_delay = repeat_pict / (2*fps)\ - * - encoding: unused\ - * - decoding: Set by libavcodec.\ - */\ - int repeat_pict;\ - \ - /**\ - * \ - */\ - int qscale_type;\ - \ - /**\ - * The content of the picture is interlaced.\ - * - encoding: Set by user.\ - * - decoding: Set by libavcodec. (default 0)\ - */\ - int interlaced_frame;\ - \ - /**\ - * If the content is interlaced, is top field displayed first.\ - * - encoding: Set by user.\ - * - decoding: Set by libavcodec.\ - */\ - int top_field_first;\ - \ - /**\ - * Pan scan.\ - * - encoding: Set by user.\ - * - decoding: Set by libavcodec.\ - */\ - AVPanScan *pan_scan;\ - \ - /**\ - * Tell user application that palette has changed from previous frame.\ - * - encoding: ??? (no palette-enabled encoder yet)\ - * - decoding: Set by libavcodec. (default 0).\ - */\ - int palette_has_changed;\ - \ - /**\ - * codec suggestion on buffer type if != 0\ - * - encoding: unused\ - * - decoding: Set by libavcodec. (before get_buffer() call)).\ - */\ - int buffer_hints;\ -\ - /**\ - * DCT coefficients\ - * - encoding: unused\ - * - decoding: Set by libavcodec.\ - */\ - short *dct_coeff;\ -\ - /**\ - * motion referece frame index\ - * - encoding: Set by user.\ - * - decoding: Set by libavcodec.\ - */\ - int8_t *ref_index[2];\ -\ - /**\ - * reordered opaque 64bit number (generally a PTS) from AVCodecContext.reordered_opaque\ - * output in AVFrame.reordered_opaque\ - * - encoding: unused\ - * - decoding: Read by user.\ - */\ - int64_t reordered_opaque;\ -\ - /**\ - * hardware accelerator private data (FFmpeg allocated)\ - * - encoding: unused\ - * - decoding: Set by libavcodec\ - */\ - void *hwaccel_picture_private;\ - - #define FF_QSCALE_TYPE_MPEG1 0 #define FF_QSCALE_TYPE_MPEG2 1 #define FF_QSCALE_TYPE_H264 2 +#define FF_QSCALE_TYPE_VP56 3 #define FF_BUFFER_TYPE_INTERNAL 1 #define FF_BUFFER_TYPE_USER 2 ///< direct rendering buffers (image is (de)allocated by user) #define FF_BUFFER_TYPE_SHARED 4 ///< Buffer from somewhere else; don't deallocate image (data/base), all other tables are not shared. #define FF_BUFFER_TYPE_COPY 8 ///< Just a (modified) copy of some other buffer, don't deallocate anything. - -#define FF_I_TYPE 1 ///< Intra -#define FF_P_TYPE 2 ///< Predicted -#define FF_B_TYPE 3 ///< Bi-dir predicted -#define FF_S_TYPE 4 ///< S(GMC)-VOP MPEG4 -#define FF_SI_TYPE 5 ///< Switching Intra -#define FF_SP_TYPE 6 ///< Switching Predicted -#define FF_BI_TYPE 7 - #define FF_BUFFER_HINTS_VALID 0x01 // Buffer hints value is meaningful (if 0 ignore). #define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer. #define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content. #define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer (update). +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ +enum AVPacketSideDataType { + AV_PKT_DATA_PALETTE, + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES=70, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=mail/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, +}; + typedef struct AVPacket { /** * Presentation timestamp in AVStream->time_base units; the time at which @@ -923,7 +964,21 @@ typedef struct AVPacket { uint8_t *data; int size; int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + struct { + uint8_t *data; + int size; + enum AVPacketSideDataType type; + } *side_data; + int side_data_elems; + /** * Duration of this packet in AVStream->time_base units, 0 if unknown. * Equals next_pts - this_pts in presentation order. @@ -941,6 +996,8 @@ typedef struct AVPacket { * the very first frame or from this keyframe. * Is AV_NOPTS_VALUE if unknown. * This field is not the display duration of the current packet. + * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY + * set. * * The purpose of this field is to allow seeking in streams that have no * keyframes in the conventional sense. It corresponds to the @@ -950,780 +1007,909 @@ typedef struct AVPacket { */ int64_t convergence_duration; } AVPacket; -#define PKT_FLAG_KEY 0x0001 +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; +/** + * @} + */ /** * Audio Video Frame. - * New fields can be added to the end of FF_COMMON_FRAME with minor version - * bumps. - * Removal, reordering and changes to existing fields require a major - * version bump. No fields should be added into AVFrame before or after - * FF_COMMON_FRAME! - * sizeof(AVFrame) must not be used outside libav*. + * New fields can be added to the end of AVFRAME with minor version + * bumps. Similarly fields that are marked as to be only accessed by + * av_opt_ptr() can be reordered. This allows 2 forks to add fields + * without breaking compatibility with each other. + * Removal, reordering and changes in the remaining cases require + * a major version bump. + * sizeof(AVFrame) must not be used outside libavcodec. */ typedef struct AVFrame { - FF_COMMON_FRAME -} AVFrame; +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte + * - encoding: Set by user + * - decoding: set by AVCodecContext.get_buffer() + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; -/** - * main external API structure. - * New fields can be added to the end with minor version bumps. - * Removal, reordering and changes to existing fields require a major - * version bump. - * sizeof(AVCodecContext) must not be used outside libav*. - */ -typedef struct AVCodecContext { /** - * information on struct for av_log - * - set by avcodec_alloc_context + * Size, in bytes, of the data for each picture/channel plane. + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * - encoding: Set by user + * - decoding: set by AVCodecContext.get_buffer() */ - const AVClass *av_class; + int linesize[AV_NUM_DATA_POINTERS]; + /** - * the average bitrate - * - encoding: Set by user; unused for constant quantizer encoding. - * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream. + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data will always be set by get_buffer(), + * but for planar audio with more channels that can fit in data, + * extended_data must be used by the decoder in order to access all + * channels. + * + * encoding: set by user + * decoding: set by AVCodecContext.get_buffer() */ - int bit_rate; + uint8_t **extended_data; /** - * number of bits the bitstream is allowed to diverge from the reference. - * the reference can be CBR (for CBR pass1) or VBR (for pass2) - * - encoding: Set by user; unused for constant quantizer encoding. - * - decoding: unused + * width and height of the video frame + * - encoding: unused + * - decoding: Read by user. */ - int bit_rate_tolerance; + int width, height; /** - * CODEC_FLAG_*. - * - encoding: Set by user. - * - decoding: Set by user. + * number of audio samples (per channel) described by this frame + * - encoding: Set by user + * - decoding: Set by libavcodec */ - int flags; + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + * - encoding: unused + * - decoding: Read by user. + */ + int format; /** - * Some codecs need additional format info. It is stored here. - * If any muxer uses this then ALL demuxers/parsers AND encoders for the - * specific codec MUST set it correctly otherwise stream copy breaks. - * In general use of this field by muxers is not recommanded. + * 1 -> keyframe, 0-> not * - encoding: Set by libavcodec. - * - decoding: Set by libavcodec. (FIXME: Is this OK?) + * - decoding: Set by libavcodec. */ - int sub_id; + int key_frame; /** - * Motion estimation algorithm used for video coding. - * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex), - * 8 (umh), 9 (iter), 10 (tesa) [7, 8, 10 are x264 specific, 9 is snow specific] - * - encoding: MUST be set by user. - * - decoding: unused + * Picture type of the frame, see ?_TYPE below. + * - encoding: Set by libavcodec. for coded_picture (and set by user for input). + * - decoding: Set by libavcodec. */ - int me_method; + enum AVPictureType pict_type; /** - * some codecs need / can use extradata like Huffman tables. - * mjpeg: Huffman tables - * rv10: additional flags - * mpeg4: global headers (they can be in the bitstream or here) - * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger - * than extradata_size to avoid prolems if it is read with the bitstream reader. - * The bytewise contents of extradata must not depend on the architecture or CPU endianness. - * - encoding: Set/allocated/freed by libavcodec. - * - decoding: Set/allocated/freed by user. + * pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer. + * This isn't used by libavcodec unless the default get/release_buffer() is used. + * - encoding: + * - decoding: */ - uint8_t *extradata; - int extradata_size; + uint8_t *base[AV_NUM_DATA_POINTERS]; /** - * This is the fundamental unit of time (in seconds) in terms - * of which frame timestamps are represented. For fixed-fps content, - * timebase should be 1/framerate and timestamp increments should be - * identically 1. - * - encoding: MUST be set by user. - * - decoding: Set by libavcodec. + * sample aspect ratio for the video frame, 0/1 if unknown/unspecified + * - encoding: unused + * - decoding: Read by user. */ - AVRational time_base; + AVRational sample_aspect_ratio; - /* video only */ /** - * picture width / height. + * presentation timestamp in time_base units (time when frame should be shown to user) + * If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed. * - encoding: MUST be set by user. * - decoding: Set by libavcodec. - * Note: For compatibility it is possible to set this instead of - * coded_width/height before decoding. */ - int width, height; + int64_t pts; -#define FF_ASPECT_EXTENDED 15 + /** + * reordered pts from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pts; /** - * the number of pictures in a group of pictures, or 0 for intra_only - * - encoding: Set by user. - * - decoding: unused + * dts from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. */ - int gop_size; + int64_t pkt_dts; /** - * Pixel format, see PIX_FMT_xxx. - * - encoding: Set by user. + * picture number in bitstream order + * - encoding: set by + * - decoding: Set by libavcodec. + */ + int coded_picture_number; + /** + * picture number in display order + * - encoding: set by * - decoding: Set by libavcodec. */ - enum PixelFormat pix_fmt; + int display_picture_number; /** - * Frame rate emulation. If not zero, the lower layer (i.e. format handler) - * has to read frames at native frame rate. - * - encoding: Set by user. - * - decoding: unused + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + * - encoding: Set by libavcodec. for coded_picture (and set by user for input). + * - decoding: Set by libavcodec. */ - int rate_emu; + int quality; /** - * If non NULL, 'draw_horiz_band' is called by the libavcodec - * decoder to draw a horizontal band. It improves cache usage. Not - * all codecs can do that. You must check the codec capabilities - * beforehand. - * The function is also used by hardware acceleration APIs. - * It is called at least once during frame decoding to pass - * the data needed for hardware render. - * In that mode instead of pixel data, AVFrame points to - * a structure specific to the acceleration API. The application - * reads the structure and can change some fields to indicate progress - * or mark state. + * is this picture used as reference + * The values for this are the same as the MpegEncContext.picture_structure + * variable, that is 1->top field, 2->bottom field, 3->frame/both fields. + * Set to 4 for delayed, non-reference frames. * - encoding: unused - * - decoding: Set by user. - * @param height the height of the slice - * @param y the y position of the slice - * @param type 1->top field, 2->bottom field, 3->frame - * @param offset offset into the AVFrame.data from which the slice should be read + * - decoding: Set by libavcodec. (before get_buffer() call)). */ - void (*draw_horiz_band)(struct AVCodecContext *s, - const AVFrame *src, int offset[4], - int y, int type, int height); - - /* audio only */ - int sample_rate; ///< samples per second - int channels; ///< number of audio channels + int reference; /** - * audio sample format - * - encoding: Set by user. + * QP table + * - encoding: unused * - decoding: Set by libavcodec. */ - enum SampleFormat sample_fmt; ///< sample format, currently unused - - /* The following data should not be initialized. */ + int8_t *qscale_table; /** - * Samples per packet, initialized when calling 'init'. + * QP store stride + * - encoding: unused + * - decoding: Set by libavcodec. */ - int frame_size; - int frame_number; ///< audio or video frame number - int real_pict_num; ///< Returns the real picture number of previous encoded frame. + int qstride; /** - * Number of frames the decoded output will be delayed relative to - * the encoded input. - * - encoding: Set by libavcodec. - * - decoding: unused + * */ - int delay; + int qscale_type; - /* - encoding parameters */ - float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) - float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + /** + * mbskip_table[mb]>=1 if MB didn't change + * stride= mb_width = (width+15)>>4 + * - encoding: unused + * - decoding: Set by libavcodec. + */ + uint8_t *mbskip_table; /** - * minimum quantizer + * motion vector table + * @code + * example: + * int mv_sample_log2= 4 - motion_subsample_log2; + * int mb_width= (width+15)>>4; + * int mv_stride= (mb_width << mv_sample_log2) + 1; + * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y]; + * @endcode * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ - int qmin; + int16_t (*motion_val[2])[2]; /** - * maximum quantizer + * macroblock type table + * mb_type_base + mb_width + 2 * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ - int qmax; + uint32_t *mb_type; /** - * maximum quantizer difference between frames - * - encoding: Set by user. - * - decoding: unused + * DCT coefficients + * - encoding: unused + * - decoding: Set by libavcodec. */ - int max_qdiff; + short *dct_coeff; /** - * maximum number of B-frames between non-B-frames - * Note: The output will be delayed by max_b_frames+1 relative to the input. + * motion reference frame index + * the order in which these are stored can depend on the codec. * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ - int max_b_frames; + int8_t *ref_index[2]; /** - * qscale factor between IP and B-frames - * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). - * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). - * - encoding: Set by user. - * - decoding: unused + * for some private data of the user + * - encoding: unused + * - decoding: Set by user. */ - float b_quant_factor; + void *opaque; - /** obsolete FIXME remove */ - int rc_strategy; -#define FF_RC_STRATEGY_XVID 1 + /** + * error + * - encoding: Set by libavcodec. if flags&CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; - int b_frame_strategy; + /** + * type of the buffer (to keep track of who has to deallocate data[*]) + * - encoding: Set by the one who allocates it. + * - decoding: Set by the one who allocates it. + * Note: User allocated (direct rendering) & internal buffers cannot coexist currently. + */ + int type; /** - * hurry up amount + * When decoding, this signals how much the picture must be delayed. + * extra_delay = repeat_pict / (2*fps) * - encoding: unused - * - decoding: Set by user. 1-> Skip B-frames, 2-> Skip IDCT/dequant too, 5-> Skip everything except header - * @deprecated Deprecated in favor of skip_idct and skip_frame. + * - decoding: Set by libavcodec. */ - int hurry_up; - - struct AVCodec *codec; - - void *priv_data; - - int rtp_payload_size; /* The size of the RTP payload: the coder will */ - /* do its best to deliver a chunk with size */ - /* below rtp_payload_size, the chunk will start */ - /* with a start code on some codecs like H.263. */ - /* This doesn't take account of any particular */ - /* headers inside the transmitted RTP payload. */ - - - /* The RTP callback: This function is called */ - /* every time the encoder has a packet to send. */ - /* It depends on the encoder if the data starts */ - /* with a Start Code (it should). H.263 does. */ - /* mb_nb contains the number of macroblocks */ - /* encoded in the RTP payload. */ - void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); - - /* statistics, used for 2-pass encoding */ - int mv_bits; - int header_bits; - int i_tex_bits; - int p_tex_bits; - int i_count; - int p_count; - int skip_count; - int misc_bits; + int repeat_pict; /** - * number of bits used for the previously encoded frame - * - encoding: Set by libavcodec. - * - decoding: unused + * The content of the picture is interlaced. + * - encoding: Set by user. + * - decoding: Set by libavcodec. (default 0) */ - int frame_bits; + int interlaced_frame; /** - * Private data of the user, can be used to carry app specific stuff. + * If the content is interlaced, is top field displayed first. * - encoding: Set by user. - * - decoding: Set by user. + * - decoding: Set by libavcodec. */ - void *opaque; - - char codec_name[32]; - enum CodecType codec_type; /* see CODEC_TYPE_xxx */ - enum CodecID codec_id; /* see CODEC_ID_xxx */ + int top_field_first; /** - * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). - * This is used to work around some encoder bugs. - * A demuxer should set this to what is stored in the field used to identify the codec. - * If there are multiple such fields in a container then the demuxer should choose the one - * which maximizes the information about the used codec. - * If the codec tag field in a container is larger then 32 bits then the demuxer should - * remap the longer ID to 32 bits with a table or other structure. Alternatively a new - * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated - * first. - * - encoding: Set by user, if not then the default based on codec_id will be used. - * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + * Tell user application that palette has changed from previous frame. + * - encoding: ??? (no palette-enabled encoder yet) + * - decoding: Set by libavcodec. (default 0). */ - unsigned int codec_tag; + int palette_has_changed; /** - * Work around bugs in encoders which sometimes cannot be detected automatically. - * - encoding: Set by user - * - decoding: Set by user + * codec suggestion on buffer type if != 0 + * - encoding: unused + * - decoding: Set by libavcodec. (before get_buffer() call)). */ - int workaround_bugs; -#define FF_BUG_AUTODETECT 1 ///< autodetection -#define FF_BUG_OLD_MSMPEG4 2 -#define FF_BUG_XVID_ILACE 4 -#define FF_BUG_UMP4 8 -#define FF_BUG_NO_PADDING 16 -#define FF_BUG_AMV 32 -#define FF_BUG_AC_VLC 0 ///< Will be removed, libavcodec can now handle these non-compliant files by default. -#define FF_BUG_QPEL_CHROMA 64 -#define FF_BUG_STD_QPEL 128 -#define FF_BUG_QPEL_CHROMA2 256 -#define FF_BUG_DIRECT_BLOCKSIZE 512 -#define FF_BUG_EDGE 1024 -#define FF_BUG_HPEL_CHROMA 2048 -#define FF_BUG_DC_CLIP 4096 -#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. -//#define FF_BUG_FAKE_SCALABILITY 16 //Autodetection should work 100%. + int buffer_hints; /** - * luma single coefficient elimination threshold + * Pan scan. * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ - int luma_elim_threshold; + AVPanScan *pan_scan; /** - * chroma single coeff elimination threshold - * - encoding: Set by user. - * - decoding: unused + * reordered opaque 64bit (generally an integer or a double precision float + * PTS but can be anything). + * The user sets AVCodecContext.reordered_opaque to represent the input at + * that time, + * the decoder reorders values as needed and sets AVFrame.reordered_opaque + * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + * @deprecated in favor of pkt_pts + * - encoding: unused + * - decoding: Read by user. */ - int chroma_elim_threshold; + int64_t reordered_opaque; /** - * strictly follow the standard (MPEG4, ...). - * - encoding: Set by user. - * - decoding: Set by user. - * Setting this to STRICT or higher means the encoder and decoder will - * generally do stupid things. While setting it to inofficial or lower - * will mean the encoder might use things that are not supported by all - * spec compliant decoders. Decoders make no difference between normal, - * inofficial and experimental, that is they always try to decode things - * when they can unless they are explicitly asked to behave stupid - * (=strictly conform to the specs) + * hardware accelerator private data (FFmpeg-allocated) + * - encoding: unused + * - decoding: Set by libavcodec */ - int strict_std_compliance; -#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to a older more strict version of the spec or reference software. -#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. -#define FF_COMPLIANCE_NORMAL 0 -#define FF_COMPLIANCE_INOFFICIAL -1 ///< Allow inofficial extensions. -#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + void *hwaccel_picture_private; /** - * qscale offset between IP and B-frames - * - encoding: Set by user. - * - decoding: unused + * the AVCodecContext which ff_thread_get_buffer() was last called on + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. */ - float b_quant_offset; + struct AVCodecContext *owner; + + /** + * used by multithreading to store frame-specific info + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + void *thread_opaque; /** - * Error recognization; higher values will detect more errors but may - * misdetect some more or less valid parts as errors. + * log2 of the size of the block which a single vector in motion_val represents: + * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2) * - encoding: unused - * - decoding: Set by user. + * - decoding: Set by libavcodec. */ - int error_recognition; -#define FF_ER_CAREFUL 1 -#define FF_ER_COMPLIANT 2 -#define FF_ER_AGGRESSIVE 3 -#define FF_ER_VERY_AGGRESSIVE 4 + uint8_t motion_subsample_log2; /** - * Called at the beginning of each frame to get a buffer for it. - * If pic.reference is set then the frame will be read later by libavcodec. - * avcodec_align_dimensions() should be used to find the required width and - * height, as they normally need to be rounded up to the next multiple of 16. + * Sample rate of the audio data. + * * - encoding: unused - * - decoding: Set by libavcodec., user can override. + * - decoding: read by user */ - int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); + int sample_rate; /** - * Called to release buffers which were allocated with get_buffer. - * A released buffer can be reused in get_buffer(). - * pic.data[*] must be set to NULL. + * Channel layout of the audio data. + * * - encoding: unused - * - decoding: Set by libavcodec., user can override. + * - decoding: read by user. */ - void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); + uint64_t channel_layout; /** - * Size of the frame reordering buffer in the decoder. - * For MPEG-2 it is 1 IPB or 0 low delay IP. - * - encoding: Set by libavcodec. - * - decoding: Set by libavcodec. + * frame timestamp estimated using various heuristics, in stream time base + * Code outside libavcodec should access this field using: + * av_frame_get_best_effort_timestamp(frame) + * - encoding: unused + * - decoding: set by libavcodec, read by user. */ - int has_b_frames; + int64_t best_effort_timestamp; /** - * number of bytes per packet if constant and known or 0 - * Used by some WAV based audio codecs. + * reordered pos from the last AVPacket that has been input into the decoder + * Code outside libavcodec should access this field using: + * av_frame_get_pkt_pos(frame) + * - encoding: unused + * - decoding: Read by user. */ - int block_align; + int64_t pkt_pos; - int parse_only; /* - decoding only: If true, only parsing is done - (function avcodec_parse_frame()). The frame - data is returned. Only MPEG codecs support this now. */ + /** + * duration of the corresponding packet, expressed in + * AVStream->time_base units, 0 if unknown. + * Code outside libavcodec should access this field using: + * av_frame_get_pkt_duration(frame) + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_duration; /** - * 0-> h263 quant 1-> mpeg quant + * metadata. + * Code outside libavcodec should access this field using: + * av_frame_get_metadata(frame) * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ - int mpeg_quant; + AVDictionary *metadata; /** - * pass1 encoding statistics output buffer - * - encoding: Set by libavcodec. - * - decoding: unused + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * Code outside libavcodec should access this field using: + * av_frame_get_decode_error_flags(frame) + * - encoding: unused + * - decoding: set by libavcodec, read by user. */ - char *stats_out; + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 /** - * pass2 encoding statistics input buffer - * Concatenated stuff from stats_out of pass1 should be placed here. - * - encoding: Allocated/set/freed by user. - * - decoding: unused + * number of audio channels, only used for audio. + * Code outside libavcodec should access this field using: + * av_frame_get_channels(frame) + * - encoding: unused + * - decoding: Read by user. */ - char *stats_in; + int64_t channels; +} AVFrame; + +/** + * Accessors for some AVFrame fields. + * The position of these field in the structure is not part of the ABI, + * they should not be accessed directly outside libavcodec. + */ +int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame); +void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val); +int64_t av_frame_get_pkt_duration (const AVFrame *frame); +void av_frame_set_pkt_duration (AVFrame *frame, int64_t val); +int64_t av_frame_get_pkt_pos (const AVFrame *frame); +void av_frame_set_pkt_pos (AVFrame *frame, int64_t val); +int64_t av_frame_get_channel_layout (const AVFrame *frame); +void av_frame_set_channel_layout (AVFrame *frame, int64_t val); +int av_frame_get_channels (const AVFrame *frame); +void av_frame_set_channels (AVFrame *frame, int val); +int av_frame_get_sample_rate (const AVFrame *frame); +void av_frame_set_sample_rate (AVFrame *frame, int val); +AVDictionary *av_frame_get_metadata (const AVFrame *frame); +void av_frame_set_metadata (AVFrame *frame, AVDictionary *val); +int av_frame_get_decode_error_flags (const AVFrame *frame); +void av_frame_set_decode_error_flags (AVFrame *frame, int val); + +struct AVCodecInternal; + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * Please use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { /** - * ratecontrol qmin qmax limiting method - * 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax. - * - encoding: Set by user. - * - decoding: unused + * information on struct for av_log + * - set by avcodec_alloc_context3 */ - float rc_qsquish; + const AVClass *av_class; + int log_level_offset; - float rc_qmod_amp; - int rc_qmod_freq; + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + char codec_name[32]; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ /** - * ratecontrol override, see RcOverride - * - encoding: Allocated/set/freed by user. - * - decoding: unused + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. */ - RcOverride *rc_override; - int rc_override_count; + unsigned int codec_tag; /** - * rate control equation - * - encoding: Set by user - * - decoding: unused + * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * - encoding: unused + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. */ - const char *rc_eq; + unsigned int stream_codec_tag; +#if FF_API_SUB_ID /** - * maximum bitrate - * - encoding: Set by user. - * - decoding: unused + * @deprecated this field is unused */ - int rc_max_rate; + attribute_deprecated int sub_id; +#endif + + void *priv_data; /** - * minimum bitrate - * - encoding: Set by user. - * - decoding: unused + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. */ - int rc_min_rate; + struct AVCodecInternal *internal; /** - * decoder bitstream buffer size + * Private data of the user, can be used to carry app specific stuff. * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by user. */ - int rc_buffer_size; - float rc_buffer_aggressivity; + void *opaque; /** - * qscale factor between P and I-frames - * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset). - * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). - * - encoding: Set by user. - * - decoding: unused + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream. */ - float i_quant_factor; + int bit_rate; /** - * qscale offset between P and I-frames - * - encoding: Set by user. + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. * - decoding: unused */ - float i_quant_offset; + int bit_rate_tolerance; /** - * initial complexity for pass1 ratecontrol + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. * - encoding: Set by user. * - decoding: unused */ - float rc_initial_cplx; + int global_quality; /** - * DCT algorithm, see FF_DCT_* below * - encoding: Set by user. * - decoding: unused */ - int dct_algo; -#define FF_DCT_AUTO 0 -#define FF_DCT_FASTINT 1 -#define FF_DCT_INT 2 -#define FF_DCT_MMX 3 -#define FF_DCT_MLIB 4 -#define FF_DCT_ALTIVEC 5 -#define FF_DCT_FAAN 6 + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 /** - * luminance masking (0-> disabled) + * CODEC_FLAG_*. * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by user. */ - float lumi_masking; + int flags; /** - * temporary complexity masking (0-> disabled) - * - encoding: Set by user. - * - decoding: unused - */ - float temporal_cplx_masking; - - /** - * spatial complexity masking (0-> disabled) + * CODEC_FLAG2_* * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by user. */ - float spatial_cplx_masking; + int flags2; /** - * p block masking (0-> disabled) - * - encoding: Set by user. - * - decoding: unused + * some codecs need / can use extradata like Huffman tables. + * mjpeg: Huffman tables + * rv10: additional flags + * mpeg4: global headers (they can be in the bitstream or here) + * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid prolems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. */ - float p_masking; + uint8_t *extradata; + int extradata_size; /** - * darkness masking (0-> disabled) - * - encoding: Set by user. - * - decoding: unused + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. */ - float dark_masking; + AVRational time_base; /** - * IDCT algorithm, see FF_IDCT_* below. - * - encoding: Set by user. - * - decoding: Set by user. + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. */ - int idct_algo; -#define FF_IDCT_AUTO 0 -#define FF_IDCT_INT 1 -#define FF_IDCT_SIMPLE 2 -#define FF_IDCT_SIMPLEMMX 3 -#define FF_IDCT_LIBMPEG2MMX 4 -#define FF_IDCT_PS2 5 -#define FF_IDCT_MLIB 6 -#define FF_IDCT_ARM 7 -#define FF_IDCT_ALTIVEC 8 -#define FF_IDCT_SH4 9 -#define FF_IDCT_SIMPLEARM 10 -#define FF_IDCT_H264 11 -#define FF_IDCT_VP3 12 -#define FF_IDCT_IPP 13 -#define FF_IDCT_XVIDMMX 14 -#define FF_IDCT_CAVS 15 -#define FF_IDCT_SIMPLEARMV5TE 16 -#define FF_IDCT_SIMPLEARMV6 17 -#define FF_IDCT_SIMPLEVIS 18 -#define FF_IDCT_WMV2 19 -#define FF_IDCT_FAAN 20 -#define FF_IDCT_EA 21 -#define FF_IDCT_SIMPLENEON 22 -#define FF_IDCT_SIMPLEALPHA 23 + int ticks_per_frame; /** - * slice count + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this is the number of "priming" samples added to the + * beginning of the stream. The decoded output will be delayed by this + * many samples relative to the input to the encoder. Note that this + * field is purely informational and does not directly affect the pts + * output by the encoder, which should always be based on the actual + * presentation time, including any delay. + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * * - encoding: Set by libavcodec. - * - decoding: Set by user (or 0). - */ - int slice_count; - /** - * slice offsets in the frame in bytes - * - encoding: Set/allocated by libavcodec. - * - decoding: Set/allocated by user (or NULL). + * - decoding: Set by libavcodec. */ - int *slice_offset; + int delay; - /** - * error concealment flags - * - encoding: unused - * - decoding: Set by user. - */ - int error_concealment; -#define FF_EC_GUESS_MVS 1 -#define FF_EC_DEBLOCK 2 + /* video only */ /** - * dsp_mask could be add used to disable unwanted CPU features - * CPU features (i.e. MMX, SSE. ...) - * - * With the FORCE flag you may instead enable given CPU features. - * (Dangerous: Usable in case of misdetection, improper usage however will - * result into program crash.) + * picture width / height. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. + * Note: For compatibility it is possible to set this instead of + * coded_width/height before decoding. */ - unsigned dsp_mask; -#define FF_MM_FORCE 0x80000000 /* Force usage of selected flags (OR) */ - /* lower 16 bits - CPU features */ -#define FF_MM_MMX 0x0001 ///< standard MMX -#define FF_MM_3DNOW 0x0004 ///< AMD 3DNOW -#if LIBAVCODEC_VERSION_MAJOR < 53 -#define FF_MM_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext -#endif -#define FF_MM_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext -#define FF_MM_SSE 0x0008 ///< SSE functions -#define FF_MM_SSE2 0x0010 ///< PIV SSE2 functions -#define FF_MM_3DNOWEXT 0x0020 ///< AMD 3DNowExt -#define FF_MM_SSE3 0x0040 ///< Prescott SSE3 functions -#define FF_MM_SSSE3 0x0080 ///< Conroe SSSE3 functions -#define FF_MM_SSE4 0x0100 ///< Penryn SSE4.1 functions -#define FF_MM_SSE42 0x0200 ///< Nehalem SSE4.2 functions -#define FF_MM_IWMMXT 0x0100 ///< XScale IWMMXT -#define FF_MM_ALTIVEC 0x0001 ///< standard AltiVec + int width, height; /** - * bits per sample/pixel from the demuxer (needed for huffyuv). - * - encoding: Set by libavcodec. - * - decoding: Set by user. + * Bitstream width / height, may be different from width/height if lowres enabled. + * - encoding: unused + * - decoding: Set by user before init if known. Codec should override / dynamically change if needed. */ - int bits_per_coded_sample; + int coded_width, coded_height; + +#define FF_ASPECT_EXTENDED 15 /** - * prediction method (needed for huffyuv) + * the number of pictures in a group of pictures, or 0 for intra_only * - encoding: Set by user. * - decoding: unused */ - int prediction_method; -#define FF_PRED_LEFT 0 -#define FF_PRED_PLANE 1 -#define FF_PRED_MEDIAN 2 + int gop_size; /** - * sample aspect ratio (0 if unknown) - * That is the width of a pixel divided by the height of the pixel. - * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. * - encoding: Set by user. - * - decoding: Set by libavcodec. + * - decoding: Set by user if known, overridden by libavcodec if known */ - AVRational sample_aspect_ratio; + enum AVPixelFormat pix_fmt; /** - * the picture in the bitstream - * - encoding: Set by libavcodec. - * - decoding: Set by libavcodec. + * Motion estimation algorithm used for video coding. + * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex), + * 8 (umh), 9 (iter), 10 (tesa) [7, 8, 10 are x264 specific, 9 is snow specific] + * - encoding: MUST be set by user. + * - decoding: unused */ - AVFrame *coded_frame; + int me_method; /** - * debug - * - encoding: Set by user. + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read */ - int debug; -#define FF_DEBUG_PICT_INFO 1 -#define FF_DEBUG_RC 2 -#define FF_DEBUG_BITSTREAM 4 -#define FF_DEBUG_MB_TYPE 8 -#define FF_DEBUG_QP 16 -#define FF_DEBUG_MV 32 -#define FF_DEBUG_DCT_COEFF 0x00000040 -#define FF_DEBUG_SKIP 0x00000080 -#define FF_DEBUG_STARTCODE 0x00000100 -#define FF_DEBUG_PTS 0x00000200 -#define FF_DEBUG_ER 0x00000400 -#define FF_DEBUG_MMCO 0x00000800 -#define FF_DEBUG_BUGS 0x00001000 -#define FF_DEBUG_VIS_QP 0x00002000 -#define FF_DEBUG_VIS_MB_TYPE 0x00004000 -#define FF_DEBUG_BUFFERS 0x00008000 + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); /** - * debug - * - encoding: Set by user. - * - decoding: Set by user. + * callback to negotiate the pixelFormat + * @param fmt is the list of formats which are supported by the codec, + * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. + * The first is always the native one. + * @return the chosen format + * - encoding: unused + * - decoding: Set by user, if not set the native format will be chosen. */ - int debug_mv; -#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames -#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames -#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); /** - * error - * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR. + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. * - decoding: unused */ - uint64_t error[4]; + int max_b_frames; /** - * minimum MB quantizer - * - encoding: unused + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. * - decoding: unused */ - int mb_qmin; + float b_quant_factor; + + /** obsolete FIXME remove */ + int rc_strategy; +#define FF_RC_STRATEGY_XVID 1 + + int b_frame_strategy; +#if FF_API_MPV_GLOBAL_OPTS /** - * maximum MB quantizer - * - encoding: unused + * luma single coefficient elimination threshold + * - encoding: Set by user. * - decoding: unused */ - int mb_qmax; + attribute_deprecated int luma_elim_threshold; /** - * motion estimation comparison function + * chroma single coeff elimination threshold * - encoding: Set by user. * - decoding: unused */ - int me_cmp; + attribute_deprecated int chroma_elim_threshold; +#endif + /** - * subpixel motion estimation comparison function + * qscale offset between IP and B-frames * - encoding: Set by user. * - decoding: unused */ - int me_sub_cmp; + float b_quant_offset; + /** - * macroblock comparison function (not supported yet) - * - encoding: Set by user. - * - decoding: unused + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. */ - int mb_cmp; + int has_b_frames; + /** - * interlaced DCT comparison function + * 0-> h263 quant 1-> mpeg quant * - encoding: Set by user. * - decoding: unused */ - int ildct_cmp; -#define FF_CMP_SAD 0 -#define FF_CMP_SSE 1 -#define FF_CMP_SATD 2 -#define FF_CMP_DCT 3 -#define FF_CMP_PSNR 4 -#define FF_CMP_BIT 5 -#define FF_CMP_RD 6 -#define FF_CMP_ZERO 7 -#define FF_CMP_VSAD 8 -#define FF_CMP_VSSE 9 -#define FF_CMP_NSSE 10 -#define FF_CMP_W53 11 -#define FF_CMP_W97 12 -#define FF_CMP_DCTMAX 13 -#define FF_CMP_DCT264 14 -#define FF_CMP_CHROMA 256 + int mpeg_quant; /** - * ME diamond size & shape + * qscale factor between P and I-frames + * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). * - encoding: Set by user. * - decoding: unused */ - int dia_size; + float i_quant_factor; /** - * amount of previous MV predictors (2a+1 x 2a+1 square) + * qscale offset between P and I-frames * - encoding: Set by user. * - decoding: unused */ - int last_predictor_count; + float i_quant_offset; /** - * prepass for motion estimation + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + int slice_count; + /** + * prediction method (needed for huffyuv) + * - encoding: Set by user. + * - decoding: unused + */ + int prediction_method; +#define FF_PRED_LEFT 0 +#define FF_PRED_PLANE 1 +#define FF_PRED_MEDIAN 2 + + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + int *slice_offset; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * prepass for motion estimation * - encoding: Set by user. * - decoding: unused */ @@ -1750,17 +1936,6 @@ typedef struct AVCodecContext { */ int me_subpel_quality; - /** - * callback to negotiate the pixelFormat - * @param fmt is the list of formats which are supported by the codec, - * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. - * The first is always the native one. - * @return the chosen format - * - encoding: unused - * - decoding: Set by user, if not set the native format will be chosen. - */ - enum PixelFormat (*get_format)(struct AVCodecContext *s, const enum PixelFormat * fmt); - /** * DTG active format information (additional aspect ratio * information only used in DVB MPEG-2 transport streams) @@ -1802,65 +1977,14 @@ typedef struct AVCodecContext { */ int inter_quant_bias; +#if FF_API_COLOR_TABLE_ID /** * color table ID * - encoding: unused * - decoding: Which clrtable should be used for 8bit RGB images. * Tables have to be stored somewhere. FIXME */ - int color_table_id; - - /** - * internal_buffer count - * Don't touch, used by libavcodec default_get_buffer(). - */ - int internal_buffer_count; - - /** - * internal_buffers - * Don't touch, used by libavcodec default_get_buffer(). - */ - void *internal_buffer; - -#define FF_LAMBDA_SHIFT 7 -#define FF_LAMBDA_SCALE (1< ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). - * This is used to work around some encoder bugs. - * - encoding: unused - * - decoding: Set by user, will be converted to uppercase by libavcodec during init. - */ - unsigned int stream_codec_tag; - /** * scene change detection threshold * 0 is default, larger means fewer detected scene changes. @@ -1921,527 +2037,707 @@ typedef struct AVCodecContext { int scenechange_threshold; /** - * minimum Lagrange multipler + * noise reduction strength * - encoding: Set by user. * - decoding: unused */ - int lmin; + int noise_reduction; +#if FF_API_INTER_THRESHOLD /** - * maximum Lagrange multipler + * @deprecated this field is unused + */ + attribute_deprecated int inter_threshold; +#endif + +#if FF_API_MPV_GLOBAL_OPTS + /** + * @deprecated use mpegvideo private options instead + */ + attribute_deprecated int quantizer_noise_shaping; +#endif + + /** + * Motion estimation threshold below which no motion estimation is + * performed, but instead the user specified motion vectors are used. + * * - encoding: Set by user. * - decoding: unused */ - int lmax; + int me_threshold; /** - * palette control structure - * - encoding: ??? (no palette-enabled encoder yet) - * - decoding: Set by user. + * Macroblock threshold below which the user specified macroblock types will be used. + * - encoding: Set by user. + * - decoding: unused */ - struct AVPaletteControl *palctrl; + int mb_threshold; /** - * noise reduction strength + * precision of the intra DC coefficient - 8 * - encoding: Set by user. * - decoding: unused */ - int noise_reduction; + int intra_dc_precision; /** - * Called at the beginning of a frame to get cr buffer for it. - * Buffer type (size, hints) must be the same. libavcodec won't check it. - * libavcodec will pass previous buffer in pic, function should return - * same buffer or new buffer with old frame "painted" into it. - * If pic.data[0] == NULL must behave like get_buffer(). + * Number of macroblock rows at the top which are skipped. * - encoding: unused - * - decoding: Set by libavcodec., user can override + * - decoding: Set by user. */ - int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); + int skip_top; /** - * Number of bits which should be loaded into the rc buffer before decoding starts. + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * Border processing masking, raises the quantizer for mbs on the borders + * of the picture. * - encoding: Set by user. * - decoding: unused */ - int rc_initial_buffer_occupancy; + float border_masking; /** - * + * minimum MB lagrange multipler * - encoding: Set by user. * - decoding: unused */ - int inter_threshold; + int mb_lmin; /** - * CODEC_FLAG2_* + * maximum MB lagrange multipler * - encoding: Set by user. - * - decoding: Set by user. + * - decoding: unused */ - int flags2; + int mb_lmax; /** - * Simulates errors in the bitstream to test error concealment. + * * - encoding: Set by user. * - decoding: unused */ - int error_rate; + int me_penalty_compensation; /** - * MP3 antialias algorithm, see FF_AA_* below. - * - encoding: unused - * - decoding: Set by user. + * + * - encoding: Set by user. + * - decoding: unused */ - int antialias_algo; -#define FF_AA_AUTO 0 -#define FF_AA_FASTINT 1 //not implemented yet -#define FF_AA_INT 2 -#define FF_AA_FLOAT 3 + int bidir_refine; + /** - * quantizer noise shaping + * * - encoding: Set by user. * - decoding: unused */ - int quantizer_noise_shaping; + int brd_scale; /** - * thread count - * is used to decide how many independent tasks should be passed to execute() + * minimum GOP size * - encoding: Set by user. - * - decoding: Set by user. + * - decoding: unused */ - int thread_count; + int keyint_min; /** - * The codec may call this to execute several independent things. - * It will return only after finishing all tasks. - * The user may replace this with some multithreaded implementation, - * the default implementation will execute the parts serially. - * @param count the number of things to execute - * - encoding: Set by libavcodec, user can override. - * - decoding: Set by libavcodec, user can override. + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. */ - int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + int refs; /** - * thread opaque - * Can be used by execute() to store some per AVCodecContext stuff. - * - encoding: set by execute() - * - decoding: set by execute() + * chroma qp offset from luma + * - encoding: Set by user. + * - decoding: unused */ - void *thread_opaque; + int chromaoffset; /** - * Motion estimation threshold below which no motion estimation is - * performed, but instead the user specified motion vectors are used. - * + * Multiplied by qscale for each frame and added to scene_change_score. * - encoding: Set by user. * - decoding: unused */ - int me_threshold; + int scenechange_factor; /** - * Macroblock threshold below which the user specified macroblock types will be used. + * + * Note: Value depends upon the compare function used for fullpel ME. * - encoding: Set by user. * - decoding: unused */ - int mb_threshold; + int mv0_threshold; /** - * precision of the intra DC coefficient - 8 + * Adjust sensitivity of b_frame_strategy 1. * - encoding: Set by user. * - decoding: unused */ - int intra_dc_precision; + int b_sensitivity; /** - * noise vs. sse weight for the nsse comparsion function - * - encoding: Set by user. - * - decoding: unused + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec */ - int nsse_weight; + enum AVColorPrimaries color_primaries; /** - * Number of macroblock rows at the top which are skipped. - * - encoding: unused - * - decoding: Set by user. + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec */ - int skip_top; + enum AVColorTransferCharacteristic color_trc; /** - * Number of macroblock rows at the bottom which are skipped. - * - encoding: unused - * - decoding: Set by user. + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec */ - int skip_bottom; + enum AVColorSpace colorspace; /** - * profile - * - encoding: Set by user. - * - decoding: Set by libavcodec. + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec */ - int profile; -#define FF_PROFILE_UNKNOWN -99 -#define FF_PROFILE_AAC_MAIN 0 -#define FF_PROFILE_AAC_LOW 1 -#define FF_PROFILE_AAC_SSR 2 -#define FF_PROFILE_AAC_LTP 3 + enum AVColorRange color_range; /** - * level - * - encoding: Set by user. - * - decoding: Set by libavcodec. + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec */ - int level; -#define FF_LEVEL_UNKNOWN -99 + enum AVChromaLocation chroma_sample_location; /** - * low resolution decoding, 1-> 1/2 size, 2->1/4 size - * - encoding: unused + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** Field order + * - encoding: set by libavcodec * - decoding: Set by user. */ - int lowres; + enum AVFieldOrder field_order; + + /* audio only */ + int sample_rate; ///< samples per second + int channels; ///< number of audio channels /** - * Bitstream width / height, may be different from width/height if lowres - * or other things are used. - * - encoding: unused - * - decoding: Set by user before init if known. Codec should override / dynamically change if needed. + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. */ - int coded_width, coded_height; + enum AVSampleFormat sample_fmt; ///< sample format + /* The following data should not be initialized. */ /** - * frame skip threshold - * - encoding: Set by user. - * - decoding: unused + * Samples per packet, initialized when calling 'init'. */ - int frame_skip_threshold; + int frame_size; /** - * frame skip factor - * - encoding: Set by user. - * - decoding: unused + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. */ - int frame_skip_factor; + int frame_number; /** - * frame skip exponent - * - encoding: Set by user. - * - decoding: unused + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. */ - int frame_skip_exp; + int block_align; /** - * frame skip comparison function + * Audio cutoff bandwidth (0 means "automatic") * - encoding: Set by user. * - decoding: unused */ - int frame_skip_cmp; + int cutoff; +#if FF_API_REQUEST_CHANNELS /** - * Border processing masking, raises the quantizer for mbs on the borders - * of the picture. - * - encoding: Set by user. - * - decoding: unused + * Decoder should decode to this many channels if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + * @deprecated Deprecated in favor of request_channel_layout. */ - float border_masking; + int request_channels; +#endif /** - * minimum MB lagrange multipler - * - encoding: Set by user. - * - decoding: unused + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. */ - int mb_lmin; + uint64_t channel_layout; /** - * maximum MB lagrange multipler - * - encoding: Set by user. - * - decoding: unused + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. */ - int mb_lmax; + uint64_t request_channel_layout; /** - * + * Type of service that the audio stream conveys. * - encoding: Set by user. - * - decoding: unused + * - decoding: Set by libavcodec. */ - int me_penalty_compensation; + enum AVAudioServiceType audio_service_type; /** - * - * - encoding: unused + * desired sample format + * - encoding: Not used. * - decoding: Set by user. + * Decoder will decode to this format if it can. */ - enum AVDiscard skip_loop_filter; + enum AVSampleFormat request_sample_fmt; /** + * Called at the beginning of each frame to get a buffer for it. + * + * The function will set AVFrame.data[], AVFrame.linesize[]. + * AVFrame.extended_data[] must also be set, but it should be the same as + * AVFrame.data[] except for planar audio with more channels than can fit + * in AVFrame.data[]. In that case, AVFrame.data[] shall still contain as + * many data pointers as it can hold. + * + * if CODEC_CAP_DR1 is not set then get_buffer() must call + * avcodec_default_get_buffer() instead of providing buffers allocated by + * some other means. + * + * AVFrame.data[] should be 32- or 16-byte-aligned unless the CPU doesn't + * need it. avcodec_default_get_buffer() aligns the output buffer properly, + * but if get_buffer() is overridden then alignment considerations should + * be taken into account. + * + * @see avcodec_default_get_buffer() + * + * Video: + * + * If pic.reference is set then the frame will be read later by libavcodec. + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * If frame multithreading is used and thread_safe_callbacks is set, + * it may be called from a different thread, but not from more than one at + * once. Does not need to be reentrant. + * + * @see release_buffer(), reget_buffer() + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * Decoders cannot use the buffer after returning from + * avcodec_decode_audio4(), so they will not call release_buffer(), as it + * is assumed to be released immediately upon return. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() * * - encoding: unused - * - decoding: Set by user. + * - decoding: Set by libavcodec, user can override. */ - enum AVDiscard skip_idct; + int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); /** - * + * Called to release buffers which were allocated with get_buffer. + * A released buffer can be reused in get_buffer(). + * pic.data[*] must be set to NULL. + * May be called from a different thread if frame multithreading is used, + * but not by more than one thread at once, so does not need to be reentrant. * - encoding: unused - * - decoding: Set by user. + * - decoding: Set by libavcodec, user can override. */ - enum AVDiscard skip_frame; + void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); /** - * - * - encoding: Set by user. - * - decoding: unused + * Called at the beginning of a frame to get cr buffer for it. + * Buffer type (size, hints) must be the same. libavcodec won't check it. + * libavcodec will pass previous buffer in pic, function should return + * same buffer or new buffer with old frame "painted" into it. + * If pic.data[0] == NULL must behave like get_buffer(). + * if CODEC_CAP_DR1 is not set then reget_buffer() must call + * avcodec_default_reget_buffer() instead of providing buffers allocated by + * some other means. + * - encoding: unused + * - decoding: Set by libavcodec, user can override. */ - int bidir_refine; + int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); + + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) /** - * + * minimum quantizer * - encoding: Set by user. * - decoding: unused */ - int brd_scale; + int qmin; /** - * constant rate factor - quality-based VBR - values ~correspond to qps + * maximum quantizer * - encoding: Set by user. * - decoding: unused */ - float crf; + int qmax; /** - * constant quantization parameter rate control method + * maximum quantizer difference between frames * - encoding: Set by user. * - decoding: unused */ - int cqp; + int max_qdiff; /** - * minimum GOP size + * ratecontrol qmin qmax limiting method + * 0-> clipping, 1-> use a nice continuous function to limit qscale wthin qmin/qmax. * - encoding: Set by user. * - decoding: unused */ - int keyint_min; + float rc_qsquish; + + float rc_qmod_amp; + int rc_qmod_freq; /** - * number of reference frames + * decoder bitstream buffer size * - encoding: Set by user. - * - decoding: Set by lavc. + * - decoding: unused */ - int refs; + int rc_buffer_size; /** - * chroma qp offset from luma - * - encoding: Set by user. + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. * - decoding: unused */ - int chromaoffset; + int rc_override_count; + RcOverride *rc_override; /** - * Influences how often B-frames are used. - * - encoding: Set by user. + * rate control equation + * - encoding: Set by user * - decoding: unused */ - int bframebias; + const char *rc_eq; /** - * trellis RD quantization + * maximum bitrate * - encoding: Set by user. * - decoding: unused */ - int trellis; + int rc_max_rate; /** - * Reduce fluctuations in qp (before curve compression). + * minimum bitrate * - encoding: Set by user. * - decoding: unused */ - float complexityblur; + int rc_min_rate; + + float rc_buffer_aggressivity; /** - * in-loop deblocking filter alphac0 parameter - * alpha is in the range -6...6 + * initial complexity for pass1 ratecontrol * - encoding: Set by user. * - decoding: unused */ - int deblockalpha; + float rc_initial_cplx; /** - * in-loop deblocking filter beta parameter - * beta is in the range -6...6 + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. * - encoding: Set by user. - * - decoding: unused + * - decoding: unused. */ - int deblockbeta; + float rc_max_available_vbv_use; /** - * macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4 + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. * - encoding: Set by user. - * - decoding: unused + * - decoding: unused. */ - int partitions; -#define X264_PART_I4X4 0x001 /* Analyze i4x4 */ -#define X264_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */ -#define X264_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */ -#define X264_PART_P4X4 0x020 /* Analyze p8x4, p4x8, p4x4 */ -#define X264_PART_B8X8 0x100 /* Analyze b16x8, b8x16 and b8x8 */ + float rc_min_vbv_overflow_use; /** - * direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto) + * Number of bits which should be loaded into the rc buffer before decoding starts. * - encoding: Set by user. * - decoding: unused */ - int directpred; + int rc_initial_buffer_occupancy; +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 +#define FF_CODER_TYPE_RAW 2 +#define FF_CODER_TYPE_RLE 3 +#define FF_CODER_TYPE_DEFLATE 4 /** - * Audio cutoff bandwidth (0 means "automatic") + * coder type * - encoding: Set by user. * - decoding: unused */ - int cutoff; + int coder_type; /** - * Multiplied by qscale for each frame and added to scene_change_score. + * context model * - encoding: Set by user. * - decoding: unused */ - int scenechange_factor; + int context_model; /** - * - * Note: Value depends upon the compare function used for fullpel ME. + * minimum Lagrange multipler * - encoding: Set by user. * - decoding: unused */ - int mv0_threshold; + int lmin; /** - * Adjusts sensitivity of b_frame_strategy 1. + * maximum Lagrange multipler * - encoding: Set by user. * - decoding: unused */ - int b_sensitivity; + int lmax; /** + * frame skip threshold * - encoding: Set by user. * - decoding: unused */ - int compression_level; -#define FF_COMPRESSION_DEFAULT -1 + int frame_skip_threshold; /** - * Sets whether to use LPC mode - used by FLAC encoder. + * frame skip factor * - encoding: Set by user. * - decoding: unused */ - int use_lpc; + int frame_skip_factor; /** - * LPC coefficient precision - used by FLAC encoder + * frame skip exponent * - encoding: Set by user. * - decoding: unused */ - int lpc_coeff_precision; + int frame_skip_exp; /** + * frame skip comparison function * - encoding: Set by user. * - decoding: unused */ - int min_prediction_order; + int frame_skip_cmp; /** + * trellis RD quantization * - encoding: Set by user. * - decoding: unused */ - int max_prediction_order; + int trellis; /** - * search method for selecting prediction order * - encoding: Set by user. * - decoding: unused */ - int prediction_order_method; + int min_prediction_order; /** * - encoding: Set by user. * - decoding: unused */ - int min_partition_order; + int max_prediction_order; /** - * - encoding: Set by user. + * GOP timecode frame start number + * - encoding: Set by user, in non drop frame format + * - decoding: Set by libavcodec (timecode in the 25 bits format, -1 if unset) + */ + int64_t timecode_frame_start; + + /* The RTP callback: This function is called */ + /* every time the encoder has a packet to send. */ + /* It depends on the encoder if the data starts */ + /* with a Start Code (it should). H.263 does. */ + /* mb_nb contains the number of macroblocks */ + /* encoded in the RTP payload. */ + void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); + + int rtp_payload_size; /* The size of the RTP payload: the coder will */ + /* do its best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263. */ + /* This doesn't take account of any particular */ + /* headers inside the transmitted RTP payload. */ + + /* statistics, used for 2-pass encoding */ + int mv_bits; + int header_bits; + int i_tex_bits; + int p_tex_bits; + int i_count; + int p_count; + int skip_count; + int misc_bits; + + /** + * number of bits used for the previously encoded frame + * - encoding: Set by libavcodec. * - decoding: unused */ - int max_partition_order; + int frame_bits; /** - * GOP timecode frame start number, in non drop frame format - * - encoding: Set by user. + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. * - decoding: unused */ - int64_t timecode_frame_start; + char *stats_out; -#if LIBAVCODEC_VERSION_MAJOR < 53 /** - * Decoder should decode to this many channels if it can (0 for default) - * - encoding: unused - * - decoding: Set by user. - * @deprecated Deprecated in favor of request_channel_layout. + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused */ - int request_channels; -#endif + char *stats_in; /** - * Percentage of dynamic range compression to be applied by the decoder. - * The default value is 1.0, corresponding to full compression. - * - encoding: unused + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_OLD_MSMPEG4 2 +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_AC_VLC 0 ///< Will be removed, libavcodec can now handle these non-compliant files by default. +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 + + /** + * strictly follow the standard (MPEG4, ...). + * - encoding: Set by user. * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) */ - float drc_scale; + int strict_std_compliance; +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. /** - * opaque 64bit number (generally a PTS) that will be reordered and - * output in AVFrame.reordered_opaque + * error concealment flags * - encoding: unused * - decoding: Set by user. */ - int64_t reordered_opaque; + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 /** - * Bits per sample/pixel of internal libavcodec pixel/sample format. - * This field is applicable only when sample_fmt is SAMPLE_FMT_S32. - * - encoding: set by user. - * - decoding: set by libavcodec. + * debug + * - encoding: Set by user. + * - decoding: Set by user. */ - int bits_per_raw_sample; + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_MV 32 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_PTS 0x00000200 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_VIS_QP 0x00002000 +#define FF_DEBUG_VIS_MB_TYPE 0x00004000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 /** - * Audio channel layout. - * - encoding: set by user. - * - decoding: set by libavcodec. + * debug + * - encoding: Set by user. + * - decoding: Set by user. */ - int64_t channel_layout; + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames /** - * Request decoder to use this channel layout if it can (0 for default) + * Error recognition; may misdetect some more or less valid parts as errors. * - encoding: unused * - decoding: Set by user. */ - int64_t request_channel_layout; + int err_recognition; +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) +#define AV_EF_BUFFER (1<<2) +#define AV_EF_EXPLODE (1<<3) + +#define AV_EF_CAREFUL (1<<16) +#define AV_EF_COMPLIANT (1<<17) +#define AV_EF_AGGRESSIVE (1<<18) - /** - * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. - * - encoding: Set by user. - * - decoding: unused. - */ - float rc_max_available_vbv_use; /** - * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. - * - encoding: Set by user. - * - decoding: unused. + * opaque 64bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * @deprecated in favor of pkt_pts + * - encoding: unused + * - decoding: Set by user. */ - float rc_min_vbv_overflow_use; + int64_t reordered_opaque; /** * Hardware accelerator in use @@ -2450,15 +2746,6 @@ typedef struct AVCodecContext { */ struct AVHWAccel *hwaccel; - /** - * For some codecs, the time base is closer to the field rate than the frame rate. - * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration - * if no telecine is used ... - * - * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. - */ - int ticks_per_frame; - /** * Hardware accelerator context. * For some hardware accelerators, a global context needs to be @@ -2472,80 +2759,451 @@ typedef struct AVCodecContext { void *hwaccel_context; /** - * Chromaticity coordinates of the source primaries. - * - encoding: Set by user - * - decoding: Set by libavcodec + * error + * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR. + * - decoding: unused */ - enum AVColorPrimaries color_primaries; + uint64_t error[AV_NUM_DATA_POINTERS]; /** - * Color Transfer Characteristic. - * - encoding: Set by user - * - decoding: Set by libavcodec + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused */ - enum AVColorTransferCharacteristic color_trc; + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 /** - * YUV colorspace type. - * - encoding: Set by user - * - decoding: Set by libavcodec + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. */ - enum AVColorSpace colorspace; + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_LIBMPEG2MMX 4 +#if FF_API_MMI +#define FF_IDCT_MMI 5 +#endif +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SH4 9 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_H264 11 +#define FF_IDCT_VP3 12 +#define FF_IDCT_IPP 13 +#define FF_IDCT_XVIDMMX 14 +#define FF_IDCT_CAVS 15 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_SIMPLEVIS 18 +#define FF_IDCT_WMV2 19 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_EA 21 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_SIMPLEALPHA 23 +#define FF_IDCT_BINK 24 +#if FF_API_DSP_MASK /** - * MPEG vs JPEG YUV range. - * - encoding: Set by user - * - decoding: Set by libavcodec + * Unused. + * @deprecated use av_set_cpu_flags_mask() instead. */ - enum AVColorRange color_range; + attribute_deprecated unsigned dsp_mask; +#endif /** - * This defines the location of chroma samples. - * - encoding: Set by user - * - decoding: Set by libavcodec + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. */ - enum AVChromaLocation chroma_sample_location; -} AVCodecContext; + int bits_per_coded_sample; -/** - * AVCodec. - */ -typedef struct AVCodec { /** - * Name of the codec implementation. - * The name is globally unique among encoders and among decoders (but an - * encoder and a decoder can share the same name). - * This is the primary way to find a codec from the user perspective. + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. */ - const char *name; - enum CodecType type; - enum CodecID id; - int priv_data_size; - int (*init)(AVCodecContext *); - int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data); - int (*close)(AVCodecContext *); - int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); + int bits_per_raw_sample; + /** - * Codec capabilities. - * see CODEC_CAP_* + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * the picture in the bitstream + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + AVFrame *coded_frame; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * Set by the client if its custom get_buffer() callback can be called + * synchronously from another thread, which allows faster multithreaded decoding. + * draw_horiz_band() will be called from other threads regardless of this setting. + * Ignored if the default get_buffer() is used. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_safe_callbacks; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * thread opaque + * Can be used by execute() to store some per AVCodecContext stuff. + * - encoding: set by execute() + * - decoding: set by execute() + */ + void *thread_opaque; + + /** + * noise vs. sse weight for the nsse comparsion function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int profile; +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + + /** + * level + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int level; +#define FF_LEVEL_UNKNOWN -99 + + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + + /** + * Simulates errors in the bitstream to test error concealment. + * - encoding: Set by user. + * - decoding: unused + */ + int error_rate; + + /** + * Current packet as passed into the decoder, to avoid having + * to pass the packet into every function. Currently only valid + * inside lavc and get/release_buffer callbacks. + * - decoding: set by avcodec_decode_*, read by get_buffer() for setting pkt_pts + * - encoding: unused + */ + AVPacket *pkt; + + /** + * VBV delay coded in the last frame (in periods of a 27 MHz clock). + * Used for compliant TS muxing. + * - encoding: Set by libavcodec. + * - decoding: unused. + */ + uint64_t vbv_delay; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are. + * Code outside libavcodec should access this field using: + * avcodec_set_pkt_timebase(avctx) + * - encoding unused. + * - decodimg set by user + */ + AVRational pkt_timebase; + + /** + * AVCodecDescriptor + * Code outside libavcodec should access this field using: + * avcodec_get_codec_descriptior(avctx) + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const AVCodecDescriptor *codec_descriptor; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame +} AVCodecContext; + +AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); +void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); + +const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); +void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc); + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +typedef struct AVCodecDefault AVCodecDefault; + +struct AVSubtitle; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see CODEC_CAP_* */ int capabilities; + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int priv_data_size; struct AVCodec *next; + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * If defined, called on thread contexts when they are created. + * If the codec allocates writable tables in init(), re-allocate them here. + * priv_data will be set to a copy of the original. + */ + int (*init_thread_copy)(AVCodecContext *); + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const AVCodecDefault *defaults; + + /** + * Initialize codec static data, called from avcodec_register(). + */ + void (*init_static_data)(struct AVCodec *codec); + + int (*init)(AVCodecContext *); + int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, + const struct AVSubtitle *sub); + /** + * Encode data to an AVPacket. + * + * @param avctx codec context + * @param avpkt output AVPacket (may contain a user-provided buffer) + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, + int *got_packet_ptr); + int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); + int (*close)(AVCodecContext *); /** * Flush buffers. * Will be called when seeking */ void (*flush)(AVCodecContext *); - const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} - const enum PixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 - /** - * Descriptive name for the codec, meant to be more human readable than \p name. - * You \e should use the NULL_IF_CONFIG_SMALL() macro to define it. - */ - const char *long_name; - const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 - const enum SampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 - const int64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 } AVCodec; /** @@ -2562,23 +3220,23 @@ typedef struct AVHWAccel { /** * Type of codec implemented by the hardware accelerator. * - * See CODEC_TYPE_xxx + * See AVMEDIA_TYPE_xxx */ - enum CodecType type; + enum AVMediaType type; /** * Codec implemented by the hardware accelerator. * - * See CODEC_ID_xxx + * See AV_CODEC_ID_xxx */ - enum CodecID id; + enum AVCodecID id; /** * Supported pixel format. * * Only hardware accelerated formats are supported here. */ - enum PixelFormat pix_fmt; + enum AVPixelFormat pix_fmt; /** * Hardware accelerated codec capabilities. @@ -2594,7 +3252,7 @@ typedef struct AVHWAccel { * Meaningful frame information (codec specific) is guaranteed to * be parsed at this point. This function is mandatory. * - * Note that \p buf can be NULL along with \p buf_size set to 0. + * Note that buf can be NULL along with buf_size set to 0. * Otherwise, this means the whole frame is available at this point. * * @param avctx the codec context @@ -2638,40 +3296,25 @@ typedef struct AVHWAccel { int priv_data_size; } AVHWAccel; +/** + * @defgroup lavc_picture AVPicture + * + * Functions for working with AVPicture + * @{ + */ + /** * four components are given, that's all. * the last component is alpha */ typedef struct AVPicture { - uint8_t *data[4]; - int linesize[4]; ///< number of bytes per line + uint8_t *data[AV_NUM_DATA_POINTERS]; + int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line } AVPicture; -#if LIBAVCODEC_VERSION_MAJOR < 53 /** - * AVPaletteControl - * This structure defines a method for communicating palette changes - * between and demuxer and a decoder. - * - * @deprecated Use AVPacket to send palette changes instead. - * This is totally broken. + * @} */ -#define AVPALETTE_SIZE 1024 -#define AVPALETTE_COUNT 256 -typedef struct AVPaletteControl { - - /* Demuxer sets this to 1 to indicate the palette has changed; - * decoder resets to 0. */ - int palette_changed; - - /* 4-byte ARGB palette entries, stored in native byte order; note that - * the individual palette components should be on a 8-bit scale; if - * the palette data comes from an IBM VGA native format, the component - * data is probably 6 bits in size and needs to be scaled. */ - unsigned int palette[AVPALETTE_COUNT]; - -} AVPaletteControl attribute_deprecated; -#endif enum AVSubtitleType { SUBTITLE_NONE, @@ -2709,10 +3352,16 @@ typedef struct AVSubtitleRect { /** * 0 terminated ASS/SSA compatible event line. - * The pressentation of this is unaffected by the other values in this + * The presentation of this is unaffected by the other values in this * struct. */ char *ass; + + /** + * 1 indicates this subtitle is a forced subtitle. + * A forced subtitle should be displayed even when subtitles are hidden. + */ + int forced; } AVSubtitleRect; typedef struct AVSubtitle { @@ -2721,638 +3370,1343 @@ typedef struct AVSubtitle { uint32_t end_display_time; /* relative to packet pts, in ms */ unsigned num_rects; AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE } AVSubtitle; -/* packet functions */ - /** - * @deprecated use NULL instead + * If c is NULL, returns the first registered codec, + * if c is non-NULL, returns the next registered codec after c, + * or NULL if c is the last one. */ -attribute_deprecated void av_destruct_packet_nofree(AVPacket *pkt); +AVCodec *av_codec_next(const AVCodec *c); /** - * Default packet destructor. + * Return the LIBAVCODEC_VERSION_INT constant. */ -void av_destruct_packet(AVPacket *pkt); +unsigned avcodec_version(void); /** - * Initialize optional fields of a packet with default values. - * - * @param pkt packet + * Return the libavcodec build-time configuration. */ -void av_init_packet(AVPacket *pkt); +const char *avcodec_configuration(void); /** - * Allocate the payload of a packet and initialize its fields with - * default values. - * - * @param pkt packet - * @param size wanted payload size - * @return 0 if OK, AVERROR_xxx otherwise + * Return the libavcodec license. */ -int av_new_packet(AVPacket *pkt, int size); +const char *avcodec_license(void); /** - * Reduce packet size, correctly zeroing padding + * Register the codec codec and initialize libavcodec. * - * @param pkt packet - * @param size new size + * @warning either this function or avcodec_register_all() must be called + * before any other libavcodec functions. + * + * @see avcodec_register_all() */ -void av_shrink_packet(AVPacket *pkt, int size); +void avcodec_register(AVCodec *codec); /** - * @warning This is a hack - the packet memory allocation stuff is broken. The - * packet is allocated if it was not really allocated. + * Register all the codecs, parsers and bitstream filters which were enabled at + * configuration time. If you do not call this function you can select exactly + * which formats you want to support, by using the individual registration + * functions. + * + * @see avcodec_register + * @see av_register_codec_parser + * @see av_register_bitstream_filter */ -int av_dup_packet(AVPacket *pkt); +void avcodec_register_all(void); + +#if FF_API_ALLOC_CONTEXT /** - * Free a packet. + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct can be deallocated by simply calling av_free(). * - * @param pkt packet to free + * @return An AVCodecContext filled with default values or NULL on failure. + * @see avcodec_get_context_defaults + * + * @deprecated use avcodec_alloc_context3() */ -void av_free_packet(AVPacket *pkt); +attribute_deprecated +AVCodecContext *avcodec_alloc_context(void); -/* resample.c */ +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +attribute_deprecated +AVCodecContext *avcodec_alloc_context2(enum AVMediaType); -struct ReSampleContext; -struct AVResampleContext; +/** + * Set the fields of the given AVCodecContext to default values. + * + * @param s The AVCodecContext of which the fields should be set to default values. + * @deprecated use avcodec_get_context_defaults3 + */ +attribute_deprecated +void avcodec_get_context_defaults(AVCodecContext *s); -typedef struct ReSampleContext ReSampleContext; +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +attribute_deprecated +void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType); +#endif + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct can be deallocated by calling avcodec_close() on it followed + * by av_free(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + * @see avcodec_get_context_defaults + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Set the fields of the given AVCodecContext to default values corresponding + * to the given codec (defaults may be codec-dependent). + * + * Do not call this function if a non-NULL codec has been passed + * to avcodec_alloc_context3() that allocated this AVCodecContext. + * If codec is non-NULL, it is illegal to call avcodec_open2() with a + * different codec on this AVCodecContext. + */ +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +/** + * Get the AVClass for AVFrame. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_frame_class(void); + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Copy the settings of the source AVCodecContext into the destination + * AVCodecContext. The resulting destination codec context will be + * unopened, i.e. you are required to call avcodec_open2() before you + * can use this AVCodecContext to decode/encode video/audio data. + * + * @param dest target codec context, should be initialized with + * avcodec_alloc_context3(), but otherwise uninitialized + * @param src source codec context + * @return AVERROR() on error (e.g. memory allocation error), 0 on success + */ +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using avcodec_free_frame(). + * + * @return An AVFrame filled with default values or NULL on failure. + * @see avcodec_get_frame_defaults + */ +AVFrame *avcodec_alloc_frame(void); + +/** + * Set the fields of the given AVFrame to default values. + * + * @param frame The AVFrame of which the fields should be set to default values. + */ +void avcodec_get_frame_defaults(AVFrame *frame); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. + * + * @param frame frame to be freed. The pointer will be set to NULL. + * + * @warning this function does NOT free the data buffers themselves + * (it does not know how, since they might have been allocated with + * a custom get_buffer()). + */ +void avcodec_free_frame(AVFrame **frame); -#if LIBAVCODEC_VERSION_MAJOR < 53 +#if FF_API_AVCODEC_OPEN /** - * @deprecated Use av_audio_resample_init() instead. + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated. + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @code + * avcodec_register_all(); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open(context, codec) < 0) + * exit(1); + * @endcode + * + * @param avctx The context which will be set up to use the given codec. + * @param codec The codec to use within the context. + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3, avcodec_find_decoder, avcodec_find_encoder, avcodec_close + * + * @deprecated use avcodec_open2 */ -attribute_deprecated ReSampleContext *audio_resample_init(int output_channels, int input_channels, - int output_rate, int input_rate); +attribute_deprecated +int avcodec_open(AVCodecContext *avctx, AVCodec *codec); #endif + /** - * Initializes audio resampling context + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). * - * @param output_channels number of output channels - * @param input_channels number of input channels - * @param output_rate output sample rate - * @param input_rate input sample rate - * @param sample_fmt_out requested output sample format - * @param sample_fmt_in input sample format - * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq - * @param log2_phase_count log2 of the number of entries in the polyphase filterbank - * @param linear If 1 then the used FIR filter will be linearly interpolated - between the 2 closest, if 0 the closest will be used - * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate - * @return allocated ReSampleContext, NULL if error occured + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @code + * avcodec_register_all(); + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * avcodec_get_context_defaults3() for this context, then this + * parameter MUST be either NULL or equal to the previously passed + * codec. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). */ -ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, - int output_rate, int input_rate, - enum SampleFormat sample_fmt_out, - enum SampleFormat sample_fmt_in, - int filter_length, int log2_phase_count, - int linear, double cutoff); +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); -int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); -void audio_resample_close(ReSampleContext *s); +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() / + * avcodec_get_context_defaults3() with a non-NULL codec. Subsequent calls will + * do nothing. + */ +int avcodec_close(AVCodecContext *avctx); +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); /** - * Initializes an audio resampler. - * Note, if either rate is not an integer then simply scale both rates up so they are. - * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq - * @param log2_phase_count log2 of the number of entries in the polyphase filterbank - * @param linear If 1 then the used FIR filter will be linearly interpolated - between the 2 closest, if 0 the closest will be used - * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate + * @} */ -struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff); /** - * resamples. - * @param src an array of unconsumed samples - * @param consumed the number of samples of src which have been consumed are returned here - * @param src_size the number of unconsumed samples available - * @param dst_size the amount of space in samples available in dst - * @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context. - * @return the number of samples written in dst or -1 if an error occurred + * @addtogroup lavc_packet + * @{ */ -int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx); +/** + * Default packet destructor. + */ +void av_destruct_packet(AVPacket *pkt); /** - * Compensates samplerate/timestamp drift. The compensation is done by changing - * the resampler parameters, so no audible clicks or similar distortions occur - * @param compensation_distance distance in output samples over which the compensation should be performed - * @param sample_delta number of output samples which should be output less + * Initialize optional fields of a packet with default values. * - * example: av_resample_compensate(c, 10, 500) - * here instead of 510 samples only 500 samples would be output + * Note, this does not touch the data and size members, which have to be + * initialized separately. * - * note, due to rounding the actual compensation might be slightly different, - * especially if the compensation_distance is large and the in_rate used during init is small + * @param pkt packet */ -void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance); -void av_resample_close(struct AVResampleContext *c); +void av_init_packet(AVPacket *pkt); /** - * Allocate memory for a picture. Call avpicture_free to free it. + * Allocate the payload of a packet and initialize its fields with + * default values. * - * @param picture the picture to be filled in - * @param pix_fmt the format of the picture - * @param width the width of the picture - * @param height the height of the picture - * @return zero if successful, a negative value if not + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise */ -int avpicture_alloc(AVPicture *picture, enum PixelFormat pix_fmt, int width, int height); +int av_new_packet(AVPacket *pkt, int size); /** - * Free a picture previously allocated by avpicture_alloc(). + * Reduce packet size, correctly zeroing padding * - * @param picture the AVPicture to be freed + * @param pkt packet + * @param size new size */ -void avpicture_free(AVPicture *picture); +void av_shrink_packet(AVPacket *pkt, int size); /** - * Fill in the AVPicture fields. - * The fields of the given AVPicture are filled in by using the 'ptr' address - * which points to the image data buffer. Depending on the specified picture - * format, one or multiple image data pointers and line sizes will be set. - * If a planar format is specified, several pointers will be set pointing to - * the different picture planes and the line sizes of the different planes - * will be stored in the lines_sizes array. - * Call with ptr == NULL to get the required size for the ptr buffer. + * Increase packet size, correctly zeroing padding * - * @param picture AVPicture whose fields are to be filled in - * @param ptr Buffer which will contain or contains the actual image data - * @param pix_fmt The format in which the picture data is stored. - * @param width the width of the image in pixels - * @param height the height of the image in pixels - * @return size of the image data in bytes + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet */ -int avpicture_fill(AVPicture *picture, uint8_t *ptr, - int pix_fmt, int width, int height); -int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height, - unsigned char *dest, int dest_size); +int av_grow_packet(AVPacket *pkt, int grow_by); /** - * Calculate the size in bytes that a picture of the given width and height - * would occupy if stored in the given picture format. - * Note that this returns the size of a compact representation as generated - * by avpicture_layout, which can be smaller than the size required for e.g. - * avpicture_fill. - * - * @param pix_fmt the given picture format - * @param width the width of the image - * @param height the height of the image - * @return Image data size in bytes or -1 on error (e.g. too large dimensions). - */ -int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height); -void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift); -const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt); -void avcodec_set_dimensions(AVCodecContext *s, int width, int height); + * @warning This is a hack - the packet memory allocation stuff is broken. The + * packet is allocated if it was not really allocated. + */ +int av_dup_packet(AVPacket *pkt); /** - * Returns the pixel format corresponding to the name \p name. + * Copy packet, including contents * - * If there is no pixel format with name \p name, then looks for a - * pixel format with the name corresponding to the native endian - * format of \p name. - * For example in a little-endian system, first looks for "gray16", - * then for "gray16le". + * @return 0 on success, negative AVERROR on fail + */ +int av_copy_packet(AVPacket *dst, AVPacket *src); + +/** + * Free a packet. * - * Finally if no pixel format has been found, returns \c PIX_FMT_NONE. + * @param pkt packet to free */ -enum PixelFormat avcodec_get_pix_fmt(const char* name); -unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat p); +void av_free_packet(AVPacket *pkt); -#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ -#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ -#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ -#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ -#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ -#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); /** - * Computes what kind of losses will occur when converting from one specific - * pixel format to another. - * When converting from one pixel format to another, information loss may occur. - * For example, when converting from RGB24 to GRAY, the color information will - * be lost. Similarly, other losses occur when converting from some formats to - * other formats. These losses can involve loss of chroma, but also loss of - * resolution, loss of color depth, loss due to the color space conversion, loss - * of the alpha bits or loss due to color quantization. - * avcodec_get_fix_fmt_loss() informs you about the various types of losses - * which will occur when converting from one pixel format to another. + * Shrink the already allocated side data buffer * - * @param[in] dst_pix_fmt destination pixel format - * @param[in] src_pix_fmt source pixel format - * @param[in] has_alpha Whether the source pixel format alpha channel is used. - * @return Combination of flags informing you what kind of losses will occur. + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure */ -int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt, - int has_alpha); +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); /** - * Finds the best pixel format to convert to given a certain source pixel - * format. When converting from one pixel format to another, information loss - * may occur. For example, when converting from RGB24 to GRAY, the color - * information will be lost. Similarly, other losses occur when converting from - * some formats to other formats. avcodec_find_best_pix_fmt() searches which of - * the given pixel formats should be used to suffer the least amount of loss. - * The pixel formats from which it chooses one, are determined by the - * \p pix_fmt_mask parameter. + * Get side information from packet. * - * @code - * src_pix_fmt = PIX_FMT_YUV420P; - * pix_fmt_mask = (1 << PIX_FMT_YUV422P) || (1 << PIX_FMT_RGB24); - * dst_pix_fmt = avcodec_find_best_pix_fmt(pix_fmt_mask, src_pix_fmt, alpha, &loss); - * @endcode + * @param pkt packet + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int *size); + +int av_packet_merge_side_data(AVPacket *pkt); + +int av_packet_split_side_data(AVPacket *pkt); + + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * Find a registered decoder with a matching codec ID. * - * @param[in] pix_fmt_mask bitmask determining which pixel format to choose from - * @param[in] src_pix_fmt source pixel format - * @param[in] has_alpha Whether the source pixel format alpha channel is used. - * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. - * @return The best pixel format to convert to or -1 if none was found. + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. */ -enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, - int has_alpha, int *loss_ptr); +AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder_by_name(const char *name); + +int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); +int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); + +/** + * Return the amount of padding in pixels which the get_buffer callback must + * provide around the edge of the image for codecs which do not have the + * CODEC_FLAG_EMU_EDGE flag. + * + * @return Required padding in pixels. + */ +unsigned avcodec_get_edge_width(void); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased + * according to avcodec_get_edge_width() before. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased + * according to avcodec_get_edge_width() before. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +#if FF_API_OLD_DECODE_AUDIO +/** + * Wrapper function which calls avcodec_decode_audio4. + * + * @deprecated Use avcodec_decode_audio4 instead. + * + * Decode the audio frame of size avpkt->size from avpkt->data into samples. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. In this case, + * avcodec_decode_audio3 has to be called again with an AVPacket that contains + * the remaining data in order to decode the second frame etc. + * If no frame + * could be outputted, frame_size_ptr is zero. Otherwise, it is the + * decompressed frame size in bytes. + * + * @warning You must set frame_size_ptr to the allocated size of the + * output buffer before calling avcodec_decode_audio3(). + * + * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer avpkt->data should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @warning You must not provide a custom get_buffer() when using + * avcodec_decode_audio3(). Doing so will override it with + * avcodec_default_get_buffer. Use avcodec_decode_audio4() instead, + * which does allow the application to provide a custom get_buffer(). + * + * @note You might have to align the input buffer avpkt->data and output buffer + * samples. The alignment requirements depend on the CPU: On some CPUs it isn't + * necessary at all, on others it won't work at all if not aligned and on others + * it will work but it will have an impact on performance. + * + * In practice, avpkt->data should have 4 byte alignment at minimum and + * samples should be 16 byte aligned unless the CPU doesn't need it + * (AltiVec and SSE do). + * + * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @param avctx the codec context + * @param[out] samples the output buffer, sample type in avctx->sample_fmt + * If the sample format is planar, each channel plane will + * be the same size, with no padding between channels. + * @param[in,out] frame_size_ptr the output buffer size in bytes + * @param[in] avpkt The input AVPacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields. + * All decoders are designed to use the least fields possible though. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame data was decompressed (used) from the input AVPacket. + */ +attribute_deprecated int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, + int *frame_size_ptr, + AVPacket *avpkt); +#endif + +/** + * Decode the audio frame of size avpkt->size from avpkt->data into frame. + * + * Some decoders may support multiple frames in a single AVPacket. Such + * decoders would then just decode the first frame. In this case, + * avcodec_decode_audio4 has to be called again with an AVPacket containing + * the remaining data in order to decode the second frame, etc... + * Even if no frames are returned, the packet needs to be fed to the decoder + * with remaining data until it is completely consumed or an error occurs. + * + * @warning The input buffer, avpkt->data must be FF_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note You might have to align the input buffer. The alignment requirements + * depend on the CPU and the decoder. + * + * @param avctx the codec context + * @param[out] frame The AVFrame in which to store decoded audio samples. + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer(). The + * decoder may, however, only utilize part of the buffer by + * setting AVFrame.nb_samples to a smaller value in the + * output frame. + * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is + * non-zero. + * @param[in] avpkt The input AVPacket containing the input buffer. + * At least avpkt->data and avpkt->size should be set. Some + * decoders might also require additional fields to be set. + * @return A negative error code is returned if an error occurred during + * decoding, otherwise the number of bytes consumed from the input + * AVPacket is returned. + */ +int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, const AVPacket *avpkt); + +/** + * Decode the video frame of size avpkt->size from avpkt->data into picture. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. + * + * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer buf should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @note You might have to align the input buffer avpkt->data. + * The alignment requirements depend on the CPU: on some CPUs it isn't + * necessary at all, on others it won't work at all if not aligned and on others + * it will work but it will have an impact on performance. + * + * In practice, avpkt->data should have 4 byte alignment at minimum. + * + * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @param avctx the codec context + * @param[out] picture The AVFrame in which the decoded video frame will be stored. + * Use avcodec_alloc_frame to get an AVFrame, the codec will + * allocate memory for the actual bitmap. + * with default get/release_buffer(), the decoder frees/reuses the bitmap as it sees fit. + * with overridden get/release_buffer() (needs CODEC_CAP_DR1) the user decides into what buffer the decoder + * decodes and the decoder tells the user once it does not need the data anymore, + * the user app can at this point free/reuse/keep the memory as it sees fit. + * + * @param[in] avpkt The input AVpacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields like + * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least + * fields possible. + * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame could be decompressed. + */ +int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + const AVPacket *avpkt); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expect to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * @param avctx the codec context + * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be + freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt); + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +typedef struct AVCodecParserContext { + void *priv_data; + struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + /** + * Time difference in stream time base units from the pts of this + * packet to the point at which the output from the decoder has converged + * independent from the availability of previous frames. That is, the + * frames are virtually identical no matter if decoding started from + * the very first frame or from this keyframe. + * Is AV_NOPTS_VALUE if unknown. + * This field is not the display duration of the current frame. + * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY + * set. + * + * The purpose of this field is to allow seeking in streams that have no + * keyframes in the conventional sense. It corresponds to the + * recovery point SEI in H.264 and match_time_delta in NUT. It is also + * essential for some types of subtitle streams to ensure that all + * subtitles are correctly displayed after seeking. + */ + int64_t convergence_duration; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[5]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); + struct AVCodecParser *next; +} AVCodecParser; + +AVCodecParser *av_parser_next(AVCodecParser *c); + +void av_register_codec_parser(AVCodecParser *parser); +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +int av_parser_change(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder_by_name(const char *name); + +#if FF_API_OLD_ENCODE_AUDIO +/** + * Encode an audio frame from samples into buf. + * + * @deprecated Use avcodec_encode_audio2 instead. + * + * @note The output buffer should be at least FF_MIN_BUFFER_SIZE bytes large. + * However, for codecs with avctx->frame_size equal to 0 (e.g. PCM) the user + * will know how much space is needed because it depends on the value passed + * in buf_size as described below. In that case a lower value can be used. + * + * @param avctx the codec context + * @param[out] buf the output buffer + * @param[in] buf_size the output buffer size + * @param[in] samples the input buffer containing the samples + * The number of samples read from this buffer is frame_size*channels, + * both of which are defined in avctx. + * For codecs which have avctx->frame_size equal to 0 (e.g. PCM) the number of + * samples read from samples is equal to: + * buf_size * 8 / (avctx->channels * av_get_bits_per_sample(avctx->codec_id)) + * This also implies that av_get_bits_per_sample() must not return 0 for these + * codecs. + * @return On error a negative value is returned, on success zero or the number + * of bytes used to encode the data read from the input buffer. + */ +int attribute_deprecated avcodec_encode_audio(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const short *samples); +#endif + +/** + * Encode a frame of audio. + * + * Takes input samples from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay, split, and combine input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. If avpkt->data and + * avpkt->size are set, avpkt->destruct must also be set. All + * other AVPacket fields will be reset by the encoder using + * av_init_packet(). If avpkt->data is NULL, the encoder will + * allocate it. The encoder will set avpkt->size to the size + * of the output packet. + * + * If this function fails or produces no output, avpkt will be + * freed using av_free_packet() (i.e. avpkt->destruct will be + * called to free the user supplied buffer). + * @param[in] frame AVFrame containing the raw audio data to be encoded. + * May be NULL when flushing an encoder that has the + * CODEC_CAP_DELAY capability set. + * If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + */ +int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +#if FF_API_OLD_ENCODE_VIDEO +/** + * @deprecated use avcodec_encode_video2() instead. + * + * Encode a video frame from pict into buf. + * The input picture should be + * stored using a specific format, namely avctx.pix_fmt. + * + * @param avctx the codec context + * @param[out] buf the output buffer for the bitstream of encoded frame + * @param[in] buf_size the size of the output buffer in bytes + * @param[in] pict the input picture to encode + * @return On error a negative value is returned, on success zero or the number + * of bytes used from the output buffer. + */ +attribute_deprecated +int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict); +#endif + +/** + * Encode a frame of video. + * + * Takes input raw video data from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay and reorder input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. All other AVPacket fields + * will be reset by the encoder using av_init_packet(). If + * avpkt->data is NULL, the encoder will allocate it. + * The encoder will set avpkt->size to the size of the + * output packet. The returned data (if any) belongs to the + * caller, he is responsible for freeing it. + * + * If this function fails or produces no output, avpkt will be + * freed using av_free_packet() (i.e. avpkt->destruct will be + * called to free the user supplied buffer). + * @param[in] frame AVFrame containing the raw video data to be encoded. + * May be NULL when flushing an encoder that has the + * CODEC_CAP_DELAY capability set. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + */ +int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +#if FF_API_AVCODEC_RESAMPLE +/** + * @defgroup lavc_resample Audio resampling + * @ingroup libavc + * @deprecated use libswresample instead + * + * @{ + */ +struct ReSampleContext; +struct AVResampleContext; + +typedef struct ReSampleContext ReSampleContext; + +/** + * Initialize audio resampling context. + * + * @param output_channels number of output channels + * @param input_channels number of input channels + * @param output_rate output sample rate + * @param input_rate input sample rate + * @param sample_fmt_out requested output sample format + * @param sample_fmt_in input sample format + * @param filter_length length of each FIR filter in the filterbank relative to the cutoff frequency + * @param log2_phase_count log2 of the number of entries in the polyphase filterbank + * @param linear if 1 then the used FIR filter will be linearly interpolated + between the 2 closest, if 0 the closest will be used + * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate + * @return allocated ReSampleContext, NULL if error occurred + */ +attribute_deprecated +ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, + int output_rate, int input_rate, + enum AVSampleFormat sample_fmt_out, + enum AVSampleFormat sample_fmt_in, + int filter_length, int log2_phase_count, + int linear, double cutoff); +attribute_deprecated +int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); /** - * Print in buf the string corresponding to the pixel format with - * number pix_fmt, or an header if pix_fmt is negative. + * Free resample context. * - * @param[in] buf the buffer where to write the string - * @param[in] buf_size the size of buf - * @param[in] pix_fmt the number of the pixel format to print the corresponding info string, or - * a negative value to print the corresponding header. - * Meaningful values for obtaining a pixel format info vary from 0 to PIX_FMT_NB -1. + * @param s a non-NULL pointer to a resample context previously + * created with av_audio_resample_init() */ -void avcodec_pix_fmt_string (char *buf, int buf_size, enum PixelFormat pix_fmt); +attribute_deprecated +void audio_resample_close(ReSampleContext *s); -#define FF_ALPHA_TRANSP 0x0001 /* image has some totally transparent pixels */ -#define FF_ALPHA_SEMI_TRANSP 0x0002 /* image has some transparent pixels */ /** - * Tell if an image really has transparent alpha values. - * @return ored mask of FF_ALPHA_xxx constants + * Initialize an audio resampler. + * Note, if either rate is not an integer then simply scale both rates up so they are. + * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq + * @param log2_phase_count log2 of the number of entries in the polyphase filterbank + * @param linear If 1 then the used FIR filter will be linearly interpolated + between the 2 closest, if 0 the closest will be used + * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate */ -int img_get_alpha_info(const AVPicture *src, - enum PixelFormat pix_fmt, int width, int height); - -/* deinterlace a picture */ -/* deinterlace - if not supported return -1 */ -int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, - enum PixelFormat pix_fmt, int width, int height); - -/* external high level API */ +attribute_deprecated +struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff); /** - * If c is NULL, returns the first registered codec, - * if c is non-NULL, returns the next registered codec after c, - * or NULL if c is the last one. + * Resample an array of samples using a previously configured context. + * @param src an array of unconsumed samples + * @param consumed the number of samples of src which have been consumed are returned here + * @param src_size the number of unconsumed samples available + * @param dst_size the amount of space in samples available in dst + * @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context. + * @return the number of samples written in dst or -1 if an error occurred */ -AVCodec *av_codec_next(AVCodec *c); +attribute_deprecated +int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx); -/** - * Returns the LIBAVCODEC_VERSION_INT constant. - */ -unsigned avcodec_version(void); /** - * Initializes libavcodec. + * Compensate samplerate/timestamp drift. The compensation is done by changing + * the resampler parameters, so no audible clicks or similar distortions occur + * @param compensation_distance distance in output samples over which the compensation should be performed + * @param sample_delta number of output samples which should be output less + * + * example: av_resample_compensate(c, 10, 500) + * here instead of 510 samples only 500 samples would be output * - * @warning This function \e must be called before any other libavcodec - * function. + * note, due to rounding the actual compensation might be slightly different, + * especially if the compensation_distance is large and the in_rate used during init is small */ -void avcodec_init(void); +attribute_deprecated +void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance); +attribute_deprecated +void av_resample_close(struct AVResampleContext *c); -#if LIBAVCODEC_VERSION_MAJOR < 53 /** - * @deprecated Deprecated in favor of avcodec_register(). + * @} */ -attribute_deprecated void register_avcodec(AVCodec *codec); #endif /** - * Register the codec \p codec and initialize libavcodec. - * - * @see avcodec_init() + * @addtogroup lavc_picture + * @{ */ -void avcodec_register(AVCodec *codec); /** - * Finds a registered encoder with a matching codec ID. + * Allocate memory for a picture. Call avpicture_free() to free it. * - * @param id CodecID of the requested encoder - * @return An encoder if one was found, NULL otherwise. + * @see avpicture_fill() + * + * @param picture the picture to be filled in + * @param pix_fmt the format of the picture + * @param width the width of the picture + * @param height the height of the picture + * @return zero if successful, a negative value if not */ -AVCodec *avcodec_find_encoder(enum CodecID id); +int avpicture_alloc(AVPicture *picture, enum AVPixelFormat pix_fmt, int width, int height); /** - * Finds a registered encoder with the specified name. + * Free a picture previously allocated by avpicture_alloc(). + * The data buffer used by the AVPicture is freed, but the AVPicture structure + * itself is not. * - * @param name name of the requested encoder - * @return An encoder if one was found, NULL otherwise. + * @param picture the AVPicture to be freed */ -AVCodec *avcodec_find_encoder_by_name(const char *name); +void avpicture_free(AVPicture *picture); /** - * Finds a registered decoder with a matching codec ID. + * Fill in the AVPicture fields, always assume a linesize alignment of + * 1. * - * @param id CodecID of the requested decoder - * @return A decoder if one was found, NULL otherwise. + * @see av_image_fill_arrays() */ -AVCodec *avcodec_find_decoder(enum CodecID id); +int avpicture_fill(AVPicture *picture, uint8_t *ptr, + enum AVPixelFormat pix_fmt, int width, int height); /** - * Finds a registered decoder with the specified name. + * Copy pixel data from an AVPicture into a buffer, always assume a + * linesize alignment of 1. * - * @param name name of the requested decoder - * @return A decoder if one was found, NULL otherwise. + * @see av_image_copy_to_buffer() */ -AVCodec *avcodec_find_decoder_by_name(const char *name); -void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); +int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, + int width, int height, + unsigned char *dest, int dest_size); /** - * Sets the fields of the given AVCodecContext to default values. + * Calculate the size in bytes that a picture of the given width and height + * would occupy if stored in the given picture format. + * Always assume a linesize alignment of 1. * - * @param s The AVCodecContext of which the fields should be set to default values. + * @see av_image_get_buffer_size(). */ -void avcodec_get_context_defaults(AVCodecContext *s); +int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height); -/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! - * we WILL change its arguments and name a few times! */ -void avcodec_get_context_defaults2(AVCodecContext *s, enum CodecType); +/** + * deinterlace - if not supported return -1 + */ +int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height); +/** + * Copy image src to dst. Wraps av_image_copy(). + */ +void av_picture_copy(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height); /** - * Allocates an AVCodecContext and sets its fields to default values. The - * resulting struct can be deallocated by simply calling av_free(). - * - * @return An AVCodecContext filled with default values or NULL on failure. - * @see avcodec_get_context_defaults + * Crop image top and left side. */ -AVCodecContext *avcodec_alloc_context(void); +int av_picture_crop(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int top_band, int left_band); -/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! - * we WILL change its arguments and name a few times! */ -AVCodecContext *avcodec_alloc_context2(enum CodecType); +/** + * Pad image. + */ +int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum AVPixelFormat pix_fmt, + int padtop, int padbottom, int padleft, int padright, int *color); /** - * Sets the fields of the given AVFrame to default values. - * - * @param pic The AVFrame of which the fields should be set to default values. + * @} */ -void avcodec_get_frame_defaults(AVFrame *pic); /** - * Allocates an AVFrame and sets its fields to default values. The resulting - * struct can be deallocated by simply calling av_free(). + * @defgroup lavc_misc Utility functions + * @ingroup libavc * - * @return An AVFrame filled with default values or NULL on failure. - * @see avcodec_get_frame_defaults + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ */ -AVFrame *avcodec_alloc_frame(void); - -int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); -void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); -int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); -void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); /** - * Checks if the given dimension of a picture is valid, meaning that all - * bytes of the picture can be addressed with a signed int. + * @defgroup lavc_misc_pixfmt Pixel formats * - * @param[in] w Width of the picture. - * @param[in] h Height of the picture. - * @return Zero if valid, a negative value if invalid. + * Functions for working with pixel formats. + * @{ */ -int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h); -enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt); -int avcodec_thread_init(AVCodecContext *s, int thread_count); -void avcodec_thread_free(AVCodecContext *s); -int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); -int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); -//FIXME func typedef +void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift); /** - * Initializes the AVCodecContext to use the given AVCodec. Prior to using this - * function the context has to be allocated. - * - * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), - * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for - * retrieving a codec. - * - * @warning This function is not thread safe! - * - * @code - * avcodec_register_all(); - * codec = avcodec_find_decoder(CODEC_ID_H264); - * if (!codec) - * exit(1); - * - * context = avcodec_alloc_context(); - * - * if (avcodec_open(context, codec) < 0) - * exit(1); - * @endcode - * - * @param avctx The context which will be set up to use the given codec. - * @param codec The codec to use within the context. - * @return zero on success, a negative value on error - * @see avcodec_alloc_context, avcodec_find_decoder, avcodec_find_encoder + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. */ -int avcodec_open(AVCodecContext *avctx, AVCodec *codec); +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ -#if LIBAVCODEC_VERSION_MAJOR < 53 /** - * Decodes an audio frame from \p buf into \p samples. - * Wrapper function which calls avcodec_decode_audio3. + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * avcodec_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. * - * @deprecated Use avcodec_decode_audio3 instead. - * @param avctx the codec context - * @param[out] samples the output buffer - * @param[in,out] frame_size_ptr the output buffer size in bytes - * @param[in] buf the input buffer - * @param[in] buf_size the input buffer size in bytes - * @return On error a negative value is returned, otherwise the number of bytes - * used or zero if no frame could be decompressed. + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). */ -attribute_deprecated int avcodec_decode_audio2(AVCodecContext *avctx, int16_t *samples, - int *frame_size_ptr, - const uint8_t *buf, int buf_size); -#endif +int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, + int has_alpha); +#if FF_API_FIND_BEST_PIX_FMT /** - * Decodes the audio frame of size avpkt->size from avpkt->data into samples. - * Some decoders may support multiple frames in a single AVPacket, such - * decoders would then just decode the first frame. - * If no frame - * could be decompressed, \p frame_size_ptr is zero. Otherwise, it is the - * decompressed frame size in \e bytes. - * - * @warning You \e must set \p frame_size_ptr to the allocated size of the - * output buffer before calling avcodec_decode_audio3(). + * @deprecated use avcodec_find_best_pix_fmt_of_2() instead. * - * @warning The input buffer must be \c FF_INPUT_BUFFER_PADDING_SIZE larger than - * the actual read bytes because some optimized bitstream readers read 32 or 64 - * bits at once and could read over the end. + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_mask parameter. * - * @warning The end of the input buffer \p avpkt->data should be set to 0 to ensure that - * no overreading happens for damaged MPEG streams. + * Note, only the first 64 pixel formats will fit in pix_fmt_mask. * - * @note You might have to align the input buffer \p avpkt->data and output buffer \p - * samples. The alignment requirements depend on the CPU: On some CPUs it isn't - * necessary at all, on others it won't work at all if not aligned and on others - * it will work but it will have an impact on performance. In practice, the - * bitstream should have 4 byte alignment at minimum and all sample data should - * be 16 byte aligned unless the CPU doesn't need it (AltiVec and SSE do). If - * the linesize is not a multiple of 16 then there's no sense in aligning the - * start of the buffer to 16. + * @code + * src_pix_fmt = AV_PIX_FMT_YUV420P; + * pix_fmt_mask = (1 << AV_PIX_FMT_YUV422P) | (1 << AV_PIX_FMT_RGB24); + * dst_pix_fmt = avcodec_find_best_pix_fmt(pix_fmt_mask, src_pix_fmt, alpha, &loss); + * @endcode * - * @param avctx the codec context - * @param[out] samples the output buffer - * @param[in,out] frame_size_ptr the output buffer size in bytes - * @param[in] avpkt The input AVPacket containing the input buffer. - * @return On error a negative value is returned, otherwise the number of bytes - * used or zero if no frame could be decompressed. + * @param[in] pix_fmt_mask bitmask determining which pixel format to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. */ -int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, - int *frame_size_ptr, - AVPacket *avpkt); +attribute_deprecated +enum AVPixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); +#endif /* FF_API_FIND_BEST_PIX_FMT */ -#if LIBAVCODEC_VERSION_MAJOR < 53 /** - * Decodes a video frame from \p buf into \p picture. - * Wrapper function which calls avcodec_decode_video2. + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. * - * @deprecated Use avcodec_decode_video2 instead. - * @param avctx the codec context - * @param[out] picture The AVFrame in which the decoded video frame will be stored. - * @param[in] buf the input buffer - * @param[in] buf_size the size of the input buffer in bytes - * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. - * @return On error a negative value is returned, otherwise the number of bytes - * used or zero if no frame could be decompressed. + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. */ -attribute_deprecated int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, - int *got_picture_ptr, - const uint8_t *buf, int buf_size); -#endif +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); /** - * Decodes the video frame of size avpkt->size from avpkt->data into picture. - * Some decoders may support multiple frames in a single AVPacket, such - * decoders would then just decode the first frame. - * - * @warning The input buffer must be \c FF_INPUT_BUFFER_PADDING_SIZE larger than - * the actual read bytes because some optimized bitstream readers read 32 or 64 - * bits at once and could read over the end. - * - * @warning The end of the input buffer \p buf should be set to 0 to ensure that - * no overreading happens for damaged MPEG streams. + * Find the best pixel format to convert to given a certain source pixel + * format and a selection of two destination pixel formats. When converting from + * one pixel format to another, information loss may occur. For example, when converting + * from RGB24 to GRAY, the color information will be lost. Similarly, other losses occur when + * converting from some formats to other formats. avcodec_find_best_pix_fmt_of_2() selects which of + * the given pixel formats should be used to suffer the least amount of loss. * - * @note You might have to align the input buffer \p avpkt->data and output buffer \p - * samples. The alignment requirements depend on the CPU: on some CPUs it isn't - * necessary at all, on others it won't work at all if not aligned and on others - * it will work but it will have an impact on performance. In practice, the - * bitstream should have 4 byte alignment at minimum and all sample data should - * be 16 byte aligned unless the CPU doesn't need it (AltiVec and SSE do). If - * the linesize is not a multiple of 16 then there's no sense in aligning the - * start of the buffer to 16. + * If one of the destination formats is AV_PIX_FMT_NONE the other pixel format (if valid) will be + * returned. * - * @note Some codecs have a delay between input and output, these need to be - * feeded with avpkt->data=NULL, avpkt->size=0 at the end to return the remaining frames. + * @code + * src_pix_fmt = AV_PIX_FMT_YUV420P; + * dst_pix_fmt1= AV_PIX_FMT_RGB24; + * dst_pix_fmt2= AV_PIX_FMT_GRAY8; + * dst_pix_fmt3= AV_PIX_FMT_RGB8; + * loss= FF_LOSS_CHROMA; // don't care about chroma loss, so chroma loss will be ignored. + * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, alpha, &loss); + * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, dst_pix_fmt3, src_pix_fmt, alpha, &loss); + * @endcode * - * @param avctx the codec context - * @param[out] picture The AVFrame in which the decoded video frame will be stored. - * @param[in] avpkt The input AVpacket containing the input buffer. - * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. - * @return On error a negative value is returned, otherwise the number of bytes - * used or zero if no frame could be decompressed. + * @param[in] dst_pix_fmt1 One of the two destination pixel formats to choose from + * @param[in] dst_pix_fmt2 The other of the two destination pixel formats to choose from + * @param[in] src_pix_fmt Source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[in, out] loss_ptr Combination of loss flags. In: selects which of the losses to ignore, i.e. + * NULL or value of zero means we care about all losses. Out: the loss + * that occurs when converting from src to selected dst pixel format. + * @return The best pixel format to convert to or -1 if none was found. */ -int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, - int *got_picture_ptr, - AVPacket *avpkt); +enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); -#if LIBAVCODEC_VERSION_MAJOR < 53 -/* Decode a subtitle message. Return -1 if error, otherwise return the - * number of bytes used. If no subtitle could be decompressed, - * got_sub_ptr is zero. Otherwise, the subtitle is stored in *sub. */ -attribute_deprecated int avcodec_decode_subtitle(AVCodecContext *avctx, AVSubtitle *sub, - int *got_sub_ptr, - const uint8_t *buf, int buf_size); +attribute_deprecated +#if AV_HAVE_INCOMPATIBLE_FORK_ABI +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); +#else +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); #endif + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + /** - * Decodes a subtitle message. - * Returns a negative value on error, otherwise returns the number of bytes used. - * If no subtitle could be decompressed, \p got_sub_ptr is zero. - * Otherwise, the subtitle is stored in \p *sub. - * - * @param avctx the codec context - * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored. - * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. - * @param[in] avpkt The input AVPacket containing the input buffer. + * @} */ -int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt); -int avcodec_parse_frame(AVCodecContext *avctx, uint8_t **pdata, - int *data_size_ptr, - uint8_t *buf, int buf_size); + +void avcodec_set_dimensions(AVCodecContext *s, int width, int height); /** - * Encodes an audio frame from \p samples into \p buf. + * Put a string representing the codec tag codec_tag in buf. * - * @note The output buffer should be at least \c FF_MIN_BUFFER_SIZE bytes large. - * However, for PCM audio the user will know how much space is needed - * because it depends on the value passed in \p buf_size as described - * below. In that case a lower value can be used. - * - * @param avctx the codec context - * @param[out] buf the output buffer - * @param[in] buf_size the output buffer size - * @param[in] samples the input buffer containing the samples - * The number of samples read from this buffer is frame_size*channels, - * both of which are defined in \p avctx. - * For PCM audio the number of samples read from \p samples is equal to - * \p buf_size * input_sample_size / output_sample_size. - * @return On error a negative value is returned, on success zero or the number - * of bytes used to encode the data read from the input buffer. + * @param buf_size size in bytes of buf + * @return the length of the string that would have been generated if + * enough space had been available, excluding the trailing null */ -int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, - const short *samples); +size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag); -/** - * Encodes a video frame from \p pict into \p buf. - * The input picture should be - * stored using a specific format, namely \c avctx.pix_fmt. - * - * @param avctx the codec context - * @param[out] buf the output buffer for the bitstream of encoded frame - * @param[in] buf_size the size of the output buffer in bytes - * @param[in] pict the input picture to encode - * @return On error a negative value is returned, on success zero or the number - * of bytes used from the output buffer. +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. */ -int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, - const AVFrame *pict); -int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, - const AVSubtitle *sub); +const char *av_get_profile_name(const AVCodec *codec, int profile); -int avcodec_close(AVCodecContext *avctx); +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef /** - * Register all the codecs, parsers and bitstream filters which were enabled at - * configuration time. If you do not call this function you can select exactly - * which formats you want to support, by using the individual registration - * functions. + * Fill audio frame data and linesize. + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. * - * @see avcodec_register - * @see av_register_codec_parser - * @see av_register_bitstream_filter + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return 0 on success, negative error code on failure */ -void avcodec_register_all(void); +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); /** * Flush buffers, should be called when seeking or when switching to a different stream. @@ -3361,223 +4715,41 @@ void avcodec_flush_buffers(AVCodecContext *avctx); void avcodec_default_free_buffers(AVCodecContext *s); -/* misc useful functions */ - /** - * Returns a single letter to describe the given picture type \p pict_type. + * Return codec bits per sample. * - * @param[in] pict_type the picture type - * @return A single character representing the picture type. + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. */ -char av_get_pict_type_char(int pict_type); +int av_get_bits_per_sample(enum AVCodecID codec_id); /** - * Returns codec bits per sample. - * - * @param[in] codec_id the codec - * @return Number of bits per sample or zero if unknown for the given codec. + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE */ -int av_get_bits_per_sample(enum CodecID codec_id); +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); /** - * Returns sample format bits per sample. + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. * - * @param[in] sample_fmt the sample format - * @return Number of bits per sample or zero if unknown for the given sample format. + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. */ -int av_get_bits_per_sample_format(enum SampleFormat sample_fmt); - -/* frame parsing */ -typedef struct AVCodecParserContext { - void *priv_data; - struct AVCodecParser *parser; - int64_t frame_offset; /* offset of the current frame */ - int64_t cur_offset; /* current offset - (incremented by each av_parser_parse()) */ - int64_t next_frame_offset; /* offset of the next frame */ - /* video info */ - int pict_type; /* XXX: Put it back in AVCodecContext. */ - /** - * This field is used for proper frame duration computation in lavf. - * It signals, how much longer the frame duration of the current frame - * is compared to normal frame duration. - * - * frame_duration = (1 + repeat_pict) * time_base - * - * It is used by codecs like H.264 to display telecined material. - */ - int repeat_pict; /* XXX: Put it back in AVCodecContext. */ - int64_t pts; /* pts of the current frame */ - int64_t dts; /* dts of the current frame */ - - /* private data */ - int64_t last_pts; - int64_t last_dts; - int fetch_timestamp; - -#define AV_PARSER_PTS_NB 4 - int cur_frame_start_index; - int64_t cur_frame_offset[AV_PARSER_PTS_NB]; - int64_t cur_frame_pts[AV_PARSER_PTS_NB]; - int64_t cur_frame_dts[AV_PARSER_PTS_NB]; - - int flags; -#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 - - int64_t offset; ///< byte offset from starting packet start - int64_t cur_frame_end[AV_PARSER_PTS_NB]; - - /*! - * Set by parser to 1 for key frames and 0 for non-key frames. - * It is initialized to -1, so if the parser doesn't set this flag, - * old-style fallback using FF_I_TYPE picture type as key frames - * will be used. - */ - int key_frame; - - /** - * Time difference in stream time base units from the pts of this - * packet to the point at which the output from the decoder has converged - * independent from the availability of previous frames. That is, the - * frames are virtually identical no matter if decoding started from - * the very first frame or from this keyframe. - * Is AV_NOPTS_VALUE if unknown. - * This field is not the display duration of the current frame. - * - * The purpose of this field is to allow seeking in streams that have no - * keyframes in the conventional sense. It corresponds to the - * recovery point SEI in H.264 and match_time_delta in NUT. It is also - * essential for some types of subtitle streams to ensure that all - * subtitles are correctly displayed after seeking. - */ - int64_t convergence_duration; - - // Timestamp generation support: - /** - * Synchronization point for start of timestamp generation. - * - * Set to >0 for sync point, 0 for no sync point and <0 for undefined - * (default). - * - * For example, this corresponds to presence of H.264 buffering period - * SEI message. - */ - int dts_sync_point; - - /** - * Offset of the current timestamp against last timestamp sync point in - * units of AVCodecContext.time_base. - * - * Set to INT_MIN when dts_sync_point unused. Otherwise, it must - * contain a valid timestamp offset. - * - * Note that the timestamp of sync point has usually a nonzero - * dts_ref_dts_delta, which refers to the previous sync point. Offset of - * the next frame after timestamp sync point will be usually 1. - * - * For example, this corresponds to H.264 cpb_removal_delay. - */ - int dts_ref_dts_delta; - - /** - * Presentation delay of current frame in units of AVCodecContext.time_base. - * - * Set to INT_MIN when dts_sync_point unused. Otherwise, it must - * contain valid non-negative timestamp delta (presentation time of a frame - * must not lie in the past). - * - * This delay represents the difference between decoding and presentation - * time of the frame. - * - * For example, this corresponds to H.264 dpb_output_delay. - */ - int pts_dts_delta; - - /** - * Position of the packet in file. - * - * Analogous to cur_frame_pts/dts - */ - int64_t cur_frame_pos[AV_PARSER_PTS_NB]; - - /** - * Byte position of currently parsed frame in stream. - */ - int64_t pos; - - /** - * Previous frame byte position. - */ - int64_t last_pos; -} AVCodecParserContext; - -typedef struct AVCodecParser { - int codec_ids[5]; /* several codec IDs are permitted */ - int priv_data_size; - int (*parser_init)(AVCodecParserContext *s); - int (*parser_parse)(AVCodecParserContext *s, - AVCodecContext *avctx, - const uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size); - void (*parser_close)(AVCodecParserContext *s); - int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); - struct AVCodecParser *next; -} AVCodecParser; - -AVCodecParser *av_parser_next(AVCodecParser *c); - -void av_register_codec_parser(AVCodecParser *parser); -AVCodecParserContext *av_parser_init(int codec_id); - -#if LIBAVCODEC_VERSION_MAJOR < 53 -attribute_deprecated -int av_parser_parse(AVCodecParserContext *s, - AVCodecContext *avctx, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, - int64_t pts, int64_t dts); -#endif +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); /** - * Parse a packet. - * - * @param s parser context. - * @param avctx codec context. - * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. - * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. - * @param buf input buffer. - * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output). - * @param pts input presentation timestamp. - * @param dts input decoding timestamp. - * @param pos input byte position in stream. - * @return the number of bytes of the input bitstream used. - * - * Example: - * @code - * while(in_len){ - * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, - * in_data, in_len, - * pts, dts, pos); - * in_data += len; - * in_len -= len; + * Return audio frame duration. * - * if(size) - * decode_frame(data, size); - * } - * @endcode + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. */ -int av_parser_parse2(AVCodecParserContext *s, - AVCodecContext *avctx, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, - int64_t pts, int64_t dts, - int64_t pos); - -int av_parser_change(AVCodecParserContext *s, - AVCodecContext *avctx, - uint8_t **poutbuf, int *poutbuf_size, - const uint8_t *buf, int buf_size, int keyframe); -void av_parser_close(AVCodecParserContext *s); +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); typedef struct AVBitStreamFilterContext { @@ -3612,15 +4784,14 @@ AVBitStreamFilter *av_bitstream_filter_next(AVBitStreamFilter *f); /* memory */ /** - * Reallocates the given block if it is not large enough, otherwise it - * does nothing. + * Reallocate the given block if it is not large enough, otherwise do nothing. * * @see av_realloc */ -void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size); +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); /** - * Allocates a buffer, reusing the given one if large enough. + * Allocate a buffer, reusing the given one if large enough. * * Contrary to av_fast_realloc the current buffer contents might not be * preserved and on error the old buffer is freed, thus no special @@ -3631,74 +4802,58 @@ void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size); * @param min_size minimum size of *ptr buffer after returning, *ptr will be NULL and * *size 0 if an error occurred. */ -void av_fast_malloc(void *ptr, unsigned int *size, unsigned int min_size); +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); /** - * Copy image 'src' to 'dst'. + * Same behaviour av_fast_malloc but the buffer has additional + * FF_INPUT_PADDING_SIZE at the end which will will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. */ -void av_picture_copy(AVPicture *dst, const AVPicture *src, - enum PixelFormat pix_fmt, int width, int height); +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); /** - * Crop image top and left side. + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. */ -int av_picture_crop(AVPicture *dst, const AVPicture *src, - enum PixelFormat pix_fmt, int top_band, int left_band); +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); /** - * Pad image. + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. */ -int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum PixelFormat pix_fmt, - int padtop, int padbottom, int padleft, int padright, int *color); - unsigned int av_xiphlacing(unsigned char *s, unsigned int v); /** - * Parses \p str and put in \p width_ptr and \p height_ptr the detected values. - * - * @return 0 in case of a successful parsing, a negative value otherwise - * @param[in] str the string to parse: it has to be a string in the format - * x or a valid video frame size abbreviation. - * @param[in,out] width_ptr pointer to the variable which will contain the detected - * frame width value - * @param[in,out] height_ptr pointer to the variable which will contain the detected - * frame height value + * Log a generic warning message about a missing feature. This function is + * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) + * only, and would normally not be used by applications. + * @param[in] avc a pointer to an arbitrary struct of which the first field is + * a pointer to an AVClass struct + * @param[in] feature string containing the name of the missing feature + * @param[in] want_sample indicates if samples are wanted which exhibit this feature. + * If want_sample is non-zero, additional verbage will be added to the log + * message which tells the user how to report samples to the development + * mailing list. */ -int av_parse_video_frame_size(int *width_ptr, int *height_ptr, const char *str); +void av_log_missing_feature(void *avc, const char *feature, int want_sample); /** - * Parses \p str and put in \p frame_rate the detected values. - * - * @return 0 in case of a successful parsing, a negative value otherwise - * @param[in] str the string to parse: it has to be a string in the format - * /, a float number or a valid video rate abbreviation - * @param[in,out] frame_rate pointer to the AVRational which will contain the detected - * frame rate + * Log a generic warning message asking for a sample. This function is + * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) + * only, and would normally not be used by applications. + * @param[in] avc a pointer to an arbitrary struct of which the first field is + * a pointer to an AVClass struct + * @param[in] msg string containing an optional message, or NULL if no message */ -int av_parse_video_frame_rate(AVRational *frame_rate, const char *str); - -/* error handling */ -#if EINVAL > 0 -#define AVERROR(e) (-(e)) /**< Returns a negative error code from a POSIX error code, to return from library functions. */ -#define AVUNERROR(e) (-(e)) /**< Returns a POSIX error code from a library function error return value. */ -#else -/* Some platforms have E* and errno already negated. */ -#define AVERROR(e) (e) -#define AVUNERROR(e) (e) -#endif -#define AVERROR_UNKNOWN AVERROR(EINVAL) /**< unknown error */ -#define AVERROR_IO AVERROR(EIO) /**< I/O error */ -#define AVERROR_NUMEXPECTED AVERROR(EDOM) /**< Number syntax expected in filename. */ -#define AVERROR_INVALIDDATA AVERROR(EINVAL) /**< invalid data found */ -#define AVERROR_NOMEM AVERROR(ENOMEM) /**< not enough memory */ -#define AVERROR_NOFMT AVERROR(EILSEQ) /**< unknown format */ -#define AVERROR_NOTSUPP AVERROR(ENOSYS) /**< Operation not supported. */ -#define AVERROR_NOENT AVERROR(ENOENT) /**< No such file or directory. */ -#define AVERROR_EOF AVERROR(EPIPE) /**< End of file. */ -#define AVERROR_PATCHWELCOME -MKTAG('P','A','W','E') /**< Not yet implemented in FFmpeg. Patches welcome. */ +void av_log_ask_for_sample(void *avc, const char *msg, ...) av_printf_format(2, 3); /** - * Registers the hardware accelerator \p hwaccel. + * Register the hardware accelerator hwaccel. */ void av_register_hwaccel(AVHWAccel *hwaccel); @@ -3709,4 +4864,81 @@ void av_register_hwaccel(AVHWAccel *hwaccel); */ AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel); + +/** + * Lock operation used by lockmgr + */ +enum AVLockOp { + AV_LOCK_CREATE, ///< Create a mutex + AV_LOCK_OBTAIN, ///< Lock the mutex + AV_LOCK_RELEASE, ///< Unlock the mutex + AV_LOCK_DESTROY, ///< Free mutex resources +}; + +/** + * Register a user provided lock manager supporting the operations + * specified by AVLockOp. mutex points to a (void *) where the + * lockmgr should store/get a pointer to a user allocated mutex. It's + * NULL upon AV_LOCK_CREATE and != NULL for all other ops. + * + * @param cb User defined callback. Note: FFmpeg may invoke calls to this + * callback during the call to av_lockmgr_register(). + * Thus, the application must be prepared to handle that. + * If cb is set to NULL the lockmgr will be unregistered. + * Also note that during unregistration the previously registered + * lockmgr callback may also be invoked. + */ +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + #endif /* AVCODEC_AVCODEC_H */ diff --git a/extra_lib/include/libavcodec/avfft.h b/extra_lib/include/libavcodec/avfft.h new file mode 100644 index 0000000..2d20a45 --- /dev/null +++ b/extra_lib/include/libavcodec/avfft.h @@ -0,0 +1,116 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AVFFT_H +#define AVCODEC_AVFFT_H + +/** + * @file + * @ingroup lavc_fft + * FFT functions + */ + +/** + * @defgroup lavc_fft FFT functions + * @ingroup lavc_misc + * + * @{ + */ + +typedef float FFTSample; + +typedef struct FFTComplex { + FFTSample re, im; +} FFTComplex; + +typedef struct FFTContext FFTContext; + +/** + * Set up a complex FFT. + * @param nbits log2 of the length of the input array + * @param inverse if 0 perform the forward transform, if 1 perform the inverse + */ +FFTContext *av_fft_init(int nbits, int inverse); + +/** + * Do the permutation needed BEFORE calling ff_fft_calc(). + */ +void av_fft_permute(FFTContext *s, FFTComplex *z); + +/** + * Do a complex FFT with the parameters defined in av_fft_init(). The + * input data must be permuted before. No 1.0/sqrt(n) normalization is done. + */ +void av_fft_calc(FFTContext *s, FFTComplex *z); + +void av_fft_end(FFTContext *s); + +FFTContext *av_mdct_init(int nbits, int inverse, double scale); +void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_end(FFTContext *s); + +/* Real Discrete Fourier Transform */ + +enum RDFTransformType { + DFT_R2C, + IDFT_C2R, + IDFT_R2C, + DFT_C2R, +}; + +typedef struct RDFTContext RDFTContext; + +/** + * Set up a real FFT. + * @param nbits log2 of the length of the input array + * @param trans the type of transform + */ +RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans); +void av_rdft_calc(RDFTContext *s, FFTSample *data); +void av_rdft_end(RDFTContext *s); + +/* Discrete Cosine Transform */ + +typedef struct DCTContext DCTContext; + +enum DCTTransformType { + DCT_II = 0, + DCT_III, + DCT_I, + DST_I, +}; + +/** + * Set up DCT. + * @param nbits size of the input array: + * (1 << nbits) for DCT-II, DCT-III and DST-I + * (1 << nbits) + 1 for DCT-I + * + * @note the first element of the input of DST-I is ignored + */ +DCTContext *av_dct_init(int nbits, enum DCTTransformType type); +void av_dct_calc(DCTContext *s, FFTSample *data); +void av_dct_end (DCTContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVFFT_H */ diff --git a/extra_lib/include/libavcodec/dxva2.h b/extra_lib/include/libavcodec/dxva2.h new file mode 100644 index 0000000..7d27ca5 --- /dev/null +++ b/extra_lib/include/libavcodec/dxva2.h @@ -0,0 +1,88 @@ +/* + * DXVA2 HW acceleration + * + * copyright (c) 2009 Laurent Aimar + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DXVA_H +#define AVCODEC_DXVA_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_dxva2 + * Public libavcodec DXVA2 header. + */ + +#include + +#include +#include + +/** + * @defgroup lavc_codec_hwaccel_dxva2 DXVA2 + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards + +/** + * This structure is used to provides the necessary configurations and data + * to the DXVA2 FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct dxva_context { + /** + * DXVA2 decoder object + */ + IDirectXVideoDecoder *decoder; + + /** + * DXVA2 configuration used to create the decoder + */ + const DXVA2_ConfigPictureDecode *cfg; + + /** + * The number of surface in the surface array + */ + unsigned surface_count; + + /** + * The array of Direct3D surfaces used to create the decoder + */ + LPDIRECT3DSURFACE9 *surface; + + /** + * A bit field configuring the workarounds needed for using the decoder + */ + uint64_t workaround; + + /** + * Private to the FFmpeg AVHWAccel implementation + */ + unsigned report_id; +}; + +/** + * @} + */ + +#endif /* AVCODEC_DXVA_H */ diff --git a/extra_lib/include/libavcodec/old_codec_ids.h b/extra_lib/include/libavcodec/old_codec_ids.h new file mode 100644 index 0000000..ded4cc7 --- /dev/null +++ b/extra_lib/include/libavcodec/old_codec_ids.h @@ -0,0 +1,398 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_OLD_CODEC_IDS_H +#define AVCODEC_OLD_CODEC_IDS_H + +#include "libavutil/common.h" + +/* + * This header exists to prevent new codec IDs from being accidentally added to + * the deprecated list. + * Do not include it directly. It will be removed on next major bump + * + * Do not add new items to this list. Use the AVCodecID enum instead. + */ + + CODEC_ID_NONE = AV_CODEC_ID_NONE, + + /* video codecs */ + CODEC_ID_MPEG1VIDEO, + CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + CODEC_ID_MPEG2VIDEO_XVMC, + CODEC_ID_H261, + CODEC_ID_H263, + CODEC_ID_RV10, + CODEC_ID_RV20, + CODEC_ID_MJPEG, + CODEC_ID_MJPEGB, + CODEC_ID_LJPEG, + CODEC_ID_SP5X, + CODEC_ID_JPEGLS, + CODEC_ID_MPEG4, + CODEC_ID_RAWVIDEO, + CODEC_ID_MSMPEG4V1, + CODEC_ID_MSMPEG4V2, + CODEC_ID_MSMPEG4V3, + CODEC_ID_WMV1, + CODEC_ID_WMV2, + CODEC_ID_H263P, + CODEC_ID_H263I, + CODEC_ID_FLV1, + CODEC_ID_SVQ1, + CODEC_ID_SVQ3, + CODEC_ID_DVVIDEO, + CODEC_ID_HUFFYUV, + CODEC_ID_CYUV, + CODEC_ID_H264, + CODEC_ID_INDEO3, + CODEC_ID_VP3, + CODEC_ID_THEORA, + CODEC_ID_ASV1, + CODEC_ID_ASV2, + CODEC_ID_FFV1, + CODEC_ID_4XM, + CODEC_ID_VCR1, + CODEC_ID_CLJR, + CODEC_ID_MDEC, + CODEC_ID_ROQ, + CODEC_ID_INTERPLAY_VIDEO, + CODEC_ID_XAN_WC3, + CODEC_ID_XAN_WC4, + CODEC_ID_RPZA, + CODEC_ID_CINEPAK, + CODEC_ID_WS_VQA, + CODEC_ID_MSRLE, + CODEC_ID_MSVIDEO1, + CODEC_ID_IDCIN, + CODEC_ID_8BPS, + CODEC_ID_SMC, + CODEC_ID_FLIC, + CODEC_ID_TRUEMOTION1, + CODEC_ID_VMDVIDEO, + CODEC_ID_MSZH, + CODEC_ID_ZLIB, + CODEC_ID_QTRLE, + CODEC_ID_SNOW, + CODEC_ID_TSCC, + CODEC_ID_ULTI, + CODEC_ID_QDRAW, + CODEC_ID_VIXL, + CODEC_ID_QPEG, + CODEC_ID_PNG, + CODEC_ID_PPM, + CODEC_ID_PBM, + CODEC_ID_PGM, + CODEC_ID_PGMYUV, + CODEC_ID_PAM, + CODEC_ID_FFVHUFF, + CODEC_ID_RV30, + CODEC_ID_RV40, + CODEC_ID_VC1, + CODEC_ID_WMV3, + CODEC_ID_LOCO, + CODEC_ID_WNV1, + CODEC_ID_AASC, + CODEC_ID_INDEO2, + CODEC_ID_FRAPS, + CODEC_ID_TRUEMOTION2, + CODEC_ID_BMP, + CODEC_ID_CSCD, + CODEC_ID_MMVIDEO, + CODEC_ID_ZMBV, + CODEC_ID_AVS, + CODEC_ID_SMACKVIDEO, + CODEC_ID_NUV, + CODEC_ID_KMVC, + CODEC_ID_FLASHSV, + CODEC_ID_CAVS, + CODEC_ID_JPEG2000, + CODEC_ID_VMNC, + CODEC_ID_VP5, + CODEC_ID_VP6, + CODEC_ID_VP6F, + CODEC_ID_TARGA, + CODEC_ID_DSICINVIDEO, + CODEC_ID_TIERTEXSEQVIDEO, + CODEC_ID_TIFF, + CODEC_ID_GIF, + CODEC_ID_DXA, + CODEC_ID_DNXHD, + CODEC_ID_THP, + CODEC_ID_SGI, + CODEC_ID_C93, + CODEC_ID_BETHSOFTVID, + CODEC_ID_PTX, + CODEC_ID_TXD, + CODEC_ID_VP6A, + CODEC_ID_AMV, + CODEC_ID_VB, + CODEC_ID_PCX, + CODEC_ID_SUNRAST, + CODEC_ID_INDEO4, + CODEC_ID_INDEO5, + CODEC_ID_MIMIC, + CODEC_ID_RL2, + CODEC_ID_ESCAPE124, + CODEC_ID_DIRAC, + CODEC_ID_BFI, + CODEC_ID_CMV, + CODEC_ID_MOTIONPIXELS, + CODEC_ID_TGV, + CODEC_ID_TGQ, + CODEC_ID_TQI, + CODEC_ID_AURA, + CODEC_ID_AURA2, + CODEC_ID_V210X, + CODEC_ID_TMV, + CODEC_ID_V210, + CODEC_ID_DPX, + CODEC_ID_MAD, + CODEC_ID_FRWU, + CODEC_ID_FLASHSV2, + CODEC_ID_CDGRAPHICS, + CODEC_ID_R210, + CODEC_ID_ANM, + CODEC_ID_BINKVIDEO, + CODEC_ID_IFF_ILBM, + CODEC_ID_IFF_BYTERUN1, + CODEC_ID_KGV1, + CODEC_ID_YOP, + CODEC_ID_VP8, + CODEC_ID_PICTOR, + CODEC_ID_ANSI, + CODEC_ID_A64_MULTI, + CODEC_ID_A64_MULTI5, + CODEC_ID_R10K, + CODEC_ID_MXPEG, + CODEC_ID_LAGARITH, + CODEC_ID_PRORES, + CODEC_ID_JV, + CODEC_ID_DFA, + CODEC_ID_WMV3IMAGE, + CODEC_ID_VC1IMAGE, + CODEC_ID_UTVIDEO, + CODEC_ID_BMV_VIDEO, + CODEC_ID_VBLE, + CODEC_ID_DXTORY, + CODEC_ID_V410, + CODEC_ID_XWD, + CODEC_ID_CDXL, + CODEC_ID_XBM, + CODEC_ID_ZEROCODEC, + CODEC_ID_MSS1, + CODEC_ID_MSA1, + CODEC_ID_TSCC2, + CODEC_ID_MTS2, + CODEC_ID_CLLC, + CODEC_ID_Y41P = MKBETAG('Y','4','1','P'), + CODEC_ID_ESCAPE130 = MKBETAG('E','1','3','0'), + CODEC_ID_EXR = MKBETAG('0','E','X','R'), + CODEC_ID_AVRP = MKBETAG('A','V','R','P'), + + CODEC_ID_G2M = MKBETAG( 0 ,'G','2','M'), + CODEC_ID_AVUI = MKBETAG('A','V','U','I'), + CODEC_ID_AYUV = MKBETAG('A','Y','U','V'), + CODEC_ID_V308 = MKBETAG('V','3','0','8'), + CODEC_ID_V408 = MKBETAG('V','4','0','8'), + CODEC_ID_YUV4 = MKBETAG('Y','U','V','4'), + CODEC_ID_SANM = MKBETAG('S','A','N','M'), + CODEC_ID_PAF_VIDEO = MKBETAG('P','A','F','V'), + + /* various PCM "codecs" */ + CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + CODEC_ID_PCM_S16LE = 0x10000, + CODEC_ID_PCM_S16BE, + CODEC_ID_PCM_U16LE, + CODEC_ID_PCM_U16BE, + CODEC_ID_PCM_S8, + CODEC_ID_PCM_U8, + CODEC_ID_PCM_MULAW, + CODEC_ID_PCM_ALAW, + CODEC_ID_PCM_S32LE, + CODEC_ID_PCM_S32BE, + CODEC_ID_PCM_U32LE, + CODEC_ID_PCM_U32BE, + CODEC_ID_PCM_S24LE, + CODEC_ID_PCM_S24BE, + CODEC_ID_PCM_U24LE, + CODEC_ID_PCM_U24BE, + CODEC_ID_PCM_S24DAUD, + CODEC_ID_PCM_ZORK, + CODEC_ID_PCM_S16LE_PLANAR, + CODEC_ID_PCM_DVD, + CODEC_ID_PCM_F32BE, + CODEC_ID_PCM_F32LE, + CODEC_ID_PCM_F64BE, + CODEC_ID_PCM_F64LE, + CODEC_ID_PCM_BLURAY, + CODEC_ID_PCM_LXF, + CODEC_ID_S302M, + CODEC_ID_PCM_S8_PLANAR, + + /* various ADPCM codecs */ + CODEC_ID_ADPCM_IMA_QT = 0x11000, + CODEC_ID_ADPCM_IMA_WAV, + CODEC_ID_ADPCM_IMA_DK3, + CODEC_ID_ADPCM_IMA_DK4, + CODEC_ID_ADPCM_IMA_WS, + CODEC_ID_ADPCM_IMA_SMJPEG, + CODEC_ID_ADPCM_MS, + CODEC_ID_ADPCM_4XM, + CODEC_ID_ADPCM_XA, + CODEC_ID_ADPCM_ADX, + CODEC_ID_ADPCM_EA, + CODEC_ID_ADPCM_G726, + CODEC_ID_ADPCM_CT, + CODEC_ID_ADPCM_SWF, + CODEC_ID_ADPCM_YAMAHA, + CODEC_ID_ADPCM_SBPRO_4, + CODEC_ID_ADPCM_SBPRO_3, + CODEC_ID_ADPCM_SBPRO_2, + CODEC_ID_ADPCM_THP, + CODEC_ID_ADPCM_IMA_AMV, + CODEC_ID_ADPCM_EA_R1, + CODEC_ID_ADPCM_EA_R3, + CODEC_ID_ADPCM_EA_R2, + CODEC_ID_ADPCM_IMA_EA_SEAD, + CODEC_ID_ADPCM_IMA_EA_EACS, + CODEC_ID_ADPCM_EA_XAS, + CODEC_ID_ADPCM_EA_MAXIS_XA, + CODEC_ID_ADPCM_IMA_ISS, + CODEC_ID_ADPCM_G722, + CODEC_ID_ADPCM_IMA_APC, + CODEC_ID_VIMA = MKBETAG('V','I','M','A'), + + /* AMR */ + CODEC_ID_AMR_NB = 0x12000, + CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + CODEC_ID_RA_144 = 0x13000, + CODEC_ID_RA_288, + + /* various DPCM codecs */ + CODEC_ID_ROQ_DPCM = 0x14000, + CODEC_ID_INTERPLAY_DPCM, + CODEC_ID_XAN_DPCM, + CODEC_ID_SOL_DPCM, + + /* audio codecs */ + CODEC_ID_MP2 = 0x15000, + CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + CODEC_ID_AAC, + CODEC_ID_AC3, + CODEC_ID_DTS, + CODEC_ID_VORBIS, + CODEC_ID_DVAUDIO, + CODEC_ID_WMAV1, + CODEC_ID_WMAV2, + CODEC_ID_MACE3, + CODEC_ID_MACE6, + CODEC_ID_VMDAUDIO, + CODEC_ID_FLAC, + CODEC_ID_MP3ADU, + CODEC_ID_MP3ON4, + CODEC_ID_SHORTEN, + CODEC_ID_ALAC, + CODEC_ID_WESTWOOD_SND1, + CODEC_ID_GSM, ///< as in Berlin toast format + CODEC_ID_QDM2, + CODEC_ID_COOK, + CODEC_ID_TRUESPEECH, + CODEC_ID_TTA, + CODEC_ID_SMACKAUDIO, + CODEC_ID_QCELP, + CODEC_ID_WAVPACK, + CODEC_ID_DSICINAUDIO, + CODEC_ID_IMC, + CODEC_ID_MUSEPACK7, + CODEC_ID_MLP, + CODEC_ID_GSM_MS, /* as found in WAV */ + CODEC_ID_ATRAC3, + CODEC_ID_VOXWARE, + CODEC_ID_APE, + CODEC_ID_NELLYMOSER, + CODEC_ID_MUSEPACK8, + CODEC_ID_SPEEX, + CODEC_ID_WMAVOICE, + CODEC_ID_WMAPRO, + CODEC_ID_WMALOSSLESS, + CODEC_ID_ATRAC3P, + CODEC_ID_EAC3, + CODEC_ID_SIPR, + CODEC_ID_MP1, + CODEC_ID_TWINVQ, + CODEC_ID_TRUEHD, + CODEC_ID_MP4ALS, + CODEC_ID_ATRAC1, + CODEC_ID_BINKAUDIO_RDFT, + CODEC_ID_BINKAUDIO_DCT, + CODEC_ID_AAC_LATM, + CODEC_ID_QDMC, + CODEC_ID_CELT, + CODEC_ID_G723_1, + CODEC_ID_G729, + CODEC_ID_8SVX_EXP, + CODEC_ID_8SVX_FIB, + CODEC_ID_BMV_AUDIO, + CODEC_ID_RALF, + CODEC_ID_IAC, + CODEC_ID_ILBC, + CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), + CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), + CODEC_ID_SONIC = MKBETAG('S','O','N','C'), + CODEC_ID_SONIC_LS = MKBETAG('S','O','N','L'), + CODEC_ID_PAF_AUDIO = MKBETAG('P','A','F','A'), + CODEC_ID_OPUS = MKBETAG('O','P','U','S'), + + /* subtitle codecs */ + CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + CODEC_ID_DVD_SUBTITLE = 0x17000, + CODEC_ID_DVB_SUBTITLE, + CODEC_ID_TEXT, ///< raw UTF-8 text + CODEC_ID_XSUB, + CODEC_ID_SSA, + CODEC_ID_MOV_TEXT, + CODEC_ID_HDMV_PGS_SUBTITLE, + CODEC_ID_DVB_TELETEXT, + CODEC_ID_SRT, + CODEC_ID_MICRODVD = MKBETAG('m','D','V','D'), + CODEC_ID_EIA_608 = MKBETAG('c','6','0','8'), + CODEC_ID_JACOSUB = MKBETAG('J','S','U','B'), + CODEC_ID_SAMI = MKBETAG('S','A','M','I'), + CODEC_ID_REALTEXT = MKBETAG('R','T','X','T'), + CODEC_ID_SUBVIEWER = MKBETAG('S','u','b','V'), + + /* other specific kind of codecs (generally used for attachments) */ + CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + CODEC_ID_TTF = 0x18000, + CODEC_ID_BINTEXT = MKBETAG('B','T','X','T'), + CODEC_ID_XBIN = MKBETAG('X','B','I','N'), + CODEC_ID_IDF = MKBETAG( 0 ,'I','D','F'), + CODEC_ID_OTF = MKBETAG( 0 ,'O','T','F'), + + CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it + + CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + +#endif /* AVCODEC_OLD_CODEC_IDS_H */ diff --git a/extra_lib/include/libavcodec/vaapi.h b/extra_lib/include/libavcodec/vaapi.h new file mode 100644 index 0000000..815a27e --- /dev/null +++ b/extra_lib/include/libavcodec/vaapi.h @@ -0,0 +1,173 @@ +/* + * Video Acceleration API (shared data between FFmpeg and the video player) + * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VAAPI_H +#define AVCODEC_VAAPI_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vaapi + * Public libavcodec VA API header. + */ + +#include + +/** + * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding + * @ingroup lavc_codec_hwaccel + * @{ + */ + +/** + * This structure is used to share data between the FFmpeg library and + * the client video application. + * This shall be zero-allocated and available as + * AVCodecContext.hwaccel_context. All user members can be set once + * during initialization or through each AVCodecContext.get_buffer() + * function call. In any case, they must be valid prior to calling + * decoding functions. + */ +struct vaapi_context { + /** + * Window system dependent data + * + * - encoding: unused + * - decoding: Set by user + */ + void *display; + + /** + * Configuration ID + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t config_id; + + /** + * Context ID (video decode pipeline) + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t context_id; + + /** + * VAPictureParameterBuffer ID + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t pic_param_buf_id; + + /** + * VAIQMatrixBuffer ID + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t iq_matrix_buf_id; + + /** + * VABitPlaneBuffer ID (for VC-1 decoding) + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t bitplane_buf_id; + + /** + * Slice parameter/data buffer IDs + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t *slice_buf_ids; + + /** + * Number of effective slice buffer IDs to send to the HW + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int n_slice_buf_ids; + + /** + * Size of pre-allocated slice_buf_ids + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_buf_ids_alloc; + + /** + * Pointer to VASliceParameterBuffers + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + void *slice_params; + + /** + * Size of a VASliceParameterBuffer element + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_param_size; + + /** + * Size of pre-allocated slice_params + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_params_alloc; + + /** + * Number of slices currently filled in + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_count; + + /** + * Pointer to slice data buffer base + * - encoding: unused + * - decoding: Set by libavcodec + */ + const uint8_t *slice_data; + + /** + * Current size of slice data + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t slice_data_size; +}; + +/* @} */ + +#endif /* AVCODEC_VAAPI_H */ diff --git a/extra_lib/include/libavcodec/vda.h b/extra_lib/include/libavcodec/vda.h new file mode 100644 index 0000000..ccbf375 --- /dev/null +++ b/extra_lib/include/libavcodec/vda.h @@ -0,0 +1,226 @@ +/* + * VDA HW acceleration + * + * copyright (c) 2011 Sebastien Zwickert + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VDA_H +#define AVCODEC_VDA_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vda + * Public libavcodec VDA header. + */ + +#include "libavcodec/version.h" + +#if FF_API_VDA_ASYNC +#include +#endif + +#include + +// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes +// http://openradar.appspot.com/8026390 +#undef __GNUC_STDC_INLINE__ + +#define Picture QuickdrawPicture +#include +#undef Picture + +/** + * @defgroup lavc_codec_hwaccel_vda VDA + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#if FF_API_VDA_ASYNC +/** + * This structure is used to store decoded frame information and data. + * + * @deprecated Use synchronous decoding mode. + */ +typedef struct { + /** + * The PTS of the frame. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int64_t pts; + + /** + * The CoreVideo buffer that contains the decoded data. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + CVPixelBufferRef cv_buffer; + + /** + * A pointer to the next frame. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + struct vda_frame *next_frame; +} vda_frame; +#endif + +/** + * This structure is used to provide the necessary configurations and data + * to the VDA FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct vda_context { + /** + * VDA decoder object. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + VDADecoder decoder; + + /** + * The Core Video pixel buffer that contains the current image data. + * + * encoding: unused + * decoding: Set by libavcodec. Unset by user. + */ + CVPixelBufferRef cv_buffer; + + /** + * Use the hardware decoder in synchronous mode. + * + * encoding: unused + * decoding: Set by user. + */ + int use_sync_decoding; + +#if FF_API_VDA_ASYNC + /** + * VDA frames queue ordered by presentation timestamp. + * + * @deprecated Use synchronous decoding mode. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + vda_frame *queue; + + /** + * Mutex for locking queue operations. + * + * @deprecated Use synchronous decoding mode. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + pthread_mutex_t queue_mutex; +#endif + + /** + * The frame width. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int width; + + /** + * The frame height. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int height; + + /** + * The frame format. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int format; + + /** + * The pixel format for output image buffers. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + OSType cv_pix_fmt_type; + + /** + * The current bitstream buffer. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + uint8_t *priv_bitstream; + + /** + * The current size of the bitstream. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int priv_bitstream_size; + + /** + * The reference size used for fast reallocation. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int priv_allocated_size; +}; + +/** Create the video decoder. */ +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size); + +/** Destroy the video decoder. */ +int ff_vda_destroy_decoder(struct vda_context *vda_ctx); + +#if FF_API_VDA_ASYNC +/** + * Return the top frame of the queue. + * + * @deprecated Use synchronous decoding mode. + */ +vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx); + +/** + * Release the given frame. + * + * @deprecated Use synchronous decoding mode. + */ +void ff_vda_release_vda_frame(vda_frame *frame); +#endif + +/** + * @} + */ + +#endif /* AVCODEC_VDA_H */ diff --git a/extra_lib/include/libavcodec/vdpau.h b/extra_lib/include/libavcodec/vdpau.h new file mode 100644 index 0000000..23394b5 --- /dev/null +++ b/extra_lib/include/libavcodec/vdpau.h @@ -0,0 +1,94 @@ +/* + * The Video Decode and Presentation API for UNIX (VDPAU) is used for + * hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1. + * + * Copyright (C) 2008 NVIDIA + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VDPAU_H +#define AVCODEC_VDPAU_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vdpau + * Public libavcodec VDPAU header. + */ + + +/** + * @defgroup lavc_codec_hwaccel_vdpau VDPAU Decoder and Renderer + * @ingroup lavc_codec_hwaccel + * + * VDPAU hardware acceleration has two modules + * - VDPAU decoding + * - VDPAU presentation + * + * The VDPAU decoding module parses all headers using FFmpeg + * parsing mechanisms and uses VDPAU for the actual decoding. + * + * As per the current implementation, the actual decoding + * and rendering (API calls) are done as part of the VDPAU + * presentation (vo_vdpau.c) module. + * + * @{ + */ + +#include +#include + +/** @brief The videoSurface is used for rendering. */ +#define FF_VDPAU_STATE_USED_FOR_RENDER 1 + +/** + * @brief The videoSurface is needed for reference/prediction. + * The codec manipulates this. + */ +#define FF_VDPAU_STATE_USED_FOR_REFERENCE 2 + +/** + * @brief This structure is used as a callback between the FFmpeg + * decoder (vd_) and presentation (vo_) module. + * This is used for defining a video frame containing surface, + * picture parameter, bitstream information etc which are passed + * between the FFmpeg decoder and its clients. + */ +struct vdpau_render_state { + VdpVideoSurface surface; ///< Used as rendered surface, never changed. + + int state; ///< Holds FF_VDPAU_STATE_* values. + + /** Describe size/location of the compressed video data. + Set to 0 when freeing bitstream_buffers. */ + int bitstream_buffers_allocated; + int bitstream_buffers_used; + /** The user is responsible for freeing this buffer using av_freep(). */ + VdpBitstreamBuffer *bitstream_buffers; + + /** picture parameter information for all supported codecs */ + union VdpPictureInfo { + VdpPictureInfoH264 h264; + VdpPictureInfoMPEG1Or2 mpeg; + VdpPictureInfoVC1 vc1; + VdpPictureInfoMPEG4Part2 mpeg4; + } info; +}; + +/* @}*/ + +#endif /* AVCODEC_VDPAU_H */ diff --git a/extra_lib/include/libavcodec/version.h b/extra_lib/include/libavcodec/version.h new file mode 100644 index 0000000..b2d5c1b --- /dev/null +++ b/extra_lib/include/libavcodec/version.h @@ -0,0 +1,107 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/avutil.h" + +#define LIBAVCODEC_VERSION_MAJOR 54 +#define LIBAVCODEC_VERSION_MINOR 67 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#ifndef FF_API_REQUEST_CHANNELS +#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_ALLOC_CONTEXT +#define FF_API_ALLOC_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_AVCODEC_OPEN +#define FF_API_AVCODEC_OPEN (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_OLD_DECODE_AUDIO +#define FF_API_OLD_DECODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_OLD_TIMECODE +#define FF_API_OLD_TIMECODE (LIBAVCODEC_VERSION_MAJOR < 55) +#endif + +#ifndef FF_API_OLD_ENCODE_AUDIO +#define FF_API_OLD_ENCODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_OLD_ENCODE_VIDEO +#define FF_API_OLD_ENCODE_VIDEO (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_MPV_GLOBAL_OPTS +#define FF_API_MPV_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_COLOR_TABLE_ID +#define FF_API_COLOR_TABLE_ID (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_INTER_THRESHOLD +#define FF_API_INTER_THRESHOLD (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_SUB_ID +#define FF_API_SUB_ID (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_DSP_MASK +#define FF_API_DSP_MASK (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_FIND_BEST_PIX_FMT +#define FF_API_FIND_BEST_PIX_FMT (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_CODEC_ID +#define FF_API_CODEC_ID (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_VDA_ASYNC +#define FF_API_VDA_ASYNC (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_AVCODEC_RESAMPLE +#define FF_API_AVCODEC_RESAMPLE (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_LIBMPEG2 +#define FF_API_LIBMPEG2 (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_MMI +#define FF_API_MMI (LIBAVCODEC_VERSION_MAJOR < 55) +#endif + +#endif /* AVCODEC_VERSION_H */ diff --git a/extra_lib/include/libavcodec/xvmc.h b/extra_lib/include/libavcodec/xvmc.h new file mode 100644 index 0000000..b2bf518 --- /dev/null +++ b/extra_lib/include/libavcodec/xvmc.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2003 Ivan Kalvachev + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_XVMC_H +#define AVCODEC_XVMC_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_xvmc + * Public libavcodec XvMC header. + */ + +#include + +#include "avcodec.h" + +/** + * @defgroup lavc_codec_hwaccel_xvmc XvMC + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct + the number is 1337 speak for the letters IDCT MCo (motion compensation) */ + +struct xvmc_pix_fmt { + /** The field contains the special constant value AV_XVMC_ID. + It is used as a test that the application correctly uses the API, + and that there is no corruption caused by pixel routines. + - application - set during initialization + - libavcodec - unchanged + */ + int xvmc_id; + + /** Pointer to the block array allocated by XvMCCreateBlocks(). + The array has to be freed by XvMCDestroyBlocks(). + Each group of 64 values represents one data block of differential + pixel information (in MoCo mode) or coefficients for IDCT. + - application - set the pointer during initialization + - libavcodec - fills coefficients/pixel data into the array + */ + short* data_blocks; + + /** Pointer to the macroblock description array allocated by + XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks(). + - application - set the pointer during initialization + - libavcodec - fills description data into the array + */ + XvMCMacroBlock* mv_blocks; + + /** Number of macroblock descriptions that can be stored in the mv_blocks + array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_mv_blocks; + + /** Number of blocks that can be stored at once in the data_blocks array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_data_blocks; + + /** Indicate that the hardware would interpret data_blocks as IDCT + coefficients and perform IDCT on them. + - application - set during initialization + - libavcodec - unchanged + */ + int idct; + + /** In MoCo mode it indicates that intra macroblocks are assumed to be in + unsigned format; same as the XVMC_INTRA_UNSIGNED flag. + - application - set during initialization + - libavcodec - unchanged + */ + int unsigned_intra; + + /** Pointer to the surface allocated by XvMCCreateSurface(). + It has to be freed by XvMCDestroySurface() on application exit. + It identifies the frame and its state on the video hardware. + - application - set during initialization + - libavcodec - unchanged + */ + XvMCSurface* p_surface; + +/** Set by the decoder before calling ff_draw_horiz_band(), + needed by the XvMCRenderSurface function. */ +//@{ + /** Pointer to the surface used as past reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_past_surface; + + /** Pointer to the surface used as future reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_future_surface; + + /** top/bottom field or frame + - application - unchanged + - libavcodec - set + */ + unsigned int picture_structure; + + /** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence + - application - unchanged + - libavcodec - set + */ + unsigned int flags; +//}@ + + /** Number of macroblock descriptions in the mv_blocks array + that have already been passed to the hardware. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may increment it + with filled_mb_block_num or zero both. + - libavcodec - unchanged + */ + int start_mv_blocks_num; + + /** Number of new macroblock descriptions in the mv_blocks array (after + start_mv_blocks_num) that are filled by libavcodec and have to be + passed to the hardware. + - application - zeroes it on get_buffer() or after successful + ff_draw_horiz_band(). + - libavcodec - increment with one of each stored MB + */ + int filled_mv_blocks_num; + + /** Number of the next free data block; one data block consists of + 64 short values in the data_blocks array. + All blocks before this one have already been claimed by placing their + position into the corresponding block description structure field, + that are part of the mv_blocks array. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may zero it together + with start_mb_blocks_num. + - libavcodec - each decoded macroblock increases it by the number + of coded blocks it contains. + */ + int next_free_data_block_num; +}; + +/** + * @} + */ + +#endif /* AVCODEC_XVMC_H */ diff --git a/extra_lib/include/libavformat/avformat.h b/extra_lib/include/libavformat/avformat.h index 5c4ddd9..ba29771 100644 --- a/extra_lib/include/libavformat/avformat.h +++ b/extra_lib/include/libavformat/avformat.h @@ -21,111 +21,295 @@ #ifndef AVFORMAT_AVFORMAT_H #define AVFORMAT_AVFORMAT_H -#define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 33 -#define LIBAVFORMAT_VERSION_MICRO 0 - -#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ - LIBAVFORMAT_VERSION_MINOR, \ - LIBAVFORMAT_VERSION_MICRO) -#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ - LIBAVFORMAT_VERSION_MINOR, \ - LIBAVFORMAT_VERSION_MICRO) -#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT - -#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) +/** + * @file + * @ingroup libavf + * Main libavformat public API header + */ /** - * Returns the LIBAVFORMAT_VERSION_INT constant. + * @defgroup libavf I/O and Muxing/Demuxing Library + * @{ + * + * Libavformat (lavf) is a library for dealing with various media container + * formats. Its main two purposes are demuxing - i.e. splitting a media file + * into component streams, and the reverse process of muxing - writing supplied + * data in a specified container format. It also has an @ref lavf_io + * "I/O module" which supports a number of protocols for accessing the data (e.g. + * file, tcp, http and others). Before using lavf, you need to call + * av_register_all() to register all compiled muxers, demuxers and protocols. + * Unless you are absolutely sure you won't use libavformat's network + * capabilities, you should also call avformat_network_init(). + * + * A supported input format is described by an AVInputFormat struct, conversely + * an output format is described by AVOutputFormat. You can iterate over all + * registered input/output formats using the av_iformat_next() / + * av_oformat_next() functions. The protocols layer is not part of the public + * API, so you can only get the names of supported protocols with the + * avio_enum_protocols() function. + * + * Main lavf structure used for both muxing and demuxing is AVFormatContext, + * which exports all information about the file being read or written. As with + * most Libavformat structures, its size is not part of public ABI, so it cannot be + * allocated on stack or directly with av_malloc(). To create an + * AVFormatContext, use avformat_alloc_context() (some functions, like + * avformat_open_input() might do that for you). + * + * Most importantly an AVFormatContext contains: + * @li the @ref AVFormatContext.iformat "input" or @ref AVFormatContext.oformat + * "output" format. It is either autodetected or set by user for input; + * always set by user for output. + * @li an @ref AVFormatContext.streams "array" of AVStreams, which describe all + * elementary streams stored in the file. AVStreams are typically referred to + * using their index in this array. + * @li an @ref AVFormatContext.pb "I/O context". It is either opened by lavf or + * set by user for input, always set by user for output (unless you are dealing + * with an AVFMT_NOFILE format). + * + * @section lavf_options Passing options to (de)muxers + * Lavf allows to configure muxers and demuxers using the @ref avoptions + * mechanism. Generic (format-independent) libavformat options are provided by + * AVFormatContext, they can be examined from a user program by calling + * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass + * from avformat_get_class()). Private (format-specific) options are provided by + * AVFormatContext.priv_data if and only if AVInputFormat.priv_class / + * AVOutputFormat.priv_class of the corresponding format struct is non-NULL. + * Further options may be provided by the @ref AVFormatContext.pb "I/O context", + * if its AVClass is non-NULL, and the protocols layer. See the discussion on + * nesting in @ref avoptions documentation to learn how to access those. + * + * @defgroup lavf_decoding Demuxing + * @{ + * Demuxers read a media file and split it into chunks of data (@em packets). A + * @ref AVPacket "packet" contains one or more encoded frames which belongs to a + * single elementary stream. In the lavf API this process is represented by the + * avformat_open_input() function for opening a file, av_read_frame() for + * reading a single packet and finally avformat_close_input(), which does the + * cleanup. + * + * @section lavf_decoding_open Opening a media file + * The minimum information required to open a file is its URL or filename, which + * is passed to avformat_open_input(), as in the following code: + * @code + * const char *url = "in.mp3"; + * AVFormatContext *s = NULL; + * int ret = avformat_open_input(&s, url, NULL, NULL); + * if (ret < 0) + * abort(); + * @endcode + * The above code attempts to allocate an AVFormatContext, open the + * specified file (autodetecting the format) and read the header, exporting the + * information stored there into s. Some formats do not have a header or do not + * store enough information there, so it is recommended that you call the + * avformat_find_stream_info() function which tries to read and decode a few + * frames to find missing information. + * + * In some cases you might want to preallocate an AVFormatContext yourself with + * avformat_alloc_context() and do some tweaking on it before passing it to + * avformat_open_input(). One such case is when you want to use custom functions + * for reading input data instead of lavf internal I/O layer. + * To do that, create your own AVIOContext with avio_alloc_context(), passing + * your reading callbacks to it. Then set the @em pb field of your + * AVFormatContext to newly created AVIOContext. + * + * Since the format of the opened file is in general not known until after + * avformat_open_input() has returned, it is not possible to set demuxer private + * options on a preallocated context. Instead, the options should be passed to + * avformat_open_input() wrapped in an AVDictionary: + * @code + * AVDictionary *options = NULL; + * av_dict_set(&options, "video_size", "640x480", 0); + * av_dict_set(&options, "pixel_format", "rgb24", 0); + * + * if (avformat_open_input(&s, url, NULL, &options) < 0) + * abort(); + * av_dict_free(&options); + * @endcode + * This code passes the private options 'video_size' and 'pixel_format' to the + * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it + * cannot know how to interpret raw video data otherwise. If the format turns + * out to be something different than raw video, those options will not be + * recognized by the demuxer and therefore will not be applied. Such unrecognized + * options are then returned in the options dictionary (recognized options are + * consumed). The calling program can handle such unrecognized options as it + * wishes, e.g. + * @code + * AVDictionaryEntry *e; + * if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + * fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key); + * abort(); + * } + * @endcode + * + * After you have finished reading the file, you must close it with + * avformat_close_input(). It will free everything associated with the file. + * + * @section lavf_decoding_read Reading from an opened file + * Reading data from an opened AVFormatContext is done by repeatedly calling + * av_read_frame() on it. Each call, if successful, will return an AVPacket + * containing encoded data for one AVStream, identified by + * AVPacket.stream_index. This packet may be passed straight into the libavcodec + * decoding functions avcodec_decode_video2(), avcodec_decode_audio4() or + * avcodec_decode_subtitle2() if the caller wishes to decode the data. + * + * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be + * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for + * pts/dts, 0 for duration) if the stream does not provide them. The timing + * information will be in AVStream.time_base units, i.e. it has to be + * multiplied by the timebase to convert them to seconds. + * + * The packet data belongs to the demuxer and is invalid after the next call to + * av_read_frame(). The user must free the packet with av_free_packet() before + * calling av_read_frame() again or closing the file. + * + * @section lavf_decoding_seek Seeking + * @} + * + * @defgroup lavf_encoding Muxing + * @{ + * @} + * + * @defgroup lavf_io I/O Read/Write + * @{ + * @} + * + * @defgroup lavf_codec Demuxers + * @{ + * @defgroup lavf_codec_native Native Demuxers + * @{ + * @} + * @defgroup lavf_codec_wrappers External library wrappers + * @{ + * @} + * @} + * @defgroup lavf_protos I/O Protocols + * @{ + * @} + * @defgroup lavf_internal Internal + * @{ + * @} + * @} + * */ -unsigned avformat_version(void); #include #include /* FILE */ #include "libavcodec/avcodec.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" #include "avio.h" +#include "libavformat/version.h" + +#if FF_API_AV_GETTIME +#include "libavutil/time.h" +#endif struct AVFormatContext; -/* - * Public Metadata API. +/** + * @defgroup metadata_api Public Metadata API + * @{ + * @ingroup libavf * The metadata API allows libavformat to export metadata tags to a client - * application using a sequence of key/value pairs. + * application when demuxing. Conversely it allows a client application to + * set metadata when muxing. + * + * Metadata is exported or set as pairs of key/value strings in the 'metadata' + * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs + * using the @ref lavu_dict "AVDictionary" API. Like all strings in FFmpeg, + * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata + * exported by demuxers isn't checked to be valid UTF-8 in most cases. + * * Important concepts to keep in mind: - * 1. Keys are unique; there can never be 2 tags with the same key. This is + * - Keys are unique; there can never be 2 tags with the same key. This is * also meant semantically, i.e., a demuxer should not knowingly produce * several keys that are literally different but semantically identical. * E.g., key=Author5, key=Author6. In this example, all authors must be * placed in the same tag. - * 2. Metadata is flat, not hierarchical; there are no subtags. If you + * - Metadata is flat, not hierarchical; there are no subtags. If you * want to store, e.g., the email address of the child of producer Alice * and actor Bob, that could have key=alice_and_bobs_childs_email_address. - * 3. A tag whose value is localized for a particular language is appended - * with a dash character ('-') and the ISO 639-2/B 3-letter language code. - * For example: Author-ger=Michael, Author-eng=Mike - * The original/default language is in the unqualified "Author" tag. - * A demuxer should set a default if it sets any translated tag. - */ - -#define AV_METADATA_MATCH_CASE 1 -#define AV_METADATA_IGNORE_SUFFIX 2 - -typedef struct { - char *key; - char *value; -}AVMetadataTag; - -typedef struct AVMetadata AVMetadata; -typedef struct AVMetadataConv AVMetadataConv; - -/** - * Gets a metadata element with matching key. - * @param prev Set to the previous matching element to find the next. - * @param flags Allows case as well as suffix-insensitive comparisons. - * @return Found tag or NULL, changing key or value leads to undefined behavior. - */ -AVMetadataTag * -av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags); - -/** - * Sets the given tag in m, overwriting an existing tag. - * @param key tag key to add to m (will be av_strduped) - * @param value tag value to add to m (will be av_strduped) - * @return >= 0 on success otherwise an error code <0 - */ -int av_metadata_set(AVMetadata **pm, const char *key, const char *value); - -/** - * Convert all the metadata sets from ctx according to the source and - * destination conversion tables. - * @param d_conv destination tags format conversion table - * @param s_conv source tags format conversion table - */ -void av_metadata_conv(struct AVFormatContext *ctx,const AVMetadataConv *d_conv, - const AVMetadataConv *s_conv); - -/** - * Frees all the memory allocated for an AVMetadata struct. + * - Several modifiers can be applied to the tag name. This is done by + * appending a dash character ('-') and the modifier name in the order + * they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng. + * - language -- a tag whose value is localized for a particular language + * is appended with the ISO 639-2/B 3-letter language code. + * For example: Author-ger=Michael, Author-eng=Mike + * The original/default language is in the unqualified "Author" tag. + * A demuxer should set a default if it sets any translated tag. + * - sorting -- a modified version of a tag that should be used for + * sorting will have '-sort' appended. E.g. artist="The Beatles", + * artist-sort="Beatles, The". + * + * - Demuxers attempt to export metadata in a generic format, however tags + * with no generic equivalents are left as they are stored in the container. + * Follows a list of generic tag names: + * + @verbatim + album -- name of the set this work belongs to + album_artist -- main creator of the set/album, if different from artist. + e.g. "Various Artists" for compilation albums. + artist -- main creator of the work + comment -- any additional description of the file. + composer -- who composed the work, if different from artist. + copyright -- name of copyright holder. + creation_time-- date when the file was created, preferably in ISO 8601. + date -- date when the work was created, preferably in ISO 8601. + disc -- number of a subset, e.g. disc in a multi-disc collection. + encoder -- name/settings of the software/hardware that produced the file. + encoded_by -- person/group who created the file. + filename -- original name of the file. + genre -- . + language -- main language in which the work is performed, preferably + in ISO 639-2 format. Multiple languages can be specified by + separating them with commas. + performer -- artist who performed the work, if different from artist. + E.g for "Also sprach Zarathustra", artist would be "Richard + Strauss" and performer "London Philharmonic Orchestra". + publisher -- name of the label/publisher. + service_name -- name of the service in broadcasting (channel name). + service_provider -- name of the service provider in broadcasting. + title -- name of the work. + track -- number of this work in the set, can be in form current/total. + variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of + @endverbatim + * + * Look in the examples section for an application example how to use the Metadata API. + * + * @} */ -void av_metadata_free(AVMetadata **m); - /* packet functions */ /** - * Allocate and read the payload of a packet and initialize its fields with - * default values. + * Allocate and read the payload of a packet and initialize its + * fields with default values. * * @param pkt packet * @param size desired payload size * @return >0 (read size) if OK, AVERROR_xxx otherwise */ -int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size); +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size); +/** + * Read data and append it to the current content of the AVPacket. + * If pkt->size is 0 this is identical to av_get_packet. + * Note that this uses av_grow_packet and thus involves a realloc + * which is inefficient. Thus this function should only be used + * when there is no reasonable way to know (an upper bound of) + * the final size. + * + * @param pkt packet + * @param size amount of data to read + * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data + * will not be lost even if an error occurs. + */ +int av_append_packet(AVIOContext *s, AVPacket *pkt, int size); + /*************************************************/ /* fractional numbers for exact pts handling */ @@ -142,39 +326,20 @@ typedef struct AVFrac { struct AVCodecTag; -/** This structure contains the data a format has to probe a file. */ +/** + * This structure contains the data a format has to probe a file. + */ typedef struct AVProbeData { const char *filename; - unsigned char *buf; - int buf_size; + unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ + int buf_size; /**< Size of buf except extra allocated bytes */ } AVProbeData; #define AVPROBE_SCORE_MAX 100 ///< maximum score, half of that is used for file-extension-based detection +#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) #define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer -typedef struct AVFormatParameters { - AVRational time_base; - int sample_rate; - int channels; - int width; - int height; - enum PixelFormat pix_fmt; - int channel; /**< Used to select DV channel. */ - const char *standard; /**< TV standard, NTSC, PAL, SECAM */ - unsigned int mpeg2ts_raw:1; /**< Force raw MPEG-2 transport stream output, if possible. */ - unsigned int mpeg2ts_compute_pcr:1; /**< Compute exact PCR for each transport - stream packet (only meaningful if - mpeg2ts_raw is TRUE). */ - unsigned int initial_pause:1; /**< Do not begin to play the stream - immediately (RTSP only). */ - unsigned int prealloced_context:1; -#if LIBAVFORMAT_VERSION_INT < (53<<16) - enum CodecID video_codec_id; - enum CodecID audio_codec_id; -#endif -} AVFormatParameters; - -//! Demuxer will use url_fopen, no opened file should be provided by the caller. +/// Demuxer will use avio_open, no opened file should be provided by the caller. #define AVFMT_NOFILE 0x0001 #define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ #define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ @@ -183,9 +348,29 @@ typedef struct AVFormatParameters { #define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ #define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ #define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */ -#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. */ +#define AVFMT_TS_DISCONT 0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */ #define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ +#define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ +#define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fallback to binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fallback to generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ +#define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */ +#if LIBAVFORMAT_VERSION_MAJOR <= 54 +#define AVFMT_TS_NONSTRICT 0x8020000 //we try to be compatible to the ABIs of ffmpeg and major forks +#else +#define AVFMT_TS_NONSTRICT 0x20000 +#endif + /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ + +#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ +/** + * @addtogroup lavf_encoding + * @{ + */ typedef struct AVOutputFormat { const char *name; /** @@ -196,69 +381,157 @@ typedef struct AVOutputFormat { const char *long_name; const char *mime_type; const char *extensions; /**< comma-separated filename extensions */ - /** size of private data so that it can be allocated in the wrapper */ - int priv_data_size; /* output support */ - enum CodecID audio_codec; /**< default audio codec */ - enum CodecID video_codec; /**< default video codec */ - int (*write_header)(struct AVFormatContext *); - int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); - int (*write_trailer)(struct AVFormatContext *); - /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */ + enum AVCodecID audio_codec; /**< default audio codec */ + enum AVCodecID video_codec; /**< default video codec */ + enum AVCodecID subtitle_codec; /**< default subtitle codec */ + /** + * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_RAWPICTURE, + * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, + * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, + * AVFMT_TS_NONSTRICT + */ int flags; - /** Currently only used to set pixel format if not YUV420P. */ - int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *); - int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, - AVPacket *in, int flush); /** * List of supported codec_id-codec_tag pairs, ordered by "better - * choice first". The arrays are all terminated by CODEC_ID_NONE. + * choice first". The arrays are all terminated by AV_CODEC_ID_NONE. */ const struct AVCodecTag * const *codec_tag; - enum CodecID subtitle_codec; /**< default subtitle codec */ - const AVMetadataConv *metadata_conv; + const AVClass *priv_class; ///< AVClass for the private context - /* private fields */ + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ struct AVOutputFormat *next; + /** + * size of private data so that it can be allocated in the wrapper + */ + int priv_data_size; + + int (*write_header)(struct AVFormatContext *); + /** + * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags, + * pkt can be NULL in order to flush data buffered in the muxer. + * When flushing, return 0 if there still is more data to flush, + * or 1 if everything was flushed and there is no more buffered + * data. + */ + int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); + int (*write_trailer)(struct AVFormatContext *); + /** + * Currently only used to set pixel format if not YUV420P. + */ + int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, + AVPacket *in, int flush); + /** + * Test if the given codec can be stored in this container. + * + * @return 1 if the codec is supported, 0 if it is not. + * A negative number if unknown. + * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC + */ + int (*query_codec)(enum AVCodecID id, int std_compliance); + + void (*get_output_timestamp)(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); } AVOutputFormat; +/** + * @} + */ +/** + * @addtogroup lavf_decoding + * @{ + */ typedef struct AVInputFormat { + /** + * A comma separated list of short names for the format. New names + * may be appended with a minor bump. + */ const char *name; + /** * Descriptive name for the format, meant to be more human-readable * than name. You should use the NULL_IF_CONFIG_SMALL() macro * to define it. */ const char *long_name; - /** Size of private data so that it can be allocated in the wrapper. */ + + /** + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS. + */ + int flags; + + /** + * If extensions are defined, then no probe is done. You should + * usually not use extension format guessing because it is not + * reliable enough + */ + const char *extensions; + + const struct AVCodecTag * const *codec_tag; + + const AVClass *priv_class; ///< AVClass for the private context + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + struct AVInputFormat *next; + + /** + * Raw demuxers store their codec ID here. + */ + int raw_codec_id; + + /** + * Size of private data so that it can be allocated in the wrapper. + */ int priv_data_size; + /** * Tell if a given file has a chance of being parsed as this format. * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes * big so you do not have to check for that unless you need more. */ int (*read_probe)(AVProbeData *); - /** Read the format header and initialize the AVFormatContext - structure. Return 0 if OK. 'ap' if non-NULL contains - additional parameters. Only used in raw format right - now. 'av_new_stream' should be called to create new streams. */ - int (*read_header)(struct AVFormatContext *, - AVFormatParameters *ap); - /** Read one packet and put it in 'pkt'. pts and flags are also - set. 'av_new_stream' can be called only if the flag - AVFMTCTX_NOHEADER is used. - @return 0 on success, < 0 on error. - When returning an error, pkt must not have been allocated - or must be freed before returning */ + + /** + * Read the format header and initialize the AVFormatContext + * structure. Return 0 if OK. Only used in raw format right + * now. 'avformat_new_stream' should be called to create new streams. + */ + int (*read_header)(struct AVFormatContext *); + + /** + * Read one packet and put it in 'pkt'. pts and flags are also + * set. 'avformat_new_stream' can be called only if the flag + * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a + * background thread). + * @return 0 on success, < 0 on error. + * When returning an error, pkt must not have been allocated + * or must be freed before returning + */ int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); - /** Close the stream. The AVFormatContext and AVStreams are not - freed by this function */ + + /** + * Close the stream. The AVFormatContext and AVStreams are not + * freed by this function + */ int (*read_close)(struct AVFormatContext *); -#if LIBAVFORMAT_VERSION_MAJOR < 53 /** * Seek to a given timestamp relative to the frames in * stream component stream_index. @@ -269,32 +542,26 @@ typedef struct AVInputFormat { */ int (*read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags); -#endif + /** - * Gets the next timestamp in stream[stream_index].time_base units. + * Get the next timestamp in stream[stream_index].time_base units. * @return the timestamp or AV_NOPTS_VALUE if an error occurred */ int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit); - /** Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER. */ - int flags; - /** If extensions are defined, then no probe is done. You should - usually not use extension format guessing because it is not - reliable enough */ - const char *extensions; - /** General purpose read-only value that the format can use. */ - int value; - /** Start/resume playing - only meaningful if using a network-based format - (RTSP). */ + /** + * Start/resume playing - only meaningful if using a network-based format + * (RTSP). + */ int (*read_play)(struct AVFormatContext *); - /** Pause playing - only meaningful if using a network-based format - (RTSP). */ + /** + * Pause playing - only meaningful if using a network-based format + * (RTSP). + */ int (*read_pause)(struct AVFormatContext *); - const struct AVCodecTag * const *codec_tag; - /** * Seek to timestamp ts. * Seeking will be done so that the point from which all active streams @@ -302,23 +569,30 @@ typedef struct AVInputFormat { * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL. */ int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); - - const AVMetadataConv *metadata_conv; - - /* private fields */ - struct AVInputFormat *next; } AVInputFormat; +/** + * @} + */ enum AVStreamParseType { AVSTREAM_PARSE_NONE, AVSTREAM_PARSE_FULL, /**< full parsing and repack */ AVSTREAM_PARSE_HEADERS, /**< Only parse headers, do not repack. */ AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */ + AVSTREAM_PARSE_FULL_ONCE, /**< full parsing and repack of the first frame only, only implemented for H.264 currently */ + AVSTREAM_PARSE_FULL_RAW=MKTAG(0,'R','A','W'), /**< full parsing and repack with timestamp and position generation by parser for raw + this assumes that each packet in the file contains no demuxer level headers and + just codec level data, otherwise position generation would fail */ }; typedef struct AVIndexEntry { int64_t pos; - int64_t timestamp; + int64_t timestamp; /**< + * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available + * when seeking to this entry. That means preferable PTS on keyframe based formats. + * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better + * is known + */ #define AVINDEX_KEYFRAME 0x0001 int flags:2; int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment). @@ -332,6 +606,23 @@ typedef struct AVIndexEntry { #define AV_DISPOSITION_LYRICS 0x0010 #define AV_DISPOSITION_KARAOKE 0x0020 +/** + * Track should be used during playback by default. + * Useful for subtitle track that should be displayed + * even when user did not explicitly ask for subtitles. + */ +#define AV_DISPOSITION_FORCED 0x0040 +#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */ +#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */ +#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */ +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The single packet associated with it will be returned + * among the first few packets read from the file unless seeking takes place. + * It can also be accessed at any time in AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC 0x0400 + /** * Stream structure. * New fields can be added to the end with minor version bumps. @@ -341,8 +632,25 @@ typedef struct AVIndexEntry { */ typedef struct AVStream { int index; /**< stream index in AVFormatContext */ - int id; /**< format-specific stream ID */ - AVCodecContext *codec; /**< codec context */ + /** + * Format-specific stream ID. + * decoding: set by libavformat + * encoding: set by the user + */ + int id; + /** + * Codec context associated with this stream. Allocated and freed by + * libavformat. + * + * - decoding: The demuxer exports codec information stored in the headers + * here. + * - encoding: The user sets codec information, the muxer writes it to the + * output. Mandatory fields as specified in AVCodecContext + * documentation must be set even if this AVCodecContext is + * not actually used for encoding. + */ + AVCodecContext *codec; +#if FF_API_R_FRAME_RATE /** * Real base framerate of the stream. * This is the lowest framerate with which all timestamps can be @@ -352,29 +660,27 @@ typedef struct AVStream { * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. */ AVRational r_frame_rate; +#endif void *priv_data; - /* internal data used in av_find_stream_info() */ - int64_t first_dts; - /** encoding: pts generation when outputting stream */ + /** + * encoding: pts generation when outputting stream + */ struct AVFrac pts; /** * This is the fundamental unit of time (in seconds) in terms - * of which frame timestamps are represented. For fixed-fps content, - * time base should be 1/framerate and timestamp increments should be 1. + * of which frame timestamps are represented. + * + * decoding: set by libavformat + * encoding: set by libavformat in avformat_write_header. The muxer may use the + * user-provided value of @ref AVCodecContext.time_base "codec->time_base" + * as a hint. */ AVRational time_base; - int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ - /* ffmpeg.c private use */ - int stream_copy; /**< If set, just copy stream. */ - enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. - //FIXME move stuff to a flags field? - /** Quality, as it has been removed from AVCodecContext and put in AVVideoFrame. - * MN: dunno if that is the right place for it */ - float quality; + /** - * Decoding: pts of the first frame of the stream, in stream time base. + * Decoding: pts of the first frame of the stream in presentation order, in stream time base. * Only set this if you are absolutely 100% sure that the value you set * it to really is the pts of the first frame. * This may be undefined (AV_NOPTS_VALUE). @@ -382,6 +688,7 @@ typedef struct AVStream { * demuxer must NOT set this. */ int64_t start_time; + /** * Decoding: duration of the stream, in stream time base. * If a source file does not specify a duration, but does specify @@ -389,36 +696,11 @@ typedef struct AVStream { */ int64_t duration; -#if LIBAVFORMAT_VERSION_INT < (53<<16) - char language[4]; /** ISO 639-2/B 3-letter language code (empty string if undefined) */ -#endif - - /* av_read_frame() support */ - enum AVStreamParseType need_parsing; - struct AVCodecParserContext *parser; - - int64_t cur_dts; - int last_IP_duration; - int64_t last_IP_pts; - /* av_seek_frame() support */ - AVIndexEntry *index_entries; /**< Only used if the format does not - support seeking natively. */ - int nb_index_entries; - unsigned int index_entries_allocated_size; - int64_t nb_frames; ///< number of frames in this stream if known or 0 -#if LIBAVFORMAT_VERSION_INT < (53<<16) - int64_t unused[4+1]; - - char *filename; /**< source filename of the stream */ -#endif - int disposition; /**< AV_DISPOSITION_* bit field */ - AVProbeData probe_data; -#define MAX_REORDER_DELAY 16 - int64_t pts_buffer[MAX_REORDER_DELAY+1]; + enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. /** * sample aspect ratio (0 if unknown) @@ -427,12 +709,54 @@ typedef struct AVStream { */ AVRational sample_aspect_ratio; - AVMetadata *metadata; + AVDictionary *metadata; - /* av_read_frame() support */ - const uint8_t *cur_ptr; - int cur_len; - AVPacket cur_pkt; + /** + * Average framerate + */ + AVRational avg_frame_rate; + + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + /** + * Stream information used internally by av_find_stream_info() + */ +#define MAX_STD_TIMEBASES (60*12+6) + struct { + int64_t last_dts; + int64_t duration_gcd; + int duration_count; + double duration_error[2][2][MAX_STD_TIMEBASES]; + int64_t codec_info_duration; + int64_t codec_info_duration_fields; + int found_decoder; + + /** + * Those are used for average framerate estimation. + */ + int64_t fps_first_dts; + int fps_first_dts_idx; + int64_t fps_last_dts; + int fps_last_dts_idx; + + } *info; + + int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ // Timestamp generation support: /** @@ -443,6 +767,80 @@ typedef struct AVStream { * AV_NOPTS_VALUE by default. */ int64_t reference_dts; + int64_t first_dts; + int64_t cur_dts; + int64_t last_IP_pts; + int last_IP_duration; + + /** + * Number of packets to buffer for codec probing + */ +#define MAX_PROBE_PACKETS 2500 + int probe_packets; + + /** + * Number of frames that have been demuxed during av_find_stream_info() + */ + int codec_info_nb_frames; + + /** + * Stream Identifier + * This is the MPEG-TS stream identifier +1 + * 0 means unknown + */ + int stream_identifier; + + int64_t interleaver_chunk_size; + int64_t interleaver_chunk_duration; + + /* av_read_frame() support */ + enum AVStreamParseType need_parsing; + struct AVCodecParserContext *parser; + + /** + * last packet in packet_buffer for this stream when muxing. + */ + struct AVPacketList *last_in_packet_buffer; + AVProbeData probe_data; +#define MAX_REORDER_DELAY 16 + int64_t pts_buffer[MAX_REORDER_DELAY+1]; + + AVIndexEntry *index_entries; /**< Only used if the format does not + support seeking natively. */ + int nb_index_entries; + unsigned int index_entries_allocated_size; + + /** + * stream probing state + * -1 -> probing finished + * 0 -> no probing requested + * rest -> perform probing with request_probe being the minimum score to accept. + * NOT PART OF PUBLIC API + */ + int request_probe; + /** + * Indicates that everything up to the next keyframe + * should be discarded. + */ + int skip_to_keyframe; + + /** + * Number of samples to skip at the start of the frame decoded from the next packet. + */ + int skip_samples; + + /** + * Number of internally decoded frames, used internally in libavformat, do not access + * its lifetime differs from info which is why its not in that structure. + */ + int nb_decoded_frames; + + /** + * Timestamp offset added to timestamps before muxing + * NOT PART OF PUBLIC API + */ + int64_t mux_ts_offset; + } AVStream; #define AV_PROGRAM_RUNNING 1 @@ -455,15 +853,15 @@ typedef struct AVStream { */ typedef struct AVProgram { int id; -#if LIBAVFORMAT_VERSION_INT < (53<<16) - char *provider_name; ///< network name for DVB streams - char *name; ///< service name for DVB streams -#endif int flags; enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller unsigned int *stream_index; unsigned int nb_stream_indexes; - AVMetadata *metadata; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; } AVProgram; #define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present @@ -473,100 +871,128 @@ typedef struct AVChapter { int id; ///< unique ID to identify the chapter AVRational time_base; ///< time base in which the start/end timestamps are specified int64_t start, end; ///< chapter start/end time in time_base units -#if LIBAVFORMAT_VERSION_INT < (53<<16) - char *title; ///< chapter title -#endif - AVMetadata *metadata; + AVDictionary *metadata; } AVChapter; -#define MAX_STREAMS 20 + +/** + * The duration of a video can be estimated through various ways, and this enum can be used + * to know how the duration was estimated. + */ +enum AVDurationEstimationMethod { + AVFMT_DURATION_FROM_PTS, ///< Duration accurately estimated from PTSes + AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration + AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate) +}; /** * Format I/O context. * New fields can be added to the end with minor version bumps. * Removal, reordering and changes to existing fields require a major * version bump. - * sizeof(AVFormatContext) must not be used outside libav*. + * sizeof(AVFormatContext) must not be used outside libav*, use + * avformat_alloc_context() to create an AVFormatContext. */ typedef struct AVFormatContext { - const AVClass *av_class; /**< Set by avformat_alloc_context. */ - /* Can only be iformat or oformat, not both at the same time. */ + /** + * A class for logging and AVOptions. Set by avformat_alloc_context(). + * Exports (de)muxer private options if they exist. + */ + const AVClass *av_class; + + /** + * Can only be iformat or oformat, not both at the same time. + * + * decoding: set by avformat_open_input(). + * encoding: set by the user. + */ struct AVInputFormat *iformat; struct AVOutputFormat *oformat; + + /** + * Format private data. This is an AVOptions-enabled struct + * if and only if iformat/oformat.priv_class is not NULL. + */ void *priv_data; - ByteIOContext *pb; - unsigned int nb_streams; - AVStream *streams[MAX_STREAMS]; - char filename[1024]; /**< input or output filename */ - /* stream info */ - int64_t timestamp; -#if LIBAVFORMAT_VERSION_INT < (53<<16) - char title[512]; - char author[512]; - char copyright[512]; - char comment[512]; - char album[512]; - int year; /**< ID3 year, 0 if none */ - int track; /**< track number, 0 if none */ - char genre[32]; /**< ID3 genre */ -#endif + /** + * I/O context. + * + * decoding: either set by the user before avformat_open_input() (then + * the user must close it manually) or set by avformat_open_input(). + * encoding: set by the user. + * + * Do NOT set this field if AVFMT_NOFILE flag is set in + * iformat/oformat.flags. In such a case, the (de)muxer will handle + * I/O in some other way and this field will be NULL. + */ + AVIOContext *pb; + + /* stream info */ int ctx_flags; /**< Format-specific flags, see AVFMTCTX_xx */ - /* private data for pts handling (do not modify directly). */ - /** This buffer is only needed when packets were already buffered but - not decoded, for example to get the codec parameters in MPEG - streams. */ - struct AVPacketList *packet_buffer; - /** Decoding: position of the first frame of the component, in - AV_TIME_BASE fractional seconds. NEVER set this value directly: - It is deduced from the AVStream values. */ + /** + * A list of all streams in the file. New streams are created with + * avformat_new_stream(). + * + * decoding: streams are created by libavformat in avformat_open_input(). + * If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also + * appear in av_read_frame(). + * encoding: streams are created by the user before avformat_write_header(). + */ + unsigned int nb_streams; + AVStream **streams; + + char filename[1024]; /**< input or output filename */ + + /** + * Decoding: position of the first frame of the component, in + * AV_TIME_BASE fractional seconds. NEVER set this value directly: + * It is deduced from the AVStream values. + */ int64_t start_time; - /** Decoding: duration of the stream, in AV_TIME_BASE fractional - seconds. NEVER set this value directly: it is deduced from the - AVStream values. */ - int64_t duration; - /** decoding: total file size, 0 if unknown */ - int64_t file_size; - /** Decoding: total stream bitrate in bit/s, 0 if not - available. Never set it directly if the file_size and the - duration are known as FFmpeg can compute it automatically. */ - int bit_rate; - /* av_read_frame() support */ - AVStream *cur_st; -#if LIBAVFORMAT_VERSION_INT < (53<<16) - const uint8_t *cur_ptr_deprecated; - int cur_len_deprecated; - AVPacket cur_pkt_deprecated; -#endif + /** + * Decoding: duration of the stream, in AV_TIME_BASE fractional + * seconds. Only set this value if you know none of the individual stream + * durations and also do not set any of them. This is deduced from the + * AVStream values if not set. + */ + int64_t duration; - /* av_seek_frame() support */ - int64_t data_offset; /** offset of the first packet */ - int index_built; + /** + * Decoding: total stream bitrate in bit/s, 0 if not + * available. Never set it directly if the file_size and the + * duration are known as FFmpeg can compute it automatically. + */ + int bit_rate; - int mux_rate; - int packet_size; - int preload; + unsigned int packet_size; int max_delay; -#define AVFMT_NOOUTPUTLOOP -1 -#define AVFMT_INFINITEOUTPUTLOOP 0 - /** number of times to loop output in formats that support it */ - int loop_output; - int flags; #define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames. #define AVFMT_FLAG_IGNIDX 0x0002 ///< Ignore index. #define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input. +#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS +#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container +#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled +#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible +#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it. +#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted +#define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Enable RTP MP4A-LATM payload +#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) +#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted) +#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Don't merge side data but keep it separate. - int loop_input; - /** decoding: size of data to probe; encoding: unused. */ + /** + * decoding: size of data to probe; encoding: unused. + */ unsigned int probesize; /** - * Maximum time (in AV_TIME_BASE units) during which the input should - * be analyzed in av_find_stream_info(). + * decoding: maximum time (in AV_TIME_BASE units) during which the input should + * be analyzed in avformat_find_stream_info(). */ int max_analyze_duration; @@ -580,17 +1006,19 @@ typedef struct AVFormatContext { * Forced video codec_id. * Demuxing: Set by user. */ - enum CodecID video_codec_id; + enum AVCodecID video_codec_id; + /** * Forced audio codec_id. * Demuxing: Set by user. */ - enum CodecID audio_codec_id; + enum AVCodecID audio_codec_id; + /** * Forced subtitle codec_id. * Demuxing: Set by user. */ - enum CodecID subtitle_codec_id; + enum AVCodecID subtitle_codec_id; /** * Maximum amount of memory in bytes to use for the index of each stream. @@ -613,12 +1041,130 @@ typedef struct AVFormatContext { unsigned int nb_chapters; AVChapter **chapters; + AVDictionary *metadata; + + /** + * Start time of the stream in real world time, in microseconds + * since the unix epoch (00:00 1st January 1970). That is, pts=0 + * in the stream was captured at this real world time. + * - encoding: Set by user. + * - decoding: Unused. + */ + int64_t start_time_realtime; + + /** + * decoding: number of frames used to probe fps + */ + int fps_probe_size; + + /** + * Error recognition; higher values will detect more errors but may + * misdetect some more or less valid parts as errors. + * - encoding: unused + * - decoding: Set by user. + */ + int error_recognition; + + /** + * Custom interrupt callbacks for the I/O layer. + * + * decoding: set by the user before avformat_open_input(). + * encoding: set by the user before avformat_write_header() + * (mainly useful for AVFMT_NOFILE formats). The callback + * should also be passed to avio_open2() if it's used to + * open the file. + */ + AVIOInterruptCB interrupt_callback; + /** * Flags to enable debugging. */ int debug; #define FF_FDEBUG_TS 0x0001 + /** + * Transport stream id. + * This will be moved into demuxer private options. Thus no API/ABI compatibility + */ + int ts_id; + + /** + * Audio preload in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int audio_preload; + + /** + * Max chunk time in microseconds. + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int max_chunk_duration; + + /** + * Max chunk size in bytes + * Note, not all formats support this and unpredictable things may happen if it is used when not supported. + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int max_chunk_size; + + /** + * forces the use of wallclock timestamps as pts/dts of packets + * This has undefined results in the presence of B frames. + * - encoding: unused + * - decoding: Set by user via AVOptions (NO direct access) + */ + int use_wallclock_as_timestamps; + + /** + * Avoids negative timestamps during muxing + * 0 -> allow negative timestamps + * 1 -> avoid negative timestamps + * -1 -> choose automatically (default) + * Note, this is only works when interleave_packet_per_dts is in use + * - encoding: Set by user via AVOptions (NO direct access) + * - decoding: unused + */ + int avoid_negative_ts; + + /** + * avio flags, used to force AVIO_FLAG_DIRECT. + * - encoding: unused + * - decoding: Set by user via AVOptions (NO direct access) + */ + int avio_flags; + + /** + * The duration field can be estimated through various ways, and this field can be used + * to know how the duration was estimated. + * - encoding: unused + * - decoding: Read by user via AVOptions (NO direct access) + */ + enum AVDurationEstimationMethod duration_estimation_method; + + /***************************************************************** + * All fields below this line are not part of the public API. They + * may not be used outside of libavformat and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + /** + * This buffer is only needed when packets were already buffered but + * not decoded, for example to get the codec parameters in MPEG + * streams. + */ + struct AVPacketList *packet_buffer; + struct AVPacketList *packet_buffer_end; + + /* av_seek_frame() support */ + int64_t data_offset; /**< offset of the first packet */ + /** * Raw packets from the demuxer, prior to parsing and decoding. * This buffer is used for buffering packets until the codec can @@ -627,21 +1173,83 @@ typedef struct AVFormatContext { */ struct AVPacketList *raw_packet_buffer; struct AVPacketList *raw_packet_buffer_end; - - struct AVPacketList *packet_buffer_end; - - AVMetadata *metadata; + /** + * Packets split by the parser get queued here. + */ + struct AVPacketList *parse_queue; + struct AVPacketList *parse_queue_end; + /** + * Remaining size available for raw_packet_buffer, in bytes. + */ +#define RAW_PACKET_BUFFER_SIZE 2500000 + int raw_packet_buffer_remaining_size; } AVFormatContext; +/** + * Returns the method used to set ctx->duration. + * + * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE. + */ +enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx); + typedef struct AVPacketList { AVPacket pkt; struct AVPacketList *next; } AVPacketList; -#if LIBAVFORMAT_VERSION_INT < (53<<16) -extern AVInputFormat *first_iformat; -extern AVOutputFormat *first_oformat; -#endif + +/** + * @defgroup lavf_core Core functions + * @ingroup libavf + * + * Functions for querying libavformat capabilities, allocating core structures, + * etc. + * @{ + */ + +/** + * Return the LIBAVFORMAT_VERSION_INT constant. + */ +unsigned avformat_version(void); + +/** + * Return the libavformat build-time configuration. + */ +const char *avformat_configuration(void); + +/** + * Return the libavformat license. + */ +const char *avformat_license(void); + +/** + * Initialize libavformat and register all the muxers, demuxers and + * protocols. If you do not call this function, then you can select + * exactly which formats you want to support. + * + * @see av_register_input_format() + * @see av_register_output_format() + * @see av_register_protocol() + */ +void av_register_all(void); + +void av_register_input_format(AVInputFormat *format); +void av_register_output_format(AVOutputFormat *format); + +/** + * Do global initialization of network components. This is optional, + * but recommended, since it avoids the overhead of implicitly + * doing the setup for each session. + * + * Calling this function will become mandatory if using network + * protocols at some major version bump. + */ +int avformat_network_init(void); + +/** + * Undo the initialization done by avformat_network_init. + */ +int avformat_network_deinit(void); /** * If f is NULL, returns the first registered input format, @@ -657,98 +1265,98 @@ AVInputFormat *av_iformat_next(AVInputFormat *f); */ AVOutputFormat *av_oformat_next(AVOutputFormat *f); -enum CodecID av_guess_image2_codec(const char *filename); - -/* XXX: Use automatic init with either ELF sections or C file parser */ -/* modules. */ - -/* utils.c */ -void av_register_input_format(AVInputFormat *format); -void av_register_output_format(AVOutputFormat *format); -AVOutputFormat *guess_stream_format(const char *short_name, - const char *filename, - const char *mime_type); -AVOutputFormat *guess_format(const char *short_name, - const char *filename, - const char *mime_type); - /** - * Guesses the codec ID based upon muxer and filename. + * Allocate an AVFormatContext. + * avformat_free_context() can be used to free the context and everything + * allocated by the framework within it. */ -enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, - const char *filename, const char *mime_type, - enum CodecType type); +AVFormatContext *avformat_alloc_context(void); /** - * Send a nice hexadecimal dump of a buffer to the specified file stream. - * - * @param f The file stream pointer where the dump should be sent to. - * @param buf buffer - * @param size buffer size + * Free an AVFormatContext and all its streams. + * @param s context to free + */ +void avformat_free_context(AVFormatContext *s); + +/** + * Get the AVClass for AVFormatContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. * - * @see av_hex_dump_log, av_pkt_dump, av_pkt_dump_log + * @see av_opt_find(). */ -void av_hex_dump(FILE *f, uint8_t *buf, int size); +const AVClass *avformat_get_class(void); /** - * Send a nice hexadecimal dump of a buffer to the log. + * Add a new stream to a media file. * - * @param avcl A pointer to an arbitrary struct of which the first field is a - * pointer to an AVClass struct. - * @param level The importance level of the message, lower values signifying - * higher importance. - * @param buf buffer - * @param size buffer size + * When demuxing, it is called by the demuxer in read_header(). If the + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also + * be called in read_packet(). + * + * When muxing, should be called by the user before avformat_write_header(). * - * @see av_hex_dump, av_pkt_dump, av_pkt_dump_log + * @param c If non-NULL, the AVCodecContext corresponding to the new stream + * will be initialized to use this codec. This is needed for e.g. codec-specific + * defaults to be set, so codec should be provided if it is known. + * + * @return newly created stream or NULL on error. */ -void av_hex_dump_log(void *avcl, int level, uint8_t *buf, int size); +AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c); + +AVProgram *av_new_program(AVFormatContext *s, int id); /** - * Send a nice dump of a packet to the specified file stream. - * - * @param f The file stream pointer where the dump should be sent to. - * @param pkt packet to dump - * @param dump_payload True if the payload must be displayed, too. + * @} */ -void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload); + +#if FF_API_PKT_DUMP +attribute_deprecated void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload); +attribute_deprecated void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, + int dump_payload); +#endif + +#if FF_API_ALLOC_OUTPUT_CONTEXT /** - * Send a nice dump of a packet to the log. - * - * @param avcl A pointer to an arbitrary struct of which the first field is a - * pointer to an AVClass struct. - * @param level The importance level of the message, lower values signifying - * higher importance. - * @param pkt packet to dump - * @param dump_payload True if the payload must be displayed, too. + * @deprecated deprecated in favor of avformat_alloc_output_context2() */ -void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload); +attribute_deprecated +AVFormatContext *avformat_alloc_output_context(const char *format, + AVOutputFormat *oformat, + const char *filename); +#endif /** - * Initialize libavformat and register all the muxers, demuxers and - * protocols. If you do not call this function, then you can select - * exactly which formats you want to support. + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. * - * @see av_register_input_format() - * @see av_register_output_format() - * @see av_register_protocol() + * @param *ctx is set to the created format context, or to NULL in + * case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure */ -void av_register_all(void); - -/** codec tag <-> codec id */ -enum CodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); -unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum CodecID id); +int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, + const char *format_name, const char *filename); -/* media file input */ +/** + * @addtogroup lavf_decoding + * @{ + */ /** - * Finds AVInputFormat based on the short name of the input format. + * Find AVInputFormat based on the short name of the input format. */ AVInputFormat *av_find_input_format(const char *short_name); /** - * Guess file format. + * Guess the file format. * * @param is_opened Whether the file is already opened; determines whether * demuxers with or without AVFMT_NOFILE are probed. @@ -756,44 +1364,71 @@ AVInputFormat *av_find_input_format(const char *short_name); AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); /** - * Allocates all the structures needed to read an input stream. - * This does not open the needed codecs for decoding the stream[s]. + * Guess the file format. + * + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_max A probe score larger that this is required to accept a + * detection, the variable is set to the actual detection + * score afterwards. + * If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended + * to retry with a larger probe buffer. */ -int av_open_input_stream(AVFormatContext **ic_ptr, - ByteIOContext *pb, const char *filename, - AVInputFormat *fmt, AVFormatParameters *ap); +AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max); /** - * Open a media file as input. The codecs are not opened. Only the file - * header (if present) is read. + * Guess the file format. * - * @param ic_ptr The opened media file handle is put here. - * @param filename filename to open - * @param fmt If non-NULL, force the file format to use. - * @param buf_size optional buffer size (zero if default is OK) - * @param ap Additional parameters needed when opening the file - * (NULL if default). - * @return 0 if OK, AVERROR_xxx otherwise + * @param is_opened Whether the file is already opened; determines whether + * demuxers with or without AVFMT_NOFILE are probed. + * @param score_ret The score of the best detection. */ -int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, - AVInputFormat *fmt, - int buf_size, - AVFormatParameters *ap); +AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret); -#if LIBAVFORMAT_VERSION_MAJOR < 53 /** - * @deprecated Use avformat_alloc_context() instead. + * Probe a bytestream to determine the input format. Each time a probe returns + * with a score that is too low, the probe buffer size is increased and another + * attempt is made. When the maximum probe size is reached, the input format + * with the highest score is returned. + * + * @param pb the bytestream to probe + * @param fmt the input format is put here + * @param filename the filename of the stream + * @param logctx the log context + * @param offset the offset within the bytestream to probe from + * @param max_probe_size the maximum probe buffer size (zero for default) + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise */ -attribute_deprecated AVFormatContext *av_alloc_format_context(void); -#endif +int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, + const char *filename, void *logctx, + unsigned int offset, unsigned int max_probe_size); /** - * Allocate an AVFormatContext. - * Can be freed with av_free() but do not forget to free everything you - * explicitly allocated as well! + * Open an input stream and read the header. The codecs are not opened. + * The stream must be closed with av_close_input_file(). + * + * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). + * May be a pointer to NULL, in which case an AVFormatContext is allocated by this + * function and written into ps. + * Note that a user-supplied AVFormatContext will be freed on failure. + * @param filename Name of the stream to open. + * @param fmt If non-NULL, this parameter forces a specific input format. + * Otherwise the format is autodetected. + * @param options A dictionary filled with AVFormatContext and demuxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. + * + * @return 0 on success, a negative AVERROR on failure. + * + * @note If you want to use custom IO, preallocate the format context and set its pb field. */ -AVFormatContext *avformat_alloc_context(void); +int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options); +attribute_deprecated +int av_demuxer_open(AVFormatContext *ic); + +#if FF_API_FORMAT_PARAMETERS /** * Read packets of a media file to get stream information. This * is useful for file formats with no headers such as MPEG. This @@ -806,10 +1441,84 @@ AVFormatContext *avformat_alloc_context(void); * @return >=0 if OK, AVERROR_xxx on error * @todo Let the user decide somehow what information is needed so that * we do not waste time getting stuff the user does not need. + * + * @deprecated use avformat_find_stream_info. */ +attribute_deprecated int av_find_stream_info(AVFormatContext *ic); +#endif + +/** + * Read packets of a media file to get stream information. This + * is useful for file formats with no headers such as MPEG. This + * function also computes the real framerate in case of MPEG-2 repeat + * frame mode. + * The logical file position is not changed by this function; + * examined packets may be buffered for later processing. + * + * @param ic media file handle + * @param options If non-NULL, an ic.nb_streams long array of pointers to + * dictionaries, where i-th member contains options for + * codec corresponding to i-th stream. + * On return each dictionary will be filled with options that were not found. + * @return >=0 if OK, AVERROR_xxx on error + * + * @note this function isn't guaranteed to open all the codecs, so + * options being non-empty at return is a perfectly normal behavior. + * + * @todo Let the user decide somehow what information is needed so that + * we do not waste time getting stuff the user does not need. + */ +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); + +/** + * Find the programs which belong to a given stream. + * + * @param ic media file handle + * @param last the last found program, the search will start after this + * program, or from the beginning if it is NULL + * @param s stream index + * @return the next program which belongs to s, NULL if no program is found or + * the last program is not among the programs of ic. + */ +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s); /** + * Find the "best" stream in the file. + * The best stream is determined according to various heuristics as the most + * likely to be what the user expects. + * If the decoder parameter is non-NULL, av_find_best_stream will find the + * default decoder for the stream's codec; streams for which no decoder can + * be found are ignored. + * + * @param ic media file handle + * @param type stream type: video, audio, subtitles, etc. + * @param wanted_stream_nb user-requested stream number, + * or -1 for automatic selection + * @param related_stream try to find a stream related (eg. in the same + * program) to this one, or -1 if none + * @param decoder_ret if non-NULL, returns the decoder for the + * selected stream + * @param flags flags; none are currently defined + * @return the non-negative stream number in case of success, + * AVERROR_STREAM_NOT_FOUND if no stream with the requested type + * could be found, + * AVERROR_DECODER_NOT_FOUND if streams were found but no decoder + * @note If av_find_best_stream returns successfully and decoder_ret is not + * NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. + */ +int av_find_best_stream(AVFormatContext *ic, + enum AVMediaType type, + int wanted_stream_nb, + int related_stream, + AVCodec **decoder_ret, + int flags); + +#if FF_API_READ_PACKET +/** + * @deprecated use AVFMT_FLAG_NOFILLIN | AVFMT_FLAG_NOPARSE to read raw + * unprocessed packets + * * Read a transport packet from a media file. * * This function is obsolete and should never be used. @@ -819,10 +1528,17 @@ int av_find_stream_info(AVFormatContext *ic); * @param pkt is filled * @return 0 if OK, AVERROR_xxx on error */ +attribute_deprecated int av_read_packet(AVFormatContext *s, AVPacket *pkt); +#endif /** * Return the next frame of a stream. + * This function returns what is stored in the file, and does not validate + * that what is there are valid frames for the decoder. It will split what is + * stored in the file into frames and return one for each call. It will not + * omit invalid data between valid frames so as to give the decoder the maximum + * information possible for decoding. * * The returned packet is valid * until the next av_read_frame() or until av_close_input_file() and @@ -876,9 +1592,9 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, * @param ts target timestamp * @param max_ts largest acceptable timestamp * @param flags flags - * @returns >=0 on success, error code otherwise + * @return >=0 on success, error code otherwise * - * @NOTE This is part of the new seek API which is still under construction. + * @note This is part of the new seek API which is still under construction. * Thus do not use this yet. It may change at any time, do not expect * ABI compatibility yet! */ @@ -897,19 +1613,27 @@ int av_read_play(AVFormatContext *s); */ int av_read_pause(AVFormatContext *s); +#if FF_API_CLOSE_INPUT_FILE /** - * Free a AVFormatContext allocated by av_open_input_stream. - * @param s context to free - */ -void av_close_input_stream(AVFormatContext *s); - -/** + * @deprecated use avformat_close_input() * Close a media file (but not its codecs). * * @param s media file handle */ +attribute_deprecated void av_close_input_file(AVFormatContext *s); +#endif + +/** + * Close an opened input AVFormatContext. Free it and all its contents + * and set *s to NULL. + */ +void avformat_close_input(AVFormatContext **s); +/** + * @} + */ +#if FF_API_NEW_STREAM /** * Add a new stream to a media file. * @@ -920,117 +1644,44 @@ void av_close_input_file(AVFormatContext *s); * @param s media file handle * @param id file-format-dependent stream ID */ +attribute_deprecated AVStream *av_new_stream(AVFormatContext *s, int id); -AVProgram *av_new_program(AVFormatContext *s, int id); - -/** - * Add a new chapter. - * This function is NOT part of the public API - * and should ONLY be used by demuxers. - * - * @param s media file handle - * @param id unique ID for this chapter - * @param start chapter start time in time_base units - * @param end chapter end time in time_base units - * @param title chapter title - * - * @return AVChapter or NULL on error - */ -AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, - int64_t start, int64_t end, const char *title); +#endif +#if FF_API_SET_PTS_INFO /** - * Set the pts for a given stream. - * - * @param s stream - * @param pts_wrap_bits number of bits effectively used by the pts - * (used for wrap control, 33 is the value for MPEG) - * @param pts_num numerator to convert to seconds (MPEG: 1) - * @param pts_den denominator to convert to seconds (MPEG: 90000) + * @deprecated this function is not supposed to be called outside of lavf */ +attribute_deprecated void av_set_pts_info(AVStream *s, int pts_wrap_bits, - int pts_num, int pts_den); + unsigned int pts_num, unsigned int pts_den); +#endif #define AVSEEK_FLAG_BACKWARD 1 ///< seek backward #define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes #define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes - -int av_find_default_stream_index(AVFormatContext *s); - -/** - * Gets the index for a specific timestamp. - * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond - * to the timestamp which is <= the requested one, if backward - * is 0, then it will be >= - * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise - * @return < 0 if no such timestamp could be found - */ -int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); +#define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number /** - * Ensures the index uses less memory than the maximum specified in - * AVFormatContext.max_index_size by discarding entries if it grows - * too large. - * This function is not part of the public API and should only be called - * by demuxers. + * @addtogroup lavf_encoding + * @{ */ -void ff_reduce_index(AVFormatContext *s, int stream_index); - /** - * Add an index entry into a sorted list. Update the entry if the list - * already contains it. + * Allocate the stream private data and write the stream header to + * an output media file. * - * @param timestamp timestamp in the time base of the given stream - */ -int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, - int size, int distance, int flags); - -/** - * Does a binary search using av_index_search_timestamp() and - * AVCodec.read_timestamp(). - * This is not supposed to be called directly by a user application, - * but by demuxers. - * @param target_ts target timestamp in the time base of the given stream - * @param stream_index stream number - */ -int av_seek_frame_binary(AVFormatContext *s, int stream_index, - int64_t target_ts, int flags); - -/** - * Updates cur_dts of all streams based on the given timestamp and AVStream. + * @param s Media file handle, must be allocated with avformat_alloc_context(). + * Its oformat field must be set to the desired output format; + * Its pb field must be set to an already openened AVIOContext. + * @param options An AVDictionary filled with AVFormatContext and muxer-private options. + * On return this parameter will be destroyed and replaced with a dict containing + * options that were not found. May be NULL. * - * Stream ref_st unchanged, others set cur_dts in their native time base. - * Only needed for timestamp wrapping or if (dts not set and pts!=dts). - * @param timestamp new dts expressed in time_base of param ref_st - * @param ref_st reference stream giving time_base of param timestamp - */ -void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp); - -/** - * Does a binary search using read_timestamp(). - * This is not supposed to be called directly by a user application, - * but by demuxers. - * @param target_ts target timestamp in the time base of the given stream - * @param stream_index stream number - */ -int64_t av_gen_search(AVFormatContext *s, int stream_index, - int64_t target_ts, int64_t pos_min, - int64_t pos_max, int64_t pos_limit, - int64_t ts_min, int64_t ts_max, - int flags, int64_t *ts_ret, - int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); - -/** media file output */ -int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap); - -/** - * Allocate the stream private data and write the stream header to an - * output media file. + * @return 0 on success, negative AVERROR on failure. * - * @param s media file handle - * @return 0 if OK, AVERROR_xxx on error + * @see av_opt_find, av_dict_set, avio_open, av_oformat_next. */ -int av_write_header(AVFormatContext *s); +int avformat_write_header(AVFormatContext *s, AVDictionary **options); /** * Write a packet to an output media file. @@ -1041,13 +1692,17 @@ int av_write_header(AVFormatContext *s); * * @param s media file handle * @param pkt The packet, which contains the stream_index, buf/buf_size, - dts/pts, ... - * @return < 0 on error, = 0 if OK, 1 if end of stream wanted + * dts/pts, ... + * This can be NULL (at any time, not just at the end), in + * order to immediately flush data buffered within the muxer, + * for muxers that buffer up data internally before writing it + * to the output. + * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush */ int av_write_frame(AVFormatContext *s, AVPacket *pkt); /** - * Writes a packet to an output media file ensuring correct interleaving. + * Write a packet to an output media file ensuring correct interleaving. * * The packet must contain one audio or video frame. * If the packets are already correctly interleaved, the application should @@ -1057,109 +1712,224 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt); * demuxer level. * * @param s media file handle - * @param pkt The packet, which contains the stream_index, buf/buf_size, - dts/pts, ... - * @return < 0 on error, = 0 if OK, 1 if end of stream wanted + * @param pkt The packet containing the data to be written. Libavformat takes + * ownership of the data and will free it when it sees fit using the packet's + * This can be NULL (at any time, not just at the end), to flush the + * interleaving queues. + * @ref AVPacket.destruct "destruct" field. The caller must not access the data + * after this function returns, as it may already be freed. + * Packet's @ref AVPacket.stream_index "stream_index" field must be set to the + * index of the corresponding stream in @ref AVFormatContext.streams + * "s.streams". + * It is very strongly recommended that timing information (@ref AVPacket.pts + * "pts", @ref AVPacket.dts "dts" @ref AVPacket.duration "duration") is set to + * correct values. + * + * @return 0 on success, a negative AVERROR on error. */ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); +#if FF_API_INTERLEAVE_PACKET /** - * Interleave a packet per dts in an output media file. - * - * Packets with pkt->destruct == av_destruct_packet will be freed inside this - * function, so they cannot be used after it. Note that calling av_free_packet() - * on them is still safe. - * - * @param s media file handle - * @param out the interleaved packet will be output here - * @param in the input packet - * @param flush 1 if no further packets are available as input and all - * remaining packets should be output - * @return 1 if a packet was output, 0 if no packet could be output, - * < 0 if an error occurred + * @deprecated this function was never meant to be called by the user + * programs. */ +attribute_deprecated int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush); +#endif /** - * @brief Write the stream trailer to an output media file and - * free the file private data. + * Write the stream trailer to an output media file and free the + * file private data. * - * May only be called after a successful call to av_write_header. + * May only be called after a successful call to avformat_write_header. * * @param s media file handle * @return 0 if OK, AVERROR_xxx on error */ int av_write_trailer(AVFormatContext *s); -void dump_format(AVFormatContext *ic, - int index, - const char *url, - int is_output); +/** + * Return the output format in the list of registered output formats + * which best matches the provided parameters, or return NULL if + * there is no match. + * + * @param short_name if non-NULL checks if short_name matches with the + * names of the registered formats + * @param filename if non-NULL checks if filename terminates with the + * extensions of the registered formats + * @param mime_type if non-NULL checks if mime_type matches with the + * MIME type of the registered formats + */ +AVOutputFormat *av_guess_format(const char *short_name, + const char *filename, + const char *mime_type); -#if LIBAVFORMAT_VERSION_MAJOR < 53 /** - * Parses width and height out of string str. - * @deprecated Use av_parse_video_frame_size instead. + * Guess the codec ID based upon muxer and filename. */ -attribute_deprecated int parse_image_size(int *width_ptr, int *height_ptr, - const char *str); +enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type); /** - * Converts framerate from a string to a fraction. - * @deprecated Use av_parse_video_frame_rate instead. + * Get timing information for the data currently output. + * The exact meaning of "currently output" depends on the format. + * It is mostly relevant for devices that have an internal buffer and/or + * work in real time. + * @param s media file handle + * @param stream stream in the media file + * @param dts[out] DTS of the last packet output for the stream, in stream + * time_base units + * @param wall[out] absolute time when that packet whas output, + * in microsecond + * @return 0 if OK, AVERROR(ENOSYS) if the format does not support it + * Note: some formats or devices may not allow to measure dts and wall + * atomically. */ -attribute_deprecated int parse_frame_rate(int *frame_rate, int *frame_rate_base, - const char *arg); -#endif +int av_get_output_timestamp(struct AVFormatContext *s, int stream, + int64_t *dts, int64_t *wall); + /** - * Parses datestr and returns a corresponding number of microseconds. - * @param datestr String representing a date or a duration. - * - If a date the syntax is: - * @code - * [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]} - * @endcode - * Time is local time unless Z is appended, in which case it is - * interpreted as UTC. - * If the year-month-day part is not specified it takes the current - * year-month-day. - * Returns the number of microseconds since 1st of January, 1970 up to - * the time of the parsed date or INT64_MIN if datestr cannot be - * successfully parsed. - * - If a duration the syntax is: - * @code - * [-]HH[:MM[:SS[.m...]]] - * [-]S+[.m...] - * @endcode - * Returns the number of microseconds contained in a time interval - * with the specified duration or INT64_MIN if datestr cannot be - * successfully parsed. - * @param duration Flag which tells how to interpret datestr, if - * not zero datestr is interpreted as a duration, otherwise as a - * date. + * @} + */ + + +/** + * @defgroup lavf_misc Utility functions + * @ingroup libavf + * @{ + * + * Miscellaneous utility functions related to both muxing and demuxing + * (or neither). + */ + +/** + * Send a nice hexadecimal dump of a buffer to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump(FILE *f, const uint8_t *buf, int size); + +/** + * Send a nice hexadecimal dump of a buffer to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param buf buffer + * @param size buffer size + * + * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2 + */ +void av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size); + +/** + * Send a nice dump of a packet to the specified file stream. + * + * @param f The file stream pointer where the dump should be sent to. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st); + + +/** + * Send a nice dump of a packet to the log. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message, lower values signifying + * higher importance. + * @param pkt packet to dump + * @param dump_payload True if the payload must be displayed, too. + * @param st AVStream that the packet belongs to + */ +void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, + AVStream *st); + +/** + * Get the AVCodecID for the given codec tag tag. + * If no codec id is found returns AV_CODEC_ID_NONE. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + */ +enum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag); + +/** + * Get the codec tag for the given codec id id. + * If no codec tag is found returns 0. + * + * @param tags list of supported codec_id-codec_tag pairs, as stored + * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag + */ +unsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id); + +int av_find_default_stream_index(AVFormatContext *s); + +/** + * Get the index for a specific timestamp. + * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond + * to the timestamp which is <= the requested one, if backward + * is 0, then it will be >= + * if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise + * @return < 0 if no such timestamp could be found */ -int64_t parse_date(const char *datestr, int duration); +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); -/** Gets the current time in microseconds. */ -int64_t av_gettime(void); +/** + * Add an index entry into a sorted list. Update the entry if the list + * already contains it. + * + * @param timestamp timestamp in the time base of the given stream + */ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, + int size, int distance, int flags); -/* ffm-specific for ffserver */ -#define FFM_PACKET_SIZE 4096 -int64_t ffm_read_write_index(int fd); -int ffm_write_write_index(int fd, int64_t pos); -void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size); /** - * Attempts to find a specific tag in a URL. + * Split a URL string into components. + * + * The pointers to buffers for storing individual components may be null, + * in order to ignore that component. Buffers for components not found are + * set to empty strings. If the port is not found, it is set to a negative + * value. * - * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. - * Return 1 if found. + * @param proto the buffer for the protocol + * @param proto_size the size of the proto buffer + * @param authorization the buffer for the authorization + * @param authorization_size the size of the authorization buffer + * @param hostname the buffer for the host name + * @param hostname_size the size of the hostname buffer + * @param port_ptr a pointer to store the port number in + * @param path the buffer for the path + * @param path_size the size of the path buffer + * @param url the URL to split */ -int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); +void av_url_split(char *proto, int proto_size, + char *authorization, int authorization_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + + +void av_dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); /** - * Returns in 'buf' the path with '%d' replaced by a number. + * Return in 'buf' the path with '%d' replaced by a number. * * Also handles the '%0nd' format where 'n' is the total number * of digits and '%%'. @@ -1190,49 +1960,96 @@ int av_filename_number_test(const char *filename); * all the contexts in the array (an AVCodecContext per RTP stream) * must contain only one AVStream. * @param n_files number of AVCodecContexts contained in ac - * @param buff buffer where the SDP will be stored (must be allocated by - * the caller) + * @param buf buffer where the SDP will be stored (must be allocated by + * the caller) * @param size the size of the buffer * @return 0 if OK, AVERROR_xxx on error */ -int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size); +int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size); -#ifdef HAVE_AV_CONFIG_H +/** + * Return a positive value if the given filename has one of the given + * extensions, 0 otherwise. + * + * @param extensions a comma-separated list of filename extensions + */ +int av_match_ext(const char *filename, const char *extensions); -void ff_dynarray_add(intptr_t **tab_ptr, int *nb_ptr, intptr_t elem); +/** + * Test if the given container can store a codec. + * + * @param std_compliance standards compliance level, one of FF_COMPLIANCE_* + * + * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot. + * A negative number if this information is not available. + */ +int avformat_query_codec(AVOutputFormat *ofmt, enum AVCodecID codec_id, int std_compliance); -#ifdef __GNUC__ -#define dynarray_add(tab, nb_ptr, elem)\ -do {\ - __typeof__(tab) _tab = (tab);\ - __typeof__(elem) _elem = (elem);\ - (void)sizeof(**_tab == _elem); /* check that types are compatible */\ - ff_dynarray_add((intptr_t **)_tab, nb_ptr, (intptr_t)_elem);\ -} while(0) -#else -#define dynarray_add(tab, nb_ptr, elem)\ -do {\ - ff_dynarray_add((intptr_t **)(tab), nb_ptr, (intptr_t)(elem));\ -} while(0) -#endif +/** + * @defgroup riff_fourcc RIFF FourCCs + * @{ + * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are + * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the + * following code: + * @code + * uint32_t tag = MKTAG('H', '2', '6', '4'); + * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 }; + * enum AVCodecID id = av_codec_get_id(table, tag); + * @endcode + */ +/** + * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_video_tags(void); +/** + * @return the table mapping RIFF FourCCs for audio to AVCodecID. + */ +const struct AVCodecTag *avformat_get_riff_audio_tags(void); + +/** + * @} + */ -time_t mktimegm(struct tm *tm); -struct tm *brktimegm(time_t secs, struct tm *tm); -const char *small_strptime(const char *p, const char *fmt, - struct tm *dt); +/** + * Guess the sample aspect ratio of a frame, based on both the stream and the + * frame aspect ratio. + * + * Since the frame aspect ratio is set by the codec but the stream aspect ratio + * is set by the demuxer, these two may not be equal. This function tries to + * return the value that you should use if you would like to display the frame. + * + * Basic logic is to use the stream aspect ratio if it is set to something sane + * otherwise use the frame aspect ratio. This way a container setting, which is + * usually easy to modify can override the coded value in the frames. + * + * @param format the format context which the stream is part of + * @param stream the stream which the frame is part of + * @param frame the frame with the aspect ratio to be determined + * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea + */ +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame); -struct in_addr; -int resolve_host(struct in_addr *sin_addr, const char *hostname); +/** + * Check if the stream st contained in s is matched by the stream specifier + * spec. + * + * See the "stream specifiers" chapter in the documentation for the syntax + * of spec. + * + * @return >0 if st is matched by spec; + * 0 if st is not matched by spec; + * AVERROR code if spec is invalid + * + * @note A stream specifier can match several streams in the format. + */ +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec); -void url_split(char *proto, int proto_size, - char *authorization, int authorization_size, - char *hostname, int hostname_size, - int *port_ptr, - char *path, int path_size, - const char *url); +void avformat_queue_attached_pictures(AVFormatContext *s); -int match_ext(const char *filename, const char *extensions); -#endif /* HAVE_AV_CONFIG_H */ +/** + * @} + */ #endif /* AVFORMAT_AVFORMAT_H */ diff --git a/extra_lib/include/libavformat/avio.h b/extra_lib/include/libavformat/avio.h index 06749fb..17b341d 100644 --- a/extra_lib/include/libavformat/avio.h +++ b/extra_lib/include/libavformat/avio.h @@ -21,202 +21,162 @@ #define AVFORMAT_AVIO_H /** - * @file libavformat/avio.h - * unbuffered I/O operations - * - * @warning This file has to be considered an internal but installed - * header, so it should not be directly included in your projects. + * @file + * @ingroup lavf_io + * Buffered I/O operations */ -#if !defined(WIN32) && !defined(_WIN32_WCE) #include -#endif #include "libavutil/common.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" -/* unbuffered I/O */ - -/** - * URL Context. - * New fields can be added to the end with minor version bumps. - * Removal, reordering and changes to existing fields require a major - * version bump. - * sizeof(URLContext) must not be used outside libav*. - */ -typedef struct URLContext { -#if LIBAVFORMAT_VERSION_MAJOR >= 53 - const AVClass *av_class; ///< information for av_log(). Set by url_open(). -#endif - struct URLProtocol *prot; - int flags; - int is_streamed; /**< true if streamed (no seek possible), default = false */ - int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */ - void *priv_data; - char *filename; /**< specified filename */ -} URLContext; - -typedef struct URLPollEntry { - URLContext *handle; - int events; - int revents; -} URLPollEntry; - -#define URL_RDONLY 0 -#define URL_WRONLY 1 -#define URL_RDWR 2 - -typedef int URLInterruptCB(void); - -int url_open_protocol (URLContext **puc, struct URLProtocol *up, - const char *filename, int flags); -int url_open(URLContext **h, const char *filename, int flags); -int url_read(URLContext *h, unsigned char *buf, int size); -int url_write(URLContext *h, unsigned char *buf, int size); -int64_t url_seek(URLContext *h, int64_t pos, int whence); -int url_close(URLContext *h); -int url_exist(const char *filename); -int64_t url_filesize(URLContext *h); - -/** - * Return the file descriptor associated with this URL. For RTP, this - * will return only the RTP file descriptor, not the RTCP file descriptor. - * To get both, use rtp_get_file_handles(). - * - * @return the file descriptor associated with this URL, or <0 on error. - */ -int url_get_file_handle(URLContext *h); - -/** - * Return the maximum packet size associated to packetized file - * handle. If the file is not packetized (stream like HTTP or file on - * disk), then 0 is returned. - * - * @param h file handle - * @return maximum packet size in bytes - */ -int url_get_max_packet_size(URLContext *h); -void url_get_filename(URLContext *h, char *buf, int buf_size); - -/** - * The callback is called in blocking functions to test regulary if - * asynchronous interruption is needed. AVERROR(EINTR) is returned - * in this case by the interrupted function. 'NULL' means no interrupt - * callback is given. - */ -void url_set_interrupt_cb(URLInterruptCB *interrupt_cb); - -/* not implemented */ -int url_poll(URLPollEntry *poll_table, int n, int timeout); - -/** - * Pause and resume playing - only meaningful if using a network streaming - * protocol (e.g. MMS). - * @param pause 1 for pause, 0 for resume - */ -int av_url_read_pause(URLContext *h, int pause); - -/** - * Seek to a given timestamp relative to some component stream. - * Only meaningful if using a network streaming protocol (e.g. MMS.). - * @param stream_index The stream index that the timestamp is relative to. - * If stream_index is (-1) the timestamp should be in AV_TIME_BASE - * units from the beginning of the presentation. - * If a stream_index >= 0 is used and the protocol does not support - * seeking based on component streams, the call will fail with ENOTSUP. - * @param timestamp timestamp in AVStream.time_base units - * or if there is no stream specified then in AV_TIME_BASE units. - * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE - * and AVSEEK_FLAG_ANY. The protocol may silently ignore - * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will - * fail with ENOTSUP if used and not supported. - * @return >= 0 on success - * @see AVInputFormat::read_seek - */ -int64_t av_url_read_seek(URLContext *h, int stream_index, - int64_t timestamp, int flags); - -/** - * Passing this as the "whence" parameter to a seek function causes it to - * return the filesize without seeking anywhere. Supporting this is optional. - * If it is not supported then the seek function will return <0. - */ -#define AVSEEK_SIZE 0x10000 - -typedef struct URLProtocol { - const char *name; - int (*url_open)(URLContext *h, const char *filename, int flags); - int (*url_read)(URLContext *h, unsigned char *buf, int size); - int (*url_write)(URLContext *h, unsigned char *buf, int size); - int64_t (*url_seek)(URLContext *h, int64_t pos, int whence); - int (*url_close)(URLContext *h); - struct URLProtocol *next; - int (*url_read_pause)(URLContext *h, int pause); - int64_t (*url_read_seek)(URLContext *h, int stream_index, - int64_t timestamp, int flags); - int (*url_get_file_handle)(URLContext *h); -} URLProtocol; +#include "libavformat/version.h" -#if LIBAVFORMAT_VERSION_MAJOR < 53 -extern URLProtocol *first_protocol; -#endif -extern URLInterruptCB *url_interrupt_cb; - -/** - * If protocol is NULL, returns the first registered protocol, - * if protocol is non-NULL, returns the next registered protocol after protocol, - * or NULL if protocol is the last one. - */ -URLProtocol *av_protocol_next(URLProtocol *p); +#define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */ -#if LIBAVFORMAT_VERSION_MAJOR < 53 /** - * @deprecated Use av_register_protocol() instead. + * Callback for checking whether to abort blocking functions. + * AVERROR_EXIT is returned in this case by the interrupted + * function. During blocking operations, callback is called with + * opaque as parameter. If the callback returns 1, the + * blocking operation will be aborted. + * + * No members can be added to this struct without a major bump, if + * new elements have been added after this struct in AVFormatContext + * or AVIOContext. */ -attribute_deprecated int register_protocol(URLProtocol *protocol); -#endif - -int av_register_protocol(URLProtocol *protocol); +typedef struct AVIOInterruptCB { + int (*callback)(void*); + void *opaque; +} AVIOInterruptCB; /** * Bytestream IO Context. * New fields can be added to the end with minor version bumps. * Removal, reordering and changes to existing fields require a major * version bump. - * sizeof(ByteIOContext) must not be used outside libav*. + * sizeof(AVIOContext) must not be used outside libav*. + * + * @note None of the function pointers in AVIOContext should be called + * directly, they should only be set by the client application + * when implementing custom I/O. Normally these are set to the + * function pointers specified in avio_alloc_context() */ -typedef struct { - unsigned char *buffer; - int buffer_size; - unsigned char *buf_ptr, *buf_end; - void *opaque; +typedef struct AVIOContext { + /** + * A class for private options. + * + * If this AVIOContext is created by avio_open2(), av_class is set and + * passes the options down to protocols. + * + * If this AVIOContext is manually allocated, then av_class may be set by + * the caller. + * + * warning -- this field can be NULL, be sure to not pass this AVIOContext + * to any av_opt_* functions in that case. + */ + const AVClass *av_class; + unsigned char *buffer; /**< Start of the buffer. */ + int buffer_size; /**< Maximum buffer size */ + unsigned char *buf_ptr; /**< Current position in the buffer */ + unsigned char *buf_end; /**< End of the data, may be less than + buffer+buffer_size if the read function returned + less data than requested, e.g. for streams where + no more data has been received yet. */ + void *opaque; /**< A private pointer, passed to the read/write/seek/... + functions. */ int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); int64_t (*seek)(void *opaque, int64_t offset, int whence); - int64_t pos; /**< position in the file of the current buffer */ - int must_flush; /**< true if the next seek should flush */ - int eof_reached; /**< true if eof reached */ - int write_flag; /**< true if open for writing */ - int is_streamed; + int64_t pos; /**< position in the file of the current buffer */ + int must_flush; /**< true if the next seek should flush */ + int eof_reached; /**< true if eof reached */ + int write_flag; /**< true if open for writing */ int max_packet_size; unsigned long checksum; unsigned char *checksum_ptr; unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size); - int error; ///< contains the error code or 0 if no error happened + int error; /**< contains the error code or 0 if no error happened */ + /** + * Pause or resume playback for network streaming protocols - e.g. MMS. + */ int (*read_pause)(void *opaque, int pause); + /** + * Seek to a given timestamp in stream with the specified stream_index. + * Needed for some network streaming protocols which don't support seeking + * to byte position. + */ int64_t (*read_seek)(void *opaque, int stream_index, int64_t timestamp, int flags); -} ByteIOContext; + /** + * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable. + */ + int seekable; + + /** + * max filesize, used to limit allocations + * This field is internal to libavformat and access from outside is not allowed. + */ + int64_t maxsize; + + /** + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ + int direct; + + /** + * Bytes read statistic + * This field is internal to libavformat and access from outside is not allowed. + */ + int64_t bytes_read; + + /** + * seek statistic + * This field is internal to libavformat and access from outside is not allowed. + */ + int seek_count; +} AVIOContext; -int init_put_byte(ByteIOContext *s, - unsigned char *buffer, - int buffer_size, - int write_flag, - void *opaque, - int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), - int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), - int64_t (*seek)(void *opaque, int64_t offset, int whence)); -ByteIOContext *av_alloc_put_byte( +/* unbuffered I/O */ + +/** + * Return AVIO_FLAG_* access flags corresponding to the access permissions + * of the resource in url, or a negative value corresponding to an + * AVERROR code in case of failure. The returned access flags are + * masked by the value in flags. + * + * @note This function is intrinsically unsafe, in the sense that the + * checked resource may change its existence or permission status from + * one call to another. Thus you should not trust the returned value, + * unless you are sure that no other processes are accessing the + * checked resource. + */ +int avio_check(const char *url, int flags); + +/** + * Allocate and initialize an AVIOContext for buffered I/O. It must be later + * freed with av_free(). + * + * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. + * @param buffer_size The buffer size is very important for performance. + * For protocols with fixed blocksize it should be set to this blocksize. + * For others a typical size is a cache page, e.g. 4kb. + * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise. + * @param opaque An opaque pointer to user-specific data. + * @param read_packet A function for refilling the buffer, may be NULL. + * @param write_packet A function for writing the buffer contents, may be NULL. + * The function may not change the input buffers content. + * @param seek A function for seeking to specified byte position, may be NULL. + * + * @return Allocated AVIOContext or NULL on failure. + */ +AVIOContext *avio_alloc_context( unsigned char *buffer, int buffer_size, int write_flag, @@ -225,182 +185,291 @@ ByteIOContext *av_alloc_put_byte( int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t (*seek)(void *opaque, int64_t offset, int whence)); -void put_byte(ByteIOContext *s, int b); -void put_buffer(ByteIOContext *s, const unsigned char *buf, int size); -void put_le64(ByteIOContext *s, uint64_t val); -void put_be64(ByteIOContext *s, uint64_t val); -void put_le32(ByteIOContext *s, unsigned int val); -void put_be32(ByteIOContext *s, unsigned int val); -void put_le24(ByteIOContext *s, unsigned int val); -void put_be24(ByteIOContext *s, unsigned int val); -void put_le16(ByteIOContext *s, unsigned int val); -void put_be16(ByteIOContext *s, unsigned int val); -void put_tag(ByteIOContext *s, const char *tag); +void avio_w8(AVIOContext *s, int b); +void avio_write(AVIOContext *s, const unsigned char *buf, int size); +void avio_wl64(AVIOContext *s, uint64_t val); +void avio_wb64(AVIOContext *s, uint64_t val); +void avio_wl32(AVIOContext *s, unsigned int val); +void avio_wb32(AVIOContext *s, unsigned int val); +void avio_wl24(AVIOContext *s, unsigned int val); +void avio_wb24(AVIOContext *s, unsigned int val); +void avio_wl16(AVIOContext *s, unsigned int val); +void avio_wb16(AVIOContext *s, unsigned int val); + +/** + * Write a NULL-terminated string. + * @return number of bytes written. + */ +int avio_put_str(AVIOContext *s, const char *str); -void put_strz(ByteIOContext *s, const char *buf); +/** + * Convert an UTF-8 string to UTF-16LE and write it. + * @return number of bytes written. + */ +int avio_put_str16le(AVIOContext *s, const char *str); /** - * fseek() equivalent for ByteIOContext. + * Passing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Oring this flag as into the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonble + * means that can be extreemly slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + +/** + * fseek() equivalent for AVIOContext. * @return new position or AVERROR. */ -int64_t url_fseek(ByteIOContext *s, int64_t offset, int whence); +int64_t avio_seek(AVIOContext *s, int64_t offset, int whence); /** - * Skip given number of bytes forward. - * @param offset number of bytes + * Skip given number of bytes forward + * @return new position or AVERROR. */ -void url_fskip(ByteIOContext *s, int64_t offset); +int64_t avio_skip(AVIOContext *s, int64_t offset); /** - * ftell() equivalent for ByteIOContext. + * ftell() equivalent for AVIOContext. * @return position or AVERROR. */ -int64_t url_ftell(ByteIOContext *s); +static av_always_inline int64_t avio_tell(AVIOContext *s) +{ + return avio_seek(s, 0, SEEK_CUR); +} /** - * Gets the filesize. + * Get the filesize. * @return filesize or AVERROR */ -int64_t url_fsize(ByteIOContext *s); +int64_t avio_size(AVIOContext *s); /** - * feof() equivalent for ByteIOContext. + * feof() equivalent for AVIOContext. * @return non zero if and only if end of file */ -int url_feof(ByteIOContext *s); - -int url_ferror(ByteIOContext *s); - -int av_url_read_fpause(ByteIOContext *h, int pause); -int64_t av_url_read_fseek(ByteIOContext *h, int stream_index, - int64_t timestamp, int flags); - -#define URL_EOF (-1) -/** @note return URL_EOF (-1) if EOF */ -int url_fgetc(ByteIOContext *s); +int url_feof(AVIOContext *s); /** @warning currently size is limited */ -#ifdef __GNUC__ -int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -#else -int url_fprintf(ByteIOContext *s, const char *fmt, ...); -#endif - -/** @note unlike fgets, the EOL character is not returned and a whole - line is parsed. return NULL if first char read was EOF */ -char *url_fgets(ByteIOContext *s, char *buf, int buf_size); - -void put_flush_packet(ByteIOContext *s); - +int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); /** - * Reads size bytes from ByteIOContext into buf. - * @returns number of bytes read or AVERROR + * Force flushing of buffered data to the output s. + * + * Force the buffered data to be immediately written to the output, + * without to wait to fill the internal buffer. */ -int get_buffer(ByteIOContext *s, unsigned char *buf, int size); +void avio_flush(AVIOContext *s); /** - * Reads size bytes from ByteIOContext into buf. - * This reads at most 1 packet. If that is not enough fewer bytes will be - * returned. - * @returns number of bytes read or AVERROR + * Read size bytes from AVIOContext into buf. + * @return number of bytes read or AVERROR */ -int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size); +int avio_read(AVIOContext *s, unsigned char *buf, int size); -/** @note return 0 if EOF, so you cannot use it if EOF handling is - necessary */ -int get_byte(ByteIOContext *s); -unsigned int get_le24(ByteIOContext *s); -unsigned int get_le32(ByteIOContext *s); -uint64_t get_le64(ByteIOContext *s); -unsigned int get_le16(ByteIOContext *s); +/** + * @name Functions for reading from AVIOContext + * @{ + * + * @note return 0 if EOF, so you cannot use it if EOF handling is + * necessary + */ +int avio_r8 (AVIOContext *s); +unsigned int avio_rl16(AVIOContext *s); +unsigned int avio_rl24(AVIOContext *s); +unsigned int avio_rl32(AVIOContext *s); +uint64_t avio_rl64(AVIOContext *s); +unsigned int avio_rb16(AVIOContext *s); +unsigned int avio_rb24(AVIOContext *s); +unsigned int avio_rb32(AVIOContext *s); +uint64_t avio_rb64(AVIOContext *s); +/** + * @} + */ -char *get_strz(ByteIOContext *s, char *buf, int maxlen); -unsigned int get_be16(ByteIOContext *s); -unsigned int get_be24(ByteIOContext *s); -unsigned int get_be32(ByteIOContext *s); -uint64_t get_be64(ByteIOContext *s); +/** + * Read a string from pb into buf. The reading will terminate when either + * a NULL character was encountered, maxlen bytes have been read, or nothing + * more can be read from pb. The result is guaranteed to be NULL-terminated, it + * will be truncated if buf is too small. + * Note that the string is not interpreted or validated in any way, it + * might get truncated in the middle of a sequence for multi-byte encodings. + * + * @return number of bytes read (is always <= maxlen). + * If reading ends on EOF or error, the return value will be one more than + * bytes actually read. + */ +int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen); -uint64_t ff_get_v(ByteIOContext *bc); +/** + * Read a UTF-16 string from pb and convert it to UTF-8. + * The reading will terminate when either a null or invalid character was + * encountered or maxlen bytes have been read. + * @return number of bytes read (is always <= maxlen) + */ +int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen); +int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); -static inline int url_is_streamed(ByteIOContext *s) -{ - return s->is_streamed; -} -/** @note when opened as read/write, the buffers are only used for - writing */ -int url_fdopen(ByteIOContext **s, URLContext *h); +/** + * @name URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_FLAG_READ 1 /**< read-only */ +#define AVIO_FLAG_WRITE 2 /**< write-only */ +#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */ +/** + * @} + */ -/** @warning must be called before any I/O */ -int url_setbufsize(ByteIOContext *s, int buf_size); -/** Reset the buffer for reading or writing. - * @note Will drop any data currently in the buffer without transmitting it. - * @param flags URL_RDONLY to set up the buffer for reading, or URL_WRONLY - * to set up the buffer for writing. */ -int url_resetbuf(ByteIOContext *s, int flags); +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 8 -/** @note when opened as read/write, the buffers are only used for - writing */ -int url_fopen(ByteIOContext **s, const char *filename, int flags); -int url_fclose(ByteIOContext *s); -URLContext *url_fileno(ByteIOContext *s); +/** + * Use direct mode. + * avio_read and avio_write should if possible be satisfied directly + * instead of going through a buffer, and avio_seek will always + * call the underlying seek function directly. + */ +#define AVIO_FLAG_DIRECT 0x8000 /** - * Return the maximum packet size associated to packetized buffered file - * handle. If the file is not packetized (stream like http or file on - * disk), then 0 is returned. + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. * - * @param s buffered file handle - * @return maximum packet size in bytes + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure */ -int url_fget_max_packet_size(ByteIOContext *s); +int avio_open(AVIOContext **s, const char *url, int flags); -int url_open_buf(ByteIOContext **s, uint8_t *buf, int buf_size, int flags); +/** + * Create and initialize a AVIOContext for accessing the + * resource indicated by url. + * @note When the resource indicated by url has been opened in + * read+write mode, the AVIOContext can be used only for writing. + * + * @param s Used to return the pointer to the created AVIOContext. + * In case of failure the pointed to value is set to NULL. + * @param flags flags which control how the resource indicated by url + * is to be opened + * @param int_cb an interrupt callback to be used at the protocols level + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int avio_open2(AVIOContext **s, const char *url, int flags, + const AVIOInterruptCB *int_cb, AVDictionary **options); -/** return the written or read size */ -int url_close_buf(ByteIOContext *s); +/** + * Close the resource accessed by the AVIOContext s and free it. + * This function can only be used if s was opened by avio_open(). + * + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_closep + */ +int avio_close(AVIOContext *s); /** - * Open a write only memory stream. + * Close the resource accessed by the AVIOContext *s, free it + * and set the pointer pointing to it to NULL. + * This function can only be used if s was opened by avio_open(). * - * @param s new IO context - * @return zero if no error. + * The internal buffer is automatically flushed before closing the + * resource. + * + * @return 0 on success, an AVERROR < 0 on error. + * @see avio_close */ -int url_open_dyn_buf(ByteIOContext **s); +int avio_closep(AVIOContext **s); + /** - * Open a write only packetized memory stream with a maximum packet - * size of 'max_packet_size'. The stream is stored in a memory buffer - * with a big endian 4 byte header giving the packet size in bytes. + * Open a write only memory stream. * * @param s new IO context - * @param max_packet_size maximum packet size (must be > 0) * @return zero if no error. */ -int url_open_dyn_packet_buf(ByteIOContext **s, int max_packet_size); +int avio_open_dyn_buf(AVIOContext **s); /** * Return the written size and a pointer to the buffer. The buffer - * must be freed with av_free(). + * must be freed with av_free(). + * Padding of FF_INPUT_BUFFER_PADDING_SIZE is added to the buffer. + * * @param s IO context * @param pbuffer pointer to a byte buffer * @return the length of the byte buffer */ -int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer); - -unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, - unsigned int len); -unsigned long get_checksum(ByteIOContext *s); -void init_checksum(ByteIOContext *s, - unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), - unsigned long checksum); - -/* udp.c */ -int udp_set_remote_url(URLContext *h, const char *uri); -int udp_get_local_port(URLContext *h); -#if (LIBAVFORMAT_VERSION_MAJOR <= 52) -int udp_get_file_handle(URLContext *h); -#endif +int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + +/** + * Iterate through names of available protocols. + * + * @param opaque A private pointer representing current protocol. + * It must be a pointer to NULL on first iteration and will + * be updated by successive calls to avio_enum_protocols. + * @param output If set to 1, iterate over output protocols, + * otherwise over input protocols. + * + * @return A static string containing the name of current protocol or NULL + */ +const char *avio_enum_protocols(void **opaque, int output); + +/** + * Pause and resume playing - only meaningful if using a network streaming + * protocol (e.g. MMS). + * @param pause 1 for pause, 0 for resume + */ +int avio_pause(AVIOContext *h, int pause); + +/** + * Seek to a given timestamp relative to some component stream. + * Only meaningful if using a network streaming protocol (e.g. MMS.). + * @param stream_index The stream index that the timestamp is relative to. + * If stream_index is (-1) the timestamp should be in AV_TIME_BASE + * units from the beginning of the presentation. + * If a stream_index >= 0 is used and the protocol does not support + * seeking based on component streams, the call will fail. + * @param timestamp timestamp in AVStream.time_base units + * or if there is no stream specified then in AV_TIME_BASE units. + * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE + * and AVSEEK_FLAG_ANY. The protocol may silently ignore + * AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will + * fail if used and not supported. + * @return >= 0 on success + * @see AVInputFormat::read_seek + */ +int64_t avio_seek_time(AVIOContext *h, int stream_index, + int64_t timestamp, int flags); #endif /* AVFORMAT_AVIO_H */ diff --git a/extra_lib/include/libavformat/version.h b/extra_lib/include/libavformat/version.h new file mode 100644 index 0000000..749b9e0 --- /dev/null +++ b/extra_lib/include/libavformat/version.h @@ -0,0 +1,89 @@ +/* + * Version macros. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_VERSION_H +#define AVFORMAT_VERSION_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +#include "libavutil/avutil.h" + +#define LIBAVFORMAT_VERSION_MAJOR 54 +#define LIBAVFORMAT_VERSION_MINOR 33 +#define LIBAVFORMAT_VERSION_MICRO 100 + +#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ + LIBAVFORMAT_VERSION_MINOR, \ + LIBAVFORMAT_VERSION_MICRO) +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#ifndef FF_API_OLD_AVIO +#define FF_API_OLD_AVIO (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_PKT_DUMP +#define FF_API_PKT_DUMP (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_ALLOC_OUTPUT_CONTEXT +#define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_FORMAT_PARAMETERS +#define FF_API_FORMAT_PARAMETERS (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_NEW_STREAM +#define FF_API_NEW_STREAM (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_SET_PTS_INFO +#define FF_API_SET_PTS_INFO (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_CLOSE_INPUT_FILE +#define FF_API_CLOSE_INPUT_FILE (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_APPLEHTTP_PROTO +#define FF_API_APPLEHTTP_PROTO (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_READ_PACKET +#define FF_API_READ_PACKET (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_INTERLEAVE_PACKET +#define FF_API_INTERLEAVE_PACKET (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_AV_GETTIME +#define FF_API_AV_GETTIME (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_R_FRAME_RATE +#define FF_API_R_FRAME_RATE (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif + +#endif /* AVFORMAT_VERSION_H */ diff --git a/extra_lib/include/libavutil/adler32.h b/extra_lib/include/libavutil/adler32.h new file mode 100644 index 0000000..e926ef6 --- /dev/null +++ b/extra_lib/include/libavutil/adler32.h @@ -0,0 +1,43 @@ +/* + * copyright (c) 2006 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_ADLER32_H +#define AVUTIL_ADLER32_H + +#include +#include "attributes.h" + +/** + * @ingroup lavu_crypto + * Calculate the Adler32 checksum of a buffer. + * + * Passing the return value to a subsequent av_adler32_update() call + * allows the checksum of multiple buffers to be calculated as though + * they were concatenated. + * + * @param adler initial checksum value + * @param buf pointer to input buffer + * @param len size of input buffer + * @return updated checksum + */ +unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf, + unsigned int len) av_pure; + +#endif /* AVUTIL_ADLER32_H */ diff --git a/extra_lib/include/libavutil/aes.h b/extra_lib/include/libavutil/aes.h new file mode 100644 index 0000000..9c1a54e --- /dev/null +++ b/extra_lib/include/libavutil/aes.h @@ -0,0 +1,67 @@ +/* + * copyright (c) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AES_H +#define AVUTIL_AES_H + +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_aes AES + * @ingroup lavu_crypto + * @{ + */ + +#if FF_API_CONTEXT_SIZE +extern attribute_deprecated const int av_aes_size; +#endif + +struct AVAES; + +/** + * Allocate an AVAES context. + */ +struct AVAES *av_aes_alloc(void); + +/** + * Initialize an AVAES context. + * @param key_bits 128, 192 or 256 + * @param decrypt 0 for encryption, 1 for decryption + */ +int av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * @param count number of 16 byte blocks + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_aes_crypt(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_AES_H */ diff --git a/extra_lib/include/libavutil/attributes.h b/extra_lib/include/libavutil/attributes.h new file mode 100644 index 0000000..64b46f6 --- /dev/null +++ b/extra_lib/include/libavutil/attributes.h @@ -0,0 +1,154 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > x || __GNUC__ == x && __GNUC_MINOR__ >= y) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#ifndef av_restrict +#define av_restrict restrict +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + + +#if defined(__GNUC__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#ifdef __GNUC__ +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/extra_lib/include/libavutil/audio_fifo.h b/extra_lib/include/libavutil/audio_fifo.h new file mode 100644 index 0000000..8c76388 --- /dev/null +++ b/extra_lib/include/libavutil/audio_fifo.h @@ -0,0 +1,146 @@ +/* + * Audio FIFO + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Audio FIFO Buffer + */ + +#ifndef AVUTIL_AUDIO_FIFO_H +#define AVUTIL_AUDIO_FIFO_H + +#include "avutil.h" +#include "fifo.h" +#include "samplefmt.h" + +/** + * @addtogroup lavu_audio + * @{ + */ + +/** + * Context for an Audio FIFO Buffer. + * + * - Operates at the sample level rather than the byte level. + * - Supports multiple channels with either planar or packed sample format. + * - Automatic reallocation when writing to a full buffer. + */ +typedef struct AVAudioFifo AVAudioFifo; + +/** + * Free an AVAudioFifo. + * + * @param af AVAudioFifo to free + */ +void av_audio_fifo_free(AVAudioFifo *af); + +/** + * Allocate an AVAudioFifo. + * + * @param sample_fmt sample format + * @param channels number of channels + * @param nb_samples initial allocation size, in samples + * @return newly allocated AVAudioFifo, or NULL on error + */ +AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, + int nb_samples); + +/** + * Reallocate an AVAudioFifo. + * + * @param af AVAudioFifo to reallocate + * @param nb_samples new allocation size, in samples + * @return 0 if OK, or negative AVERROR code on failure + */ +int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples); + +/** + * Write data to an AVAudioFifo. + * + * The AVAudioFifo will be reallocated automatically if the available space + * is less than nb_samples. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param af AVAudioFifo to write to + * @param data audio data plane pointers + * @param nb_samples number of samples to write + * @return number of samples actually written, or negative AVERROR + * code on failure. + */ +int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples); + +/** + * Read data from an AVAudioFifo. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param af AVAudioFifo to read from + * @param data audio data plane pointers + * @param nb_samples number of samples to read + * @return number of samples actually read, or negative AVERROR code + * on failure. + */ +int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples); + +/** + * Drain data from an AVAudioFifo. + * + * Removes the data without reading it. + * + * @param af AVAudioFifo to drain + * @param nb_samples number of samples to drain + * @return 0 if OK, or negative AVERROR code on failure + */ +int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples); + +/** + * Reset the AVAudioFifo buffer. + * + * This empties all data in the buffer. + * + * @param af AVAudioFifo to reset + */ +void av_audio_fifo_reset(AVAudioFifo *af); + +/** + * Get the current number of samples in the AVAudioFifo available for reading. + * + * @param af the AVAudioFifo to query + * @return number of samples available for reading + */ +int av_audio_fifo_size(AVAudioFifo *af); + +/** + * Get the current number of samples in the AVAudioFifo available for writing. + * + * @param af the AVAudioFifo to query + * @return number of samples available for writing + */ +int av_audio_fifo_space(AVAudioFifo *af); + +/** + * @} + */ + +#endif /* AVUTIL_AUDIO_FIFO_H */ diff --git a/extra_lib/include/libavutil/audioconvert.h b/extra_lib/include/libavutil/audioconvert.h new file mode 100644 index 0000000..76eb278 --- /dev/null +++ b/extra_lib/include/libavutil/audioconvert.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AUDIOCONVERT_H +#define AVUTIL_AUDIOCONVERT_H + +#include + +/** + * @file + * audio conversion routines + */ + +/** + * @addtogroup lavu_audio + * @{ + */ + +/** + * @defgroup channel_masks Audio channel masks + * @{ + */ +#define AV_CH_FRONT_LEFT 0x00000001 +#define AV_CH_FRONT_RIGHT 0x00000002 +#define AV_CH_FRONT_CENTER 0x00000004 +#define AV_CH_LOW_FREQUENCY 0x00000008 +#define AV_CH_BACK_LEFT 0x00000010 +#define AV_CH_BACK_RIGHT 0x00000020 +#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040 +#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080 +#define AV_CH_BACK_CENTER 0x00000100 +#define AV_CH_SIDE_LEFT 0x00000200 +#define AV_CH_SIDE_RIGHT 0x00000400 +#define AV_CH_TOP_CENTER 0x00000800 +#define AV_CH_TOP_FRONT_LEFT 0x00001000 +#define AV_CH_TOP_FRONT_CENTER 0x00002000 +#define AV_CH_TOP_FRONT_RIGHT 0x00004000 +#define AV_CH_TOP_BACK_LEFT 0x00008000 +#define AV_CH_TOP_BACK_CENTER 0x00010000 +#define AV_CH_TOP_BACK_RIGHT 0x00020000 +#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix. +#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT. +#define AV_CH_WIDE_LEFT 0x0000000080000000ULL +#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL +#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL +#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL +#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL + +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. */ +#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL + +/** + * @} + * @defgroup channel_mask_c Audio channel convenience macros + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_NB +}; + +/** + * @} + */ + +/** + * Return a channel layout id that matches name, or 0 if no match is found. + * + * name can be one or several of the following notations, + * separated by '+' or '|': + * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, + * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); + * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, + * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); + * - a number of channels, in decimal, optionally followed by 'c', yielding + * the default channel layout for that number of channels (@see + * av_get_default_channel_layout); + * - a channel layout mask, in hexadecimal starting with "0x" (see the + * AV_CH_* macros). + * + * Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7" + */ +uint64_t av_get_channel_layout(const char *name); + +/** + * Return a description of a channel layout. + * If nb_channels is <= 0, it is guessed from the channel_layout. + * + * @param buf put here the string containing the channel layout + * @param buf_size size in bytes of the buffer + */ +void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); + +struct AVBPrint; +/** + * Append a description of a channel layout to a bprint buffer. + */ +void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); + +/** + * Return the number of channels in the channel layout. + */ +int av_get_channel_layout_nb_channels(uint64_t channel_layout); + +/** + * Return default channel layout for a given number of channels. + */ +int64_t av_get_default_channel_layout(int nb_channels); + +/** + * Get the index of a channel in channel_layout. + * + * @param channel a channel layout describing exactly one channel which must be + * present in channel_layout. + * + * @return index of channel in channel_layout on success, a negative AVERROR + * on error. + */ +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel); + +/** + * Get the channel with the given index in channel_layout. + */ +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); + +/** + * Get the name of a given channel. + * + * @return channel name on success, NULL on error. + */ +const char *av_get_channel_name(uint64_t channel); + +/** + * Get the description of a given channel. + * + * @param channel a channel layout with a single channel + * @return channel description on success, NULL on error + */ +const char *av_get_channel_description(uint64_t channel); + +/** + * Get the value and name of a standard channel layout. + * + * @param[in] index index in an internal list, starting at 0 + * @param[out] layout channel layout mask + * @param[out] name name of the layout + * @return 0 if the layout exists, + * <0 if index is beyond the limits + */ +int av_get_standard_channel_layout(unsigned index, uint64_t *layout, + const char **name); + +/** + * @} + */ + +#endif /* AVUTIL_AUDIOCONVERT_H */ diff --git a/extra_lib/include/libavutil/avassert.h b/extra_lib/include/libavutil/avassert.h new file mode 100644 index 0000000..e100d0b --- /dev/null +++ b/extra_lib/include/libavutil/avassert.h @@ -0,0 +1,66 @@ +/* + * copyright (c) 2010 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * simple assert() macros that are a bit more flexible than ISO C assert(). + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_AVASSERT_H +#define AVUTIL_AVASSERT_H + +#include +#include "avutil.h" +#include "log.h" + +/** + * assert() equivalent, that is always enabled. + */ +#define av_assert0(cond) do { \ + if (!(cond)) { \ + av_log(NULL, AV_LOG_FATAL, "Assertion %s failed at %s:%d\n", \ + AV_STRINGIFY(cond), __FILE__, __LINE__); \ + abort(); \ + } \ +} while (0) + + +/** + * assert() equivalent, that does not lie in speed critical code. + * These asserts() thus can be enabled without fearing speedloss. + */ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0 +#define av_assert1(cond) av_assert0(cond) +#else +#define av_assert1(cond) ((void)0) +#endif + + +/** + * assert() equivalent, that does lie in speed critical code. + */ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 +#define av_assert2(cond) av_assert0(cond) +#else +#define av_assert2(cond) ((void)0) +#endif + +#endif /* AVUTIL_AVASSERT_H */ diff --git a/extra_lib/include/libavutil/avconfig.h b/extra_lib/include/libavutil/avconfig.h new file mode 100644 index 0000000..2ec333d --- /dev/null +++ b/extra_lib/include/libavutil/avconfig.h @@ -0,0 +1,7 @@ +/* Generated by ffconf */ +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H +#define AV_HAVE_BIGENDIAN 0 +#define AV_HAVE_FAST_UNALIGNED 1 +#define AV_HAVE_INCOMPATIBLE_FORK_ABI 0 +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/extra_lib/include/libavutil/avstring.h b/extra_lib/include/libavutil/avstring.h new file mode 100644 index 0000000..f73d6e7 --- /dev/null +++ b/extra_lib/include/libavutil/avstring.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include "attributes.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +/** + * Convert a number to a av_malloced string. + */ +char *av_d2str(double d); + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/extra_lib/include/libavutil/avutil.h b/extra_lib/include/libavutil/avutil.h index fac1f5e..ae6eef1 100644 --- a/extra_lib/include/libavutil/avutil.h +++ b/extra_lib/include/libavutil/avutil.h @@ -22,42 +22,238 @@ #define AVUTIL_AVUTIL_H /** - * @file libavutil/avutil.h + * @file * external API header */ +/* + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @subpage libavfilter graph based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @subpage libpostproc post processing library + * @li @subpage libswscale color conversion and scaling library + */ + +/** + * @defgroup lavu Common utility functions + * + * @brief + * libavutil contains the code shared across all the other FFmpeg + * libraries + * + * @note In order to use the functions provided by avutil you must include + * the specific header. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Maths + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup lavu_internal Internal + * + * Not exported functions, for internal usage only + * + * @{ + * + * @} + */ + -#define AV_STRINGIFY(s) AV_TOSTRING(s) -#define AV_TOSTRING(s) #s +/** + * @addtogroup lavu_ver + * @{ + */ -#define AV_VERSION_INT(a, b, c) (a<<16 | b<<8 | c) -#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c -#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); -#define LIBAVUTIL_VERSION_MAJOR 50 -#define LIBAVUTIL_VERSION_MINOR 3 -#define LIBAVUTIL_VERSION_MICRO 0 +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); -#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ - LIBAVUTIL_VERSION_MINOR, \ - LIBAVUTIL_VERSION_MICRO) -#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ - LIBAVUTIL_VERSION_MINOR, \ - LIBAVUTIL_VERSION_MICRO) -#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT +/** + * Return the libavutil license. + */ +const char *avutil_license(void); -#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) +/** + * @} + */ /** - * Returns the LIBAVUTIL_VERSION_INT constant. + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< + +/** + * @defgroup lavu_base64 Base64 + * @ingroup lavu_crypto + * @{ + */ + + +/** + * Decode a base64-encoded string. + * + * @param out buffer for decoded data + * @param in null-terminated input string + * @param out_size size in bytes of the out buffer, must be at + * least 3/4 of the length of in + * @return number of bytes written, or a negative value in case of + * invalid input + */ +int av_base64_decode(uint8_t *out, const char *in, int out_size); + +/** + * Encode data to base64 and null-terminate. + * + * @param out buffer for encoded data + * @param out_size size in bytes of the output buffer, must be at + * least AV_BASE64_SIZE(in_size) + * @param in_size size in bytes of the 'in' buffer + * @return 'out' or NULL in case of error + */ +char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size); + +/** + * Calculate the output size needed to base64-encode x bytes. + */ +#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1) + + /** + * @} + */ + +#endif /* AVUTIL_BASE64_H */ diff --git a/extra_lib/include/libavutil/blowfish.h b/extra_lib/include/libavutil/blowfish.h new file mode 100644 index 0000000..0b00453 --- /dev/null +++ b/extra_lib/include/libavutil/blowfish.h @@ -0,0 +1,77 @@ +/* + * Blowfish algorithm + * Copyright (c) 2012 Samuel Pitoiset + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_BLOWFISH_H +#define AVUTIL_BLOWFISH_H + +#include + +/** + * @defgroup lavu_blowfish Blowfish + * @ingroup lavu_crypto + * @{ + */ + +#define AV_BF_ROUNDS 16 + +typedef struct AVBlowfish { + uint32_t p[AV_BF_ROUNDS + 2]; + uint32_t s[4][256]; +} AVBlowfish; + +/** + * Initialize an AVBlowfish context. + * + * @param ctx an AVBlowfish context + * @param key a key + * @param key_len length of the key + */ +void av_blowfish_init(struct AVBlowfish *ctx, const uint8_t *key, int key_len); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * + * @param ctx an AVBlowfish context + * @param xl left four bytes halves of input to be encrypted + * @param xr right four bytes halves of input to be encrypted + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_blowfish_crypt_ecb(struct AVBlowfish *ctx, uint32_t *xl, uint32_t *xr, + int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * + * @param ctx an AVBlowfish context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_blowfish_crypt(struct AVBlowfish *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_BLOWFISH_H */ diff --git a/extra_lib/include/libavutil/bprint.h b/extra_lib/include/libavutil/bprint.h new file mode 100644 index 0000000..2bef18d --- /dev/null +++ b/extra_lib/include/libavutil/bprint.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012 Nicolas George + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_BPRINT_H +#define AVUTIL_BPRINT_H + +#include "attributes.h" + +/** + * Define a structure with extra padding to a fixed size + * This helps ensuring binary compatibility with future versions. + */ +#define FF_PAD_STRUCTURE(size, ...) \ + __VA_ARGS__ \ + char reserved_padding[size - sizeof(struct { __VA_ARGS__ })]; + +/** + * Buffer to print data progressively + * + * The string buffer grows as necessary and is always 0-terminated. + * The content of the string is never accessed, and thus is + * encoding-agnostic and can even hold binary data. + * + * Small buffers are kept in the structure itself, and thus require no + * memory allocation at all (unless the contents of the buffer is needed + * after the structure goes out of scope). This is almost as lightweight as + * declaring a local "char buf[512]". + * + * The length of the string can go beyond the allocated size: the buffer is + * then truncated, but the functions still keep account of the actual total + * length. + * + * In other words, buf->len can be greater than buf->size and records the + * total length of what would have been to the buffer if there had been + * enough memory. + * + * Append operations do not need to be tested for failure: if a memory + * allocation fails, data stop being appended to the buffer, but the length + * is still updated. This situation can be tested with + * av_bprint_is_complete(). + * + * The size_max field determines several possible behaviours: + * + * size_max = -1 (= UINT_MAX) or any large value will let the buffer be + * reallocated as necessary, with an amortized linear cost. + * + * size_max = 0 prevents writing anything to the buffer: only the total + * length is computed. The write operations can then possibly be repeated in + * a buffer with exactly the necessary size + * (using size_init = size_max = len + 1). + * + * size_max = 1 is automatically replaced by the exact size available in the + * structure itself, thus ensuring no dynamic memory allocation. The + * internal buffer is large enough to hold a reasonable paragraph of text, + * such as the current paragraph. + */ +typedef struct AVBPrint { + FF_PAD_STRUCTURE(1024, + char *str; /** string so far */ + unsigned len; /** length so far */ + unsigned size; /** allocated memory */ + unsigned size_max; /** maximum allocated memory */ + char reserved_internal_buffer[1]; + ) +} AVBPrint; + +/** + * Convenience macros for special values for av_bprint_init() size_max + * parameter. + */ +#define AV_BPRINT_SIZE_UNLIMITED ((unsigned)-1) +#define AV_BPRINT_SIZE_AUTOMATIC 1 +#define AV_BPRINT_SIZE_COUNT_ONLY 0 + +/** + * Init a print buffer. + * + * @param buf buffer to init + * @param size_init initial size (including the final 0) + * @param size_max maximum size; + * 0 means do not write anything, just count the length; + * 1 is replaced by the maximum value for automatic storage; + * any large value means that the internal buffer will be + * reallocated as needed up to that limit; -1 is converted to + * UINT_MAX, the largest limit possible. + * Check also AV_BPRINT_SIZE_* macros. + */ +void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max); + +/** + * Init a print buffer using a pre-existing buffer. + * + * The buffer will not be reallocated. + * + * @param buf buffer structure to init + * @param buffer byte buffer to use for the string data + * @param size size of buffer + */ +void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size); + +/** + * Append a formated string to a print buffer. + */ +void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Append char c n times to a print buffer. + */ +void av_bprint_chars(AVBPrint *buf, char c, unsigned n); + +/** + * Reset the string to "" but keep internal allocated data. + */ +void av_bprint_clear(AVBPrint *buf); + +/** + * Test if the print buffer is complete (not truncated). + * + * It may have been truncated due to a memory allocation failure + * or the size_max limit (compare size and size_max if necessary). + */ +static inline int av_bprint_is_complete(AVBPrint *buf) +{ + return buf->len < buf->size; +} + +/** + * Finalize a print buffer. + * + * The print buffer can no longer be used afterwards, + * but the len and size fields are still valid. + * + * @arg[out] ret_str if not NULL, used to return a permanent copy of the + * buffer contents, or NULL if memory allocation fails; + * if NULL, the buffer is discarded and freed + * @return 0 for success or error code (probably AVERROR(ENOMEM)) + */ +int av_bprint_finalize(AVBPrint *buf, char **ret_str); + +#endif /* AVUTIL_BPRINT_H */ diff --git a/extra_lib/include/libavutil/bswap.h b/extra_lib/include/libavutil/bswap.h new file mode 100644 index 0000000..06f6548 --- /dev/null +++ b/extra_lib/include/libavutil/bswap.h @@ -0,0 +1,109 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * byte swapping routines + */ + +#ifndef AVUTIL_BSWAP_H +#define AVUTIL_BSWAP_H + +#include +#include "libavutil/avconfig.h" +#include "attributes.h" + +#ifdef HAVE_AV_CONFIG_H + +#include "config.h" + +#if ARCH_ARM +# include "arm/bswap.h" +#elif ARCH_AVR32 +# include "avr32/bswap.h" +#elif ARCH_BFIN +# include "bfin/bswap.h" +#elif ARCH_SH4 +# include "sh4/bswap.h" +#elif ARCH_X86 +# include "x86/bswap.h" +#endif + +#endif /* HAVE_AV_CONFIG_H */ + +#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff)) +#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16)) +#define AV_BSWAP64C(x) (AV_BSWAP32C(x) << 32 | AV_BSWAP32C((x) >> 32)) + +#define AV_BSWAPC(s, x) AV_BSWAP##s##C(x) + +#ifndef av_bswap16 +static av_always_inline av_const uint16_t av_bswap16(uint16_t x) +{ + x= (x>>8) | (x<<8); + return x; +} +#endif + +#ifndef av_bswap32 +static av_always_inline av_const uint32_t av_bswap32(uint32_t x) +{ + return AV_BSWAP32C(x); +} +#endif + +#ifndef av_bswap64 +static inline uint64_t av_const av_bswap64(uint64_t x) +{ + return (uint64_t)av_bswap32(x) << 32 | av_bswap32(x >> 32); +} +#endif + +// be2ne ... big-endian to native-endian +// le2ne ... little-endian to native-endian + +#if AV_HAVE_BIGENDIAN +#define av_be2ne16(x) (x) +#define av_be2ne32(x) (x) +#define av_be2ne64(x) (x) +#define av_le2ne16(x) av_bswap16(x) +#define av_le2ne32(x) av_bswap32(x) +#define av_le2ne64(x) av_bswap64(x) +#define AV_BE2NEC(s, x) (x) +#define AV_LE2NEC(s, x) AV_BSWAPC(s, x) +#else +#define av_be2ne16(x) av_bswap16(x) +#define av_be2ne32(x) av_bswap32(x) +#define av_be2ne64(x) av_bswap64(x) +#define av_le2ne16(x) (x) +#define av_le2ne32(x) (x) +#define av_le2ne64(x) (x) +#define AV_BE2NEC(s, x) AV_BSWAPC(s, x) +#define AV_LE2NEC(s, x) (x) +#endif + +#define AV_BE2NE16C(x) AV_BE2NEC(16, x) +#define AV_BE2NE32C(x) AV_BE2NEC(32, x) +#define AV_BE2NE64C(x) AV_BE2NEC(64, x) +#define AV_LE2NE16C(x) AV_LE2NEC(16, x) +#define AV_LE2NE32C(x) AV_LE2NEC(32, x) +#define AV_LE2NE64C(x) AV_LE2NEC(64, x) + +#endif /* AVUTIL_BSWAP_H */ diff --git a/extra_lib/include/libavutil/common.h b/extra_lib/include/libavutil/common.h index 32f2104..9ed6f11 100644 --- a/extra_lib/include/libavutil/common.h +++ b/extra_lib/include/libavutil/common.h @@ -19,7 +19,7 @@ */ /** - * @file libavutil/common.h + * @file * common internal and external API header */ @@ -28,124 +28,29 @@ #include #include +#include #include #include #include #include #include -#if !defined(EMULATE_INTTYPES) -# include -#else - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - -# ifdef CONFIG_WIN32 - typedef signed __int64 int64_t; - typedef unsigned __int64 uint64_t; -# else /* other OS */ - typedef signed long long int64_t; - typedef unsigned long long uint64_t; -# endif /* other OS */ -#endif /* HAVE_INTTYPES_H */ - - -#ifndef INT64_C -# ifdef CONFIG_MSVC -# define INT64_C(x) (x ## i64) -# define UINT64_C(x) (x ## Ui64) -# else -# define INT64_C(x) (x ## LL) -# define UINT64_C(x) (x ## ULL) -# endif -#endif - -#ifdef __GNUC__ -# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > x || __GNUC__ == x && __GNUC_MINOR__ >= y) -#else -# define AV_GCC_VERSION_AT_LEAST(x,y) 0 -#endif - -#ifndef av_always_inline -#if AV_GCC_VERSION_AT_LEAST(3,1) -# define av_always_inline __attribute__((always_inline)) inline -#else -# define av_always_inline inline -#endif -#endif - -#ifndef av_noinline -#if AV_GCC_VERSION_AT_LEAST(3,1) -# define av_noinline __attribute__((noinline)) -#else -# define av_noinline -#endif -#endif - -#ifndef av_pure -#if AV_GCC_VERSION_AT_LEAST(3,1) -# define av_pure __attribute__((pure)) -#else -# define av_pure -#endif -#endif - -#ifndef av_const -#if AV_GCC_VERSION_AT_LEAST(2,6) -# define av_const __attribute__((const)) -#else -# define av_const -#endif -#endif - -#ifndef av_cold -#if (!defined(__ICC) || __ICC > 1100) && AV_GCC_VERSION_AT_LEAST(4,3) -# define av_cold __attribute__((cold)) -#else -# define av_cold -#endif -#endif - -#ifndef av_flatten -#if AV_GCC_VERSION_AT_LEAST(4,1) -# define av_flatten __attribute__((flatten)) -#else -# define av_flatten -#endif -#endif +#include "attributes.h" +#include "version.h" +#include "libavutil/avconfig.h" -#ifndef attribute_deprecated -#if AV_GCC_VERSION_AT_LEAST(3,1) -# define attribute_deprecated __attribute__((deprecated)) +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) #else -# define attribute_deprecated -#endif -#endif - -#ifndef av_unused -#if defined(__GNUC__) -# define av_unused __attribute__((unused)) -#else -# define av_unused -#endif -#endif - -#ifndef av_uninit -#if defined(__GNUC__) && !defined(__ICC) -# define av_uninit(x) x=x -#else -# define av_uninit(x) x -#endif +# define AV_NE(be, le) (le) #endif //rounded division & shift #define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) /* assume b>0 */ #define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) #define FFABS(a) ((a) >= 0 ? (a) : (-(a))) #define FFSIGN(a) ((a) > 0 ? 1 : -1) @@ -161,7 +66,14 @@ /* misc math functions */ extern const uint8_t ff_log2_tab[256]; -static inline av_const int av_log2(unsigned int v) +/** + * Reverse the order of the bits of an 8-bits unsigned integer. + */ +#if FF_API_AV_REVERSE +extern attribute_deprecated const uint8_t av_reverse[256]; +#endif + +static av_always_inline av_const int av_log2_c(unsigned int v) { int n = 0; if (v & 0xffff0000) { @@ -177,7 +89,7 @@ static inline av_const int av_log2(unsigned int v) return n; } -static inline av_const int av_log2_16bit(unsigned int v) +static av_always_inline av_const int av_log2_16bit_c(unsigned int v) { int n = 0; if (v & 0xff00) { @@ -189,14 +101,22 @@ static inline av_const int av_log2_16bit(unsigned int v) return n; } +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +#endif + +/* Pull in unguarded fallback defines at the end of this file. */ +#include "common.h" + /** - * Clips a signed integer value into the amin-amax range. + * Clip a signed integer value into the amin-amax range. * @param a value to clip * @param amin minimum value of the clip range * @param amax maximum value of the clip range * @return clipped value */ -static inline av_const int av_clip(int a, int amin, int amax) +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) { if (a < amin) return amin; else if (a > amax) return amax; @@ -204,56 +124,156 @@ static inline av_const int av_clip(int a, int amin, int amax) } /** - * Clips a signed integer value into the 0-255 range. + * Clip a signed integer value into the 0-255 range. * @param a value to clip * @return clipped value */ -static inline av_const uint8_t av_clip_uint8(int a) +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) { - if (a&(~255)) return (-a)>>31; - else return a; + if (a&(~0xFF)) return (-a)>>31; + else return a; } /** - * Clips a signed integer value into the -32768,32767 range. + * Clip a signed integer value into the -128,127 range. * @param a value to clip * @return clipped value */ -static inline av_const int16_t av_clip_int16(int a) +static av_always_inline av_const int8_t av_clip_int8_c(int a) { - if ((a+32768) & ~65535) return (a>>31) ^ 32767; - else return a; + if ((a+0x80) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; } /** - * Clips a float value into the amin-amax range. + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (-a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (a>>63) ^ 0x7FFFFFFF; + else return (int32_t)a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1< amax) return amax; else return a; } -#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24)) -#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24)) - -/*! - * \def GET_UTF8(val, GET_BYTE, ERROR) - * Converts a UTF-8 character (up to 4 bytes long) to its 32-bit UCS-4 encoded form - * \param val is the output and should be of type uint32_t. It holds the converted - * UCS-4 character and should be a left value. - * \param GET_BYTE gets UTF-8 encoded bytes from any proper source. It can be - * a function or a statement whose return value or evaluated value is of type - * uint8_t. It will be executed up to 4 times for values in the valid UTF-8 range, - * and up to 7 times in the general case. - * \param ERROR action that should be taken when an invalid UTF-8 byte is returned - * from GET_BYTE. It should be a statement that jumps out of the macro, - * like exit(), goto, return, break, or continue. +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount(x >> 32); +} + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. */ #define GET_UTF8(val, GET_BYTE, ERROR)\ val= GET_BYTE;\ @@ -270,16 +290,37 @@ static inline av_const float av_clipf(float a, float amin, float amax) }\ } -/*! - * \def PUT_UTF8(val, tmp, PUT_BYTE) - * Converts a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). - * \param val is an input-only argument and should be of type uint32_t. It holds +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = GET_16BIT;\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = GET_16BIT - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + ERROR\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If * val is given as a function it is executed only once. - * \param tmp is a temporary variable and should be of type uint8_t. It + * @param tmp is a temporary variable and should be of type uint8_t. It * represents an intermediate value during conversion that is to be * output by PUT_BYTE. - * \param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. * It could be a function or a statement, and uses tmp as the input byte. * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be * executed up to 4 times for values in the valid UTF-8 range and up to @@ -306,11 +347,91 @@ static inline av_const float av_clipf(float a, float amin, float amax) }\ } +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + + + #include "mem.h" #ifdef HAVE_AV_CONFIG_H -# include "config.h" # include "internal.h" #endif /* HAVE_AV_CONFIG_H */ #endif /* AVUTIL_COMMON_H */ + +/* + * The following definitions are outside the multiple inclusion guard + * to ensure they are immediately available in intmath.h. + */ + +#ifndef av_log2 +# define av_log2 av_log2_c +#endif +#ifndef av_log2_16bit +# define av_log2_16bit av_log2_16bit_c +#endif +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif diff --git a/extra_lib/include/libavutil/cpu.h b/extra_lib/include/libavutil/cpu.h new file mode 100644 index 0000000..c8f34e0 --- /dev/null +++ b/extra_lib/include/libavutil/cpu.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CPU_H +#define AVUTIL_CPU_H + +#include "attributes.h" + +#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */ + + /* lower 16 bits - CPU features */ +#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX +#define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW +#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions +#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions +#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster +#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt +#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions +#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster +#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions +#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower +#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions +#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions +#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions +#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions +// #if LIBAVUTIL_VERSION_MAJOR <52 +#define AV_CPU_FLAG_CMOV 0x1001000 ///< supports cmov instruction +// #else +// #define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction +// #endif + +#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard + +#define AV_CPU_FLAG_ARMV5TE (1 << 0) +#define AV_CPU_FLAG_ARMV6 (1 << 1) +#define AV_CPU_FLAG_ARMV6T2 (1 << 2) +#define AV_CPU_FLAG_VFP (1 << 3) +#define AV_CPU_FLAG_VFPV3 (1 << 4) +#define AV_CPU_FLAG_NEON (1 << 5) + +/** + * Return the flags which specify extensions supported by the CPU. + * The returned value is affected by av_force_cpu_flags() if that was used + * before. So av_get_cpu_flags() can easily be used in a application to + * detect the enabled cpu flags. + */ +int av_get_cpu_flags(void); + +/** + * Disables cpu detection and forces the specified flags. + * -1 is a special case that disables forcing of specific flags. + */ +void av_force_cpu_flags(int flags); + +/** + * Set a mask on flags returned by av_get_cpu_flags(). + * This function is mainly useful for testing. + * Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible + * + * @warning this function is not thread safe. + */ +attribute_deprecated void av_set_cpu_flags_mask(int mask); + +/** + * Parse CPU flags from a string. + * + * The returned flags contain the specified flags as well as related unspecified flags. + * + * This function exists only for compatibility with libav. + * Please use av_parse_cpu_caps() when possible. + * @return a combination of AV_CPU_* flags, negative on error. + */ +attribute_deprecated +int av_parse_cpu_flags(const char *s); + +/** + * Parse CPU caps from a string and update the given AV_CPU_* flags based on that. + * + * @return negative on error. + */ +int av_parse_cpu_caps(unsigned *flags, const char *s); + +/* The following CPU-specific functions shall not be called directly. */ +int ff_get_cpu_flags_arm(void); +int ff_get_cpu_flags_ppc(void); +int ff_get_cpu_flags_x86(void); + +#endif /* AVUTIL_CPU_H */ diff --git a/extra_lib/include/libavutil/crc.h b/extra_lib/include/libavutil/crc.h new file mode 100644 index 0000000..1265054 --- /dev/null +++ b/extra_lib/include/libavutil/crc.h @@ -0,0 +1,43 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_CRC_H +#define AVUTIL_CRC_H + +#include +#include +#include "attributes.h" + +typedef uint32_t AVCRC; + +typedef enum { + AV_CRC_8_ATM, + AV_CRC_16_ANSI, + AV_CRC_16_CCITT, + AV_CRC_32_IEEE, + AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */ + AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ +}AVCRCId; + +int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size); +const AVCRC *av_crc_get_table(AVCRCId crc_id); +uint32_t av_crc(const AVCRC *ctx, uint32_t start_crc, const uint8_t *buffer, size_t length) av_pure; + +#endif /* AVUTIL_CRC_H */ diff --git a/extra_lib/include/libavutil/dict.h b/extra_lib/include/libavutil/dict.h new file mode 100644 index 0000000..fde3650 --- /dev/null +++ b/extra_lib/include/libavutil/dict.h @@ -0,0 +1,135 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key:value pairs. To create + * an AVDictionary, simply pass an address of a NULL pointer to + * av_dict_set(). NULL can be used as an empty dictionary wherever + * a pointer to an AVDictionary is required. + * Use av_dict_get() to retrieve an entry or iterate over all + * entries and finally av_dict_free() to free the dictionary + * and all its contents. + * + * @code + * AVDictionary *d = NULL; // "create" an empty dictionary + * av_dict_set(&d, "foo", "bar", 0); // add an entry + * + * char *k = av_strdup("key"); // if your strings are already allocated, + * char *v = av_strdup("value"); // you can avoid copying them like this + * av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + * + * AVDictionaryEntry *t = NULL; + * while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) { + * <....> // iterate over all entries in d + * } + * + * av_dict_free(&d); + * @endcode + * + */ + +#define AV_DICT_MATCH_CASE 1 +#define AV_DICT_IGNORE_SUFFIX 2 +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() and children. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() and chilren. */ +#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries. +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param flags Allows case as well as suffix-insensitive comparisons. + * @return Found entry or NULL, changing key or value leads to undefined behavior. + */ +AVDictionaryEntry * +av_dict_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key entry key to add to *pm (will be av_strduped depending on flags) + * @param value entry value to add to *pm (will be av_strduped depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src pointer to source AVDictionary struct + * @param flags flags to use when setting entries in *dst + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + */ +void av_dict_copy(AVDictionary **dst, AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/extra_lib/include/libavutil/error.h b/extra_lib/include/libavutil/error.h new file mode 100644 index 0000000..1768167 --- /dev/null +++ b/extra_lib/include/libavutil/error.h @@ -0,0 +1,116 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found + +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/extra_lib/include/libavutil/eval.h b/extra_lib/include/libavutil/eval.h new file mode 100644 index 0000000..22fa121 --- /dev/null +++ b/extra_lib/include/libavutil/eval.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2002 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * simple arithmetic expression evaluator + */ + +#ifndef AVUTIL_EVAL_H +#define AVUTIL_EVAL_H + +#include "avutil.h" + +typedef struct AVExpr AVExpr; + +/** + * Parse and evaluate an expression. + * Note, this is significantly slower than av_expr_eval(). + * + * @param res a pointer to a double where is put the result value of + * the expression, or NAN in case of error + * @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)" + * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0} + * @param const_values a zero terminated array of values for the identifiers from const_names + * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers + * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument + * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers + * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2 + * @param log_ctx parent logging context + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_expr_parse_and_eval(double *res, const char *s, + const char * const *const_names, const double *const_values, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + void *opaque, int log_offset, void *log_ctx); + +/** + * Parse an expression. + * + * @param expr a pointer where is put an AVExpr containing the parsed + * value in case of successful parsing, or NULL otherwise. + * The pointed to AVExpr must be freed with av_expr_free() by the user + * when it is not needed anymore. + * @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)" + * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0} + * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers + * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument + * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers + * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments + * @param log_ctx parent logging context + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_expr_parse(AVExpr **expr, const char *s, + const char * const *const_names, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + int log_offset, void *log_ctx); + +/** + * Evaluate a previously parsed expression. + * + * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2 + * @return the value of the expression + */ +double av_expr_eval(AVExpr *e, const double *const_values, void *opaque); + +/** + * Free a parsed expression previously created with av_expr_parse(). + */ +void av_expr_free(AVExpr *e); + +#if FF_API_OLD_EVAL_NAMES +/** + * @deprecated Deprecated in favor of av_expr_parse_and_eval(). + */ +attribute_deprecated +int av_parse_and_eval_expr(double *res, const char *s, + const char * const *const_names, const double *const_values, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + void *opaque, int log_offset, void *log_ctx); + +/** + * @deprecated Deprecated in favor of av_expr_parse(). + */ +attribute_deprecated +int av_parse_expr(AVExpr **expr, const char *s, + const char * const *const_names, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + int log_offset, void *log_ctx); +/** + * @deprecated Deprecated in favor of av_expr_eval(). + */ +attribute_deprecated +double av_eval_expr(AVExpr *e, const double *const_values, void *opaque); + +/** + * @deprecated Deprecated in favor of av_expr_free(). + */ +attribute_deprecated +void av_free_expr(AVExpr *e); +#endif /* FF_API_OLD_EVAL_NAMES */ + +/** + * Parse the string in numstr and return its value as a double. If + * the string is empty, contains only whitespaces, or does not contain + * an initial substring that has the expected syntax for a + * floating-point number, no conversion is performed. In this case, + * returns a value of zero and the value returned in tail is the value + * of numstr. + * + * @param numstr a string representing a number, may contain one of + * the International System number postfixes, for example 'K', 'M', + * 'G'. If 'i' is appended after the postfix, powers of 2 are used + * instead of powers of 10. The 'B' postfix multiplies the value for + * 8, and can be appended after another postfix or used alone. This + * allows using for example 'KB', 'MiB', 'G' and 'B' as postfix. + * @param tail if non-NULL puts here the pointer to the char next + * after the last parsed character + */ +double av_strtod(const char *numstr, char **tail); + +#endif /* AVUTIL_EVAL_H */ diff --git a/extra_lib/include/libavutil/fifo.h b/extra_lib/include/libavutil/fifo.h new file mode 100644 index 0000000..ff66c95 --- /dev/null +++ b/extra_lib/include/libavutil/fifo.h @@ -0,0 +1,155 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * a very simple circular buffer FIFO implementation + */ + +#ifndef AVUTIL_FIFO_H +#define AVUTIL_FIFO_H + +#include +#include "avutil.h" +#include "attributes.h" + +typedef struct AVFifoBuffer { + uint8_t *buffer; + uint8_t *rptr, *wptr, *end; + uint32_t rndx, wndx; +} AVFifoBuffer; + +/** + * Initialize an AVFifoBuffer. + * @param size of FIFO + * @return AVFifoBuffer or NULL in case of memory allocation failure + */ +AVFifoBuffer *av_fifo_alloc(unsigned int size); + +/** + * Free an AVFifoBuffer. + * @param f AVFifoBuffer to free + */ +void av_fifo_free(AVFifoBuffer *f); + +/** + * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied. + * @param f AVFifoBuffer to reset + */ +void av_fifo_reset(AVFifoBuffer *f); + +/** + * Return the amount of data in bytes in the AVFifoBuffer, that is the + * amount of data you can read from it. + * @param f AVFifoBuffer to read from + * @return size + */ +int av_fifo_size(AVFifoBuffer *f); + +/** + * Return the amount of space in bytes in the AVFifoBuffer, that is the + * amount of data you can write into it. + * @param f AVFifoBuffer to write into + * @return size + */ +int av_fifo_space(AVFifoBuffer *f); + +/** + * Feed data from an AVFifoBuffer to a user-supplied callback. + * @param f AVFifoBuffer to read from + * @param buf_size number of bytes to read + * @param func generic read function + * @param dest data destination + */ +int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); + +/** + * Feed data from a user-supplied callback to an AVFifoBuffer. + * @param f AVFifoBuffer to write to + * @param src data source; non-const since it may be used as a + * modifiable context by the function defined in func + * @param size number of bytes to write + * @param func generic write function; the first parameter is src, + * the second is dest_buf, the third is dest_buf_size. + * func must return the number of bytes written to dest_buf, or <= 0 to + * indicate no more data available to write. + * If func is NULL, src is interpreted as a simple byte array for source data. + * @return the number of bytes written to the FIFO + */ +int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); + +/** + * Resize an AVFifoBuffer. + * In case of reallocation failure, the old FIFO is kept unchanged. + * + * @param f AVFifoBuffer to resize + * @param size new AVFifoBuffer size in bytes + * @return <0 for failure, >=0 otherwise + */ +int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size); + +/** + * Enlarge an AVFifoBuffer. + * In case of reallocation failure, the old FIFO is kept unchanged. + * The new fifo size may be larger than the requested size. + * + * @param f AVFifoBuffer to resize + * @param additional_space the amount of space in bytes to allocate in addition to av_fifo_size() + * @return <0 for failure, >=0 otherwise + */ +int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space); + +/** + * Read and discard the specified amount of data from an AVFifoBuffer. + * @param f AVFifoBuffer to read from + * @param size amount of data to read in bytes + */ +void av_fifo_drain(AVFifoBuffer *f, int size); + +/** + * Return a pointer to the data stored in a FIFO buffer at a certain offset. + * The FIFO buffer is not modified. + * + * @param f AVFifoBuffer to peek at, f must be non-NULL + * @param offs an offset in bytes, its absolute value must be less + * than the used buffer size or the returned pointer will + * point outside to the buffer data. + * The used buffer size can be checked with av_fifo_size(). + */ +static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) +{ + uint8_t *ptr = f->rptr + offs; + if (ptr >= f->end) + ptr = f->buffer + (ptr - f->end); + else if (ptr < f->buffer) + ptr = f->end - (f->buffer - ptr); + return ptr; +} + +#if FF_API_AV_FIFO_PEEK +/** + * @deprecated Use av_fifo_peek2() instead. + */ +attribute_deprecated +static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs) +{ + return *av_fifo_peek2(f, offs); +} +#endif + +#endif /* AVUTIL_FIFO_H */ diff --git a/extra_lib/include/libavutil/file.h b/extra_lib/include/libavutil/file.h new file mode 100644 index 0000000..f637005 --- /dev/null +++ b/extra_lib/include/libavutil/file.h @@ -0,0 +1,63 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_FILE_H +#define AVUTIL_FILE_H + +#include + +#include "avutil.h" + +/** + * @file + * Misc file utilities. + */ + +/** + * Read the file with name filename, and put its content in a newly + * allocated buffer or map it with mmap() when available. + * In case of success set *bufptr to the read or mmapped buffer, and + * *size to the size in bytes of the buffer in *bufptr. + * The returned buffer must be released with av_file_unmap(). + * + * @param log_offset loglevel offset used for logging + * @param log_ctx context used for logging + * @return a non negative number in case of success, a negative value + * corresponding to an AVERROR error code in case of failure + */ +int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, + int log_offset, void *log_ctx); + +/** + * Unmap or free the buffer bufptr created by av_file_map(). + * + * @param size size in bytes of bufptr, must be the same as returned + * by av_file_map() + */ +void av_file_unmap(uint8_t *bufptr, size_t size); + +/** + * Wrapper to work around the lack of mkstemp() on mingw. + * Also, tries to create file in /tmp first, if possible. + * *prefix can be a character constant; *filename will be allocated internally. + * @return file descriptor of opened file (or -1 on error) + * and opened file name in **filename. + */ +int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx); + +#endif /* AVUTIL_FILE_H */ diff --git a/extra_lib/include/libavutil/imgutils.h b/extra_lib/include/libavutil/imgutils.h new file mode 100644 index 0000000..a9317a7 --- /dev/null +++ b/extra_lib/include/libavutil/imgutils.h @@ -0,0 +1,197 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include "avutil.h" +#include "pixdesc.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * @param dst_linesize linesize for the image plane in dst + * @param src_linesize linesize for the image plane in src + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_linesizes linesizes for the image in dst_data + * @param src_linesizes linesizes for the image in src_data + */ +void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], + const uint8_t *src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesizes linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param[in] align the assumed linesize alignment + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesizes linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/extra_lib/include/libavutil/intfloat.h b/extra_lib/include/libavutil/intfloat.h new file mode 100644 index 0000000..38d26ad --- /dev/null +++ b/extra_lib/include/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/extra_lib/include/libavutil/intfloat_readwrite.h b/extra_lib/include/libavutil/intfloat_readwrite.h index 88c6f69..9709f4d 100644 --- a/extra_lib/include/libavutil/intfloat_readwrite.h +++ b/extra_lib/include/libavutil/intfloat_readwrite.h @@ -21,10 +21,8 @@ #ifndef AVUTIL_INTFLOAT_READWRITE_H #define AVUTIL_INTFLOAT_READWRITE_H -#if !defined(WIN32) && !defined(_WIN32_WCE) #include -#endif -#include "common.h" +#include "attributes.h" /* IEEE 80 bits extended float */ typedef struct AVExtFloat { @@ -32,11 +30,11 @@ typedef struct AVExtFloat { uint8_t mantissa[8]; } AVExtFloat; -double av_int2dbl(int64_t v) av_const; -float av_int2flt(int32_t v) av_const; -double av_ext2dbl(const AVExtFloat ext) av_const; -int64_t av_dbl2int(double d) av_const; -int32_t av_flt2int(float d) av_const; -AVExtFloat av_dbl2ext(double d) av_const; +attribute_deprecated double av_int2dbl(int64_t v) av_const; +attribute_deprecated float av_int2flt(int32_t v) av_const; +attribute_deprecated double av_ext2dbl(const AVExtFloat ext) av_const; +attribute_deprecated int64_t av_dbl2int(double d) av_const; +attribute_deprecated int32_t av_flt2int(float d) av_const; +attribute_deprecated AVExtFloat av_dbl2ext(double d) av_const; #endif /* AVUTIL_INTFLOAT_READWRITE_H */ diff --git a/extra_lib/include/libavutil/intreadwrite.h b/extra_lib/include/libavutil/intreadwrite.h new file mode 100644 index 0000000..7c68ead --- /dev/null +++ b/extra_lib/include/libavutil/intreadwrite.h @@ -0,0 +1,528 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_INTREADWRITE_H +#define AVUTIL_INTREADWRITE_H + +#include +#include "libavutil/avconfig.h" +#include "attributes.h" +#include "bswap.h" + +typedef union { + uint64_t u64; + uint32_t u32[2]; + uint16_t u16[4]; + uint8_t u8 [8]; + double f64; + float f32[2]; +} av_alias av_alias64; + +typedef union { + uint32_t u32; + uint16_t u16[2]; + uint8_t u8 [4]; + float f32; +} av_alias av_alias32; + +typedef union { + uint16_t u16; + uint8_t u8 [2]; +} av_alias av_alias16; + +/* + * Arch-specific headers can provide any combination of + * AV_[RW][BLN](16|24|32|64) and AV_(COPY|SWAP|ZERO)(64|128) macros. + * Preprocessor symbols must be defined, even if these are implemented + * as inline functions. + */ + +#ifdef HAVE_AV_CONFIG_H + +#include "config.h" + +#if ARCH_ARM +# include "arm/intreadwrite.h" +#elif ARCH_AVR32 +# include "avr32/intreadwrite.h" +#elif ARCH_MIPS +# include "mips/intreadwrite.h" +#elif ARCH_PPC +# include "ppc/intreadwrite.h" +#elif ARCH_TOMI +# include "tomi/intreadwrite.h" +#elif ARCH_X86 +# include "x86/intreadwrite.h" +#endif + +#endif /* HAVE_AV_CONFIG_H */ + +/* + * Map AV_RNXX <-> AV_R[BL]XX for all variants provided by per-arch headers. + */ + +#if AV_HAVE_BIGENDIAN + +# if defined(AV_RN16) && !defined(AV_RB16) +# define AV_RB16(p) AV_RN16(p) +# elif !defined(AV_RN16) && defined(AV_RB16) +# define AV_RN16(p) AV_RB16(p) +# endif + +# if defined(AV_WN16) && !defined(AV_WB16) +# define AV_WB16(p, v) AV_WN16(p, v) +# elif !defined(AV_WN16) && defined(AV_WB16) +# define AV_WN16(p, v) AV_WB16(p, v) +# endif + +# if defined(AV_RN24) && !defined(AV_RB24) +# define AV_RB24(p) AV_RN24(p) +# elif !defined(AV_RN24) && defined(AV_RB24) +# define AV_RN24(p) AV_RB24(p) +# endif + +# if defined(AV_WN24) && !defined(AV_WB24) +# define AV_WB24(p, v) AV_WN24(p, v) +# elif !defined(AV_WN24) && defined(AV_WB24) +# define AV_WN24(p, v) AV_WB24(p, v) +# endif + +# if defined(AV_RN32) && !defined(AV_RB32) +# define AV_RB32(p) AV_RN32(p) +# elif !defined(AV_RN32) && defined(AV_RB32) +# define AV_RN32(p) AV_RB32(p) +# endif + +# if defined(AV_WN32) && !defined(AV_WB32) +# define AV_WB32(p, v) AV_WN32(p, v) +# elif !defined(AV_WN32) && defined(AV_WB32) +# define AV_WN32(p, v) AV_WB32(p, v) +# endif + +# if defined(AV_RN64) && !defined(AV_RB64) +# define AV_RB64(p) AV_RN64(p) +# elif !defined(AV_RN64) && defined(AV_RB64) +# define AV_RN64(p) AV_RB64(p) +# endif + +# if defined(AV_WN64) && !defined(AV_WB64) +# define AV_WB64(p, v) AV_WN64(p, v) +# elif !defined(AV_WN64) && defined(AV_WB64) +# define AV_WN64(p, v) AV_WB64(p, v) +# endif + +#else /* AV_HAVE_BIGENDIAN */ + +# if defined(AV_RN16) && !defined(AV_RL16) +# define AV_RL16(p) AV_RN16(p) +# elif !defined(AV_RN16) && defined(AV_RL16) +# define AV_RN16(p) AV_RL16(p) +# endif + +# if defined(AV_WN16) && !defined(AV_WL16) +# define AV_WL16(p, v) AV_WN16(p, v) +# elif !defined(AV_WN16) && defined(AV_WL16) +# define AV_WN16(p, v) AV_WL16(p, v) +# endif + +# if defined(AV_RN24) && !defined(AV_RL24) +# define AV_RL24(p) AV_RN24(p) +# elif !defined(AV_RN24) && defined(AV_RL24) +# define AV_RN24(p) AV_RL24(p) +# endif + +# if defined(AV_WN24) && !defined(AV_WL24) +# define AV_WL24(p, v) AV_WN24(p, v) +# elif !defined(AV_WN24) && defined(AV_WL24) +# define AV_WN24(p, v) AV_WL24(p, v) +# endif + +# if defined(AV_RN32) && !defined(AV_RL32) +# define AV_RL32(p) AV_RN32(p) +# elif !defined(AV_RN32) && defined(AV_RL32) +# define AV_RN32(p) AV_RL32(p) +# endif + +# if defined(AV_WN32) && !defined(AV_WL32) +# define AV_WL32(p, v) AV_WN32(p, v) +# elif !defined(AV_WN32) && defined(AV_WL32) +# define AV_WN32(p, v) AV_WL32(p, v) +# endif + +# if defined(AV_RN64) && !defined(AV_RL64) +# define AV_RL64(p) AV_RN64(p) +# elif !defined(AV_RN64) && defined(AV_RL64) +# define AV_RN64(p) AV_RL64(p) +# endif + +# if defined(AV_WN64) && !defined(AV_WL64) +# define AV_WL64(p, v) AV_WN64(p, v) +# elif !defined(AV_WN64) && defined(AV_WL64) +# define AV_WN64(p, v) AV_WL64(p, v) +# endif + +#endif /* !AV_HAVE_BIGENDIAN */ + +/* + * Define AV_[RW]N helper macros to simplify definitions not provided + * by per-arch headers. + */ + +#if defined(__GNUC__) && !defined(__TI_COMPILER_VERSION__) + +union unaligned_64 { uint64_t l; } __attribute__((packed)) av_alias; +union unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias; +union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; + +# define AV_RN(s, p) (((const union unaligned_##s *) (p))->l) +# define AV_WN(s, p, v) ((((union unaligned_##s *) (p))->l) = (v)) + +#elif defined(__DECC) + +# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) +# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) + +#elif AV_HAVE_FAST_UNALIGNED + +# define AV_RN(s, p) (((const av_alias##s*)(p))->u##s) +# define AV_WN(s, p, v) (((av_alias##s*)(p))->u##s = (v)) + +#else + +#ifndef AV_RB16 +# define AV_RB16(x) \ + ((((const uint8_t*)(x))[0] << 8) | \ + ((const uint8_t*)(x))[1]) +#endif +#ifndef AV_WB16 +# define AV_WB16(p, darg) do { \ + unsigned d = (darg); \ + ((uint8_t*)(p))[1] = (d); \ + ((uint8_t*)(p))[0] = (d)>>8; \ + } while(0) +#endif + +#ifndef AV_RL16 +# define AV_RL16(x) \ + ((((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL16 +# define AV_WL16(p, darg) do { \ + unsigned d = (darg); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + } while(0) +#endif + +#ifndef AV_RB32 +# define AV_RB32(x) \ + (((uint32_t)((const uint8_t*)(x))[0] << 24) | \ + (((const uint8_t*)(x))[1] << 16) | \ + (((const uint8_t*)(x))[2] << 8) | \ + ((const uint8_t*)(x))[3]) +#endif +#ifndef AV_WB32 +# define AV_WB32(p, darg) do { \ + unsigned d = (darg); \ + ((uint8_t*)(p))[3] = (d); \ + ((uint8_t*)(p))[2] = (d)>>8; \ + ((uint8_t*)(p))[1] = (d)>>16; \ + ((uint8_t*)(p))[0] = (d)>>24; \ + } while(0) +#endif + +#ifndef AV_RL32 +# define AV_RL32(x) \ + (((uint32_t)((const uint8_t*)(x))[3] << 24) | \ + (((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL32 +# define AV_WL32(p, darg) do { \ + unsigned d = (darg); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + } while(0) +#endif + +#ifndef AV_RB64 +# define AV_RB64(x) \ + (((uint64_t)((const uint8_t*)(x))[0] << 56) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 48) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[5] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[6] << 8) | \ + (uint64_t)((const uint8_t*)(x))[7]) +#endif +#ifndef AV_WB64 +# define AV_WB64(p, darg) do { \ + uint64_t d = (darg); \ + ((uint8_t*)(p))[7] = (d); \ + ((uint8_t*)(p))[6] = (d)>>8; \ + ((uint8_t*)(p))[5] = (d)>>16; \ + ((uint8_t*)(p))[4] = (d)>>24; \ + ((uint8_t*)(p))[3] = (d)>>32; \ + ((uint8_t*)(p))[2] = (d)>>40; \ + ((uint8_t*)(p))[1] = (d)>>48; \ + ((uint8_t*)(p))[0] = (d)>>56; \ + } while(0) +#endif + +#ifndef AV_RL64 +# define AV_RL64(x) \ + (((uint64_t)((const uint8_t*)(x))[7] << 56) | \ + ((uint64_t)((const uint8_t*)(x))[6] << 48) | \ + ((uint64_t)((const uint8_t*)(x))[5] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 8) | \ + (uint64_t)((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL64 +# define AV_WL64(p, darg) do { \ + uint64_t d = (darg); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + ((uint8_t*)(p))[4] = (d)>>32; \ + ((uint8_t*)(p))[5] = (d)>>40; \ + ((uint8_t*)(p))[6] = (d)>>48; \ + ((uint8_t*)(p))[7] = (d)>>56; \ + } while(0) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RN(s, p) AV_RB##s(p) +# define AV_WN(s, p, v) AV_WB##s(p, v) +#else +# define AV_RN(s, p) AV_RL##s(p) +# define AV_WN(s, p, v) AV_WL##s(p, v) +#endif + +#endif /* HAVE_FAST_UNALIGNED */ + +#ifndef AV_RN16 +# define AV_RN16(p) AV_RN(16, p) +#endif + +#ifndef AV_RN32 +# define AV_RN32(p) AV_RN(32, p) +#endif + +#ifndef AV_RN64 +# define AV_RN64(p) AV_RN(64, p) +#endif + +#ifndef AV_WN16 +# define AV_WN16(p, v) AV_WN(16, p, v) +#endif + +#ifndef AV_WN32 +# define AV_WN32(p, v) AV_WN(32, p, v) +#endif + +#ifndef AV_WN64 +# define AV_WN64(p, v) AV_WN(64, p, v) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RB(s, p) AV_RN##s(p) +# define AV_WB(s, p, v) AV_WN##s(p, v) +# define AV_RL(s, p) av_bswap##s(AV_RN##s(p)) +# define AV_WL(s, p, v) AV_WN##s(p, av_bswap##s(v)) +#else +# define AV_RB(s, p) av_bswap##s(AV_RN##s(p)) +# define AV_WB(s, p, v) AV_WN##s(p, av_bswap##s(v)) +# define AV_RL(s, p) AV_RN##s(p) +# define AV_WL(s, p, v) AV_WN##s(p, v) +#endif + +#define AV_RB8(x) (((const uint8_t*)(x))[0]) +#define AV_WB8(p, d) do { ((uint8_t*)(p))[0] = (d); } while(0) + +#define AV_RL8(x) AV_RB8(x) +#define AV_WL8(p, d) AV_WB8(p, d) + +#ifndef AV_RB16 +# define AV_RB16(p) AV_RB(16, p) +#endif +#ifndef AV_WB16 +# define AV_WB16(p, v) AV_WB(16, p, v) +#endif + +#ifndef AV_RL16 +# define AV_RL16(p) AV_RL(16, p) +#endif +#ifndef AV_WL16 +# define AV_WL16(p, v) AV_WL(16, p, v) +#endif + +#ifndef AV_RB32 +# define AV_RB32(p) AV_RB(32, p) +#endif +#ifndef AV_WB32 +# define AV_WB32(p, v) AV_WB(32, p, v) +#endif + +#ifndef AV_RL32 +# define AV_RL32(p) AV_RL(32, p) +#endif +#ifndef AV_WL32 +# define AV_WL32(p, v) AV_WL(32, p, v) +#endif + +#ifndef AV_RB64 +# define AV_RB64(p) AV_RB(64, p) +#endif +#ifndef AV_WB64 +# define AV_WB64(p, v) AV_WB(64, p, v) +#endif + +#ifndef AV_RL64 +# define AV_RL64(p) AV_RL(64, p) +#endif +#ifndef AV_WL64 +# define AV_WL64(p, v) AV_WL(64, p, v) +#endif + +#ifndef AV_RB24 +# define AV_RB24(x) \ + ((((const uint8_t*)(x))[0] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[2]) +#endif +#ifndef AV_WB24 +# define AV_WB24(p, d) do { \ + ((uint8_t*)(p))[2] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[0] = (d)>>16; \ + } while(0) +#endif + +#ifndef AV_RL24 +# define AV_RL24(x) \ + ((((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL24 +# define AV_WL24(p, d) do { \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + } while(0) +#endif + +/* + * The AV_[RW]NA macros access naturally aligned data + * in a type-safe way. + */ + +#define AV_RNA(s, p) (((const av_alias##s*)(p))->u##s) +#define AV_WNA(s, p, v) (((av_alias##s*)(p))->u##s = (v)) + +#ifndef AV_RN16A +# define AV_RN16A(p) AV_RNA(16, p) +#endif + +#ifndef AV_RN32A +# define AV_RN32A(p) AV_RNA(32, p) +#endif + +#ifndef AV_RN64A +# define AV_RN64A(p) AV_RNA(64, p) +#endif + +#ifndef AV_WN16A +# define AV_WN16A(p, v) AV_WNA(16, p, v) +#endif + +#ifndef AV_WN32A +# define AV_WN32A(p, v) AV_WNA(32, p, v) +#endif + +#ifndef AV_WN64A +# define AV_WN64A(p, v) AV_WNA(64, p, v) +#endif + +/* Parameters for AV_COPY*, AV_SWAP*, AV_ZERO* must be + * naturally aligned. They may be implemented using MMX, + * so emms_c() must be called before using any float code + * afterwards. + */ + +#define AV_COPY(n, d, s) \ + (((av_alias##n*)(d))->u##n = ((const av_alias##n*)(s))->u##n) + +#ifndef AV_COPY16 +# define AV_COPY16(d, s) AV_COPY(16, d, s) +#endif + +#ifndef AV_COPY32 +# define AV_COPY32(d, s) AV_COPY(32, d, s) +#endif + +#ifndef AV_COPY64 +# define AV_COPY64(d, s) AV_COPY(64, d, s) +#endif + +#ifndef AV_COPY128 +# define AV_COPY128(d, s) \ + do { \ + AV_COPY64(d, s); \ + AV_COPY64((char*)(d)+8, (char*)(s)+8); \ + } while(0) +#endif + +#define AV_SWAP(n, a, b) FFSWAP(av_alias##n, *(av_alias##n*)(a), *(av_alias##n*)(b)) + +#ifndef AV_SWAP64 +# define AV_SWAP64(a, b) AV_SWAP(64, a, b) +#endif + +#define AV_ZERO(n, d) (((av_alias##n*)(d))->u##n = 0) + +#ifndef AV_ZERO16 +# define AV_ZERO16(d) AV_ZERO(16, d) +#endif + +#ifndef AV_ZERO32 +# define AV_ZERO32(d) AV_ZERO(32, d) +#endif + +#ifndef AV_ZERO64 +# define AV_ZERO64(d) AV_ZERO(64, d) +#endif + +#ifndef AV_ZERO128 +# define AV_ZERO128(d) \ + do { \ + AV_ZERO64(d); \ + AV_ZERO64((char*)(d)+8); \ + } while(0) +#endif + +#endif /* AVUTIL_INTREADWRITE_H */ diff --git a/extra_lib/include/libavutil/lfg.h b/extra_lib/include/libavutil/lfg.h new file mode 100644 index 0000000..ec90562 --- /dev/null +++ b/extra_lib/include/libavutil/lfg.h @@ -0,0 +1,62 @@ +/* + * Lagged Fibonacci PRNG + * Copyright (c) 2008 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LFG_H +#define AVUTIL_LFG_H + +typedef struct AVLFG { + unsigned int state[64]; + int index; +} AVLFG; + +void av_lfg_init(AVLFG *c, unsigned int seed); + +/** + * Get the next random unsigned 32-bit number using an ALFG. + * + * Please also consider a simple LCG like state= state*1664525+1013904223, + * it may be good enough and faster for your specific use case. + */ +static inline unsigned int av_lfg_get(AVLFG *c){ + c->state[c->index & 63] = c->state[(c->index-24) & 63] + c->state[(c->index-55) & 63]; + return c->state[c->index++ & 63]; +} + +/** + * Get the next random unsigned 32-bit number using a MLFG. + * + * Please also consider av_lfg_get() above, it is faster. + */ +static inline unsigned int av_mlfg_get(AVLFG *c){ + unsigned int a= c->state[(c->index-55) & 63]; + unsigned int b= c->state[(c->index-24) & 63]; + return c->state[c->index++ & 63] = 2*a*b+a+b; +} + +/** + * Get the next two numbers generated by a Box-Muller Gaussian + * generator using the random numbers issued by lfg. + * + * @param out array where the two generated numbers are placed + */ +void av_bmg_get(AVLFG *lfg, double out[2]); + +#endif /* AVUTIL_LFG_H */ diff --git a/extra_lib/include/libavutil/log.h b/extra_lib/include/libavutil/log.h index 1206a2f..ba7315f 100644 --- a/extra_lib/include/libavutil/log.h +++ b/extra_lib/include/libavutil/log.h @@ -23,14 +23,29 @@ #include #include "avutil.h" +#include "attributes.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_NB, ///< not part of ABI/API +}AVClassCategory; /** - * Describes the class of an AVClass context structure. That is an + * Describe the class of an AVClass context structure. That is an * arbitrary struct of which the first field is a pointer to an * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). */ -typedef struct AVCLASS AVClass; -struct AVCLASS { +typedef struct AVClass { /** * The name of the class; usually it is the same name as the * context structure type to which the AVClass is associated. @@ -39,7 +54,7 @@ struct AVCLASS { /** * A pointer to a function which returns the name of a context - * instance \p ctx associated with the class. + * instance ctx associated with the class. */ const char* (*item_name)(void* ctx); @@ -49,7 +64,57 @@ struct AVCLASS { * @see av_set_default_options() */ const struct AVOption *option; -}; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for loging is stored. + * for example a decoder that uses eval.c could pass its AVCodecContext to eval as such + * parent context. And a av_log() implementation could then display the parent context + * can be NULL of course + */ + int parent_log_context_offset; + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Return an AVClass corresponding to next potential + * AVOptions-enabled child. + * + * The difference between child_next and this is that + * child_next iterates over _already existing_ objects, while + * child_class_next iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_next)(const struct AVClass *prev); + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); +} AVClass; /* av_log API */ @@ -87,8 +152,10 @@ struct AVCLASS { */ #define AV_LOG_DEBUG 48 +#define AV_LOG_MAX_OFFSET (AV_LOG_DEBUG - AV_LOG_QUIET) + /** - * Sends the specified message to the log if the level is less than or equal + * Send the specified message to the log if the level is less than or equal * to the current av_log_level. By default, all logging messages are sent to * stderr. This behavior can be altered by setting a different av_vlog callback * function. @@ -101,16 +168,46 @@ struct AVCLASS { * subsequent arguments are converted to output. * @see av_vlog */ -#ifdef __GNUC__ -void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4))); -#else -void av_log(void*, int level, const char *fmt, ...); -#endif +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); -void av_vlog(void*, int level, const char *fmt, va_list); +void av_vlog(void *avcl, int level, const char *fmt, va_list); int av_log_get_level(void); void av_log_set_level(int); void av_log_set_callback(void (*)(void*, int, const char*, va_list)); void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl); +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formated line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * av_dlog macros + * Useful to print debug messages that shouldn't get compiled in normally. + */ + +#ifdef DEBUG +# define av_dlog(pctx, ...) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__) +#else +# define av_dlog(pctx, ...) do { if (0) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__); } while (0) +#endif + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 +void av_log_set_flags(int arg); #endif /* AVUTIL_LOG_H */ diff --git a/extra_lib/include/libavutil/lzo.h b/extra_lib/include/libavutil/lzo.h new file mode 100644 index 0000000..060b5c9 --- /dev/null +++ b/extra_lib/include/libavutil/lzo.h @@ -0,0 +1,77 @@ +/* + * LZO 1x decompression + * copyright (c) 2006 Reimar Doeffinger + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_LZO_H +#define AVUTIL_LZO_H + +/** + * @defgroup lavu_lzo LZO + * @ingroup lavu_crypto + * + * @{ + */ + +#include + +/** @name Error flags returned by av_lzo1x_decode + * @{ */ +/// end of the input buffer reached before decoding finished +#define AV_LZO_INPUT_DEPLETED 1 +/// decoded data did not fit into output buffer +#define AV_LZO_OUTPUT_FULL 2 +/// a reference to previously decoded data was wrong +#define AV_LZO_INVALID_BACKPTR 4 +/// a non-specific error in the compressed bitstream +#define AV_LZO_ERROR 8 +/** @} */ + +#define AV_LZO_INPUT_PADDING 8 +#define AV_LZO_OUTPUT_PADDING 12 + +/** + * @brief Decodes LZO 1x compressed data. + * @param out output buffer + * @param outlen size of output buffer, number of bytes left are returned here + * @param in input buffer + * @param inlen size of input buffer, number of bytes left are returned here + * @return 0 on success, otherwise a combination of the error flags above + * + * Make sure all buffers are appropriately padded, in must provide + * AV_LZO_INPUT_PADDING, out must provide AV_LZO_OUTPUT_PADDING additional bytes. + */ +int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen); + +/** + * @brief deliberately overlapping memcpy implementation + * @param dst destination buffer; must be padded with 12 additional bytes + * @param back how many bytes back we start (the initial size of the overlapping window), must be > 0 + * @param cnt number of bytes to copy, must be >= 0 + * + * cnt > back is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of back. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +#endif /* AVUTIL_LZO_H */ diff --git a/extra_lib/include/libavutil/mathematics.h b/extra_lib/include/libavutil/mathematics.h index f437404..5458d2f 100644 --- a/extra_lib/include/libavutil/mathematics.h +++ b/extra_lib/include/libavutil/mathematics.h @@ -21,12 +21,11 @@ #ifndef AVUTIL_MATHEMATICS_H #define AVUTIL_MATHEMATICS_H -#if !defined(WIN32) && !defined(_WIN32_WCE) #include -#endif #include -#include "common.h" +#include "attributes.h" #include "rational.h" +#include "intfloat.h" #ifndef M_E #define M_E 2.7182818284590452354 /* e */ @@ -37,12 +36,33 @@ #ifndef M_LN10 #define M_LN10 2.30258509299404568402 /* log_e 10 */ #endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ #endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * @{ + */ + enum AVRounding { AV_ROUND_ZERO = 0, ///< Round toward zero. @@ -52,23 +72,58 @@ enum AVRounding { AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. }; +/** + * Return the greatest common divisor of a and b. + * If both a and b are 0 or either or both are <0 then behavior is + * undefined. + */ int64_t av_const av_gcd(int64_t a, int64_t b); /** - * Rescales a 64-bit integer with rounding to nearest. + * Rescale a 64-bit integer with rounding to nearest. * A simple a*b/c isn't possible as it can overflow. */ int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; /** - * Rescales a 64-bit integer with specified rounding. + * Rescale a 64-bit integer with specified rounding. * A simple a*b/c isn't possible as it can overflow. */ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const; /** - * Rescales a 64-bit integer by 2 rational numbers. + * Rescale a 64-bit integer by 2 rational numbers. */ int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding) av_const; + +/** + * Compare 2 timestamps each in its own timebases. + * The result of the function is undefined if one of the timestamps + * is outside the int64_t range when represented in the others timebase. + * @return -1 if ts_a is before ts_b, 1 if ts_a is after ts_b or 0 if they represent the same position + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare 2 integers modulo mod. + * That is we compare integers a and b for which only the least + * significant log2(mod) bits are known. + * + * @param mod must be a power of 2 + * @return a negative value if a is smaller than b + * a positive value if a is greater than b + * 0 if a equals b + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * @} + */ + #endif /* AVUTIL_MATHEMATICS_H */ diff --git a/extra_lib/include/libavutil/md5.h b/extra_lib/include/libavutil/md5.h new file mode 100644 index 0000000..69199cc --- /dev/null +++ b/extra_lib/include/libavutil/md5.h @@ -0,0 +1,51 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_MD5_H +#define AVUTIL_MD5_H + +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_md5 MD5 + * @ingroup lavu_crypto + * @{ + */ + +#if FF_API_CONTEXT_SIZE +extern attribute_deprecated const int av_md5_size; +#endif + +struct AVMD5; + +struct AVMD5 *av_md5_alloc(void); +void av_md5_init(struct AVMD5 *ctx); +void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, const int len); +void av_md5_final(struct AVMD5 *ctx, uint8_t *dst); +void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len); + +/** + * @} + */ + +#endif /* AVUTIL_MD5_H */ diff --git a/extra_lib/include/libavutil/mem.h b/extra_lib/include/libavutil/mem.h index e50553a..212dbf1 100644 --- a/extra_lib/include/libavutil/mem.h +++ b/extra_lib/include/libavutil/mem.h @@ -19,14 +19,45 @@ */ /** - * @file libavutil/mem.h + * @file * memory handling functions */ #ifndef AVUTIL_MEM_H #define AVUTIL_MEM_H -#include "common.h" +#include + +#include "attributes.h" +#include "error.h" +#include "avutil.h" + +/** + * @addtogroup lavu_mem + * @{ + */ + + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__TI_COMPILER_VERSION__) + #define DECLARE_ALIGNED(n,t,v) \ + AV_PRAGMA(DATA_ALIGN(v,n)) \ + t __attribute__((aligned(n))) v + #define DECLARE_ASM_CONST(n,t,v) \ + AV_PRAGMA(DATA_ALIGN(v,n)) \ + static const t __attribute__((aligned(n))) v +#elif defined(__GNUC__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif #if AV_GCC_VERSION_AT_LEAST(3,1) #define av_malloc_attrib __attribute__((__malloc__)) @@ -34,38 +65,64 @@ #define av_malloc_attrib #endif -#if (!defined(__ICC) || __ICC > 1100) && AV_GCC_VERSION_AT_LEAST(4,3) - #define av_alloc_size(n) __attribute__((alloc_size(n))) +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) #else - #define av_alloc_size(n) + #define av_alloc_size(...) #endif /** - * Allocates a block of \p size bytes with alignment suitable for all + * Allocate a block of size bytes with alignment suitable for all * memory accesses (including vectors if available on the CPU). * @param size Size in bytes for the memory block to be allocated. * @return Pointer to the allocated block, NULL if the block cannot * be allocated. * @see av_mallocz() */ -void *av_malloc(unsigned int size) av_malloc_attrib av_alloc_size(1); +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); /** - * Allocates or reallocates a block of memory. - * If \p ptr is NULL and \p size > 0, allocates a new block. If \p - * size is zero, frees the memory block pointed to by \p ptr. - * @param size Size in bytes for the memory block to be allocated or - * reallocated. + * Helper function to allocate a block of size * nmemb bytes with + * using av_malloc() + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, NULL if the block cannot + * be allocated. + * @see av_malloc() + */ +av_alloc_size(1,2) static inline void *av_malloc_array(size_t nmemb, size_t size) +{ + if (size <= 0 || nmemb >= INT_MAX / size) + return NULL; + return av_malloc(nmemb * size); +} + +/** + * Allocate or reallocate a block of memory. + * If ptr is NULL and size > 0, allocate a new block. If + * size is zero, free the memory block pointed to by ptr. * @param ptr Pointer to a memory block already allocated with * av_malloc(z)() or av_realloc() or NULL. + * @param size Size in bytes for the memory block to be allocated or + * reallocated. * @return Pointer to a newly reallocated block or NULL if the block * cannot be reallocated or the function is used to free the memory block. * @see av_fast_realloc() */ -void *av_realloc(void *ptr, unsigned int size) av_alloc_size(2); +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); /** - * Frees a memory block which has been allocated with av_malloc(z)() or + * Allocate or reallocate a block of memory. + * This function does the same thing as av_realloc, except: + * - It takes two arguments and checks the result of the multiplication for + * integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic "buf = realloc(buf); if (!buf) return -1;". + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Free a memory block which has been allocated with av_malloc(z)() or * av_realloc(). * @param ptr Pointer to the memory block which should be freed. * @note ptr = NULL is explicitly allowed. @@ -75,25 +132,54 @@ void *av_realloc(void *ptr, unsigned int size) av_alloc_size(2); void av_free(void *ptr); /** - * Allocates a block of \p size bytes with alignment suitable for all + * Allocate a block of size bytes with alignment suitable for all * memory accesses (including vectors if available on the CPU) and - * zeroes all the bytes of the block. + * zero all the bytes of the block. * @param size Size in bytes for the memory block to be allocated. * @return Pointer to the allocated block, NULL if it cannot be allocated. * @see av_malloc() */ -void *av_mallocz(unsigned int size) av_malloc_attrib av_alloc_size(1); +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); /** - * Duplicates the string \p s. + * Allocate a block of nmemb * size bytes with alignment suitable for all + * memory accesses (including vectors if available on the CPU) and + * zero all the bytes of the block. + * The allocation will fail if nmemb * size is greater than or equal + * to INT_MAX. + * @param nmemb + * @param size + * @return Pointer to the allocated block, NULL if it cannot be allocated. + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib; + +/** + * Helper function to allocate a block of size * nmemb bytes with + * using av_mallocz() + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, NULL if the block cannot + * be allocated. + * @see av_mallocz() + * @see av_malloc_array() + */ +av_alloc_size(1,2) static inline void *av_mallocz_array(size_t nmemb, size_t size) +{ + if (size <= 0 || nmemb >= INT_MAX / size) + return NULL; + return av_mallocz(nmemb * size); +} + +/** + * Duplicate the string s. * @param s string to be duplicated * @return Pointer to a newly allocated string containing a - * copy of \p s or NULL if the string cannot be allocated. + * copy of s or NULL if the string cannot be allocated. */ char *av_strdup(const char *s) av_malloc_attrib; /** - * Frees a memory block which has been allocated with av_malloc(z)() or + * Free a memory block which has been allocated with av_malloc(z)() or * av_realloc() and set the pointer pointing to it to NULL. * @param ptr Pointer to the pointer to the memory block which should * be freed. @@ -101,4 +187,37 @@ char *av_strdup(const char *s) av_malloc_attrib; */ void av_freep(void *ptr); +/** + * Add an element to a dynamic array. + * + * @param tab_ptr Pointer to the array. + * @param nb_ptr Pointer to the number of elements in the array. + * @param elem Element to be added. + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Multiply two size_t values checking for overflow. + * @return 0 if success, AVERROR(EINVAL) if overflow. + */ +static inline int av_size_mult(size_t a, size_t b, size_t *r) +{ + size_t t = a * b; + /* Hack inspired from glibc: only try the division if nelem and elsize + * are both greater than sqrt(SIZE_MAX). */ + if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) + return AVERROR(EINVAL); + *r = t; + return 0; +} + +/** + * Set the maximum size that may me allocated in one block. + */ +void av_max_alloc(size_t max); + +/** + * @} + */ + #endif /* AVUTIL_MEM_H */ diff --git a/extra_lib/include/libavutil/old_pix_fmts.h b/extra_lib/include/libavutil/old_pix_fmts.h new file mode 100644 index 0000000..57b6992 --- /dev/null +++ b/extra_lib/include/libavutil/old_pix_fmts.h @@ -0,0 +1,171 @@ +/* + * copyright (c) 2006-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OLD_PIX_FMTS_H +#define AVUTIL_OLD_PIX_FMTS_H + +/* + * This header exists to prevent new pixel formats from being accidentally added + * to the deprecated list. + * Do not include it directly. It will be removed on next major bump + * + * Do not add new items to this list. Use the AVPixelFormat enum instead. + */ + PIX_FMT_NONE = AV_PIX_FMT_NONE, + PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + PIX_FMT_GRAY8, ///< Y , 8bpp + PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette + PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range + PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range + PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range + PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing + PIX_FMT_XVMC_MPEG2_IDCT, + PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range + PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0 + PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0 + + PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1 + PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1 + + PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers + PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers + PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + + PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 + PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 + PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1 + PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1 + PIX_FMT_GRAY8A, ///< 8bit gray, 8bit alpha + PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + //the following 10 formats have the disadvantage of needing 1 format for each bit depth, thus + //If you want to support multiple bit depths, then using PIX_FMT_YUV420P16* with the bpp stored separately + //is better + PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_VDA_VLD, ///< hardware decoding through VDA + +#ifdef AV_PIX_FMT_ABI_GIT_MASTER + PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian + PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian + PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big endian + PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian + PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian + PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little endian + +#ifndef AV_PIX_FMT_ABI_GIT_MASTER + PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + PIX_FMT_0RGB=0x123+4, ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB... + PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGB0RGB0... + PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, 0BGR0BGR... + PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGR0BGR0... + PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + + PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big endian + PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little endian + PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big endian + PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little endian + + PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +#endif /* AVUTIL_OLD_PIX_FMTS_H */ diff --git a/extra_lib/include/libavutil/opt.h b/extra_lib/include/libavutil/opt.h new file mode 100644 index 0000000..81fefd9 --- /dev/null +++ b/extra_lib/include/libavutil/opt.h @@ -0,0 +1,637 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "dict.h" +#include "log.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_malloc(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_next() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_next(const AVClass *prev) + * { + * return prev ? NULL : &child_class; + * } + * @endcode + * Putting child_next() and child_class_next() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_next() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_next() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_next() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_next() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This allows to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_CONST = 128, + AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT = MKBETAG('P','F','M','T'), +#if FF_API_OLD_AVOPTIONS + FF_OPT_TYPE_FLAGS = 0, + FF_OPT_TYPE_INT, + FF_OPT_TYPE_INT64, + FF_OPT_TYPE_DOUBLE, + FF_OPT_TYPE_FLOAT, + FF_OPT_TYPE_STRING, + FF_OPT_TYPE_RATIONAL, + FF_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + FF_OPT_TYPE_CONST=128, +#endif +}; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + int flags; +#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding +#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding +#define AV_OPT_FLAG_METADATA 4 ///< some data extracted or inserted into the file like title, comment, ... +#define AV_OPT_FLAG_AUDIO_PARAM 8 +#define AV_OPT_FLAG_VIDEO_PARAM 16 +#define AV_OPT_FLAG_SUBTITLE_PARAM 32 +#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering +//FIXME think about enc-audio, ... style flags + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +#if FF_API_FIND_OPT +/** + * Look for an option in obj. Look only for the options which + * have the flags set as specified in mask and flags (that is, + * for which it is the case that opt->flags & mask == flags). + * + * @param[in] obj a pointer to a struct whose first element is a + * pointer to an AVClass + * @param[in] name the name of the option to look for + * @param[in] unit the unit of the option to look for, or any if NULL + * @return a pointer to the option found, or NULL if no option + * has been found + * + * @deprecated use av_opt_find. + */ +attribute_deprecated +const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int mask, int flags); +#endif + +#if FF_API_OLD_AVOPTIONS +/** + * Set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an + * AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. If the field is not of a string + * type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * @param[out] o_out if non-NULL put here a pointer to the AVOption + * found + * @param alloc this parameter is currently ignored + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + * @deprecated use av_opt_set() + */ +attribute_deprecated +int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out); + +attribute_deprecated const AVOption *av_set_double(void *obj, const char *name, double n); +attribute_deprecated const AVOption *av_set_q(void *obj, const char *name, AVRational n); +attribute_deprecated const AVOption *av_set_int(void *obj, const char *name, int64_t n); + +double av_get_double(void *obj, const char *name, const AVOption **o_out); +AVRational av_get_q(void *obj, const char *name, const AVOption **o_out); +int64_t av_get_int(void *obj, const char *name, const AVOption **o_out); +attribute_deprecated const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len); +attribute_deprecated const AVOption *av_next_option(void *obj, const AVOption *last); +#endif + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +#if FF_API_OLD_AVOPTIONS +attribute_deprecated +void av_opt_set_defaults2(void *s, int mask, int flags); +#endif + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); +/** + * Free all string and binary options in obj. + */ +void av_opt_free(void *obj); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +/* + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#define AV_OPT_SEARCH_CHILDREN 0x0001 /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ 0x0002 + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_set_string3(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param prev result of a previous call to this function or NULL + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double(void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +/** + * @} + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return 0 on success, a negative error code otherwise + */ +/** + * @note the returned string will av_malloc()ed and must be av_free()ed by the caller + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +/** + * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/extra_lib/include/libavutil/parseutils.h b/extra_lib/include/libavutil/parseutils.h new file mode 100644 index 0000000..da7d345 --- /dev/null +++ b/extra_lib/include/libavutil/parseutils.h @@ -0,0 +1,173 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PARSEUTILS_H +#define AVUTIL_PARSEUTILS_H + +#include + +#include "rational.h" + +/** + * @file + * misc parsing utilities + */ + +/** + * Parse str and store the parsed ratio in q. + * + * Note that a ratio with infinite (1/0) or negative value is + * considered valid, so you should check on the returned value if you + * want to exclude those values. + * + * The undefined value can be expressed using the "0:0" string. + * + * @param[in,out] q pointer to the AVRational which will contain the ratio + * @param[in] str the string to parse: it has to be a string in the format + * num:den, a float number or an expression + * @param[in] max the maximum allowed numerator and denominator + * @param[in] log_offset log level offset which is applied to the log + * level of log_ctx + * @param[in] log_ctx parent logging context + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx); + +#define av_parse_ratio_quiet(rate, str, max) \ + av_parse_ratio(rate, str, max, AV_LOG_MAX_OFFSET, NULL) + +/** + * Parse str and put in width_ptr and height_ptr the detected values. + * + * @param[in,out] width_ptr pointer to the variable which will contain the detected + * width value + * @param[in,out] height_ptr pointer to the variable which will contain the detected + * height value + * @param[in] str the string to parse: it has to be a string in the format + * width x height or a valid video size abbreviation. + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str); + +/** + * Parse str and store the detected values in *rate. + * + * @param[in,out] rate pointer to the AVRational which will contain the detected + * frame rate + * @param[in] str the string to parse: it has to be a string in the format + * rate_num / rate_den, a float number or a valid video rate abbreviation + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_video_rate(AVRational *rate, const char *str); + +/** + * Put the RGBA values that correspond to color_string in rgba_color. + * + * @param color_string a string specifying a color. It can be the name of + * a color (case insensitive match) or a [0x|#]RRGGBB[AA] sequence, + * possibly followed by "@" and a string representing the alpha + * component. + * The alpha component may be a string composed by "0x" followed by an + * hexadecimal number or a decimal number between 0.0 and 1.0, which + * represents the opacity value (0x00/0.0 means completely transparent, + * 0xff/1.0 completely opaque). + * If the alpha component is not specified then 0xff is assumed. + * The string "random" will result in a random color. + * @param slen length of the initial part of color_string containing the + * color. It can be set to -1 if color_string is a null terminated string + * containing nothing else than the color. + * @return >= 0 in case of success, a negative value in case of + * failure (for example if color_string cannot be parsed). + */ +int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, + void *log_ctx); + +/** + * Parse timestr and return in *time a corresponding number of + * microseconds. + * + * @param timeval puts here the number of microseconds corresponding + * to the string in timestr. If the string represents a duration, it + * is the number of microseconds contained in the time interval. If + * the string is a date, is the number of microseconds since 1st of + * January, 1970 up to the time of the parsed date. If timestr cannot + * be successfully parsed, set *time to INT64_MIN. + + * @param timestr a string representing a date or a duration. + * - If a date the syntax is: + * @code + * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH:MM:SS[.m...]]]}|{HHMMSS[.m...]]]}}[Z] + * now + * @endcode + * If the value is "now" it takes the current time. + * Time is local time unless Z is appended, in which case it is + * interpreted as UTC. + * If the year-month-day part is not specified it takes the current + * year-month-day. + * - If a duration the syntax is: + * @code + * [-]HH:MM:SS[.m...]]] + * [-]S+[.m...] + * @endcode + * @param duration flag which tells how to interpret timestr, if not + * zero timestr is interpreted as a duration, otherwise as a date + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_parse_time(int64_t *timeval, const char *timestr, int duration); + +/** + * Parse the input string p according to the format string fmt and + * store its results in the structure dt. + * This implementation supports only a subset of the formats supported + * by the standard strptime(). + * + * In particular it actually supports the parameters: + * - %H: the hour as a decimal number, using a 24-hour clock, in the + * range '00' through '23' + * - %M: the minute as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %S: the second as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %Y: the year as a decimal number, using the Gregorian calendar + * - %m: the month as a decimal number, in the range '1' through '12' + * - %d: the day of the month as a decimal number, in the range '1' + * through '31' + * - %%: a literal '%' + * + * @return a pointer to the first character not processed in this + * function call, or NULL in case the function fails to match all of + * the fmt string and therefore an error occurred + */ +char *av_small_strptime(const char *p, const char *fmt, struct tm *dt); + +/** + * Attempt to find a specific tag in a URL. + * + * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. + * Return 1 if found. + */ +int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); + +/** + * Convert the decomposed UTC time in tm to a time_t value. + */ +time_t av_timegm(struct tm *tm); + +#endif /* AVUTIL_PARSEUTILS_H */ diff --git a/extra_lib/include/libavutil/pixdesc.h b/extra_lib/include/libavutil/pixdesc.h new file mode 100644 index 0000000..ccbee9b --- /dev/null +++ b/extra_lib/include/libavutil/pixdesc.h @@ -0,0 +1,209 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include +#include "pixfmt.h" + +typedef struct AVComponentDescriptor{ + uint16_t plane :2; ///< which of the 4 planes contains the component + + /** + * Number of elements between 2 horizontally consecutive pixels minus 1. + * Elements are bits for bitstream formats, bytes otherwise. + */ + uint16_t step_minus1 :3; + + /** + * Number of elements before the component of the first pixel plus 1. + * Elements are bits for bitstream formats, bytes otherwise. + */ + uint16_t offset_plus1 :3; + uint16_t shift :3; ///< number of least significant bits that must be shifted away to get the value + uint16_t depth_minus1 :4; ///< number of bits in the component minus 1 +}AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor{ + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = -((-luma_width) >> log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; ///< chroma_width = -((-luma_width )>>log2_chroma_w) + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= -((-luma_height) >> log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + uint8_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 2 or 4 components, then alpha is last. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components, + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + */ + AVComponentDescriptor comp[4]; +}AVPixFmtDescriptor; + +#define PIX_FMT_BE 1 ///< Pixel format is big-endian. +#define PIX_FMT_PAL 2 ///< Pixel format has a palette in data[1], values are indexes in this palette. +#define PIX_FMT_BITSTREAM 4 ///< All values of a component are bit-wise packed end to end. +#define PIX_FMT_HWACCEL 8 ///< Pixel format is an HW accelerated format. +#define PIX_FMT_PLANAR 16 ///< At least one pixel component is not in the first data plane +#define PIX_FMT_RGB 32 ///< The pixel format contains RGB-like data (as opposed to YUV/grayscale) +/** + * The pixel format is "pseudo-paletted". This means that FFmpeg treats it as + * paletted internally, but the palette is generated by the decoder and is not + * stored in the file. + */ +#define PIX_FMT_PSEUDOPAL 64 + +#if FF_API_PIX_FMT_DESC +/** + * The array of all the pixel format descriptors. + */ +extern const AVPixFmtDescriptor av_pix_fmt_descriptors[]; +#endif + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + */ +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], const int linesize[4], + const AVPixFmtDescriptor *desc, int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + */ +void av_write_image_line(const uint16_t *src, uint8_t *data[4], const int linesize[4], + const AVPixFmtDescriptor *desc, int x, int y, int c, int w); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or an header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string (char *buf, int buf_size, enum AVPixelFormat pix_fmt); + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/extra_lib/include/libavutil/pixfmt.h b/extra_lib/include/libavutil/pixfmt.h index 4995a4d..ef7a16a 100644 --- a/extra_lib/include/libavutil/pixfmt.h +++ b/extra_lib/include/libavutil/pixfmt.h @@ -22,22 +22,28 @@ #define AVUTIL_PIXFMT_H /** - * @file libavutil/pixfmt.h + * @file * pixel format definitions * - * @warning This file has to be considered an internal but installed - * header, so it should not be directly included in your projects. */ +#include "libavutil/avconfig.h" +#include "libavutil/version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + /** - * Pixel format. Notes: + * Pixel format. * + * @note * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA * color is put together as: * (A << 24) | (R << 16) | (G << 8) | B * This is stored as BGRA on little-endian CPU architectures and ARGB on * big-endian CPUs. * + * @par * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized * image data is stored in AVFrame.data[0]. The palette is transported in * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is @@ -47,105 +53,275 @@ * This is important as many custom PAL8 video codecs that were designed * to run on the IBM VGA graphics adapter use 6-bit palette components. * + * @par * For all the 8bit per pixel formats, an RGB32 palette is in data[1] like * for pal8. This palette is filled in automatically by the function * allocating the picture. * - * Note, make sure that all newly added big endian formats have pix_fmt&1==1 - * and that all newly added little endian formats have pix_fmt&1==0 - * this allows simpler detection of big vs little endian. + * @note + * make sure that all newly added big endian formats have pix_fmt&1==1 + * and that all newly added little endian formats have pix_fmt&1==0 + * this allows simpler detection of big vs little endian. */ -enum PixelFormat { - PIX_FMT_NONE= -1, - PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) - PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr - PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... - PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... - PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) - PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) - PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) - PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) - PIX_FMT_GRAY8, ///< Y , 8bpp - PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black - PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white - PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette - PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG) - PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG) - PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG) - PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing - PIX_FMT_XVMC_MPEG2_IDCT, - PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 - PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 - PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) - PIX_FMT_BGR4, ///< packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb) - PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) - PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) - PIX_FMT_RGB4, ///< packed RGB 1:2:1, 4bpp, (msb)1R 2G 1B(lsb) - PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) - PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV - PIX_FMT_NV21, ///< as above, but U and V bytes are swapped - - PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... - PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... - PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... - PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... - - PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian - PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian - PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) - PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG) - PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) - PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, big-endian - PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, little-endian - - PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian - PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian - PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0 - PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0 - - PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian - PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian - PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1 - PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1 - - PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers - PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers - PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers - - PIX_FMT_YUV420PLE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian - PIX_FMT_YUV420PBE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian - PIX_FMT_YUV422PLE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian - PIX_FMT_YUV422PBE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian - PIX_FMT_YUV444PLE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian - PIX_FMT_YUV444PBE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian - PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing + AV_PIX_FMT_XVMC_MPEG2_IDCT, + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0 + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0 + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1 + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1 + + AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers + AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers + AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1 + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1 + AV_PIX_FMT_GRAY8A, ///< 8bit gray, 8bit alpha + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + //the following 10 formats have the disadvantage of needing 1 format for each bit depth, thus + //If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately + //is better + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_VDA_VLD, ///< hardware decoding through VDA + +#ifdef AV_PIX_FMT_ABI_GIT_MASTER + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little endian + + /** + * duplicated pixel formats for compatibility with libav. + * FFmpeg supports these formats since May 8 2012 and Jan 28 2012 (commits f9ca1ac7 and 143a5c55) + * Libav added them Oct 12 2012 with incompatible values (commit 6d5600e85) + */ + AV_PIX_FMT_YUVA422P_LIBAV, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P_LIBAV, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + +#ifndef AV_PIX_FMT_ABI_GIT_MASTER + AV_PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + AV_PIX_FMT_0RGB=0x123+4, ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB... + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGB0RGB0... + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, 0BGR0BGR... + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGR0BGR0... + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little endian + + AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions + +#if FF_API_PIX_FMT +#include "old_pix_fmts.h" +#endif }; -#ifdef WORDS_BIGENDIAN -# define PIX_FMT_NE(be, le) PIX_FMT_##be +#if AV_HAVE_INCOMPATIBLE_FORK_ABI +#define AV_PIX_FMT_YUVA422P AV_PIX_FMT_YUVA422P_LIBAV +#define AV_PIX_FMT_YUVA444P AV_PIX_FMT_YUVA444P_LIBAV +#endif + + +#define AV_PIX_FMT_Y400A AV_PIX_FMT_GRAY8A +#define AV_PIX_FMT_GBR24P AV_PIX_FMT_GBRP + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be #else -# define PIX_FMT_NE(be, le) PIX_FMT_##le +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le #endif -#define PIX_FMT_RGB32 PIX_FMT_NE(ARGB, BGRA) -#define PIX_FMT_RGB32_1 PIX_FMT_NE(RGBA, ABGR) -#define PIX_FMT_BGR32 PIX_FMT_NE(ABGR, RGBA) -#define PIX_FMT_BGR32_1 PIX_FMT_NE(BGRA, ARGB) - -#define PIX_FMT_GRAY16 PIX_FMT_NE(GRAY16BE, GRAY16LE) -#define PIX_FMT_RGB48 PIX_FMT_NE(RGB48BE, RGB48LE) -#define PIX_FMT_RGB565 PIX_FMT_NE(RGB565BE, RGB565LE) -#define PIX_FMT_RGB555 PIX_FMT_NE(RGB555BE, RGB555LE) -#define PIX_FMT_BGR565 PIX_FMT_NE(BGR565BE, BGR565LE) -#define PIX_FMT_BGR555 PIX_FMT_NE(BGR555BE, BGR555LE) - -#define PIX_FMT_YUV420P16 PIX_FMT_NE(YUV420PBE, YUV420PLE) -#define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422PBE, YUV422PLE) -#define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444PBE, YUV444PLE) +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) + +#if FF_API_PIX_FMT +#define PixelFormat AVPixelFormat + +#define PIX_FMT_Y400A AV_PIX_FMT_Y400A +#define PIX_FMT_GBR24P AV_PIX_FMT_GBR24P + +#define PIX_FMT_NE(be, le) AV_PIX_FMT_NE(be, le) + +#define PIX_FMT_RGB32 AV_PIX_FMT_RGB32 +#define PIX_FMT_RGB32_1 AV_PIX_FMT_RGB32_1 +#define PIX_FMT_BGR32 AV_PIX_FMT_BGR32 +#define PIX_FMT_BGR32_1 AV_PIX_FMT_BGR32_1 +#define PIX_FMT_0RGB32 AV_PIX_FMT_0RGB32 +#define PIX_FMT_0BGR32 AV_PIX_FMT_0BGR32 + +#define PIX_FMT_GRAY16 AV_PIX_FMT_GRAY16 +#define PIX_FMT_RGB48 AV_PIX_FMT_RGB48 +#define PIX_FMT_RGB565 AV_PIX_FMT_RGB565 +#define PIX_FMT_RGB555 AV_PIX_FMT_RGB555 +#define PIX_FMT_RGB444 AV_PIX_FMT_RGB444 +#define PIX_FMT_BGR48 AV_PIX_FMT_BGR48 +#define PIX_FMT_BGR565 AV_PIX_FMT_BGR565 +#define PIX_FMT_BGR555 AV_PIX_FMT_BGR555 +#define PIX_FMT_BGR444 AV_PIX_FMT_BGR444 + +#define PIX_FMT_YUV420P9 AV_PIX_FMT_YUV420P9 +#define PIX_FMT_YUV422P9 AV_PIX_FMT_YUV422P9 +#define PIX_FMT_YUV444P9 AV_PIX_FMT_YUV444P9 +#define PIX_FMT_YUV420P10 AV_PIX_FMT_YUV420P10 +#define PIX_FMT_YUV422P10 AV_PIX_FMT_YUV422P10 +#define PIX_FMT_YUV444P10 AV_PIX_FMT_YUV444P10 +#define PIX_FMT_YUV420P12 AV_PIX_FMT_YUV420P12 +#define PIX_FMT_YUV422P12 AV_PIX_FMT_YUV422P12 +#define PIX_FMT_YUV444P12 AV_PIX_FMT_YUV444P12 +#define PIX_FMT_YUV420P14 AV_PIX_FMT_YUV420P14 +#define PIX_FMT_YUV422P14 AV_PIX_FMT_YUV422P14 +#define PIX_FMT_YUV444P14 AV_PIX_FMT_YUV444P14 +#define PIX_FMT_YUV420P16 AV_PIX_FMT_YUV420P16 +#define PIX_FMT_YUV422P16 AV_PIX_FMT_YUV422P16 +#define PIX_FMT_YUV444P16 AV_PIX_FMT_YUV444P16 + +#define PIX_FMT_RGBA64 AV_PIX_FMT_RGBA64 +#define PIX_FMT_BGRA64 AV_PIX_FMT_BGRA64 +#define PIX_FMT_GBRP9 AV_PIX_FMT_GBRP9 +#define PIX_FMT_GBRP10 AV_PIX_FMT_GBRP10 +#define PIX_FMT_GBRP12 AV_PIX_FMT_GBRP12 +#define PIX_FMT_GBRP14 AV_PIX_FMT_GBRP14 +#define PIX_FMT_GBRP16 AV_PIX_FMT_GBRP16 +#endif #endif /* AVUTIL_PIXFMT_H */ diff --git a/extra_lib/include/libavutil/random_seed.h b/extra_lib/include/libavutil/random_seed.h new file mode 100644 index 0000000..0462a04 --- /dev/null +++ b/extra_lib/include/libavutil/random_seed.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009 Baptiste Coudurier + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_RANDOM_SEED_H +#define AVUTIL_RANDOM_SEED_H + +#include +/** + * @addtogroup lavu_crypto + * @{ + */ + +/** + * Get a seed to use in conjunction with random functions. + * This function tries to provide a good seed at a best effort bases. + * Its possible to call this function multiple times if more bits are needed. + * It can be quite slow, which is why it should only be used as seed for a faster + * PRNG. The quality of the seed depends on the platform. + */ +uint32_t av_get_random_seed(void); + +/** + * @} + */ + +#endif /* AVUTIL_RANDOM_SEED_H */ diff --git a/extra_lib/include/libavutil/rational.h b/extra_lib/include/libavutil/rational.h index 048202b..417e29e 100644 --- a/extra_lib/include/libavutil/rational.h +++ b/extra_lib/include/libavutil/rational.h @@ -20,7 +20,7 @@ */ /** - * @file libavutil/rational.h + * @file * rational numbers * @author Michael Niedermayer */ @@ -28,10 +28,14 @@ #ifndef AVUTIL_RATIONAL_H #define AVUTIL_RATIONAL_H -#if !defined(WIN32) && !defined(_WIN32_WCE) #include -#endif -#include "common.h" +#include +#include "attributes.h" + +/** + * @addtogroup lavu_math + * @{ + */ /** * rational number numerator/denominator @@ -42,20 +46,23 @@ typedef struct AVRational{ } AVRational; /** - * Compares two rationals. + * Compare two rationals. * @param a first rational * @param b second rational - * @return 0 if a==b, 1 if a>b and -1 if ab, -1 if a>63)|1; - else return 0; + if(tmp) return ((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; } /** - * Converts rational to double. + * Convert rational to double. * @param a rational to convert * @return (double) a */ @@ -64,7 +71,7 @@ static inline double av_q2d(AVRational a){ } /** - * Reduces a fraction. + * Reduce a fraction. * This is useful for framerate calculations. * @param dst_num destination numerator * @param dst_den destination denominator @@ -76,7 +83,7 @@ static inline double av_q2d(AVRational a){ int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); /** - * Multiplies two rationals. + * Multiply two rationals. * @param b first rational * @param c second rational * @return b*c @@ -84,7 +91,7 @@ int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max) AVRational av_mul_q(AVRational b, AVRational c) av_const; /** - * Divides one rational by another. + * Divide one rational by another. * @param b first rational * @param c second rational * @return b/c @@ -92,7 +99,7 @@ AVRational av_mul_q(AVRational b, AVRational c) av_const; AVRational av_div_q(AVRational b, AVRational c) av_const; /** - * Adds two rationals. + * Add two rationals. * @param b first rational * @param c second rational * @return b+c @@ -100,7 +107,7 @@ AVRational av_div_q(AVRational b, AVRational c) av_const; AVRational av_add_q(AVRational b, AVRational c) av_const; /** - * Subtracts one rational from another. + * Subtract one rational from another. * @param b first rational * @param c second rational * @return b-c @@ -108,7 +115,20 @@ AVRational av_add_q(AVRational b, AVRational c) av_const; AVRational av_sub_q(AVRational b, AVRational c) av_const; /** - * Converts a double precision floating point number to a rational. + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * inf is expressed as {1,0} or {-1,0} depending on the sign. + * * @param d double to convert * @param max the maximum allowed numerator and denominator * @return (AVRational) d @@ -116,16 +136,20 @@ AVRational av_sub_q(AVRational b, AVRational c) av_const; AVRational av_d2q(double d, int max) av_const; /** - * @return 1 if \q1 is nearer to \p q than \p q2, -1 if \p q2 is nearer - * than \p q1, 0 if they have the same distance. + * @return 1 if q1 is nearer to q than q2, -1 if q2 is nearer + * than q1, 0 if they have the same distance. */ int av_nearer_q(AVRational q, AVRational q1, AVRational q2); /** - * Finds the nearest value in \p q_list to \p q. + * Find the nearest value in q_list to q. * @param q_list an array of rationals terminated by {0, 0} * @return the index of the nearest value found in the array */ int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); +/** + * @} + */ + #endif /* AVUTIL_RATIONAL_H */ diff --git a/extra_lib/include/libavutil/samplefmt.h b/extra_lib/include/libavutil/samplefmt.h new file mode 100644 index 0000000..17300d1 --- /dev/null +++ b/extra_lib/include/libavutil/samplefmt.h @@ -0,0 +1,240 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +#include "avutil.h" +#include "attributes.h" + +/** + * Audio Sample Formats + * + * @par + * The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * @par + * The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * @par + * The data layout as used in av_samples_fill_arrays() and elsewhere in Libav + * (such as AVFrame in libavcodec) is as follows: + * + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +#if FF_API_GET_BITS_PER_SAMPLE_FMT +/** + * @deprecated Use av_get_bytes_per_sample() instead. + */ +attribute_deprecated +int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt); +#endif + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return 0 on success or a negative error code on failure + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return 0 on success or a negative error code on failure + * @see av_samples_fill_arrays() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/extra_lib/include/libavutil/sha.h b/extra_lib/include/libavutil/sha.h new file mode 100644 index 0000000..744c66f --- /dev/null +++ b/extra_lib/include/libavutil/sha.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_SHA_H +#define AVUTIL_SHA_H + +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_sha SHA + * @ingroup lavu_crypto + * @{ + */ + +#if FF_API_CONTEXT_SIZE +extern attribute_deprecated const int av_sha_size; +#endif + +struct AVSHA; + +/** + * Allocate an AVSHA context. + */ +struct AVSHA *av_sha_alloc(void); + +/** + * Initialize SHA-1 or SHA-2 hashing. + * + * @param context pointer to the function context (of size av_sha_size) + * @param bits number of bits in digest (SHA-1 - 160 bits, SHA-2 224 or 256 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_sha_init(struct AVSHA* context, int bits); + +/** + * Update hash value. + * + * @param context hash function context + * @param data input data to update hash with + * @param len input data length + */ +void av_sha_update(struct AVSHA* context, const uint8_t* data, unsigned int len); + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_sha_final(struct AVSHA* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_SHA_H */ diff --git a/extra_lib/include/libavutil/time.h b/extra_lib/include/libavutil/time.h new file mode 100644 index 0000000..90eb436 --- /dev/null +++ b/extra_lib/include/libavutil/time.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2000-2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_TIME_H +#define AVUTIL_TIME_H + +#include + +/** + * Get the current time in microseconds. + */ +int64_t av_gettime(void); + +/** + * Sleep for a period of time. Although the duration is expressed in + * microseconds, the actual delay may be rounded to the precision of the + * system timer. + * + * @param usec Number of microseconds to sleep. + * @return zero on success or (negative) error code. + */ +int av_usleep(unsigned usec); + +#endif /* AVUTIL_TIME_H */ diff --git a/extra_lib/include/libavutil/timecode.h b/extra_lib/include/libavutil/timecode.h new file mode 100644 index 0000000..17d6b95 --- /dev/null +++ b/extra_lib/include/libavutil/timecode.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2006 Smartjog S.A.S, Baptiste Coudurier + * Copyright (c) 2011-2012 Smartjog S.A.S, Clément Bœsch + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Timecode helpers header + */ + +#ifndef AVUTIL_TIMECODE_H +#define AVUTIL_TIMECODE_H + +#include +#include "rational.h" + +#define AV_TIMECODE_STR_SIZE 16 + +enum AVTimecodeFlag { + AV_TIMECODE_FLAG_DROPFRAME = 1<<0, ///< timecode is drop frame + AV_TIMECODE_FLAG_24HOURSMAX = 1<<1, ///< timecode wraps after 24 hours + AV_TIMECODE_FLAG_ALLOWNEGATIVE = 1<<2, ///< negative time values are allowed +}; + +typedef struct { + int start; ///< timecode frame start (first base frame number) + uint32_t flags; ///< flags such as drop frame, +24 hours support, ... + AVRational rate; ///< frame rate in rational form + unsigned fps; ///< frame per second; must be consistent with the rate field +} AVTimecode; + +/** + * Adjust frame number for NTSC drop frame time code. + * + * @param framenum frame number to adjust + * @return adjusted frame number + * @warning adjustment is only valid in NTSC 29.97 + * @deprecated use av_timecode_adjust_ntsc_framenum2 instead + */ +attribute_deprecated int av_timecode_adjust_ntsc_framenum(int framenum); + +/** + * Adjust frame number for NTSC drop frame time code. + * + * @param framenum frame number to adjust + * @param fps frame per second, 30 or 60 + * @return adjusted frame number + * @warning adjustment is only valid in NTSC 29.97 and 59.94 + */ +int av_timecode_adjust_ntsc_framenum2(int framenum, int fps); + +/** + * Convert frame number to SMPTE 12M binary representation. + * + * @param tc timecode data correctly initialized + * @param framenum frame number + * @return the SMPTE binary representation + * + * @note Frame number adjustment is automatically done in case of drop timecode, + * you do NOT have to call av_timecode_adjust_ntsc_framenum(). + * @note The frame number is relative to tc->start. + * @note Color frame (CF), binary group flags (BGF) and biphase mark polarity + * correction (PC) bits are set to zero. + */ +uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum); + +/** + * Load timecode string in buf. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tc timecode data correctly initialized + * @param framenum frame number + * @return the buf parameter + * + * @note Timecode representation can be a negative timecode and have more than + * 24 hours, but will only be honored if the flags are correctly set. + * @note The frame number is relative to tc->start. + */ +char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum); + +/** + * Get the timecode string from the SMPTE timecode format. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tcsmpte the 32-bit SMPTE timecode + * @param prevent_df prevent the use of a drop flag when it is known the DF bit + * is arbitrary + * @return the buf parameter + */ +char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df); + +/** + * Get the timecode string from the 25-bit timecode format (MPEG GOP format). + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tc25bit the 25-bits timecode + * @return the buf parameter + */ +char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit); + +/** + * Init a timecode struct with the passed parameters. + * + * @param log_ctx a pointer to an arbitrary struct of which the first field + * is a pointer to an AVClass struct (used for av_log) + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param flags miscellaneous flags such as drop frame, +24 hours, ... + * (see AVTimecodeFlag) + * @param frame_start the first frame number + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx); + +/** + * Parse timecode representation (hh:mm:ss[:;.]ff). + * + * @param log_ctx a pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct (used for av_log). + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param str timecode string which will determine the frame start + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx); + +/** + * Check if the timecode feature is available for the given frame rate + * + * @return 0 if supported, <0 otherwise + */ +int av_timecode_check_frame_rate(AVRational rate); + +#endif /* AVUTIL_TIMECODE_H */ diff --git a/extra_lib/include/libavutil/timestamp.h b/extra_lib/include/libavutil/timestamp.h new file mode 100644 index 0000000..c7348d8 --- /dev/null +++ b/extra_lib/include/libavutil/timestamp.h @@ -0,0 +1,74 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * timestamp utils, mostly useful for debugging/logging purposes + */ + +#ifndef AVUTIL_TIMESTAMP_H +#define AVUTIL_TIMESTAMP_H + +#include "common.h" + +#define AV_TS_MAX_STRING_SIZE 32 + +/** + * Fill the provided buffer with a string containing a timestamp + * representation. + * + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE + * @param ts the timestamp to represent + * @return the buffer in input + */ +static inline char *av_ts_make_string(char *buf, int64_t ts) +{ + if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); + else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%"PRId64"", ts); + return buf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts) + +/** + * Fill the provided buffer with a string containing a timestamp time + * representation. + * + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE + * @param ts the timestamp to represent + * @param tb the timebase of the timestamp + * @return the buffer in input + */ +static inline char *av_ts_make_time_string(char *buf, int64_t ts, AVRational *tb) +{ + if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); + else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.6g", av_q2d(*tb) * ts); + return buf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb) + +#endif /* AVUTIL_TIMESTAMP_H */ diff --git a/extra_lib/include/libavutil/version.h b/extra_lib/include/libavutil/version.h new file mode 100644 index 0000000..3e9c17f --- /dev/null +++ b/extra_lib/include/libavutil/version.h @@ -0,0 +1,138 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +/** + * @defgroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +#define AV_PRAGMA(s) _Pragma(#s) + +/** + * @} + */ + +/** + * @defgroup version_utils Library Version Macros + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) (a<<16 | b<<8 | c) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * @} + */ + + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 51 +#define LIBAVUTIL_VERSION_MINOR 76 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @} + * + * @defgroup depr_guards Deprecation guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @{ + */ + +#ifndef FF_API_OLD_EVAL_NAMES +#define FF_API_OLD_EVAL_NAMES (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_GET_BITS_PER_SAMPLE_FMT +#define FF_API_GET_BITS_PER_SAMPLE_FMT (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_FIND_OPT +#define FF_API_FIND_OPT (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_AV_FIFO_PEEK +#define FF_API_AV_FIFO_PEEK (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_OLD_AVOPTIONS +#define FF_API_OLD_AVOPTIONS (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_OLD_TC_ADJUST_FRAMENUM +#define FF_API_OLD_TC_ADJUST_FRAMENUM (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_PIX_FMT +#define FF_API_PIX_FMT (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_CONTEXT_SIZE +#define FF_API_CONTEXT_SIZE (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_PIX_FMT_DESC +#define FF_API_PIX_FMT_DESC (LIBAVUTIL_VERSION_MAJOR < 52) +#endif +#ifndef FF_API_AV_REVERSE +#define FF_API_AV_REVERSE (LIBAVUTIL_VERSION_MAJOR < 52) +#endif + +/** + * @} + */ + +#endif /* AVUTIL_VERSION_H */ + diff --git a/extra_lib/include/libavutil/xtea.h b/extra_lib/include/libavutil/xtea.h new file mode 100644 index 0000000..0899c92 --- /dev/null +++ b/extra_lib/include/libavutil/xtea.h @@ -0,0 +1,62 @@ +/* + * A 32-bit implementation of the XTEA algorithm + * Copyright (c) 2012 Samuel Pitoiset + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_XTEA_H +#define AVUTIL_XTEA_H + +#include + +/** + * @defgroup lavu_xtea XTEA + * @ingroup lavu_crypto + * @{ + */ + +typedef struct AVXTEA { + uint32_t key[16]; +} AVXTEA; + +/** + * Initialize an AVXTEA context. + * + * @param ctx an AVXTEA context + * @param key a key of 16 bytes used for encryption/decryption + */ +void av_xtea_init(struct AVXTEA *ctx, const uint8_t key[16]); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * + * @param ctx an AVXTEA context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_xtea_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_XTEA_H */ diff --git a/extra_lib/include/libswscale/swscale.h b/extra_lib/include/libswscale/swscale.h index f5856c3..ea2116c 100644 --- a/extra_lib/include/libswscale/swscale.h +++ b/extra_lib/include/libswscale/swscale.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2003 Michael Niedermayer + * Copyright (C) 2001-2011 Michael Niedermayer * * This file is part of FFmpeg. * @@ -22,31 +22,32 @@ #define SWSCALE_SWSCALE_H /** - * @file libswscale/swscale.h + * @file * @brief * external api for the swscale stuff */ -#include "libavutil/avutil.h" +#include -#define LIBSWSCALE_VERSION_MAJOR 0 -#define LIBSWSCALE_VERSION_MINOR 7 -#define LIBSWSCALE_VERSION_MICRO 1 +#include "libavutil/avutil.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "version.h" -#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ - LIBSWSCALE_VERSION_MINOR, \ - LIBSWSCALE_VERSION_MICRO) -#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ - LIBSWSCALE_VERSION_MINOR, \ - LIBSWSCALE_VERSION_MICRO) -#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT +/** + * Return the LIBSWSCALE_VERSION_INT constant. + */ +unsigned swscale_version(void); -#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) +/** + * Return the libswscale build-time configuration. + */ +const char *swscale_configuration(void); /** - * Returns the LIBSWSCALE_VERSION_INT constant. + * Return the libswscale license. */ -unsigned swscale_version(void); +const char *swscale_license(void); /* values for the flags, the stuff on the command line is different */ #define SWS_FAST_BILINEAR 1 @@ -77,11 +78,21 @@ unsigned swscale_version(void); #define SWS_ACCURATE_RND 0x40000 #define SWS_BITEXACT 0x80000 +#if FF_API_SWS_CPU_CAPS +/** + * CPU caps are autodetected now, those flags + * are only provided for API compatibility. + */ #define SWS_CPU_CAPS_MMX 0x80000000 +#define SWS_CPU_CAPS_MMXEXT 0x20000000 +#if LIBSWSCALE_VERSION_MAJOR < 3 #define SWS_CPU_CAPS_MMX2 0x20000000 +#endif #define SWS_CPU_CAPS_3DNOW 0x40000000 #define SWS_CPU_CAPS_ALTIVEC 0x10000000 #define SWS_CPU_CAPS_BFIN 0x01000000 +#define SWS_CPU_CAPS_SSE2 0x02000000 +#endif #define SWS_MAX_REDUCE_CUTOFF 0.002 @@ -93,17 +104,24 @@ unsigned swscale_version(void); #define SWS_CS_SMPTE240M 7 #define SWS_CS_DEFAULT 5 - +/** + * Return a pointer to yuv<->rgb coefficients for the given colorspace + * suitable for sws_setColorspaceDetails(). + * + * @param colorspace One of the SWS_CS_* macros. If invalid, + * SWS_CS_DEFAULT is used. + */ +const int *sws_getCoefficients(int colorspace); // when used for filters they must have an odd number of elements // coeffs cannot be shared between vectors -typedef struct { +typedef struct SwsVector { double *coeff; ///< pointer to the list of coefficients int length; ///< number of coefficients in the vector } SwsVector; // vectors can be shared -typedef struct { +typedef struct SwsFilter { SwsVector *lumH; SwsVector *lumV; SwsVector *chrH; @@ -112,10 +130,42 @@ typedef struct { struct SwsContext; +/** + * Return a positive value if pix_fmt is a supported input format, 0 + * otherwise. + */ +int sws_isSupportedInput(enum AVPixelFormat pix_fmt); + +/** + * Return a positive value if pix_fmt is a supported output format, 0 + * otherwise. + */ +int sws_isSupportedOutput(enum AVPixelFormat pix_fmt); + +/** + * Allocate an empty SwsContext. This must be filled and passed to + * sws_init_context(). For filling see AVOptions, options.c and + * sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initialize the swscaler context sws_context. + * + * @return zero or positive value on success, a negative value on + * error + */ +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + +/** + * Free the swscaler context swsContext. + * If swsContext is NULL, then does nothing. + */ void sws_freeContext(struct SwsContext *swsContext); +#if FF_API_SWS_GETCONTEXT /** - * Allocates and returns a SwsContext. You need it to perform + * Allocate and return an SwsContext. You need it to perform * scaling/conversion operations using sws_scale(). * * @param srcW the width of the source image @@ -126,18 +176,26 @@ void sws_freeContext(struct SwsContext *swsContext); * @param dstFormat the destination image format * @param flags specify which algorithm and options to use for rescaling * @return a pointer to an allocated context, or NULL in case of error + * @note this function is to be removed after a saner alternative is + * written + * @deprecated Use sws_getCachedContext() instead. */ -struct SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, - int dstW, int dstH, enum PixelFormat dstFormat, +struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param); +#endif /** - * Scales the image slice in \p srcSlice and puts the resulting scaled - * slice in the image in \p dst. A slice is a sequence of consecutive + * Scale the image slice in srcSlice and put the resulting scaled + * slice in the image in dst. A slice is a sequence of consecutive * rows in an image. * - * @param context the scaling context previously created with + * Slices have to be provided in sequential order, either in + * top-bottom or bottom-top order. If slices are provided in + * non-sequential order the behavior of the function is undefined. + * + * @param c the scaling context previously created with * sws_getContext() * @param srcSlice the array containing the pointers to the planes of * the source slice @@ -154,20 +212,18 @@ struct SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat * the destination image * @return the height of the output slice */ -int sws_scale(struct SwsContext *context, uint8_t* srcSlice[], int srcStride[], - int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]); -#if LIBSWSCALE_VERSION_MAJOR < 1 -/** - * @deprecated Use sws_scale() instead. - */ -int sws_scale_ordered(struct SwsContext *context, uint8_t* src[], - int srcStride[], int srcSliceY, int srcSliceH, - uint8_t* dst[], int dstStride[]) attribute_deprecated; -#endif +int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], + const int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *const dst[], const int dstStride[]); /** - * @param inv_table the yuv2rgb coefficients, normally ff_yuv2rgb_coeffs[x] - * @param fullRange if 1 then the luma range is 0..255 if 0 it is 16..235 + * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg) + * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg) + * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x] + * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x] + * @param brightness 16.16 fixed point brightness correction + * @param contrast 16.16 fixed point contrast correction + * @param saturation 16.16 fixed point saturation correction * @return -1 if not supported */ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], @@ -182,31 +238,35 @@ int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, int *brightness, int *contrast, int *saturation); /** - * Returns a normalized Gaussian curve used to filter stuff - * quality=3 is high quality, lower is lower quality. + * Allocate and return an uninitialized vector with length coefficients. + */ +SwsVector *sws_allocVec(int length); + +/** + * Return a normalized Gaussian curve used to filter stuff + * quality = 3 is high quality, lower is lower quality. */ SwsVector *sws_getGaussianVec(double variance, double quality); /** - * Allocates and returns a vector with \p length coefficients, all - * with the same value \p c. + * Allocate and return a vector with length coefficients, all + * with the same value c. */ SwsVector *sws_getConstVec(double c, int length); /** - * Allocates and returns a vector with just one coefficient, with + * Allocate and return a vector with just one coefficient, with * value 1.0. */ SwsVector *sws_getIdentityVec(void); /** - * Scales all the coefficients of \p a by the \p scalar value. + * Scale all the coefficients of a by the scalar value. */ void sws_scaleVec(SwsVector *a, double scalar); /** - * Scales all the coefficients of \p a so that their sum equals \p - * height." + * Scale all the coefficients of a so that their sum equals height. */ void sws_normalizeVec(SwsVector *a, double height); void sws_convVec(SwsVector *a, SwsVector *b); @@ -215,21 +275,14 @@ void sws_subVec(SwsVector *a, SwsVector *b); void sws_shiftVec(SwsVector *a, int shift); /** - * Allocates and returns a clone of the vector \p a, that is a vector - * with the same coefficients as \p a. + * Allocate and return a clone of the vector a, that is a vector + * with the same coefficients as a. */ SwsVector *sws_cloneVec(SwsVector *a); -#if LIBSWSCALE_VERSION_MAJOR < 1 -/** - * @deprecated Use sws_printVec2() instead. - */ -attribute_deprecated void sws_printVec(SwsVector *a); -#endif - /** - * Prints with av_log() a textual representation of the vector \p a - * if \p log_level <= av_log_level. + * Print with av_log() a textual representation of the vector a + * if log_level <= av_log_level. */ void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level); @@ -242,22 +295,53 @@ SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, void sws_freeFilter(SwsFilter *filter); /** - * Checks if \p context can be reused, otherwise reallocates a new - * one. + * Check if context can be reused, otherwise reallocate a new one. * - * If \p context is NULL, just calls sws_getContext() to get a new + * If context is NULL, just calls sws_getContext() to get a new * context. Otherwise, checks if the parameters are the ones already - * saved in \p context. If that is the case, returns the current - * context. Otherwise, frees \p context and gets a new context with + * saved in context. If that is the case, returns the current + * context. Otherwise, frees context and gets a new context with * the new parameters. * - * Be warned that \p srcFilter and \p dstFilter are not checked, they + * Be warned that srcFilter and dstFilter are not checked, they * are assumed to remain the same. */ struct SwsContext *sws_getCachedContext(struct SwsContext *context, - int srcW, int srcH, enum PixelFormat srcFormat, - int dstW, int dstH, enum PixelFormat dstFormat, + int srcW, int srcH, enum AVPixelFormat srcFormat, + int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param); +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits. + * + * The output frame will have the same packed format as the palette. + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits. + * + * With the palette format "ABCD", the destination frame ends up with the format "ABC". + * + * @param src source frame buffer + * @param dst destination frame buffer + * @param num_pixels number of pixels to convert + * @param palette array with [256] entries, which must match color arrangement (RGB or BGR) of src + */ +void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette); + +/** + * Get the AVClass for swsContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *sws_get_class(void); + #endif /* SWSCALE_SWSCALE_H */ diff --git a/extra_lib/include/libswscale/version.h b/extra_lib/include/libswscale/version.h new file mode 100644 index 0000000..37dcc96 --- /dev/null +++ b/extra_lib/include/libswscale/version.h @@ -0,0 +1,59 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_VERSION_H +#define SWSCALE_VERSION_H + +/** + * @file + * swscale version macros + */ + +#include "libavutil/avutil.h" + +#define LIBSWSCALE_VERSION_MAJOR 2 +#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MICRO 101 + +#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_VERSION AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \ + LIBSWSCALE_VERSION_MINOR, \ + LIBSWSCALE_VERSION_MICRO) +#define LIBSWSCALE_BUILD LIBSWSCALE_VERSION_INT + +#define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#ifndef FF_API_SWS_GETCONTEXT +#define FF_API_SWS_GETCONTEXT (LIBSWSCALE_VERSION_MAJOR < 3) +#endif +#ifndef FF_API_SWS_CPU_CAPS +#define FF_API_SWS_CPU_CAPS (LIBSWSCALE_VERSION_MAJOR < 3) +#endif +#ifndef FF_API_SWS_FORMAT_NAME +#define FF_API_SWS_FORMAT_NAME (LIBSWSCALE_VERSION_MAJOR < 3) +#endif + +#endif /* SWSCALE_VERSION_H */ diff --git a/extra_lib/include/platinum/NptStack.h b/extra_lib/include/platinum/NptStack.h index 034b3ec..933c12c 100644 --- a/extra_lib/include/platinum/NptStack.h +++ b/extra_lib/include/platinum/NptStack.h @@ -48,7 +48,7 @@ class NPT_Stack : public NPT_List public: // methods NPT_Result Push(const T& value) { - return Add(value); + return this->Add(value); } NPT_Result Peek(T& value) { diff --git a/generate_installer.bat b/generate_installer.bat index dfc5f3e..8493fbd 100644 --- a/generate_installer.bat +++ b/generate_installer.bat @@ -21,17 +21,17 @@ echo: REM ============================================ echo Retrieving version/revision information REM ============================================ -if not exist include/gpac/version.h echo version couldn't be found - check include/gpac/version.h exists -if not exist include/gpac/version.h goto Abort +if not exist include/gpac/revision.h echo version couldn't be found - check include/gpac/revision.h exists +if not exist include/gpac/revision.h goto Abort -REM execute svnversion and check if the result if found within version.h +REM execute svnversion and check if the result if found within revision.h for /f "delims=" %%i in ('svnversion.exe') do Set VarRevisionSVN=%%i REM 'M', 'S', 'P', ':' are special 'svnversion' results for /f "delims=" %%i in ('echo %VarRevisionSVN% ^| findstr /i /r M^"') do goto RevisionAbort for /f "delims=" %%i in ('echo %VarRevisionSVN% ^| findstr /i /r S^"') do goto RevisionAbort for /f "delims=" %%i in ('echo %VarRevisionSVN% ^| findstr /i /r P^"') do goto RevisionAbort for /f "delims=" %%i in ('echo %VarRevisionSVN% ^| findstr /i /r :^"') do goto RevisionAbort -for /f "delims=" %%i in ('type include\gpac\version.h ^| findstr /i /r "%VarRevisionSVN%"') do Set VarRevisionBuild=%%i +for /f "delims=" %%i in ('type include\gpac\revision.h ^| findstr /i /r "%VarRevisionSVN%"') do Set VarRevisionBuild=%%i echo VarRevisionBuild = %VarRevisionBuild% echo VarRevisionSVN = %VarRevisionSVN% if !"%VarRevisionBuild%"==!"%VarRevisionSVN%" echo local revision and last build revision are not congruent - please consider rebuilding before generating an installer diff --git a/include/gpac/avparse.h b/include/gpac/avparse.h index eeb1afa..3bd79e6 100644 --- a/include/gpac/avparse.h +++ b/include/gpac/avparse.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Authoring Tools sub-project diff --git a/include/gpac/base_coding.h b/include/gpac/base_coding.h index ee02e9c..7db5141 100644 --- a/include/gpac/base_coding.h +++ b/include/gpac/base_coding.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/bifs.h b/include/gpac/bifs.h index 94fc4c0..7f2b7cb 100644 --- a/include/gpac/bifs.h +++ b/include/gpac/bifs.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/include/gpac/bitstream.h b/include/gpac/bitstream.h index 5186288..69fd493 100644 --- a/include/gpac/bitstream.h +++ b/include/gpac/bitstream.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -88,6 +89,26 @@ GF_BitStream *gf_bs_from_file(FILE *f, u32 mode); */ void gf_bs_del(GF_BitStream *bs); +/*! + * \brief sets bitstream write cache size + * + * Sets the write cache size for file-based bitstreams. + * \param bs the target bitstream + * \param size size of the write cache in bytes + * \return error if any. + */ +GF_Err gf_bs_set_output_buffering(GF_BitStream *bs, u32 size); + + +/*! + * \brief gets bitstream write cache size + * + * Gets the write cache size for file-based bitstreams. + * \param bs the target bitstream + * \return size of the write cache in bytes, 0 if no cache + */ +u32 gf_bs_get_output_buffering(GF_BitStream *bs); + /*! * \brief integer reading * diff --git a/include/gpac/cache.h b/include/gpac/cache.h index e2b8cca..cf85b02 100644 --- a/include/gpac/cache.h +++ b/include/gpac/cache.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre, Pierre Souchay + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/color.h b/include/gpac/color.h index 5197062..13c8be9 100644 --- a/include/gpac/color.h +++ b/include/gpac/color.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools interfaces diff --git a/include/gpac/compositor.h b/include/gpac/compositor.h index ea55d1f..e0ba680 100644 --- a/include/gpac/compositor.h +++ b/include/gpac/compositor.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -159,6 +160,9 @@ Bool gf_sc_script_action(GF_Compositor *sr, u32 type, GF_Node *n, GF_JSAPIParam void gf_sc_reload_audio_filters(GF_Compositor *compositor); +Bool gf_sc_uri_is_hardcoded_proto(GF_Compositor *compositor, const char *uri); + + #ifdef __cplusplus } #endif diff --git a/include/gpac/config_file.h b/include/gpac/config_file.h index e1384a2..02415ea 100644 --- a/include/gpac/config_file.h +++ b/include/gpac/config_file.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/configuration.h b/include/gpac/configuration.h index c4f6eb1..320d552 100644 --- a/include/gpac/configuration.h +++ b/include/gpac/configuration.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2008 - + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2008-2012 * All rights reserved * * This file is part of GPAC diff --git a/include/gpac/constants.h b/include/gpac/constants.h index 601fe93..eab19e1 100644 --- a/include/gpac/constants.h +++ b/include/gpac/constants.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / exported constants @@ -543,7 +544,8 @@ enum #define GF_AVC_NALU_SVC_SUBSEQ_PARAM 15 #define GF_AVC_NALU_SLICE_AUX 19 -#define GF_AVC_NALU_SVC_SLICE 0x14 +#define GF_AVC_NALU_SVC_SLICE 20 //0x14 + /*#define GF_SVC_NALU_SLICE 0x14 #define GF_SVC_NALU_NAL_EXT_PARAM 14 diff --git a/include/gpac/crypt.h b/include/gpac/crypt.h index 6518c83..54ba9b2 100644 --- a/include/gpac/crypt.h +++ b/include/gpac/crypt.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Crypto Tools sub-project diff --git a/include/gpac/dash.h b/include/gpac/dash.h new file mode 100644 index 0000000..2f865cf --- /dev/null +++ b/include/gpac/dash.h @@ -0,0 +1,228 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2012 + * All rights reserved + * + * This file is part of GPAC / Adaptive HTTP Streaming sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#ifndef _GF_DASH_H_ +#define _GF_DASH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef GPAC_DISABLE_DASH_CLIENT + +/*! + * All the possible Mime-types for MPD files + */ +static const char * GF_DASH_MPD_MIME_TYPES[] = { "application/dash+xml", "video/vnd.3gpp.mpd", "audio/vnd.3gpp.mpd", NULL }; + +/*! + * All the possible Mime-types for M3U8 files + */ +static const char * GF_DASH_M3U8_MIME_TYPES[] = { "video/x-mpegurl", "audio/x-mpegurl", "application/x-mpegurl", "application/vnd.apple.mpegurl", NULL}; + +typedef enum +{ + /*event sent if an error occurs when setting up manifest*/ + GF_DASH_EVENT_MANIFEST_INIT_ERROR, + /*event sent before groups first segment is fetched - user shall decide which group to select at this point*/ + GF_DASH_EVENT_SELECT_GROUPS, + /*event sent if an error occurs during period setup - the download thread will exit at this point*/ + GF_DASH_EVENT_PERIOD_SETUP_ERROR, + /*event sent once the first segment of each selected group is fetched - user should load playback chain(s) at this point*/ + GF_DASH_EVENT_CREATE_PLAYBACK, + /*event sent when reseting groups at period switch or at exit - user should unload playback chain(s) at this point*/ + GF_DASH_EVENT_DESTROY_PLAYBACK, +} GF_DASHEventType; + +/*structure used for all IO operations for DASH*/ +typedef struct _gf_dash_io GF_DASHFileIO; +typedef void *GF_DASHFileIOSession; + +struct _gf_dash_io +{ + /*user private data*/ + void *udta; + + /*signals errors or specific actions to perform*/ + GF_Err (*on_dash_event)(GF_DASHFileIO *dashio, GF_DASHEventType evt, GF_Err setup_error); + + /*called whenever a file has to be deleted*/ + void (*delete_cache_file)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, const char *cache_url); + + /*create a file download session for the given resource*/ + GF_DASHFileIOSession (*create)(GF_DASHFileIO *dashio, Bool persistent, const char *url); + /*delete a file download session*/ + void (*del)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*aborts downloading in the given file session*/ + void (*abort)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*resetup the file session with a new resource to get - this allows persistent connection usage with HTTP servers*/ + GF_Err (*setup_from_url)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, const char *url); + /*set download range for the file session*/ + GF_Err (*set_range)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, u64 start_range, u64 end_range); + /*initialize the file session - all the headers shall be fetched before returning*/ + GF_Err (*init)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*download the content - synchronous call: all the file shall be fetched before returning*/ + GF_Err (*run)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + + /*get URL of the file - i tmay be different from the original one if resource relocation happened*/ + const char *(*get_url)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*get the name of the cache file. If NULL is returned, the file cannot be cached and its associated UTL will be used when + the client request file to play*/ + const char *(*get_cache_name)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*get the MIME type of the file*/ + const char *(*get_mime)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*get the average download rate for the session*/ + u32 (*get_bytes_per_sec)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); + /*get the totla size on bytes for the session*/ + u32 (*get_total_size)(GF_DASHFileIO *dashio, GF_DASHFileIOSession session); +}; + +typedef struct __dash_client GF_DashClient; + +typedef enum +{ + GF_DASH_SELECT_QUALITY_LOWEST, + GF_DASH_SELECT_QUALITY_HIGHEST, + GF_DASH_SELECT_BANDWIDTH_LOWEST, + GF_DASH_SELECT_BANDWIDTH_HIGHEST +} GF_DASHInitialSelectionMode; + +/*create a new DASH client: + @dash_io: DASH callbacks to the user + @max_cache_duration_sec: maximum duration in seconds for the cached media + @auto_switch_count: forces representation switching every auto_switch_count segments + @keep_files: do not delete files from the cache + @disable_switching: turn off bandwidth switching algorithm + @first_select_mode: indicates which representation to select upon startup +*/ +GF_DashClient *gf_dash_new(GF_DASHFileIO *dash_io, + u32 max_cache_duration_sec, + u32 auto_switch_count, + Bool keep_files, + Bool disable_switching, + GF_DASHInitialSelectionMode first_select_mode); + +/*delete the DASH client*/ +void gf_dash_del(GF_DashClient *dash); + +/*open the DASH client for the specific manifest file*/ +GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url); +/*closes the dash client*/ +void gf_dash_close(GF_DashClient *dash); + +/*returns URL of the DASH manifest file*/ +const char *gf_dash_get_url(GF_DashClient *dash); + +/*get title and source for this MPD*/ +void gf_dash_get_info(GF_DashClient *dash, const char **title, const char **source); + +/*switches quality up or down*/ +void gf_dash_switch_quality(GF_DashClient *dash, Bool switch_up); + +/*indicates whether the DASH client is running or not. For the moment, the DASH client is always run by an internal thread*/ +Bool gf_dash_is_running(GF_DashClient *dash); + +/*get duration of the presentation*/ +Double gf_dash_get_duration(GF_DashClient *dash); +/*check that the given file has the right XML root element*/ +Bool gf_dash_check_mpd_root_type(const char *local_url); + + +/*returns the number of groups. A group is a set of media resources that are alternate of each other in terms of bandwidth/quality.*/ +u32 gf_dash_get_group_count(GF_DashClient *dash); +/*associate user data (or NULL) with this group*/ +GF_Err gf_dash_set_group_udta(GF_DashClient *dash, u32 group_index, void *udta); +/*returns the user data associated with this group*/ +void *gf_dash_get_group_udta(GF_DashClient *dash, u32 group_index); +/*indicates whether a group is selected for playback or not. Currently groups cannot be selected during playback*/ +Bool gf_dash_is_group_selected(GF_DashClient *dash, u32 group_index); + +/*selects a group for playback. If other groups are alternate to this group (through the @group attribute), they are automatically deselected. */ +void gf_dash_group_select(GF_DashClient *dash, u32 idx, Bool select); + +/*performs selection of representations based on language code*/ +void gf_dash_groups_set_language(GF_DashClient *dash, const char *lang_3cc); + +/*returns the mime type of the media resources in this group*/ +const char *gf_dash_group_get_segment_mime(GF_DashClient *dash, u32 idx); +/*returns the URL of tyhe first media resource to play (init segment or first media segment depending on format). start_range and end_range are optional*/ +const char *gf_dash_group_get_segment_init_url(GF_DashClient *dash, u32 idx, u64 *start_range, u64 *end_range); + +/*returns the URL and byte range of the next media resource to play in this group. +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 +original_url is optional and may be used to het the URI of the segment +*/ +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); +/*discards the first media resource in the queue of this group*/ +void gf_dash_group_discard_segment(GF_DashClient *dash, u32 idx); +/*get the number of media resources available in the cache for this group*/ +u32 gf_dash_group_get_num_segments_ready(GF_DashClient *dash, u32 idx, Bool *group_is_done); +/*get the maximum number of media resources that can be put in the cache for this group*/ +u32 gf_dash_group_get_max_segments_in_cache(GF_DashClient *dash, u32 idx); +/*indicates to the DASH engine that the group playback has been stopped by the user*/ +void gf_dash_set_group_done(GF_DashClient *dash, u32 idx, Bool done); +/*gets presentationTimeOffset and timescale for the active representation*/ +GF_Err gf_dash_group_get_presentation_time_offset(GF_DashClient *dash, u32 idx, u64 *presentation_time_offset, u32 *timescale); + +/*returns 1 if the playback position is in the last period of the presentation*/ +Bool gf_dash_in_last_period(GF_DashClient *dash); +/*return value: + 1 if the period switching has been requested (due to seeking), + 2 if the switching is in progress (all groups will soon be destroyed and plyback will be stoped and restarted) + 0 if no switching is requested +*/ +u32 gf_dash_get_period_switch_status(GF_DashClient *dash); +/*request period switch - this is typically called when the media engine signals that no more data is available for playback*/ +void gf_dash_request_period_switch(GF_DashClient *dash); +/*returns 1 if the DASH engine is currently setting up a period (creating groups and fetching initial segments)*/ +Bool gf_dash_in_period_setup(GF_DashClient *dash); +/*seeks playback to the given time. If period changes, all playback is stopped and restarted*/ +void gf_dash_seek(GF_DashClient *dash, Double start_range); +/*gets playback start range for the first segment to play after the seek has been done. This is the amount of data to skip from the first segment to be played*/ +Double gf_dash_get_playback_start_range(GF_DashClient *dash); +/*when seeking, this flag is set when the seek is outside of the previously playing segment.*/ +Bool gf_dash_group_segment_switch_forced(GF_DashClient *dash, u32 idx); + +/*returns the start_time of the first segment in the queue (usually the one being played)*/ +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*/ +void gf_dash_allow_local_mpd_update(GF_DashClient *dash, Bool allow_local_mpd_update); + + +#endif //GPAC_DISABLE_DASH_CLIENT + + +#ifdef __cplusplus +} +#endif + +#endif /*_GF_DASH_H_*/ + diff --git a/include/gpac/download.h b/include/gpac/download.h index 5d5380f..a28f9d2 100644 --- a/include/gpac/download.h +++ b/include/gpac/download.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -47,7 +48,7 @@ extern "C" { #endif #include -#include +#include #include @@ -413,7 +414,7 @@ extern "C" { * \return GF_OK if everything went fine, an error otherwise */ GF_Err gf_dm_wget_with_cache(GF_DownloadManager * dm, - const char *url, const char *filename); + const char *url, const char *filename, u64 start_range, u64 end_range); /*! * \brief Same as gf_dm_wget_with_cache, but initializes the GF_DownloadManager by itself. @@ -422,7 +423,7 @@ extern "C" { * \param filename The filename to download * \return GF_OK if everything went fine, an error otherwise */ - GF_Err gf_dm_wget(const char *url, const char *filename); + GF_Err gf_dm_wget(const char *url, const char *filename, u64 start_range, u64 end_range); /*! *\brief Reset session diff --git a/include/gpac/dsmcc.h b/include/gpac/dsmcc.h index 3812761..ae43750 100644 --- a/include/gpac/dsmcc.h +++ b/include/gpac/dsmcc.h @@ -1,9 +1,29 @@ -/* - * Copyright (c) TELECOM ParisTech 2011 +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jonathan Sillan + * Copyright (c) Telecom ParisTech 2011-2012 + * All rights reserved + * + * This file is part of GPAC / common tools sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * */ - #ifndef _GF_DSMCC_H_ #define _GF_DSMCC_H_ diff --git a/include/gpac/dvb_mpe.h b/include/gpac/dvb_mpe.h index f96664e..2151836 100644 --- a/include/gpac/dvb_mpe.h +++ b/include/gpac/dvb_mpe.h @@ -1,12 +1,13 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Walid B.H - Jean Le Feuvre - * Copyright (c)2006-200X ENST - All rights reserved + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2006-2012 + * All rights reserved * * This file is part of GPAC / MPEG2-TS sub-project * - * GPAC is gf_free software; you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the gf_free Software Foundation; either version 2, or (at your option) * any later version. diff --git a/include/gpac/esi.h b/include/gpac/esi.h index e2f8e77..bb110d3 100644 --- a/include/gpac/esi.h +++ b/include/gpac/esi.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2006-2012 * All rights reserved * * This file is part of GPAC / Elementary Stream Interface sub-project diff --git a/include/gpac/events.h b/include/gpac/events.h index 2fbe8ed..ef58600 100644 --- a/include/gpac/events.h +++ b/include/gpac/events.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Events management diff --git a/include/gpac/events_constants.h b/include/gpac/events_constants.h index f1693fd..56b3549 100644 --- a/include/gpac/events_constants.h +++ b/include/gpac/events_constants.h @@ -1,136 +1,136 @@ -/* - * GPAC - Multimedia Framework C SDK - * - * Copyright (c) Jean Le Feuvre 2000-2005 - * Copyright (c) Telecom-Paristech 2005-20xx - * All rights reserved - * - * This file is part of GPAC / Events management - * - * GPAC is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * GPAC is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#ifndef _GF_EVENTS_CONSTANTS_H_ -#define _GF_EVENTS_CONSTANTS_H_ - - - -/* - minimal event system - - DO NOT CHANGE THEIR POSITION IN THE LIST, USED TO SPEED UP FILTERING OF USER INPUT EVENTS -*/ - -/*events*/ -enum { - - /****************************************************** - - Events used for both GPAC internals and DOM Events - - *******************************************************/ - /*MouseEvents*/ - GF_EVENT_CLICK, - GF_EVENT_MOUSEUP, - GF_EVENT_MOUSEDOWN, - GF_EVENT_MOUSEOVER, - GF_EVENT_MOUSEOUT, - /*!! ALL MOUSE EVENTS SHALL BE DECLARED BEFORE MOUSEMOVE !! */ - GF_EVENT_MOUSEMOVE, - /*mouse wheel event*/ - GF_EVENT_MOUSEWHEEL, - - /*Key Events*/ - GF_EVENT_KEYUP, - GF_EVENT_KEYDOWN, /* covers KeyDown, KeyPress and AccessKey */ - GF_EVENT_LONGKEYPRESS, - /*character input*/ - GF_EVENT_TEXTINPUT, - - - /****************************************************** - - Events used for DOM Events only - - *******************************************************/ - GF_EVENT_TEXTSELECT, - - /*DOM UIEvents*/ - GF_EVENT_FOCUSIN, - GF_EVENT_FOCUSOUT, - GF_EVENT_ACTIVATE, - GF_EVENT_CHANGE, - GF_EVENT_FOCUS, - GF_EVENT_BLUR, - /*SVG (HTML) Events*/ - GF_EVENT_LOAD, - GF_EVENT_UNLOAD, - GF_EVENT_ABORT, - GF_EVENT_ERROR, - GF_EVENT_RESIZE, - GF_EVENT_SCROLL, - GF_EVENT_ZOOM, - GF_EVENT_BEGIN, /*this is a fake event, it is NEVER fired, only used in SMIL begin*/ - GF_EVENT_BEGIN_EVENT, - GF_EVENT_END, /*this is a fake event, it is NEVER fired, only used in SMIL end*/ - GF_EVENT_END_EVENT, - GF_EVENT_REPEAT, /*this is a fake event, it is NEVER fired, only used in SMIL repeat*/ - GF_EVENT_REPEAT_EVENT, - - /*DOM MutationEvents - NOT SUPPORTED YET*/ - GF_EVENT_TREE_MODIFIED, - GF_EVENT_NODE_INSERTED, - GF_EVENT_NODE_REMOVED, - GF_EVENT_NODE_INSERTED_DOC, - GF_EVENT_NODE_REMOVED_DOC, - GF_EVENT_ATTR_MODIFIED, - GF_EVENT_CHAR_DATA_MODIFIED, - GF_EVENT_NODE_NAME_CHANGED, - GF_EVENT_ATTR_NAME_CHANGED, - - GF_EVENT_DCCI_PROP_CHANGE, - - /*LASeR events*/ - GF_EVENT_ACTIVATED, - GF_EVENT_DEACTIVATED, - GF_EVENT_PAUSE, - GF_EVENT_PAUSED_EVENT, - GF_EVENT_PLAY, - GF_EVENT_REPEAT_KEY, - GF_EVENT_RESUME_EVENT, - GF_EVENT_SHORT_ACCESSKEY, - /*pseudo-event, only used in LASeR coding*/ - GF_EVENT_EXECUTION_TIME, - - /*MediaAccess events - cf http://www.w3.org/TR/MediaAccessEvents*/ -#if 0 - GF_EVENT_MEDIA_BEGIN_SESSION_SETUP, - GF_EVENT_MEDIA_END_SESSION_SETUP, - GF_EVENT_MEDIA_DATA_REQUEST, - GF_EVENT_MEDIA_PLAYABLE, - GF_EVENT_MEDIA_NOT_PLAYABLE, - GF_EVENT_MEDIA_DATA_PROGRESS, - GF_EVENT_MEDIA_END_OF_DATA, - GF_EVENT_MEDIA_STOP, - GF_EVENT_MEDIA_ERROR, -#endif - - /*HTML5 media events*/ - +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved + * + * This file is part of GPAC / Events management + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#ifndef _GF_EVENTS_CONSTANTS_H_ +#define _GF_EVENTS_CONSTANTS_H_ + + + +/* + minimal event system + + DO NOT CHANGE THEIR POSITION IN THE LIST, USED TO SPEED UP FILTERING OF USER INPUT EVENTS +*/ + +/*events*/ +enum { + + /****************************************************** + + Events used for both GPAC internals and DOM Events + + *******************************************************/ + /*MouseEvents*/ + GF_EVENT_CLICK, + GF_EVENT_MOUSEUP, + GF_EVENT_MOUSEDOWN, + GF_EVENT_MOUSEOVER, + GF_EVENT_MOUSEOUT, + /*!! ALL MOUSE EVENTS SHALL BE DECLARED BEFORE MOUSEMOVE !! */ + GF_EVENT_MOUSEMOVE, + /*mouse wheel event*/ + GF_EVENT_MOUSEWHEEL, + + /*Key Events*/ + GF_EVENT_KEYUP, + GF_EVENT_KEYDOWN, /* covers KeyDown, KeyPress and AccessKey */ + GF_EVENT_LONGKEYPRESS, + /*character input*/ + GF_EVENT_TEXTINPUT, + + + /****************************************************** + + Events used for DOM Events only + + *******************************************************/ + GF_EVENT_TEXTSELECT, + + /*DOM UIEvents*/ + GF_EVENT_FOCUSIN, + GF_EVENT_FOCUSOUT, + GF_EVENT_ACTIVATE, + GF_EVENT_CHANGE, + GF_EVENT_FOCUS, + GF_EVENT_BLUR, + /*SVG (HTML) Events*/ + GF_EVENT_LOAD, + GF_EVENT_UNLOAD, + GF_EVENT_ABORT, + GF_EVENT_ERROR, + GF_EVENT_RESIZE, + GF_EVENT_SCROLL, + GF_EVENT_ZOOM, + GF_EVENT_BEGIN, /*this is a fake event, it is NEVER fired, only used in SMIL begin*/ + GF_EVENT_BEGIN_EVENT, + GF_EVENT_END, /*this is a fake event, it is NEVER fired, only used in SMIL end*/ + GF_EVENT_END_EVENT, + GF_EVENT_REPEAT, /*this is a fake event, it is NEVER fired, only used in SMIL repeat*/ + GF_EVENT_REPEAT_EVENT, + + /*DOM MutationEvents - NOT SUPPORTED YET*/ + GF_EVENT_TREE_MODIFIED, + GF_EVENT_NODE_INSERTED, + GF_EVENT_NODE_REMOVED, + GF_EVENT_NODE_INSERTED_DOC, + GF_EVENT_NODE_REMOVED_DOC, + GF_EVENT_ATTR_MODIFIED, + GF_EVENT_CHAR_DATA_MODIFIED, + GF_EVENT_NODE_NAME_CHANGED, + GF_EVENT_ATTR_NAME_CHANGED, + + GF_EVENT_DCCI_PROP_CHANGE, + + /*LASeR events*/ + GF_EVENT_ACTIVATED, + GF_EVENT_DEACTIVATED, + GF_EVENT_PAUSE, + GF_EVENT_PAUSED_EVENT, + GF_EVENT_PLAY, + GF_EVENT_REPEAT_KEY, + GF_EVENT_RESUME_EVENT, + GF_EVENT_SHORT_ACCESSKEY, + /*pseudo-event, only used in LASeR coding*/ + GF_EVENT_EXECUTION_TIME, + + /*MediaAccess events - cf http://www.w3.org/TR/MediaAccessEvents*/ +#if 0 + GF_EVENT_MEDIA_BEGIN_SESSION_SETUP, + GF_EVENT_MEDIA_END_SESSION_SETUP, + GF_EVENT_MEDIA_DATA_REQUEST, + GF_EVENT_MEDIA_PLAYABLE, + GF_EVENT_MEDIA_NOT_PLAYABLE, + GF_EVENT_MEDIA_DATA_PROGRESS, + GF_EVENT_MEDIA_END_OF_DATA, + GF_EVENT_MEDIA_STOP, + GF_EVENT_MEDIA_ERROR, +#endif + + /*HTML5 media events*/ + GF_EVENT_MEDIA_SETUP_BEGIN, /*not HTML5 but should be :)*/ GF_EVENT_MEDIA_SETUP_DONE, /*not HTML5 but should be :)*/ GF_EVENT_MEDIA_LOAD_START, @@ -152,349 +152,349 @@ enum { GF_EVENT_MEDIA_TIME_UPDATE, GF_EVENT_MEDIA_RATECHANGE, GF_EVENT_MEDIA_VOLUME_CHANGED, - - GF_EVENT_BATTERY, - GF_EVENT_CPU, - GF_EVENT_UNKNOWN, - - - /****************************************************** - - Events used for GPAC internals only - - *******************************************************/ - - /*same as mousedown, generated internally by GPAC*/ - GF_EVENT_DBLCLICK, - - /*scene attached event, dispatched when the root node of a scene is loaded and - attached to the window or parent object (animation, inline, ...)*/ - GF_EVENT_SCENE_ATTACHED, - - /*VP resize attached event, dispatched when viewport of a scene is being modified - attached to the window or parent object (animation, inline, ...)*/ - GF_EVENT_VP_RESIZE, - - /*window events*/ - /*size has changed - indicate new w & h in .x end .y fields of event. - When sent from gpac to a video plugin, indicates the output size should be changed. This is only sent when the plugin - manages the output video himself - When sent from a video plugin to gpac, indicates the output size has been changed. This is only sent when the plugin - manages the output video himself - */ - GF_EVENT_SIZE, - /*signals the scene size (if indicated in scene) upon connection (sent to the user event proc only) - if scene size hasn't changed (seeking or other) this event is not sent - */ - GF_EVENT_SCENE_SIZE, - GF_EVENT_SHOWHIDE, /*window show/hide (minimized or other). This is also sent to the user to signal focus switch in fullscreen*/ - GF_EVENT_SET_CURSOR, /*set mouse cursor*/ - GF_EVENT_SET_CAPTION, /*set window caption*/ - GF_EVENT_MOVE, /*move window*/ - GF_EVENT_REFRESH, /*window needs repaint (whenever needed, eg restore, hide->show, background refresh, paint)*/ - GF_EVENT_QUIT, /*window is being closed*/ - /*video hw setup message: - - when sent from gpac to plugin, indicates that the plugin should re-setup hardware context due to a window resize: - * for 2D output, this means resizing the backbuffer if needed (depending on HW constraints) - * for 3D output, this means re-setup of OpenGL context (depending on HW constraints). Depending on windowing systems - and implementations, it could be possible to resize a window without destroying the GL context. - - - when sent from plugin to gpac, indicates that hardware resources must be resetup before next render step (this is mainly - due to discard all openGL textures and cached objects) - */ - GF_EVENT_VIDEO_SETUP, - /*queries the list of system colors - only exchanged between compositor and video output*/ - GF_EVENT_SYS_COLORS, - - /*indicates some text has been pasted - from video output to compositor only*/ - GF_EVENT_PASTE_TEXT, - /*queries for text to be copied - from video output to compositor only*/ - GF_EVENT_COPY_TEXT, - - /*terminal events*/ - GF_EVENT_CONNECT, /*signal URL is connected*/ - GF_EVENT_DURATION, /*signal duration of presentation*/ - GF_EVENT_EOS, /*signal End of scene playback*/ - GF_EVENT_AUTHORIZATION, /*indicates a user and pass is queried*/ - GF_EVENT_NAVIGATE, /*indicates the user app should load or jump to the given URL.*/ - GF_EVENT_NAVIGATE_INFO, /*indicates the link or its description under the mouse pointer*/ - GF_EVENT_MESSAGE, /*message from the MPEG-4 terminal*/ - GF_EVENT_PROGRESS, /*progress message from the MPEG-4 terminal*/ - GF_EVENT_FORWARDED, /*event forwarded by service (MPEG-2, RTP, ...)*/ - GF_EVENT_VIEWPOINTS, /*indicates viewpoint list has changed - no struct associated*/ - GF_EVENT_STREAMLIST, /*indicates stream list has changed - no struct associated - only used when no scene info is present*/ - GF_EVENT_METADATA, /*indicates a change in associated metadata*/ - GF_EVENT_MIGRATE, /*indicates a session migration request*/ - GF_EVENT_DISCONNECT, /*indicates the current url should be disconnected*/ - GF_EVENT_RESOLUTION, /*indicates the screen resolution has changed*/ - GF_EVENT_OPENFILE, - /* Events for Keyboad */ - GF_EVENT_TEXT_EDITING_START, - GF_EVENT_TEXT_EDITING_END -}; - -/*GPAC/DOM3 key codes*/ -enum { - GF_KEY_UNIDENTIFIED = 0, - GF_KEY_ACCEPT = 1, /* "Accept" The Accept (Commit) key.*/ - GF_KEY_AGAIN, /* "Again" The Again key.*/ - GF_KEY_ALLCANDIDATES, /* "AllCandidates" The All Candidates key.*/ - GF_KEY_ALPHANUM, /*"Alphanumeric" The Alphanumeric key.*/ - GF_KEY_ALT, /*"Alt" The Alt (Menu) key.*/ - GF_KEY_ALTGRAPH, /*"AltGraph" The Alt-Graph key.*/ - GF_KEY_APPS, /*"Apps" The Application key.*/ - GF_KEY_ATTN, /*"Attn" The ATTN key.*/ - GF_KEY_BROWSERBACK, /*"BrowserBack" The Browser Back key.*/ - GF_KEY_BROWSERFAVORITES, /*"BrowserFavorites" The Browser Favorites key.*/ - GF_KEY_BROWSERFORWARD, /*"BrowserForward" The Browser Forward key.*/ - GF_KEY_BROWSERHOME, /*"BrowserHome" The Browser Home key.*/ - GF_KEY_BROWSERREFRESH, /*"BrowserRefresh" The Browser Refresh key.*/ - GF_KEY_BROWSERSEARCH, /*"BrowserSearch" The Browser Search key.*/ - GF_KEY_BROWSERSTOP, /*"BrowserStop" The Browser Stop key.*/ - GF_KEY_CAPSLOCK, /*"CapsLock" The Caps Lock (Capital) key.*/ - GF_KEY_CLEAR, /*"Clear" The Clear key.*/ - GF_KEY_CODEINPUT, /*"CodeInput" The Code Input key.*/ - GF_KEY_COMPOSE, /*"Compose" The Compose key.*/ - GF_KEY_CONTROL, /*"Control" The Control (Ctrl) key.*/ - GF_KEY_CRSEL, /*"Crsel" The Crsel key.*/ - GF_KEY_CONVERT, /*"Convert" The Convert key.*/ - GF_KEY_COPY, /*"Copy" The Copy key.*/ - GF_KEY_CUT, /*"Cut" The Cut key.*/ - GF_KEY_DOWN, /*"Down" The Down Arrow key.*/ - GF_KEY_END, /*"End" The End key.*/ - GF_KEY_ENTER, /*"Enter" The Enter key. - Note: This key identifier is also used for the Return (Macintosh numpad) key.*/ - GF_KEY_ERASEEOF, /*"EraseEof" The Erase EOF key.*/ - GF_KEY_EXECUTE, /*"Execute" The Execute key.*/ - GF_KEY_EXSEL, /*"Exsel" The Exsel key.*/ - GF_KEY_F1, /*"F1" The F1 key.*/ - GF_KEY_F2, /*"F2" The F2 key.*/ - GF_KEY_F3, /*"F3" The F3 key.*/ - GF_KEY_F4, /*"F4" The F4 key.*/ - GF_KEY_F5, /*"F5" The F5 key.*/ - GF_KEY_F6, /*"F6" The F6 key.*/ - GF_KEY_F7, /*"F7" The F7 key.*/ - GF_KEY_F8, /*"F8" The F8 key.*/ - GF_KEY_F9, /*"F9" The F9 key.*/ - GF_KEY_F10, /*"F10" The F10 key.*/ - GF_KEY_F11, /*"F11" The F11 key.*/ - GF_KEY_F12, /*"F12" The F12 key.*/ - GF_KEY_F13, /*"F13" The F13 key.*/ - GF_KEY_F14, /*"F14" The F14 key.*/ - GF_KEY_F15, /*"F15" The F15 key.*/ - GF_KEY_F16, /*"F16" The F16 key.*/ - GF_KEY_F17, /*"F17" The F17 key.*/ - GF_KEY_F18, /*"F18" The F18 key.*/ - GF_KEY_F19, /*"F19" The F19 key.*/ - GF_KEY_F20, /*"F20" The F20 key.*/ - GF_KEY_F21, /*"F21" The F21 key.*/ - GF_KEY_F22, /*"F22" The F22 key.*/ - GF_KEY_F23, /*"F23" The F23 key.*/ - GF_KEY_F24, /*"F24" The F24 key.*/ - GF_KEY_FINALMODE, /*"FinalMode" The Final Mode (Final) key used on some asian keyboards.*/ - GF_KEY_FIND, /*"Find" The Find key.*/ - GF_KEY_FULLWIDTH, /*"FullWidth" The Full-Width Characters key.*/ - GF_KEY_HALFWIDTH, /*"HalfWidth" The Half-Width Characters key.*/ - GF_KEY_HANGULMODE, /*"HangulMode" The Hangul (Korean characters) Mode key.*/ - GF_KEY_HANJAMODE, /*"HanjaMode" The Hanja (Korean characters) Mode key.*/ - GF_KEY_HELP, /*"Help" The Help key.*/ - GF_KEY_HIRAGANA, /*"Hiragana" The Hiragana (Japanese Kana characters) key.*/ - GF_KEY_HOME, /*"Home" The Home key.*/ - GF_KEY_INSERT, /*"Insert" The Insert (Ins) key.*/ - GF_KEY_JAPANESEHIRAGANA, /*"JapaneseHiragana" The Japanese-Hiragana key.*/ - GF_KEY_JAPANESEKATAKANA, /*"JapaneseKatakana" The Japanese-Katakana key.*/ - GF_KEY_JAPANESEROMAJI, /*"JapaneseRomaji" The Japanese-Romaji key.*/ - GF_KEY_JUNJAMODE, /*"JunjaMode" The Junja Mode key.*/ - GF_KEY_KANAMODE, /*"KanaMode" The Kana Mode (Kana Lock) key.*/ - GF_KEY_KANJIMODE, /*"KanjiMode" The Kanji (Japanese name for ideographic characters of Chinese origin) Mode key.*/ - GF_KEY_KATAKANA, /*"Katakana" The Katakana (Japanese Kana characters) key.*/ - GF_KEY_LAUNCHAPPLICATION1, /*"LaunchApplication1" The Start Application One key.*/ - GF_KEY_LAUNCHAPPLICATION2, /*"LaunchApplication2" The Start Application Two key.*/ - GF_KEY_LAUNCHMAIL, /*"LaunchMail" The Start Mail key.*/ - GF_KEY_LEFT, /*"Left" The Left Arrow key.*/ - GF_KEY_META, /*"Meta" The Meta key.*/ - GF_KEY_MEDIANEXTTRACK, /*"MediaNextTrack" The Media Next Track key.*/ - GF_KEY_MEDIAPLAYPAUSE, /*"MediaPlayPause" The Media Play Pause key.*/ - GF_KEY_MEDIAPREVIOUSTRACK, /*"MediaPreviousTrack" The Media Previous Track key.*/ - GF_KEY_MEDIASTOP, /*"MediaStop" The Media Stok key.*/ - GF_KEY_MODECHANGE, /*"ModeChange" The Mode Change key.*/ - GF_KEY_NONCONVERT, /*"Nonconvert" The Nonconvert (Don't Convert) key.*/ - GF_KEY_NUMLOCK, /*"NumLock" The Num Lock key.*/ - GF_KEY_PAGEDOWN, /*"PageDown" The Page Down (Next) key.*/ - GF_KEY_PAGEUP, /*"PageUp" The Page Up key.*/ - GF_KEY_PASTE, /*"Paste" The Paste key.*/ - GF_KEY_PAUSE, /*"Pause" The Pause key.*/ - GF_KEY_PLAY, /*"Play" The Play key.*/ - GF_KEY_PREVIOUSCANDIDATE, /*"PreviousCandidate" The Previous Candidate function key.*/ - GF_KEY_PRINTSCREEN, /*"PrintScreen" The Print Screen (PrintScrn, SnapShot) key.*/ - GF_KEY_PROCESS, /*"Process" The Process key.*/ - GF_KEY_PROPS, /*"Props" The Props key.*/ - GF_KEY_RIGHT, /*"Right" The Right Arrow key.*/ - GF_KEY_ROMANCHARACTERS, /*"RomanCharacters" The Roman Characters function key.*/ - GF_KEY_SCROLL, /*"Scroll" The Scroll Lock key.*/ - GF_KEY_SELECT, /*"Select" The Select key.*/ - GF_KEY_SELECTMEDIA, /*"SelectMedia" The Select Media key.*/ - GF_KEY_SHIFT, /*"Shift" The Shift key.*/ - GF_KEY_STOP, /*"Stop" The Stop key.*/ - GF_KEY_UP, /*"Up" The Up Arrow key.*/ - GF_KEY_UNDO, /*"Undo" The Undo key.*/ - GF_KEY_VOLUMEDOWN, /*"VolumeDown" The Volume Down key.*/ - GF_KEY_VOLUMEMUTE, /*"VolumeMute" The Volume Mute key.*/ - GF_KEY_VOLUMEUP, /*"VolumeUp" The Volume Up key.*/ - GF_KEY_WIN, /*"Win" The Windows Logo key.*/ - GF_KEY_ZOOM, /*"Zoom" The Zoom key.*/ - GF_KEY_BACKSPACE, /*"U+0008" The Backspace (Back) key.*/ - GF_KEY_TAB, /*"U+0009" The Horizontal Tabulation (Tab) key.*/ - GF_KEY_CANCEL, /*"U+0018" The Cancel key.*/ - GF_KEY_ESCAPE, /*"U+001B" The Escape (Esc) key.*/ - GF_KEY_SPACE, /*"U+0020" The Space (Spacebar) key.*/ - GF_KEY_EXCLAMATION, /*"U+0021" The Exclamation Mark (Factorial, Bang) key (!).*/ - GF_KEY_QUOTATION, /*"U+0022" The Quotation Mark (Quote Double) key (").*/ - GF_KEY_NUMBER, /*"U+0023" The Number Sign (Pound Sign, Hash, Crosshatch, Octothorpe) key (#).*/ - GF_KEY_DOLLAR, /*"U+0024" The Dollar Sign (milreis, escudo) key ($).*/ - GF_KEY_AMPERSAND, /*"U+0026" The Ampersand key (&).*/ - GF_KEY_APOSTROPHE, /*"U+0027" The Apostrophe (Apostrophe-Quote, APL Quote) key (').*/ - GF_KEY_LEFTPARENTHESIS, /*"U+0028" The Left Parenthesis (Opening Parenthesis) key (().*/ - GF_KEY_RIGHTPARENTHESIS, /*"U+0029" The Right Parenthesis (Closing Parenthesis) key ()).*/ - GF_KEY_STAR, /*"U+002A" The Asterix (Star) key (*).*/ - GF_KEY_PLUS, /*"U+002B" The Plus Sign (Plus) key (+).*/ - GF_KEY_COMMA, /*"U+002C" The Comma (decimal separator) sign key (,).*/ - GF_KEY_HYPHEN, /*"U+002D" The Hyphen-minus (hyphen or minus sign) key (-).*/ - GF_KEY_FULLSTOP, /*"U+002E" The Full Stop (period, dot, decimal point) key (.).*/ - GF_KEY_SLASH, /*"U+002F" The Solidus (slash, virgule, shilling) key (/).*/ - GF_KEY_0, /*"U+0030" The Digit Zero key (0).*/ - GF_KEY_1, /*"U+0031" The Digit One key (1).*/ - GF_KEY_2, /*"U+0032" The Digit Two key (2).*/ - GF_KEY_3, /*"U+0033" The Digit Three key (3).*/ - GF_KEY_4, /*"U+0034" The Digit Four key (4).*/ - GF_KEY_5, /*"U+0035" The Digit Five key (5).*/ - GF_KEY_6, /*"U+0036" The Digit Six key (6).*/ - GF_KEY_7, /*"U+0037" The Digit Seven key (7).*/ - GF_KEY_8, /*"U+0038" The Digit Eight key (8).*/ - GF_KEY_9, /*"U+0039" The Digit Nine key (9).*/ - GF_KEY_COLON, /*"U+003A" The Colon key (:).*/ - GF_KEY_SEMICOLON, /*"U+003B" The Semicolon key (;).*/ - GF_KEY_LESSTHAN, /*"U+003C" The Less-Than Sign key (<).*/ - GF_KEY_EQUALS, /*"U+003D" The Equals Sign key (=).*/ - GF_KEY_GREATERTHAN, /*"U+003E" The Greater-Than Sign key (>).*/ - GF_KEY_QUESTION, /*"U+003F" The Question Mark key (?).*/ - GF_KEY_AT, /*"U+0040" The Commercial At (@) key.*/ - GF_KEY_A, /*"U+0041" The Latin Capital Letter A key (A).*/ - GF_KEY_B, /*"U+0042" The Latin Capital Letter B key (B).*/ - GF_KEY_C, /*"U+0043" The Latin Capital Letter C key (C).*/ - GF_KEY_D, /*"U+0044" The Latin Capital Letter D key (D).*/ - GF_KEY_E, /*"U+0045" The Latin Capital Letter E key (E).*/ - GF_KEY_F, /*"U+0046" The Latin Capital Letter F key (F).*/ - GF_KEY_G, /*"U+0047" The Latin Capital Letter G key (G).*/ - GF_KEY_H, /*"U+0048" The Latin Capital Letter H key (H).*/ - GF_KEY_I, /*"U+0049" The Latin Capital Letter I key (I).*/ - GF_KEY_J, /*"U+004A" The Latin Capital Letter J key (J).*/ - GF_KEY_K, /*"U+004B" The Latin Capital Letter K key (K).*/ - GF_KEY_L, /*"U+004C" The Latin Capital Letter L key (L).*/ - GF_KEY_M, /*"U+004D" The Latin Capital Letter M key (M).*/ - GF_KEY_N, /*"U+004E" The Latin Capital Letter N key (N).*/ - GF_KEY_O, /*"U+004F" The Latin Capital Letter O key (O).*/ - GF_KEY_P, /*"U+0050" The Latin Capital Letter P key (P).*/ - GF_KEY_Q, /*"U+0051" The Latin Capital Letter Q key (Q).*/ - GF_KEY_R, /*"U+0052" The Latin Capital Letter R key (R).*/ - GF_KEY_S, /*"U+0053" The Latin Capital Letter S key (S).*/ - GF_KEY_T, /*"U+0054" The Latin Capital Letter T key (T).*/ - GF_KEY_U, /*"U+0055" The Latin Capital Letter U key (U).*/ - GF_KEY_V, /*"U+0056" The Latin Capital Letter V key (V).*/ - GF_KEY_W, /*"U+0057" The Latin Capital Letter W key (W).*/ - GF_KEY_X, /*"U+0058" The Latin Capital Letter X key (X).*/ - GF_KEY_Y, /*"U+0059" The Latin Capital Letter Y key (Y).*/ - GF_KEY_Z, /*"U+005A" The Latin Capital Letter Z key (Z).*/ - GF_KEY_LEFTSQUAREBRACKET, /*"U+005B" The Left Square Bracket (Opening Square Bracket) key ([).*/ - GF_KEY_BACKSLASH, /*"U+005C" The Reverse Solidus (Backslash) key (\).*/ - GF_KEY_RIGHTSQUAREBRACKET, /*"U+005D" The Right Square Bracket (Closing Square Bracket) key (]).*/ - GF_KEY_CIRCUM, /*"U+005E" The Circumflex Accent key (^).*/ - GF_KEY_UNDERSCORE, /*"U+005F" The Low Sign (Spacing Underscore, Underscore) key (_).*/ - GF_KEY_GRAVEACCENT, /*"U+0060" The Grave Accent (Back Quote) key (`).*/ - GF_KEY_LEFTCURLYBRACKET, /*"U+007B" The Left Curly Bracket (Opening Curly Bracket, Opening Brace, Brace Left) key ({).*/ - GF_KEY_PIPE, /*"U+007C" The Vertical Line (Vertical Bar, Pipe) key (|).*/ - GF_KEY_RIGHTCURLYBRACKET, /*"U+007D" The Right Curly Bracket (Closing Curly Bracket, Closing Brace, Brace Right) key (}).*/ - GF_KEY_DEL, /*"U+007F" The Delete (Del) Key.*/ - GF_KEY_INVERTEXCLAMATION, /*"U+00A1" The Inverted Exclamation Mark key (�).*/ - GF_KEY_DEADGRAVE, /*"U+0300" The Combining Grave Accent (Greek Varia, Dead Grave) key.*/ - GF_KEY_DEADEACUTE, /*"U+0301" The Combining Acute Accent (Stress Mark, Greek Oxia, Tonos, Dead Eacute) key.*/ - GF_KEY_DEADCIRCUM, /*"U+0302" The Combining Circumflex Accent (Hat, Dead Circumflex) key.*/ - GF_KEY_DEADTILDE, /*"U+0303" The Combining Tilde (Dead Tilde) key.*/ - GF_KEY_DEADMACRON, /*"U+0304" The Combining Macron (Long, Dead Macron) key.*/ - GF_KEY_DEADBREVE, /*"U+0306" The Combining Breve (Short, Dead Breve) key.*/ - GF_KEY_DEADABOVEDOT, /*"U+0307" The Combining Dot Above (Derivative, Dead Above Dot) key.*/ - GF_KEY_DEADDIARESIS, /*"U+0308" The Combining Diaeresis (Double Dot Abode, Umlaut, Greek Dialytika, Double Derivative, Dead Diaeresis) key.*/ - GF_KEY_DEADRINGABOVE, /*"U+030A" The Combining Ring Above (Dead Above Ring) key.*/ - GF_KEY_DEADDOUBLEACUTE, /*"U+030B" The Combining Double Acute Accent (Dead Doubleacute) key.*/ - GF_KEY_DEADCARON, /*"U+030C" The Combining Caron (Hacek, V Above, Dead Caron) key.*/ - GF_KEY_DEADCEDILLA, /*"U+0327" The Combining Cedilla (Dead Cedilla) key.*/ - GF_KEY_DEADOGONEK, /*"U+0328" The Combining Ogonek (Nasal Hook, Dead Ogonek) key.*/ - GF_KEY_DEADIOTA, /*"U+0345" The Combining Greek Ypogegrammeni (Greek Non-Spacing Iota Below, Iota Subscript, Dead Iota) key.*/ - GF_KEY_EURO, /*"U+20AC" The Euro Currency Sign key (�).*/ - GF_KEY_DEADVOICESOUND, /*"U+3099" The Combining Katakana-Hiragana Voiced Sound Mark (Dead Voiced Sound) key.*/ - GF_KEY_DEADSEMIVOICESOUND, /*"U+309A" The Combining Katakana-Hiragana Semi-Voiced Sound Mark (Dead Semivoiced Sound) key. */ - /* STB */ - GF_KEY_CHANNELUP, /*ChannelUp*/ - GF_KEY_CHANNELDOWN, /*ChannelDown*/ - GF_KEY_TEXT, /*Text*/ - GF_KEY_INFO, /*Info*/ - GF_KEY_EPG, /*EPG*/ - GF_KEY_RECORD, /*Record*/ - GF_KEY_BEGINPAGE, /*BeginPage*/ - /* end STB */ - - /*non-dom keys, used in LASeR*/ - GF_KEY_CELL_SOFT1, /*soft1 key of cell phones*/ - GF_KEY_CELL_SOFT2, /*soft2 key of cell phones*/ - - /*for joystick handling*/ - GF_KEY_JOYSTICK -}; - - -/*key modifiers state - set by terminal (not set by video driver)*/ -enum -{ - GF_KEY_MOD_SHIFT = (1), - GF_KEY_MOD_CTRL = (1<<2), - GF_KEY_MOD_ALT = (1<<3), - - GF_KEY_EXT_NUMPAD = (1<<4), - GF_KEY_EXT_LEFT = (1<<5), - GF_KEY_EXT_RIGHT = (1<<6) -}; - -/*sensor signaling*/ -enum -{ - GF_CURSOR_NORMAL = 0x00, - GF_CURSOR_ANCHOR, - GF_CURSOR_TOUCH, - /*discSensor, cylinderSensor, sphereSensor*/ - GF_CURSOR_ROTATE, - /*proximitySensor & proximitySensor2D*/ - GF_CURSOR_PROXIMITY, - /*planeSensor & planeSensor2D*/ - GF_CURSOR_PLANE, - /*collision*/ - GF_CURSOR_COLLIDE, - GF_CURSOR_HIDE, -}; - -/*Mutation AttrChangeType Signaling*/ -enum -{ - GF_MUTATION_ATTRCHANGE_MODIFICATION = 0x01, - GF_MUTATION_ATTRCHANGE_ADDITION = 0x02, - GF_MUTATION_ATTRCHANGE_REMOVAL = 0x03, -}; - -enum -{ - /*events forwarded from MPEG-2 stack*/ - GF_EVT_FORWARDED_MPEG2 = 0, - /*events forwarded from RTP/RTSP/IP stack (not used yet)*/ - GF_EVT_FORWARDED_RTP_RTSP -}; - -#endif + + GF_EVENT_BATTERY, + GF_EVENT_CPU, + GF_EVENT_UNKNOWN, + + + /****************************************************** + + Events used for GPAC internals only + + *******************************************************/ + + /*same as mousedown, generated internally by GPAC*/ + GF_EVENT_DBLCLICK, + + /*scene attached event, dispatched when the root node of a scene is loaded and + attached to the window or parent object (animation, inline, ...)*/ + GF_EVENT_SCENE_ATTACHED, + + /*VP resize attached event, dispatched when viewport of a scene is being modified + attached to the window or parent object (animation, inline, ...)*/ + GF_EVENT_VP_RESIZE, + + /*window events*/ + /*size has changed - indicate new w & h in .x end .y fields of event. + When sent from gpac to a video plugin, indicates the output size should be changed. This is only sent when the plugin + manages the output video himself + When sent from a video plugin to gpac, indicates the output size has been changed. This is only sent when the plugin + manages the output video himself + */ + GF_EVENT_SIZE, + /*signals the scene size (if indicated in scene) upon connection (sent to the user event proc only) + if scene size hasn't changed (seeking or other) this event is not sent + */ + GF_EVENT_SCENE_SIZE, + GF_EVENT_SHOWHIDE, /*window show/hide (minimized or other). This is also sent to the user to signal focus switch in fullscreen*/ + GF_EVENT_SET_CURSOR, /*set mouse cursor*/ + GF_EVENT_SET_CAPTION, /*set window caption*/ + GF_EVENT_MOVE, /*move window*/ + GF_EVENT_REFRESH, /*window needs repaint (whenever needed, eg restore, hide->show, background refresh, paint)*/ + GF_EVENT_QUIT, /*window is being closed*/ + /*video hw setup message: + - when sent from gpac to plugin, indicates that the plugin should re-setup hardware context due to a window resize: + * for 2D output, this means resizing the backbuffer if needed (depending on HW constraints) + * for 3D output, this means re-setup of OpenGL context (depending on HW constraints). Depending on windowing systems + and implementations, it could be possible to resize a window without destroying the GL context. + + - when sent from plugin to gpac, indicates that hardware resources must be resetup before next render step (this is mainly + due to discard all openGL textures and cached objects) + */ + GF_EVENT_VIDEO_SETUP, + /*queries the list of system colors - only exchanged between compositor and video output*/ + GF_EVENT_SYS_COLORS, + + /*indicates some text has been pasted - from video output to compositor only*/ + GF_EVENT_PASTE_TEXT, + /*queries for text to be copied - from video output to compositor only*/ + GF_EVENT_COPY_TEXT, + + /*terminal events*/ + GF_EVENT_CONNECT, /*signal URL is connected*/ + GF_EVENT_DURATION, /*signal duration of presentation*/ + GF_EVENT_EOS, /*signal End of scene playback*/ + GF_EVENT_AUTHORIZATION, /*indicates a user and pass is queried*/ + GF_EVENT_NAVIGATE, /*indicates the user app should load or jump to the given URL.*/ + GF_EVENT_NAVIGATE_INFO, /*indicates the link or its description under the mouse pointer*/ + GF_EVENT_MESSAGE, /*message from the MPEG-4 terminal*/ + GF_EVENT_PROGRESS, /*progress message from the MPEG-4 terminal*/ + GF_EVENT_FORWARDED, /*event forwarded by service (MPEG-2, RTP, ...)*/ + GF_EVENT_VIEWPOINTS, /*indicates viewpoint list has changed - no struct associated*/ + GF_EVENT_STREAMLIST, /*indicates stream list has changed - no struct associated - only used when no scene info is present*/ + GF_EVENT_METADATA, /*indicates a change in associated metadata*/ + GF_EVENT_MIGRATE, /*indicates a session migration request*/ + GF_EVENT_DISCONNECT, /*indicates the current url should be disconnected*/ + GF_EVENT_RESOLUTION, /*indicates the screen resolution has changed*/ + GF_EVENT_OPENFILE, + /* Events for Keyboad */ + GF_EVENT_TEXT_EDITING_START, + GF_EVENT_TEXT_EDITING_END +}; + +/*GPAC/DOM3 key codes*/ +enum { + GF_KEY_UNIDENTIFIED = 0, + GF_KEY_ACCEPT = 1, /* "Accept" The Accept (Commit) key.*/ + GF_KEY_AGAIN, /* "Again" The Again key.*/ + GF_KEY_ALLCANDIDATES, /* "AllCandidates" The All Candidates key.*/ + GF_KEY_ALPHANUM, /*"Alphanumeric" The Alphanumeric key.*/ + GF_KEY_ALT, /*"Alt" The Alt (Menu) key.*/ + GF_KEY_ALTGRAPH, /*"AltGraph" The Alt-Graph key.*/ + GF_KEY_APPS, /*"Apps" The Application key.*/ + GF_KEY_ATTN, /*"Attn" The ATTN key.*/ + GF_KEY_BROWSERBACK, /*"BrowserBack" The Browser Back key.*/ + GF_KEY_BROWSERFAVORITES, /*"BrowserFavorites" The Browser Favorites key.*/ + GF_KEY_BROWSERFORWARD, /*"BrowserForward" The Browser Forward key.*/ + GF_KEY_BROWSERHOME, /*"BrowserHome" The Browser Home key.*/ + GF_KEY_BROWSERREFRESH, /*"BrowserRefresh" The Browser Refresh key.*/ + GF_KEY_BROWSERSEARCH, /*"BrowserSearch" The Browser Search key.*/ + GF_KEY_BROWSERSTOP, /*"BrowserStop" The Browser Stop key.*/ + GF_KEY_CAPSLOCK, /*"CapsLock" The Caps Lock (Capital) key.*/ + GF_KEY_CLEAR, /*"Clear" The Clear key.*/ + GF_KEY_CODEINPUT, /*"CodeInput" The Code Input key.*/ + GF_KEY_COMPOSE, /*"Compose" The Compose key.*/ + GF_KEY_CONTROL, /*"Control" The Control (Ctrl) key.*/ + GF_KEY_CRSEL, /*"Crsel" The Crsel key.*/ + GF_KEY_CONVERT, /*"Convert" The Convert key.*/ + GF_KEY_COPY, /*"Copy" The Copy key.*/ + GF_KEY_CUT, /*"Cut" The Cut key.*/ + GF_KEY_DOWN, /*"Down" The Down Arrow key.*/ + GF_KEY_END, /*"End" The End key.*/ + GF_KEY_ENTER, /*"Enter" The Enter key. + Note: This key identifier is also used for the Return (Macintosh numpad) key.*/ + GF_KEY_ERASEEOF, /*"EraseEof" The Erase EOF key.*/ + GF_KEY_EXECUTE, /*"Execute" The Execute key.*/ + GF_KEY_EXSEL, /*"Exsel" The Exsel key.*/ + GF_KEY_F1, /*"F1" The F1 key.*/ + GF_KEY_F2, /*"F2" The F2 key.*/ + GF_KEY_F3, /*"F3" The F3 key.*/ + GF_KEY_F4, /*"F4" The F4 key.*/ + GF_KEY_F5, /*"F5" The F5 key.*/ + GF_KEY_F6, /*"F6" The F6 key.*/ + GF_KEY_F7, /*"F7" The F7 key.*/ + GF_KEY_F8, /*"F8" The F8 key.*/ + GF_KEY_F9, /*"F9" The F9 key.*/ + GF_KEY_F10, /*"F10" The F10 key.*/ + GF_KEY_F11, /*"F11" The F11 key.*/ + GF_KEY_F12, /*"F12" The F12 key.*/ + GF_KEY_F13, /*"F13" The F13 key.*/ + GF_KEY_F14, /*"F14" The F14 key.*/ + GF_KEY_F15, /*"F15" The F15 key.*/ + GF_KEY_F16, /*"F16" The F16 key.*/ + GF_KEY_F17, /*"F17" The F17 key.*/ + GF_KEY_F18, /*"F18" The F18 key.*/ + GF_KEY_F19, /*"F19" The F19 key.*/ + GF_KEY_F20, /*"F20" The F20 key.*/ + GF_KEY_F21, /*"F21" The F21 key.*/ + GF_KEY_F22, /*"F22" The F22 key.*/ + GF_KEY_F23, /*"F23" The F23 key.*/ + GF_KEY_F24, /*"F24" The F24 key.*/ + GF_KEY_FINALMODE, /*"FinalMode" The Final Mode (Final) key used on some asian keyboards.*/ + GF_KEY_FIND, /*"Find" The Find key.*/ + GF_KEY_FULLWIDTH, /*"FullWidth" The Full-Width Characters key.*/ + GF_KEY_HALFWIDTH, /*"HalfWidth" The Half-Width Characters key.*/ + GF_KEY_HANGULMODE, /*"HangulMode" The Hangul (Korean characters) Mode key.*/ + GF_KEY_HANJAMODE, /*"HanjaMode" The Hanja (Korean characters) Mode key.*/ + GF_KEY_HELP, /*"Help" The Help key.*/ + GF_KEY_HIRAGANA, /*"Hiragana" The Hiragana (Japanese Kana characters) key.*/ + GF_KEY_HOME, /*"Home" The Home key.*/ + GF_KEY_INSERT, /*"Insert" The Insert (Ins) key.*/ + GF_KEY_JAPANESEHIRAGANA, /*"JapaneseHiragana" The Japanese-Hiragana key.*/ + GF_KEY_JAPANESEKATAKANA, /*"JapaneseKatakana" The Japanese-Katakana key.*/ + GF_KEY_JAPANESEROMAJI, /*"JapaneseRomaji" The Japanese-Romaji key.*/ + GF_KEY_JUNJAMODE, /*"JunjaMode" The Junja Mode key.*/ + GF_KEY_KANAMODE, /*"KanaMode" The Kana Mode (Kana Lock) key.*/ + GF_KEY_KANJIMODE, /*"KanjiMode" The Kanji (Japanese name for ideographic characters of Chinese origin) Mode key.*/ + GF_KEY_KATAKANA, /*"Katakana" The Katakana (Japanese Kana characters) key.*/ + GF_KEY_LAUNCHAPPLICATION1, /*"LaunchApplication1" The Start Application One key.*/ + GF_KEY_LAUNCHAPPLICATION2, /*"LaunchApplication2" The Start Application Two key.*/ + GF_KEY_LAUNCHMAIL, /*"LaunchMail" The Start Mail key.*/ + GF_KEY_LEFT, /*"Left" The Left Arrow key.*/ + GF_KEY_META, /*"Meta" The Meta key.*/ + GF_KEY_MEDIANEXTTRACK, /*"MediaNextTrack" The Media Next Track key.*/ + GF_KEY_MEDIAPLAYPAUSE, /*"MediaPlayPause" The Media Play Pause key.*/ + GF_KEY_MEDIAPREVIOUSTRACK, /*"MediaPreviousTrack" The Media Previous Track key.*/ + GF_KEY_MEDIASTOP, /*"MediaStop" The Media Stok key.*/ + GF_KEY_MODECHANGE, /*"ModeChange" The Mode Change key.*/ + GF_KEY_NONCONVERT, /*"Nonconvert" The Nonconvert (Don't Convert) key.*/ + GF_KEY_NUMLOCK, /*"NumLock" The Num Lock key.*/ + GF_KEY_PAGEDOWN, /*"PageDown" The Page Down (Next) key.*/ + GF_KEY_PAGEUP, /*"PageUp" The Page Up key.*/ + GF_KEY_PASTE, /*"Paste" The Paste key.*/ + GF_KEY_PAUSE, /*"Pause" The Pause key.*/ + GF_KEY_PLAY, /*"Play" The Play key.*/ + GF_KEY_PREVIOUSCANDIDATE, /*"PreviousCandidate" The Previous Candidate function key.*/ + GF_KEY_PRINTSCREEN, /*"PrintScreen" The Print Screen (PrintScrn, SnapShot) key.*/ + GF_KEY_PROCESS, /*"Process" The Process key.*/ + GF_KEY_PROPS, /*"Props" The Props key.*/ + GF_KEY_RIGHT, /*"Right" The Right Arrow key.*/ + GF_KEY_ROMANCHARACTERS, /*"RomanCharacters" The Roman Characters function key.*/ + GF_KEY_SCROLL, /*"Scroll" The Scroll Lock key.*/ + GF_KEY_SELECT, /*"Select" The Select key.*/ + GF_KEY_SELECTMEDIA, /*"SelectMedia" The Select Media key.*/ + GF_KEY_SHIFT, /*"Shift" The Shift key.*/ + GF_KEY_STOP, /*"Stop" The Stop key.*/ + GF_KEY_UP, /*"Up" The Up Arrow key.*/ + GF_KEY_UNDO, /*"Undo" The Undo key.*/ + GF_KEY_VOLUMEDOWN, /*"VolumeDown" The Volume Down key.*/ + GF_KEY_VOLUMEMUTE, /*"VolumeMute" The Volume Mute key.*/ + GF_KEY_VOLUMEUP, /*"VolumeUp" The Volume Up key.*/ + GF_KEY_WIN, /*"Win" The Windows Logo key.*/ + GF_KEY_ZOOM, /*"Zoom" The Zoom key.*/ + GF_KEY_BACKSPACE, /*"U+0008" The Backspace (Back) key.*/ + GF_KEY_TAB, /*"U+0009" The Horizontal Tabulation (Tab) key.*/ + GF_KEY_CANCEL, /*"U+0018" The Cancel key.*/ + GF_KEY_ESCAPE, /*"U+001B" The Escape (Esc) key.*/ + GF_KEY_SPACE, /*"U+0020" The Space (Spacebar) key.*/ + GF_KEY_EXCLAMATION, /*"U+0021" The Exclamation Mark (Factorial, Bang) key (!).*/ + GF_KEY_QUOTATION, /*"U+0022" The Quotation Mark (Quote Double) key (").*/ + GF_KEY_NUMBER, /*"U+0023" The Number Sign (Pound Sign, Hash, Crosshatch, Octothorpe) key (#).*/ + GF_KEY_DOLLAR, /*"U+0024" The Dollar Sign (milreis, escudo) key ($).*/ + GF_KEY_AMPERSAND, /*"U+0026" The Ampersand key (&).*/ + GF_KEY_APOSTROPHE, /*"U+0027" The Apostrophe (Apostrophe-Quote, APL Quote) key (').*/ + GF_KEY_LEFTPARENTHESIS, /*"U+0028" The Left Parenthesis (Opening Parenthesis) key (().*/ + GF_KEY_RIGHTPARENTHESIS, /*"U+0029" The Right Parenthesis (Closing Parenthesis) key ()).*/ + GF_KEY_STAR, /*"U+002A" The Asterix (Star) key (*).*/ + GF_KEY_PLUS, /*"U+002B" The Plus Sign (Plus) key (+).*/ + GF_KEY_COMMA, /*"U+002C" The Comma (decimal separator) sign key (,).*/ + GF_KEY_HYPHEN, /*"U+002D" The Hyphen-minus (hyphen or minus sign) key (-).*/ + GF_KEY_FULLSTOP, /*"U+002E" The Full Stop (period, dot, decimal point) key (.).*/ + GF_KEY_SLASH, /*"U+002F" The Solidus (slash, virgule, shilling) key (/).*/ + GF_KEY_0, /*"U+0030" The Digit Zero key (0).*/ + GF_KEY_1, /*"U+0031" The Digit One key (1).*/ + GF_KEY_2, /*"U+0032" The Digit Two key (2).*/ + GF_KEY_3, /*"U+0033" The Digit Three key (3).*/ + GF_KEY_4, /*"U+0034" The Digit Four key (4).*/ + GF_KEY_5, /*"U+0035" The Digit Five key (5).*/ + GF_KEY_6, /*"U+0036" The Digit Six key (6).*/ + GF_KEY_7, /*"U+0037" The Digit Seven key (7).*/ + GF_KEY_8, /*"U+0038" The Digit Eight key (8).*/ + GF_KEY_9, /*"U+0039" The Digit Nine key (9).*/ + GF_KEY_COLON, /*"U+003A" The Colon key (:).*/ + GF_KEY_SEMICOLON, /*"U+003B" The Semicolon key (;).*/ + GF_KEY_LESSTHAN, /*"U+003C" The Less-Than Sign key (<).*/ + GF_KEY_EQUALS, /*"U+003D" The Equals Sign key (=).*/ + GF_KEY_GREATERTHAN, /*"U+003E" The Greater-Than Sign key (>).*/ + GF_KEY_QUESTION, /*"U+003F" The Question Mark key (?).*/ + GF_KEY_AT, /*"U+0040" The Commercial At (@) key.*/ + GF_KEY_A, /*"U+0041" The Latin Capital Letter A key (A).*/ + GF_KEY_B, /*"U+0042" The Latin Capital Letter B key (B).*/ + GF_KEY_C, /*"U+0043" The Latin Capital Letter C key (C).*/ + GF_KEY_D, /*"U+0044" The Latin Capital Letter D key (D).*/ + GF_KEY_E, /*"U+0045" The Latin Capital Letter E key (E).*/ + GF_KEY_F, /*"U+0046" The Latin Capital Letter F key (F).*/ + GF_KEY_G, /*"U+0047" The Latin Capital Letter G key (G).*/ + GF_KEY_H, /*"U+0048" The Latin Capital Letter H key (H).*/ + GF_KEY_I, /*"U+0049" The Latin Capital Letter I key (I).*/ + GF_KEY_J, /*"U+004A" The Latin Capital Letter J key (J).*/ + GF_KEY_K, /*"U+004B" The Latin Capital Letter K key (K).*/ + GF_KEY_L, /*"U+004C" The Latin Capital Letter L key (L).*/ + GF_KEY_M, /*"U+004D" The Latin Capital Letter M key (M).*/ + GF_KEY_N, /*"U+004E" The Latin Capital Letter N key (N).*/ + GF_KEY_O, /*"U+004F" The Latin Capital Letter O key (O).*/ + GF_KEY_P, /*"U+0050" The Latin Capital Letter P key (P).*/ + GF_KEY_Q, /*"U+0051" The Latin Capital Letter Q key (Q).*/ + GF_KEY_R, /*"U+0052" The Latin Capital Letter R key (R).*/ + GF_KEY_S, /*"U+0053" The Latin Capital Letter S key (S).*/ + GF_KEY_T, /*"U+0054" The Latin Capital Letter T key (T).*/ + GF_KEY_U, /*"U+0055" The Latin Capital Letter U key (U).*/ + GF_KEY_V, /*"U+0056" The Latin Capital Letter V key (V).*/ + GF_KEY_W, /*"U+0057" The Latin Capital Letter W key (W).*/ + GF_KEY_X, /*"U+0058" The Latin Capital Letter X key (X).*/ + GF_KEY_Y, /*"U+0059" The Latin Capital Letter Y key (Y).*/ + GF_KEY_Z, /*"U+005A" The Latin Capital Letter Z key (Z).*/ + GF_KEY_LEFTSQUAREBRACKET, /*"U+005B" The Left Square Bracket (Opening Square Bracket) key ([).*/ + GF_KEY_BACKSLASH, /*"U+005C" The Reverse Solidus (Backslash) key (\).*/ + GF_KEY_RIGHTSQUAREBRACKET, /*"U+005D" The Right Square Bracket (Closing Square Bracket) key (]).*/ + GF_KEY_CIRCUM, /*"U+005E" The Circumflex Accent key (^).*/ + GF_KEY_UNDERSCORE, /*"U+005F" The Low Sign (Spacing Underscore, Underscore) key (_).*/ + GF_KEY_GRAVEACCENT, /*"U+0060" The Grave Accent (Back Quote) key (`).*/ + GF_KEY_LEFTCURLYBRACKET, /*"U+007B" The Left Curly Bracket (Opening Curly Bracket, Opening Brace, Brace Left) key ({).*/ + GF_KEY_PIPE, /*"U+007C" The Vertical Line (Vertical Bar, Pipe) key (|).*/ + GF_KEY_RIGHTCURLYBRACKET, /*"U+007D" The Right Curly Bracket (Closing Curly Bracket, Closing Brace, Brace Right) key (}).*/ + GF_KEY_DEL, /*"U+007F" The Delete (Del) Key.*/ + GF_KEY_INVERTEXCLAMATION, /*"U+00A1" The Inverted Exclamation Mark key (�).*/ + GF_KEY_DEADGRAVE, /*"U+0300" The Combining Grave Accent (Greek Varia, Dead Grave) key.*/ + GF_KEY_DEADEACUTE, /*"U+0301" The Combining Acute Accent (Stress Mark, Greek Oxia, Tonos, Dead Eacute) key.*/ + GF_KEY_DEADCIRCUM, /*"U+0302" The Combining Circumflex Accent (Hat, Dead Circumflex) key.*/ + GF_KEY_DEADTILDE, /*"U+0303" The Combining Tilde (Dead Tilde) key.*/ + GF_KEY_DEADMACRON, /*"U+0304" The Combining Macron (Long, Dead Macron) key.*/ + GF_KEY_DEADBREVE, /*"U+0306" The Combining Breve (Short, Dead Breve) key.*/ + GF_KEY_DEADABOVEDOT, /*"U+0307" The Combining Dot Above (Derivative, Dead Above Dot) key.*/ + GF_KEY_DEADDIARESIS, /*"U+0308" The Combining Diaeresis (Double Dot Abode, Umlaut, Greek Dialytika, Double Derivative, Dead Diaeresis) key.*/ + GF_KEY_DEADRINGABOVE, /*"U+030A" The Combining Ring Above (Dead Above Ring) key.*/ + GF_KEY_DEADDOUBLEACUTE, /*"U+030B" The Combining Double Acute Accent (Dead Doubleacute) key.*/ + GF_KEY_DEADCARON, /*"U+030C" The Combining Caron (Hacek, V Above, Dead Caron) key.*/ + GF_KEY_DEADCEDILLA, /*"U+0327" The Combining Cedilla (Dead Cedilla) key.*/ + GF_KEY_DEADOGONEK, /*"U+0328" The Combining Ogonek (Nasal Hook, Dead Ogonek) key.*/ + GF_KEY_DEADIOTA, /*"U+0345" The Combining Greek Ypogegrammeni (Greek Non-Spacing Iota Below, Iota Subscript, Dead Iota) key.*/ + GF_KEY_EURO, /*"U+20AC" The Euro Currency Sign key (�).*/ + GF_KEY_DEADVOICESOUND, /*"U+3099" The Combining Katakana-Hiragana Voiced Sound Mark (Dead Voiced Sound) key.*/ + GF_KEY_DEADSEMIVOICESOUND, /*"U+309A" The Combining Katakana-Hiragana Semi-Voiced Sound Mark (Dead Semivoiced Sound) key. */ + /* STB */ + GF_KEY_CHANNELUP, /*ChannelUp*/ + GF_KEY_CHANNELDOWN, /*ChannelDown*/ + GF_KEY_TEXT, /*Text*/ + GF_KEY_INFO, /*Info*/ + GF_KEY_EPG, /*EPG*/ + GF_KEY_RECORD, /*Record*/ + GF_KEY_BEGINPAGE, /*BeginPage*/ + /* end STB */ + + /*non-dom keys, used in LASeR*/ + GF_KEY_CELL_SOFT1, /*soft1 key of cell phones*/ + GF_KEY_CELL_SOFT2, /*soft2 key of cell phones*/ + + /*for joystick handling*/ + GF_KEY_JOYSTICK +}; + + +/*key modifiers state - set by terminal (not set by video driver)*/ +enum +{ + GF_KEY_MOD_SHIFT = (1), + GF_KEY_MOD_CTRL = (1<<2), + GF_KEY_MOD_ALT = (1<<3), + + GF_KEY_EXT_NUMPAD = (1<<4), + GF_KEY_EXT_LEFT = (1<<5), + GF_KEY_EXT_RIGHT = (1<<6) +}; + +/*sensor signaling*/ +enum +{ + GF_CURSOR_NORMAL = 0x00, + GF_CURSOR_ANCHOR, + GF_CURSOR_TOUCH, + /*discSensor, cylinderSensor, sphereSensor*/ + GF_CURSOR_ROTATE, + /*proximitySensor & proximitySensor2D*/ + GF_CURSOR_PROXIMITY, + /*planeSensor & planeSensor2D*/ + GF_CURSOR_PLANE, + /*collision*/ + GF_CURSOR_COLLIDE, + GF_CURSOR_HIDE, +}; + +/*Mutation AttrChangeType Signaling*/ +enum +{ + GF_MUTATION_ATTRCHANGE_MODIFICATION = 0x01, + GF_MUTATION_ATTRCHANGE_ADDITION = 0x02, + GF_MUTATION_ATTRCHANGE_REMOVAL = 0x03, +}; + +enum +{ + /*events forwarded from MPEG-2 stack*/ + GF_EVT_FORWARDED_MPEG2 = 0, + /*events forwarded from RTP/RTSP/IP stack (not used yet)*/ + GF_EVT_FORWARDED_RTP_RTSP +}; + +#endif diff --git a/include/gpac/filestreamer.h b/include/gpac/filestreamer.h index a400851..a882f2a 100644 --- a/include/gpac/filestreamer.h +++ b/include/gpac/filestreamer.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2008- + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2008-2012 * All rights reserved * * This file is part of GPAC / media tools sub-project diff --git a/include/gpac/ietf.h b/include/gpac/ietf.h index 7818052..1fa42b3 100644 --- a/include/gpac/ietf.h +++ b/include/gpac/ietf.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project @@ -1269,7 +1270,9 @@ enum /*ISMACryp stuff*/ GF_RTP_HAS_ISMACRYP = (1<<5), GF_RTP_ISMA_SEL_ENC = (1<<6), - GF_RTP_ISMA_HAS_KEY_IDX = (1<<7) + GF_RTP_ISMA_HAS_KEY_IDX = (1<<7), + + GF_RTP_AVC_USE_ANNEX_B = (1<<8) }; /* diff --git a/include/gpac/internal/bifs_dev.h b/include/gpac/internal/bifs_dev.h index 2920427..7dc3324 100644 --- a/include/gpac/internal/bifs_dev.h +++ b/include/gpac/internal/bifs_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/include/gpac/internal/bifs_tables.h b/include/gpac/internal/bifs_tables.h index e83cccc..748cdac 100644 --- a/include/gpac/internal/bifs_tables.h +++ b/include/gpac/internal/bifs_tables.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/include/gpac/internal/camera.h b/include/gpac/internal/camera.h index 2f031f2..340bde4 100644 --- a/include/gpac/internal/camera.h +++ b/include/gpac/internal/camera.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -167,7 +168,9 @@ typedef struct _camera /*invalidate camera to force recompute of all params*/ void camera_invalidate(GF_Camera *cam); /*updates camera. user transform is only used in 2D to set global user zoom/pan/translate*/ -void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed viewing_distance, Fixed view_distance_offset, u32 camera_layout); +void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords); +/*updates camera. user transform is only used in 2D to set global user zoom/pan/translate + stereo param*/ +void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed viewing_distance, Fixed viewing_distance_offset, u32 camera_layout); /*reset to last viewport*/ void camera_reset_viewpoint(GF_Camera *cam, Bool animate); /*move camera to given vp*/ diff --git a/include/gpac/internal/compositor_dev.h b/include/gpac/internal/compositor_dev.h index 5ab1422..afee21f 100644 --- a/include/gpac/internal/compositor_dev.h +++ b/include/gpac/internal/compositor_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Rendering sub-project @@ -476,11 +477,11 @@ struct __tag_compositor Fixed depth_gl_scale, depth_gl_strips_filter; u32 depth_gl_type; + Fixed interoccular_distance; /*increase/decrease the standard interoccular offset by the specified distance in cm*/ Fixed interoccular_offset; - /*increase/decrease the view distance by the specified distance in cm*/ - Fixed view_distance_offset; - + /*specifies distance the camera focal point and the screen plane : <0 is behind the screen, >0 is in front*/ + Fixed focus_distance; #endif u32 networks_time; diff --git a/include/gpac/internal/crypt_dev.h b/include/gpac/internal/crypt_dev.h index 9244b1e..40d2882 100644 --- a/include/gpac/internal/crypt_dev.h +++ b/include/gpac/internal/crypt_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Crypto Tools sub-project diff --git a/include/gpac/internal/dvb_mpe_dev.h b/include/gpac/internal/dvb_mpe_dev.h index 9949d07..4e32c98 100644 --- a/include/gpac/internal/dvb_mpe_dev.h +++ b/include/gpac/internal/dvb_mpe_dev.h @@ -2,11 +2,12 @@ * GPAC - Multimedia Framework C SDK * * Authors: Walid B.H - Jean Le Feuvre - * Copyright (c)2006-200X ENST - All rights reserved + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved * * This file is part of GPAC / MPEG2-TS sub-project * - * GPAC is gf_free software; you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the gf_free Software Foundation; either version 2, or (at your option) * any later version. diff --git a/include/gpac/internal/ietf_dev.h b/include/gpac/internal/ietf_dev.h index e02a7ee..84feae3 100644 --- a/include/gpac/internal/ietf_dev.h +++ b/include/gpac/internal/ietf_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/include/gpac/internal/isomedia_dev.h b/include/gpac/internal/isomedia_dev.h index 4950165..151cf0b 100644 --- a/include/gpac/internal/isomedia_dev.h +++ b/include/gpac/internal/isomedia_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -34,10 +35,17 @@ extern "C" { #ifndef GPAC_DISABLE_ISOM -//the default size is 64, cause we need to handle large boxes... +/*the default size is 64, cause we need to handle large boxes... + +the other_boxes container is by default NOT created. When parsing a box and adding +a sub-box with gf_isom_box_add_default, the list is created. +This list is destroyed befaore calling the final box destructor +This list is automatically taken into account during size() and write() functions +*/ #define GF_ISOM_BOX \ u32 type; \ u64 size; \ + GF_List *other_boxes; \ #define GF_ISOM_FULL_BOX \ GF_ISOM_BOX \ @@ -47,6 +55,7 @@ extern "C" { #define GF_ISOM_UUID_BOX \ GF_ISOM_BOX \ u8 uuid[16]; \ + u32 internal_4cc; \ typedef struct { @@ -63,6 +72,13 @@ typedef struct GF_ISOM_UUID_BOX } GF_UUIDBox; + +#define ISOM_DECL_BOX_ALLOC(__TYPE, __4cc) __TYPE *tmp; \ + GF_SAFEALLOC(tmp, __TYPE); \ + if (tmp==NULL) return NULL; \ + tmp->type = __4cc; + + /*constructor*/ GF_Box *gf_isom_box_new(u32 boxType); @@ -71,21 +87,26 @@ GF_Err gf_isom_box_read(GF_Box *ptr, GF_BitStream *bs); void gf_isom_box_del(GF_Box *ptr); GF_Err gf_isom_box_size(GF_Box *ptr); +GF_Err gf_isom_clone_box(GF_Box *src, GF_Box **dst); + GF_Err gf_isom_parse_box(GF_Box **outBox, GF_BitStream *bs); GF_Err gf_isom_read_box_list(GF_Box *s, GF_BitStream *bs, GF_Err (*add_box)(GF_Box *par, GF_Box *b)); GF_Err gf_isom_read_box_list_ex(GF_Box *parent, GF_BitStream *bs, GF_Err (*add_box)(GF_Box *par, GF_Box *b), u32 parent_type); +GF_Err gf_isom_box_add_default(GF_Box *a, GF_Box *subbox); + +#define gf_isom_full_box_init(__pre) + +//void gf_isom_full_box_init(GF_Box *ptr); GF_Err gf_isom_box_get_size(GF_Box *ptr); GF_Err gf_isom_full_box_get_size(GF_Box *ptr); GF_Err gf_isom_box_write_header(GF_Box *ptr, GF_BitStream *bs); GF_Err gf_isom_full_box_read(GF_Box *ptr, GF_BitStream *bs); GF_Err gf_isom_full_box_write(GF_Box *s, GF_BitStream *bs); -void gf_isom_full_box_init(GF_Box *ptr); -void gf_isom_box_array_del(GF_List *boxList); +void gf_isom_box_array_del(GF_List *other_boxes); GF_Err gf_isom_box_array_write(GF_Box *parent, GF_List *list, GF_BitStream *bs); GF_Err gf_isom_box_array_size(GF_Box *parent, GF_List *list); - enum { GF_ISOM_BOX_TYPE_CO64 = GF_4CC( 'c', 'o', '6', '4' ), @@ -129,13 +150,19 @@ enum GF_ISOM_BOX_TYPE_UDTA = GF_4CC( 'u', 'd', 't', 'a' ), GF_ISOM_BOX_TYPE_VMHD = GF_4CC( 'v', 'm', 'h', 'd' ), GF_ISOM_BOX_TYPE_FTYP = GF_4CC( 'f', 't', 'y', 'p' ), - GF_ISOM_BOX_TYPE_FADB = GF_4CC( 'p', 'a', 'd', 'b' ), + GF_ISOM_BOX_TYPE_PADB = GF_4CC( 'p', 'a', 'd', 'b' ), GF_ISOM_BOX_TYPE_PDIN = GF_4CC( 'p', 'd', 'i', 'n' ), GF_ISOM_BOX_TYPE_SDTP = GF_4CC( 's', 'd', 't', 'p' ), + GF_ISOM_BOX_TYPE_CSLG = GF_4CC( 'c', 's', 'l', 'g' ), GF_ISOM_BOX_TYPE_SBGP = GF_4CC( 's', 'b', 'g', 'p' ), GF_ISOM_BOX_TYPE_SGPD = GF_4CC( 's', 'g', 'p', 'd' ), + GF_ISOM_BOX_TYPE_SAIZ = GF_4CC( 's', 'a', 'i', 'z' ), + GF_ISOM_BOX_TYPE_SAIO = GF_4CC( 's', 'a', 'i', 'o' ), + GF_ISOM_BOX_TYPE_MFRA = GF_4CC( 'm', 'f', 'r', 'a' ), + GF_ISOM_BOX_TYPE_PSSH = GF_4CC( 'p', 's', 's', 'h' ), + GF_ISOM_BOX_TYPE_TENC = GF_4CC( 't', 'e', 'n', 'c' ), #ifndef GPAC_DISABLE_ISOM_FRAGMENTS /*Movie Fragments*/ @@ -163,6 +190,7 @@ enum GF_ISOM_BOX_TYPE_MP4A = GF_4CC( 'm', 'p', '4', 'a' ), GF_ISOM_BOX_TYPE_MP4V = GF_4CC( 'm', 'p', '4', 'v' ), + /*AVC / H264 extension*/ GF_ISOM_BOX_TYPE_AVCC = GF_4CC( 'a', 'v', 'c', 'C' ), GF_ISOM_BOX_TYPE_BTRT = GF_4CC( 'b', 't', 'r', 't' ), @@ -260,6 +288,14 @@ enum /*internal type for track references*/ GF_ISOM_BOX_TYPE_REFT = GF_4CC( 'R', 'E', 'F', 'T' ), +#ifndef GPAC_DISABLE_ISOM_ADOBE + /* Adobe extensions */ + GF_ISOM_BOX_TYPE_ABST = GF_4CC( 'a', 'b', 's', 't' ), + GF_ISOM_BOX_TYPE_AFRA = GF_4CC( 'a', 'f', 'r', 'a' ), + GF_ISOM_BOX_TYPE_ASRT = GF_4CC( 'a', 's', 'r', 't' ), + GF_ISOM_BOX_TYPE_AFRT = GF_4CC( 'a', 'f', 'r', 't' ), +#endif + /* Apple extensions */ GF_ISOM_BOX_TYPE_ILST = GF_4CC( 'i', 'l', 's', 't' ), @@ -309,6 +345,8 @@ enum GF_ISOM_BOX_TYPE_AC3 = GF_4CC( 'a', 'c', '-', '3' ), GF_ISOM_BOX_TYPE_DAC3 = GF_4CC( 'd', 'a', 'c', '3' ), + GF_ISOM_BOX_TYPE_EC3 = GF_4CC( 'e', 'c', '-', '3' ), + GF_ISOM_BOX_TYPE_DEC3 = GF_4CC( 'd', 'e', 'c', '3' ), GF_ISOM_BOX_TYPE_SUBS = GF_4CC( 's', 'u', 'b', 's' ), @@ -326,6 +364,14 @@ enum GF_ISOM_BOX_TYPE_GHNT = GF_4CC( 'g', 'h', 'n', 't' ), /*for compatibility with old files hinted for DSS - needs special parsing*/ GF_ISOM_BOX_TYPE_VOID = GF_4CC( 'V', 'O', 'I', 'D' ), + + + /*MS Smooth - these are actually UUID boxes*/ + GF_ISOM_BOX_UUID_PSSH = GF_4CC( 'P', 'S', 'S', 'H' ), + GF_ISOM_BOX_UUID_TENC = GF_4CC( 'T', 'E', 'N', 'C' ), + GF_ISOM_BOX_UUID_PSEC = GF_4CC( 'P', 'S', 'E', 'C' ), + GF_ISOM_BOX_UUID_TFRF = GF_4CC( 'T', 'F', 'R', 'F' ), + GF_ISOM_BOX_UUID_TFXD = GF_4CC( 'T', 'F', 'X', 'D' ), }; @@ -413,7 +459,7 @@ typedef struct { u32 boxType; u8 uuid[16]; - GF_List *boxList; + GF_List *other_boxes; } GF_UserDataMap; typedef struct @@ -435,8 +481,6 @@ typedef struct struct __tag_meta_box *meta; /*track boxes*/ GF_List *trackList; - /*other boxes*/ - GF_List *boxes; GF_ISOFile *mov; @@ -462,7 +506,6 @@ typedef struct typedef struct { GF_ISOM_BOX - GF_List *boxList; } GF_TrackReferenceBox; @@ -477,8 +520,6 @@ typedef struct GF_TrackReferenceBox *References; /*meta box if any*/ struct __tag_meta_box *meta; - /*other*/ - GF_List *boxes; GF_MovieBox *moov; /*private for media padding*/ @@ -491,6 +532,7 @@ typedef struct #ifndef GPAC_DISABLE_ISOM_FRAGMENTS u64 dts_at_seg_start; u32 sample_count_at_seg_start; + Bool first_traf_merged; #endif } GF_TrackBox; @@ -572,7 +614,6 @@ typedef struct typedef struct { GF_ISOM_FULL_BOX - GF_List *boxList; } GF_DataReferenceBox; typedef struct @@ -631,7 +672,7 @@ typedef struct typedef struct { u32 sampleCount; - u32 decodingOffset; + s32 decodingOffset; } GF_DttsEntry; typedef struct @@ -677,7 +718,7 @@ typedef struct GF_ISOM_UUID_BOX \ u16 dataReferenceIndex; \ char reserved[ 6 ]; \ - struct __tag_protect_box *protection_info; + GF_List *protections; /*base sample entry box (never used but for typecasting)*/ typedef struct @@ -685,6 +726,9 @@ typedef struct GF_ISOM_SAMPLE_ENTRY_FIELDS } GF_SampleEntryBox; +void gf_isom_sample_entry_init(GF_SampleEntryBox *ptr); +void gf_isom_sample_entry_predestroy(GF_SampleEntryBox *ptr); + typedef struct { GF_ISOM_SAMPLE_ENTRY_FIELDS @@ -766,7 +810,7 @@ typedef struct u16 revision; \ u32 vendor; \ u32 temporal_quality; \ - u32 spacial_quality; \ + u32 spatial_quality; \ u16 Width, Height; \ u32 horiz_res, vert_res; \ u32 entry_data_size; \ @@ -789,6 +833,8 @@ void gf_isom_video_sample_entry_write(GF_VisualSampleEntryBox *ent, GF_BitStream void gf_isom_video_sample_entry_size(GF_VisualSampleEntryBox *ent); #endif +void gf_isom_sample_entry_predestroy(GF_SampleEntryBox *ptr); + typedef struct { GF_ISOM_BOX @@ -899,12 +945,11 @@ typedef struct typedef struct { GF_ISOM_AUDIO_SAMPLE_ENTRY + Bool is_ec3; GF_AC3ConfigBox *info; } GF_AC3SampleEntryBox; - - typedef struct { GF_ISOM_FULL_BOX @@ -946,7 +991,6 @@ typedef struct typedef struct { GF_ISOM_FULL_BOX - GF_List *boxList; } GF_SampleDescriptionBox; @@ -1048,12 +1092,6 @@ typedef struct } GF_SampleDependencyTypeBox; -typedef struct -{ - u32 sample_delta; - GF_List *SubSamples; -} GF_SampleEntry; - typedef struct { u32 subsample_size; @@ -1062,22 +1100,41 @@ typedef struct u32 reserved; } GF_SubSampleEntry; +typedef struct +{ + u32 sample_delta; + GF_List *SubSamples; +} GF_SubSampleInfoEntry; + typedef struct { GF_ISOM_FULL_BOX GF_List *Samples; } GF_SubSampleInformationBox; -u32 gf_isom_sample_get_subsample_entry(GF_ISOFile *movie, u32 track, u32 sampleNumber, GF_SampleEntry **sub_sample); +u32 gf_isom_sample_get_subsample_entry(GF_ISOFile *movie, u32 track, u32 sampleNumber, GF_SubSampleInfoEntry **sub_sample); #ifndef GPAC_DISABLE_ISOM_WRITE GF_Err gf_isom_add_subsample_info(GF_SubSampleInformationBox *sub_samples, u32 sampleNumber, u32 subSampleSize, u8 priority, u32 reserved, Bool discardable); #endif +/* Use to relate the composition and decoding timeline when signed composition is used*/ +typedef struct +{ + GF_ISOM_FULL_BOX + + s32 compositionToDTSShift; + s32 leastDecodeToDisplayDelta; + s32 greatestDecodeToDisplayDelta; + s32 compositionStartTime; + s32 compositionEndTime; +} GF_CompositionToDecodeBox; + typedef struct { GF_ISOM_BOX GF_TimeToSampleBox *TimeToSample; GF_CompositionOffsetBox *CompositionOffset; + GF_CompositionToDecodeBox *CompositionToDecode; GF_SyncSampleBox *SyncSample; GF_SampleDescriptionBox *SampleDescription; GF_SampleSizeBox *SampleSize; @@ -1095,6 +1152,9 @@ typedef struct GF_List *sampleGroups; GF_List *sampleGroupsDescription; + GF_List *sai_sizes; + GF_List *sai_offsets; + u32 MaxSamplePerChunk; u16 groupID; u16 trackPriority; @@ -1109,7 +1169,6 @@ typedef struct __tag_media_info_box GF_Box *InfoHeader; struct __tag_data_map *dataHandler; u32 dataEntryIndex; - GF_List *boxes; } GF_MediaInformationBox; @@ -1402,6 +1461,8 @@ typedef struct GF_ISMAKMSBox *ikms; GF_ISMASampleFormatBox *isfm; struct __oma_kms_box *okms; + struct __cenc_tenc_box *tenc; + struct __piff_tenc_box *piff_tenc; } GF_SchemeInformationBox; typedef struct __tag_protect_box @@ -1436,7 +1497,6 @@ typedef struct __tag_meta_box GF_ItemProtectionBox *protections; GF_ItemInfoBox *item_infos; GF_IPMPControlBox *IPMP_control; - GF_List *other_boxes; } GF_MetaBox; @@ -1502,7 +1562,8 @@ enum GF_ISOM_TRAF_SAMPLE_DUR = 0x08, GF_ISOM_TRAF_SAMPLE_SIZE = 0x10, GF_ISOM_TRAF_SAMPLE_FLAGS = 0x20, - GF_ISOM_TRAF_DUR_EMPTY = 0x10000 + GF_ISOM_TRAF_DUR_EMPTY = 0x10000, + GF_ISOM_MOOF_BASE_OFFSET = 0x20000, }; typedef struct @@ -1539,6 +1600,11 @@ typedef struct GF_List *sampleGroups; GF_List *sampleGroupsDescription; + GF_List *sai_sizes; + GF_List *sai_offsets; + + struct __piff_sample_enc_box *piff_sample_encryption; + /*when data caching is on*/ u32 DataCache; GF_TFBaseMediaDecodeTimeBox *tfdt; @@ -1628,9 +1694,9 @@ typedef struct typedef struct { GF_ISOM_BOX + GF_List *hints; /*contains GF_SDPBox if in track, GF_RTPBox if in movie*/ GF_Box *SDP; - GF_List *boxList; } GF_HintTrackInfoBox; typedef struct @@ -1788,8 +1854,6 @@ typedef struct typedef struct { GF_ISOM_BOX - GF_List *dataRates; - GF_List *boxList; } GF_HintInfoBox; /*Apple extension*/ @@ -1811,7 +1875,6 @@ typedef struct typedef struct { GF_ISOM_BOX - GF_List *tags; } GF_ItemListBox; /*OMA (P)DCF extensions*/ @@ -1825,7 +1888,6 @@ typedef struct char *RightsIssuerURL; char *TextualHeaders; u32 TextualHeadersLen; - GF_List *ExtendedHeaders; } GF_OMADRMCommonHeaderBox; typedef struct @@ -1840,7 +1902,6 @@ typedef struct typedef struct { GF_ISOM_BOX - GF_List *boxes; } GF_OMADRMMutableInformationBox; typedef struct @@ -1896,6 +1957,96 @@ typedef struct __pcrInfo_box u64 *pcr_values; } GF_PcrInfoBox; +#ifndef GPAC_DISABLE_ISOM_ADOBE + +/*Adobe specific boxes*/ +typedef struct +{ + u64 time; + u64 offset; +} GF_AfraEntry; + +typedef struct +{ + u64 time; + u32 segment; + u32 fragment; + u64 afra_offset; + u64 offset_from_afra; +} GF_GlobalAfraEntry; + +typedef struct __adobe_frag_random_access_box +{ + GF_ISOM_FULL_BOX + Bool long_ids; + Bool long_offsets; + Bool global_entries; + u8 reserved; + u32 time_scale; + u32 entry_count; + GF_List *local_access_entries; + u32 global_entry_count; + GF_List *global_access_entries; +} GF_AdobeFragRandomAccessBox; + +typedef struct __adobe_bootstrap_info_box +{ + GF_ISOM_FULL_BOX + u32 bootstrapinfo_version; + u8 profile; + Bool live; + Bool update; + u8 reserved; + u32 time_scale; + u64 current_media_time; + u64 smpte_time_code_offset; + char *movie_identifier; + u8 server_entry_count; + GF_List *server_entry_table; + u8 quality_entry_count; + GF_List *quality_entry_table; + char *drm_data; + char *meta_data; + u8 segment_run_table_count; + GF_List *segment_run_table_entries; + u8 fragment_run_table_count; + GF_List *fragment_run_table_entries; +} GF_AdobeBootstrapInfoBox; + +typedef struct +{ + u32 first_segment; + u32 fragment_per_segment; +} GF_AdobeSegmentRunEntry; + +typedef struct __adobe_segment_run_table_box +{ + GF_ISOM_FULL_BOX + u8 quality_entry_count; + GF_List *quality_segment_url_modifiers; + u32 segment_run_entry_count; + GF_List *segment_run_entry_table; +} GF_AdobeSegmentRunTableBox; + +typedef struct +{ + u32 first_fragment; + u64 first_fragment_timestamp; + u32 fragment_duration; + u8 discontinuity_indicator; +} GF_AdobeFragmentRunEntry; + +typedef struct __adobe_fragment_run_table_box +{ + GF_ISOM_FULL_BOX + u32 timescale; + u8 quality_entry_count; + GF_List *quality_segment_url_modifiers; + u32 fragment_run_entry_count; + GF_List *fragment_run_entry_table; +} GF_AdobeFragmentRunTableBox; + +#endif /*GPAC_DISABLE_ISOM_ADOBE*/ /*********************************************************** @@ -1948,13 +2099,140 @@ typedef struct } GF_RollRecoveryEntry; +typedef struct +{ + GF_ISOM_FULL_BOX + + u32 aux_info_type; + u32 aux_info_type_parameter; + + u8 default_sample_info_size; + u32 sample_count; + u8 *sample_info_size; +} GF_SampleAuxiliaryInfoSizeBox; + +typedef struct +{ + GF_ISOM_FULL_BOX + + u32 aux_info_type; + u32 aux_info_type_parameter; + + u8 default_sample_info_size; + u32 entry_count; //1 or stco / trun count + u32 *offsets; + u64 *offsets_large; + + u64 single_offset; +} GF_SampleAuxiliaryInfoOffsetBox; + +/* + CENC stuff +*/ + +/*CENCSampleEncryptionGroupEntry - 'seig' type*/ +typedef struct +{ + u32 IsEncrypted; + u8 IV_size; + bin128 KID; +} GF_CENCSampleEncryptionGroupEntry; + +typedef struct +{ + GF_ISOM_FULL_BOX + + bin128 SystemID; + u32 KID_count; + bin128 *KIDs; + u32 private_data_size; + u8 *private_data; +} GF_ProtectionSystemHeaderBox; + +typedef struct __cenc_tenc_box +{ + GF_ISOM_FULL_BOX + + u32 IsEncrypted; + u8 IV_size; + bin128 KID; +} GF_TrackEncryptionBox; + +typedef struct __piff_tenc_box +{ + GF_ISOM_UUID_BOX + u8 version; + u32 flags; + + u32 AlgorithmID; + u8 IV_size; + bin128 KID; +} GF_PIFFTrackEncryptionBox; + +typedef struct +{ + GF_ISOM_UUID_BOX + u8 version; + u32 flags; + + bin128 SystemID; + u32 private_data_size; + u8 *private_data; +} GF_PIFFProtectionSystemHeaderBox; + + +typedef struct +{ + u32 bytes_clear_data; + u32 bytes_encrypted_data; +} GF_CENCSubSampleEntry; + +typedef struct __cenc_sample_info +{ + /*set to 1 if keyID, IV_size and algo_id are NOT the default vamlues for the track*/ + Bool is_alt_info; + bin128 keyID; + /*can be 0, 64 or 128 bits - if 64, bytes 0-7 are used and 8-15 are 0-padded*/ + bin128 IV; + u32 algo_id; + u16 IV_size; + u16 subsample_count; + GF_CENCSubSampleEntry *subsamples; +} GF_CENCSampleInfo; + +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS +GF_CENCSampleInfo *gf_isom_cenc_get_sample(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u32 sample_number); +void gf_isom_cenc_sample_del(GF_CENCSampleInfo *samp); +#endif + + +typedef struct __piff_sample_enc_box +{ + GF_ISOM_UUID_BOX + u8 version; + u32 flags; + + u32 AlgorithmID; + u8 IV_size; + bin128 KID; + + u32 sample_count; + u32 cenc_data_size; + char *cenc_data; + +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + /*pointer to container traf*/ + GF_TrackFragmentBox *traf; +#endif +} GF_PIFFSampleEncryptionBox; + /* Data Map (media storage) stuff */ /*regular file IO*/ #define GF_ISOM_DATA_FILE 0x01 -/*File Mapaing object, read-only mode on complete files (no download)*/ +/*File Maping object, read-only mode on complete files (no download)*/ #define GF_ISOM_DATA_FILE_MAPPING 0x02 /*External file object. Needs implementation*/ #define GF_ISOM_DATA_FILE_EXTERN 0x03 @@ -1992,6 +2270,7 @@ typedef struct { GF_ISOM_BASE_DATA_HANDLER FILE *stream; + Bool is_stdout; Bool last_acces_was_read; #ifndef GPAC_DISABLE_ISOM_WRITE char *temp_file; @@ -2101,7 +2380,6 @@ struct __tag_isom { #ifndef GPAC_DISABLE_ISOM_FRAGMENTS u32 FragmentsFlags, NextMoofNumber; - Bool first_moof_merged; /*active fragment*/ GF_MovieFragmentBox *moof; /*in WRITE mode, this is the current MDAT where data is written*/ @@ -2290,6 +2568,7 @@ GF_Err hnti_AddBox(GF_HintTrackInfoBox *hnti, GF_Box *a); GF_Err udta_AddBox(GF_UserDataBox *ptr, GF_Box *a); GF_Err edts_AddBox(GF_Box *s, GF_Box *a); GF_Err stdp_Read(GF_Box *s, GF_BitStream *bs); +GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a); GF_Err sdtp_Read(GF_Box *s, GF_BitStream *bs); GF_Err dinf_AddBox(GF_Box *s, GF_Box *a); GF_Err minf_AddBox(GF_Box *s, GF_Box *a); @@ -2476,6 +2755,13 @@ struct _3gpp_text_sample GF_TextSample *gf_isom_parse_texte_sample(GF_BitStream *bs); GF_TextSample *gf_isom_parse_texte_sample_from_data(char *data, u32 dataLength); +struct _generic_subtitle_sample +{ + char *text; + u32 len; +}; +GF_GenericSubtitleSample *gf_isom_parse_generic_subtitle_sample(GF_BitStream *bs); +GF_GenericSubtitleSample *gf_isom_parse_generic_subtitle_sample_from_data(char *data, u32 dataLength); /* @@ -3136,6 +3422,32 @@ GF_Err iKMS_Size(GF_Box *s); GF_Err iSFM_Size(GF_Box *s); #endif +#ifndef GPAC_DISABLE_ISOM_ADOBE +/* Adobe extensions */ +void abst_del(GF_Box *s); +GF_Err abst_Read(GF_Box *s, GF_BitStream *bs); +GF_Box *abst_New(); +void afra_del(GF_Box *s); +GF_Err afra_Read(GF_Box *s, GF_BitStream *bs); +GF_Box *afra_New(); +void asrt_del(GF_Box *s); +GF_Err asrt_Read(GF_Box *s, GF_BitStream *bs); +GF_Box *asrt_New(); +void afrt_del(GF_Box *s); +GF_Err afrt_Read(GF_Box *s, GF_BitStream *bs); +GF_Box *afrt_New(); +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err abst_Write(GF_Box *s, GF_BitStream *bs); +GF_Err abst_Size(GF_Box *s); +GF_Err afra_Write(GF_Box *s, GF_BitStream *bs); +GF_Err afra_Size(GF_Box *s); +GF_Err asrt_Write(GF_Box *s, GF_BitStream *bs); +GF_Err asrt_Size(GF_Box *s); +GF_Err afrt_Write(GF_Box *s, GF_BitStream *bs); +GF_Err afrt_Size(GF_Box *s); +#endif +#endif /*GPAC_DISABLE_ISOM_ADOBE*/ + /* Apple extensions */ void ilst_del(GF_Box *s); void ListItem_del(GF_Box *s); @@ -3155,6 +3467,7 @@ GF_Err ListItem_Size(GF_Box *s); GF_Err data_Size(GF_Box *s); #endif +GF_Err gf_box_dump(void *ptr, FILE * trace); GF_Err gb_box_array_dump(GF_List *list, FILE * trace); GF_Err reftype_dump(GF_Box *a, FILE * trace); @@ -3288,6 +3601,14 @@ GF_Err frma_dump(GF_Box *a, FILE * trace); GF_Err schm_dump(GF_Box *a, FILE * trace); GF_Err schi_dump(GF_Box *a, FILE * trace); +#ifndef GPAC_DISABLE_ISOM_ADOBE +/*Adobe extensions*/ +GF_Err abst_dump(GF_Box *a, FILE * trace); +GF_Err afra_dump(GF_Box *a, FILE * trace); +GF_Err asrt_dump(GF_Box *a, FILE * trace); +GF_Err afrt_dump(GF_Box *a, FILE * trace); +#endif + /*Apple extensions*/ GF_Err ilst_dump(GF_Box *a, FILE * trace); GF_Err ListItem_dump(GF_Box *a, FILE * trace); @@ -3388,14 +3709,14 @@ GF_Err diST_Size(GF_Box *s); GF_Err diST_dump(GF_Box *a, FILE * trace); -GF_Box *ac3_New(); +GF_Box *ac3_New(u32 boxType); void ac3_del(GF_Box *s); GF_Err ac3_Read(GF_Box *s, GF_BitStream *bs); GF_Err ac3_Write(GF_Box *s, GF_BitStream *bs); GF_Err ac3_Size(GF_Box *s); GF_Err ac3_dump(GF_Box *a, FILE * trace); -GF_Box *dac3_New(); +GF_Box *dac3_New(u32 boxType); void dac3_del(GF_Box *s); GF_Err dac3_Read(GF_Box *s, GF_BitStream *bs); GF_Err dac3_Write(GF_Box *s, GF_BitStream *bs); @@ -3468,6 +3789,63 @@ GF_Err sgpd_Size(GF_Box *s); GF_Err sgpd_Read(GF_Box *s, GF_BitStream *bs); GF_Err sgpd_dump(GF_Box *a, FILE * trace); +GF_Box *saiz_New(); +void saiz_del(GF_Box *); +GF_Err saiz_Write(GF_Box *s, GF_BitStream *bs); +GF_Err saiz_Size(GF_Box *s); +GF_Err saiz_Read(GF_Box *s, GF_BitStream *bs); +GF_Err saiz_dump(GF_Box *a, FILE * trace); + +GF_Box *saio_New(); +void saio_del(GF_Box *); +GF_Err saio_Write(GF_Box *s, GF_BitStream *bs); +GF_Err saio_Size(GF_Box *s); +GF_Err saio_Read(GF_Box *s, GF_BitStream *bs); +GF_Err saio_dump(GF_Box *a, FILE * trace); + +GF_Box *pssh_New(); +void pssh_del(GF_Box *); +GF_Err pssh_Write(GF_Box *s, GF_BitStream *bs); +GF_Err pssh_Size(GF_Box *s); +GF_Err pssh_Read(GF_Box *s, GF_BitStream *bs); +GF_Err pssh_dump(GF_Box *a, FILE * trace); + +GF_Box *tenc_New(); +void tenc_del(GF_Box *); +GF_Err tenc_Write(GF_Box *s, GF_BitStream *bs); +GF_Err tenc_Size(GF_Box *s); +GF_Err tenc_Read(GF_Box *s, GF_BitStream *bs); +GF_Err tenc_dump(GF_Box *a, FILE * trace); + +GF_Box *piff_tenc_New(); +void piff_tenc_del(GF_Box *); +GF_Err piff_tenc_Write(GF_Box *s, GF_BitStream *bs); +GF_Err piff_tenc_Size(GF_Box *s); +GF_Err piff_tenc_Read(GF_Box *s, GF_BitStream *bs); +GF_Err piff_tenc_dump(GF_Box *a, FILE * trace); + +GF_Box *piff_psec_New(); +void piff_psec_del(GF_Box *); +GF_Err piff_psec_Write(GF_Box *s, GF_BitStream *bs); +GF_Err piff_psec_Size(GF_Box *s); +GF_Err piff_psec_Read(GF_Box *s, GF_BitStream *bs); +GF_Err piff_psec_dump(GF_Box *a, FILE * trace); + +GF_Box *piff_pssh_New(); +void piff_pssh_del(GF_Box *); +GF_Err piff_pssh_Write(GF_Box *s, GF_BitStream *bs); +GF_Err piff_pssh_Size(GF_Box *s); +GF_Err piff_pssh_Read(GF_Box *s, GF_BitStream *bs); +GF_Err piff_pssh_dump(GF_Box *a, FILE * trace); + + +GF_Box *cslg_New(); +void cslg_del(GF_Box *); +GF_Err cslg_Write(GF_Box *s, GF_BitStream *bs); +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); + #endif /*GPAC_DISABLE_ISOM*/ #ifdef __cplusplus diff --git a/include/gpac/internal/laser_dev.h b/include/gpac/internal/laser_dev.h index 83ed903..c8094ea 100644 --- a/include/gpac/internal/laser_dev.h +++ b/include/gpac/internal/laser_dev.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / LASeR codec sub-project diff --git a/include/gpac/internal/m3u8.h b/include/gpac/internal/m3u8.h index 320e401..1f85eb4 100644 --- a/include/gpac/internal/m3u8.h +++ b/include/gpac/internal/m3u8.h @@ -1,7 +1,7 @@ /** * GPAC - Multimedia Framework C SDK * - * Authors: Pierre Souchay + * Authors: Pierre Souchay - Jean Le Feuvre * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * @@ -86,7 +86,7 @@ typedef enum e_playlistElementType { TYPE_PLAYLIST, TYPE_STREAM, TYPE_UNKNOWN} typedef struct s_playlistElement { int durationInfo; u64 byteRangeStart, byteRangeEnd; - int bandwidth; + int bandwidth, width, height; char * title; char * codecs; char * url; diff --git a/include/gpac/internal/media_dev.h b/include/gpac/internal/media_dev.h index 956426d..4ff8ab1 100644 --- a/include/gpac/internal/media_dev.h +++ b/include/gpac/internal/media_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -66,6 +67,8 @@ enum AVC_SUBSPS_PARSED = 1<<2, /*SUB-SPS has been declared to the upper layer*/ AVC_SUBSPS_DECLARED = 1<<3, + /*SPS extension has been parsed*/ + AVC_SPS_EXT_DECLARED = 1<<4, }; typedef struct @@ -104,6 +107,9 @@ typedef struct s32 delta_pic_order_always_zero_flag; s32 offset_for_non_ref_pic, offset_for_top_to_bottom_field; Bool frame_mbs_only_flag; + u8 chroma_format; + u8 luma_bit_depth_m8; + u8 chroma_bit_depth_m8; s16 offset_for_ref_frame[256]; @@ -188,12 +194,26 @@ typedef struct Bool is_svc; } AVCState; +typedef struct +{ + u32 NALUnitHeader; + u8 track_ref_index; + s8 sample_offset; + u32 data_offset; + u32 data_length; +} SVC_Extractor; + + /*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); /*return pps ID or -1 if error*/ s32 AVC_ReadPictParamSet(char *pps_data, u32 pps_size, AVCState *avc); -/*is slice a RAP*/ +/*return sps ID or -1 if error*/ +s32 AVC_ReadSeqParamSetExtId(char *spse_data, u32 spse_size); +/*is slice an IDR*/ Bool AVC_SliceIsIDR(AVCState *avc); +/*is slice containing intra MB only*/ +Bool AVC_SliceIsIntra(AVCState *avc); /*parses NALU, updates avc state and returns: 1 if NALU part of new frame 0 if NALU part of prev frame @@ -239,5 +259,17 @@ void gf_media_format_ttxt_sdp(GP_RTPPacketizer *builder, char *payload_name, cha #endif + +typedef enum +{ + GF_DASH_TEMPLATE_SEGMENT = 0, + GF_DASH_TEMPLATE_INITIALIZATION, + GF_DASH_TEMPLATE_TEMPLATE, + GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE, + GF_DASH_TEMPLATE_REPINDEX, +} GF_DashTemplateSegmentType; + +GF_Err gf_media_mpd_format_segment_name(GF_DashTemplateSegmentType seg_type, Bool is_bs_switching, char *segment_name, const char *output_file_name, const char *rep_id, const char *seg_rad_name, const char *seg_ext, u64 start_time, u32 bandwidth, u32 segment_number); + #endif /*_GF_MEDIA_DEV_H_*/ diff --git a/include/gpac/internal/mesh.h b/include/gpac/internal/mesh.h index 3bed651..7c35e03 100644 --- a/include/gpac/internal/mesh.h +++ b/include/gpac/internal/mesh.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/include/gpac/internal/mpd.h b/include/gpac/internal/mpd.h index 2a41d3b..dfee351 100644 --- a/include/gpac/internal/mpd.h +++ b/include/gpac/internal/mpd.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Cyril Concolato - * Copyright (c) Telecom ParisTech 2010- + * Authors: Jean Le Feuvre - Cyril Concolato + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / 3GPP/MPEG Media Presentation Description input module @@ -54,10 +54,9 @@ typedef struct u32 dummy; } GF_MPD_Subset; -/*TODO*/ typedef struct { - u32 start_time; + u64 start_time; u32 duration; /*MANDATORY*/ u32 repeat_count; } GF_MPD_SegmentTimelineEntry; @@ -94,7 +93,7 @@ typedef struct #define GF_MPD_SEGMENT_BASE \ u32 timescale; \ - u32 presentation_time_offset; \ + u64 presentation_time_offset; \ u32 index_range; \ Bool index_range_exact; \ GF_MPD_URL *initialization_segment; \ @@ -132,6 +131,9 @@ typedef struct GF_MPD_MULTIPLE_SEGMENT_BASE /*list of segments - can be NULL if no segment*/ GF_List *segment_URLs; + + char *xlink_href; + Bool xlink_actuate_on_load; } GF_MPD_SegmentList; typedef struct @@ -187,6 +189,12 @@ typedef struct { char *content_components; } GF_MPD_SubRepresentation; +typedef struct +{ + Bool disabled; + char *cached_init_segment_url; + u64 init_start_range, init_end_range; +} GF_DASH_RepresentationPlayback; typedef struct { GF_MPD_COMMON_ATTRIBUTES_ELEMENTS @@ -205,8 +213,7 @@ typedef struct { GF_List *sub_representations; /*GPAC playback implementation*/ - Bool disabled; - + GF_DASH_RepresentationPlayback playback; } GF_MPD_Representation; @@ -247,6 +254,8 @@ typedef struct GF_List *representations; + char *xlink_href; + Bool xlink_actuate_on_load; } GF_MPD_AdaptationSet; @@ -264,6 +273,8 @@ typedef struct GF_List *adaptation_sets; GF_List *subsets; + char *xlink_href; + Bool xlink_actuate_on_load; } GF_MPD_Period; typedef struct @@ -307,14 +318,17 @@ typedef struct { GF_List *metrics; /*list of GF_MPD_Period */ GF_List *periods; + + /*set during parsing*/ + const char *xml_namespace; } GF_MPD; GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *base_url); GF_MPD *gf_mpd_new(); void gf_mpd_del(GF_MPD *mpd); -/*frees a SegmentURL*/ -void gf_mpd_segment_url_free(void *_item); +/*frees a GF_MPD_SegmentURL structure (type-casted to void *)*/ +void gf_mpd_segment_url_free(void *ptr); typedef struct _gf_file_get GF_FileDownload; struct _gf_file_get diff --git a/include/gpac/internal/odf_dev.h b/include/gpac/internal/odf_dev.h index 8ff4046..15c7f0e 100644 --- a/include/gpac/internal/odf_dev.h +++ b/include/gpac/internal/odf_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/include/gpac/internal/odf_parse_common.h b/include/gpac/internal/odf_parse_common.h index 43b31c9..80c0f8c 100644 --- a/include/gpac/internal/odf_parse_common.h +++ b/include/gpac/internal/odf_parse_common.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/include/gpac/internal/scenegraph_dev.h b/include/gpac/internal/scenegraph_dev.h index d371882..5c793a8 100644 --- a/include/gpac/internal/scenegraph_dev.h +++ b/include/gpac/internal/scenegraph_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/include/gpac/internal/smjs_api.h b/include/gpac/internal/smjs_api.h index f28e0ab..756347b 100644 --- a/include/gpac/internal/smjs_api.h +++ b/include/gpac/internal/smjs_api.h @@ -40,9 +40,40 @@ #define JS_VERSION 170 #endif + +typedef struct +{ + JSClass _class; + JSObject *_proto; +} GF_JSClass; + + + /*new APIs*/ #if (JS_VERSION>=185) +#ifdef USE_FFDEV_16 +#define USE_FFDEV_15 +#endif + +#ifdef USE_FFDEV_15 +#define JSVAL_IS_OBJECT(__v) JSVAL_IS_OBJECT_OR_NULL_IMPL(JSVAL_TO_IMPL(__v)) +#define USE_FFDEV_14 +#endif + +#ifdef USE_FFDEV_14 +#define USE_FFDEV_12 + +#define JS_FinalizeStub NULL +#ifdef USE_FFDEV_16 +#define JS_NEW_OBJ_FOR_CONS(__c, __classp, __args) JS_NewObjectForConstructor(__c, &(__classp)->_class, __args) +#else +#define JS_NEW_OBJ_FOR_CONS(__c, __classp, __args) JS_NewObjectForConstructor(__c, __classp, __args) +#endif + +#else +#define JS_NEW_OBJ_FOR_CONS(__c, __classp, __args) JS_NewObjectForConstructor(__c, __args) +#endif #ifdef USE_FFDEV_12 typedef unsigned uintN; @@ -53,8 +84,28 @@ typedef double jsdouble; #define JS_NewDouble(c, v) v #define JS_PropertyStub_forSetter JS_StrictPropertyStub -#define SMJS_PROP_SETTER jsid id, JSBool strict -#define SMJS_PROP_GETTER jsid id + +#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) +#define SMJS_FUNC_PROP_SET(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, jsval *vp) +#define SMJS_FUNC_PROP_GET(func_name) SMJS_DECL_FUNC_PROP_GET( func_name ) { JSObject *obj = *(__hobj._); jsid id = *(__hid._); +#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; + +#else + +#define SMJS_DECL_FUNC_PROP_SET(func_name) JSBool func_name(JSContext *c, JSObject *obj, jsid id, JSBool strict, jsval *vp) +#define SMJS_FUNC_PROP_SET(func_name) SMJS_DECL_FUNC_PROP_SET( func_name) { +#define SMJS_DECL_FUNC_PROP_GET(func_name) JSBool func_name(JSContext *c, JSObject *obj, jsid id, jsval *vp) +#define SMJS_FUNC_PROP_GET(func_name) SMJS_DECL_FUNC_PROP_GET(func_name) { +#define SMJS_CALL_PROP_STUB() JS_PropertyStub(c, obj, id, vp) +#define DECL_FINALIZE(func_name) void func_name(JSContext *c, JSObject *obj) { + +#endif + + #define SMJS_FUNCTION_SPEC(__name, __fun, __argc) {__name, __fun, __argc, 0} #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) @@ -70,8 +121,8 @@ typedef double jsdouble; #define SMJS_FREE(__c, __str) if (__str) JS_free(__c, __str) -#define SMJS_OBJ_CONSTRUCTOR \ - JSObject *obj = JS_NewObjectForConstructor(c, argsvp); \ +#define SMJS_OBJ_CONSTRUCTOR(__classp) \ + JSObject *obj = JS_NEW_OBJ_FOR_CONS(c, __classp, argsvp); \ SMJS_SET_RVAL(OBJECT_TO_JSVAL(obj));\ #define JS_GetFunctionName(_v) (JS_GetFunctionId(_v)!=NULL) ? SMJS_CHARS_FROM_STRING(c, JS_GetFunctionId(_v)) : NULL @@ -92,8 +143,19 @@ typedef double jsdouble; #define SMJS_GET_PRIVATE(__ctx, __obj) JS_GetPrivate(__obj) #define SMJS_SET_PRIVATE(__ctx, __obj, __val) JS_SetPrivate(__obj, __val) #define SMJS_GET_PARENT(__ctx, __obj) JS_GetParent(__obj) + + +#ifdef USE_FFDEV_15 +#define JS_GET_CLASS(__ctx, __obj) JS_GetClass(* __obj._) +#else #define JS_GET_CLASS(__ctx, __obj) JS_GetClass(__obj) -#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, __class, __parent) +#endif + +#ifdef USE_FFDEV_16 +#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_New(__ctx, JS_GetConstructor(__ctx, (__class)->_proto), 0, NULL) +#else +#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, &(__class)->_class, __parent) +#endif #else @@ -104,9 +166,9 @@ typedef double jsdouble; #ifdef USE_FFDEV_11 #define JS_ClearContextThread(__ctx) #define JS_SetContextThread(__ctx) -#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, __class, __parent) +#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, &(__class)->_class, __parent) #else -#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, __class, 0, __parent) +#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, &(__class)->_class, 0, __parent) #endif #endif @@ -114,6 +176,13 @@ typedef double jsdouble; #else +#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_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) { + +#define SMJS_CALL_PROP_STUB() JS_PropertyStub(c, obj, id, vp) #define SMJS_PROP_SETTER jsval id #define SMJS_PROP_GETTER jsval id #define JS_PropertyStub_forSetter JS_PropertyStub @@ -122,7 +191,7 @@ typedef double jsdouble; #define SMJS_FUNCTION_EXT(__name, __ext) __name(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, __ext) #define SMJS_ARGS #define SMJS_OBJ -#define SMJS_OBJ_CONSTRUCTOR +#define SMJS_OBJ_CONSTRUCTOR(__classp) #define SMJS_GET_RVAL rval #define SMJS_SET_RVAL(__rval) *rval = __rval #define SMJS_CALL_ARGS c, obj, argc, argv, rval @@ -137,7 +206,7 @@ typedef double jsdouble; #define SMJS_ID_IS_INT JSVAL_IS_INT #define SMJS_ID_TO_INT JSVAL_TO_INT -#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, __class, 0, __parent) +#define SMJS_CONSTRUCT_OBJECT(__ctx, __class, __parent) JS_ConstructObject(__ctx, &(__class)->_class, 0, __parent) #define SMJS_GET_PRIVATE(__ctx, __obj) JS_GetPrivate(__ctx, __obj) #define SMJS_SET_PRIVATE(__ctx, __obj, __val) JS_SetPrivate(__ctx, __obj, __val) #define SMJS_GET_PARENT(__ctx, __obj) JS_GetParent(__ctx, __obj) @@ -150,30 +219,39 @@ extern "C" { #endif #if (JS_VERSION>=185) +#ifdef USE_FFDEV_15 +JSBool gf_sg_js_has_instance(JSContext *c, JSHandleObject obj,const jsval *val, JSBool *vp); +#else JSBool gf_sg_js_has_instance(JSContext *c, JSObject *obj,const jsval *val, JSBool *vp); +#endif #else JSBool gf_sg_js_has_instance(JSContext *c, JSObject *obj, jsval val, JSBool *vp); #endif #define JS_SETUP_CLASS(the_class, cname, flag, getp, setp, fin) \ memset(&the_class, 0, sizeof(the_class)); \ - the_class.name = cname; \ - the_class.flags = flag; \ - the_class.addProperty = JS_PropertyStub; \ - the_class.delProperty = JS_PropertyStub; \ - the_class.getProperty = getp; \ - the_class.setProperty = setp; \ - the_class.enumerate = JS_EnumerateStub; \ - the_class.resolve = JS_ResolveStub; \ - the_class.convert = JS_ConvertStub; \ - the_class.finalize = fin; \ - the_class.hasInstance = gf_sg_js_has_instance; + the_class._class.name = cname; \ + the_class._class.flags = flag; \ + the_class._class.addProperty = JS_PropertyStub; \ + the_class._class.delProperty = JS_PropertyStub; \ + the_class._class.getProperty = getp; \ + the_class._class.setProperty = setp; \ + the_class._class.enumerate = JS_EnumerateStub; \ + the_class._class.resolve = JS_ResolveStub; \ + the_class._class.convert = JS_ConvertStub; \ + the_class._class.finalize = (JSFinalizeOp) fin; \ + the_class._class.hasInstance = gf_sg_js_has_instance; #define JS_MAKE_DOUBLE(__c, __double) DOUBLE_TO_JSVAL(JS_NewDouble(__c, __double) ) -JSObject *gf_sg_js_global_object(JSContext *cx, JSClass *__class); +#define GF_JS_InstanceOf(_a, _b, __class, _d) JS_InstanceOf(_a, _b, & (__class)->_class, NULL) + +#define GF_JS_InitClass(cx, obj, parent_proto, clasp, constructor, nargs, ps, fs, static_ps, static_fs) \ + (clasp)->_proto = JS_InitClass(cx, obj, parent_proto, &(clasp)->_class, constructor, nargs, ps, fs, static_ps, static_fs); + +JSObject *gf_sg_js_global_object(JSContext *cx, GF_JSClass *__class); #ifdef __cplusplus } diff --git a/include/gpac/internal/swf_dev.h b/include/gpac/internal/swf_dev.h index 3eb9ba1..3c074a2 100644 --- a/include/gpac/internal/swf_dev.h +++ b/include/gpac/internal/swf_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project @@ -47,6 +48,14 @@ enum SWF_MOVE, }; +/*display list item (one per layer only)*/ +typedef struct +{ + GF_Matrix2D mat; + GF_ColorMatrix cmat; + u32 depth; + u32 char_id; +} DispShape; struct SWFReader { @@ -159,6 +168,11 @@ struct SWFReader GF_List *btn_over, *btn_not_over, *btn_active, *btn_not_active; /* */ + + /* SVG conversion state */ + FILE *svg_output; + /* end of SVG conversion state */ + }; @@ -168,6 +182,7 @@ GF_Err swf_parse_sprite(SWFReader *read); GF_Err swf_to_bifs_init(SWFReader *read); +GF_Err swf_to_svg_init(SWFReader *read); diff --git a/include/gpac/internal/terminal_dev.h b/include/gpac/internal/terminal_dev.h index bedef48..7240d29 100644 --- a/include/gpac/internal/terminal_dev.h +++ b/include/gpac/internal/terminal_dev.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Stream Management sub-project @@ -429,8 +430,8 @@ GF_Err gf_term_init_scheduler(GF_Terminal *term, u32 threading_mode); void gf_term_stop_scheduler(GF_Terminal *term); void gf_term_add_codec(GF_Terminal *term, GF_Codec *codec); void gf_term_remove_codec(GF_Terminal *term, GF_Codec *codec); -void gf_term_start_codec(GF_Codec *codec); -void gf_term_stop_codec(GF_Codec *codec); +void gf_term_start_codec(GF_Codec *codec, Bool is_resume); +void gf_term_stop_codec(GF_Codec *codec, Bool is_pause); void gf_term_set_threading(GF_Terminal *term, u32 mode); void gf_term_set_priority(GF_Terminal *term, s32 Priority); @@ -799,6 +800,9 @@ struct _generic_codec /*for CTS reconstruction (channels not using SL): we cannot just update timing at each frame, not precise enough since we use ms and not microsec TSs*/ u32 cur_audio_bytes, cur_video_frames; + + /*signals that CB should be resized to this value once all units in CB has been consumed (codec config change)*/ + u32 force_cb_resize; }; GF_Codec *gf_codec_new(GF_ObjectManager *odm, GF_ESD *base_layer, s32 PL, GF_Err *e); @@ -1048,7 +1052,7 @@ void gf_term_service_media_event_with_download(GF_ObjectManager *odm, u32 event_ /*checks the URL and returns the ODID (MPEG-4 od://) or GF_MEDIA_EXTERNAL_ID for all regular URLs*/ u32 gf_mo_get_od_id(MFURL *url); -void gf_scene_generate_views(GF_Scene *scene, char *url); +void gf_scene_generate_views(GF_Scene *scene, char *url, char *parent_url); GF_Err gf_codec_process_private_media(GF_Codec *codec, u32 TimeAvailable); diff --git a/include/gpac/ismacryp.h b/include/gpac/ismacryp.h index dac6e47..6653f2f 100644 --- a/include/gpac/ismacryp.h +++ b/include/gpac/ismacryp.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Authoring Tools sub-project @@ -88,21 +89,21 @@ typedef struct #if !defined(GPAC_DISABLE_MCRYPT) && !defined(GPAC_DISABLE_ISOM_WRITE) -/*encrypts track - logs, progress: info callbacks, NULL for stdout*/ +/*encrypts track - logs, progress: info callbacks, NULL for default*/ GF_Err gf_ismacryp_encrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); -/*decrypts track - logs, progress: info callbacks, NULL for stdout*/ +/*decrypts track - logs, progress: info callbacks, NULL for default*/ GF_Err gf_ismacryp_decrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u64 done, u64 total), void *cbk); /*decrypt a file @drm_file: location of DRM data (cf MP4Box doc). -@LogMsg: redirection for message or NULL for stdout +@LogMsg: redirection for message or NULL for default */ GF_Err gf_ismacryp_decrypt_file(GF_ISOFile *mp4file, const char *drm_file); /*Crypt a the file @drm_file: location of DRM data. -@LogMsg: redirection for message or NULL for stdout +@LogMsg: redirection for message or NULL for default */ GF_Err gf_ismacryp_crypt_file(GF_ISOFile *mp4file, const char *drm_file); diff --git a/include/gpac/iso639.h b/include/gpac/iso639.h index 72cbdba..e9301f7 100644 --- a/include/gpac/iso639.h +++ b/include/gpac/iso639.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC diff --git a/include/gpac/isomedia.h b/include/gpac/isomedia.h index 6010705..9c001f2 100644 --- a/include/gpac/isomedia.h +++ b/include/gpac/isomedia.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -34,43 +35,6 @@ extern "C" { #include -#ifndef GPAC_DISABLE_ISOM - -#include - -/*the isomedia file*/ -typedef struct __tag_isom GF_ISOFile; - -/*media sample object*/ -typedef struct -{ - /*data size*/ - u32 dataLength; - /*data with padding if requested*/ - char *data; - /*decoding time*/ - u64 DTS; - /*relative offset for composition if needed*/ - u32 CTS_Offset; - /*Random Access Point flag: - 0: not random access - 1: regular RAP, - 2: sample is a redundant RAP. If set when adding the sample, this will create a sample dependency entry - */ - u8 IsRAP; -} GF_ISOSample; - - -/*creates a new empty sample*/ -GF_ISOSample *gf_isom_sample_new(); - -/*delete a sample. NOTE:the buffer content will be destroyed by default. -if you wish to keep the buffer, set dataLength to 0 in the sample -before deleting it -the pointer is set to NULL after deletion*/ -void gf_isom_sample_del(GF_ISOSample **samp); - - /******************************************************************** FILE FORMAT CONSTANTS @@ -140,7 +104,10 @@ enum /*ref type for Hint tracks*/ GF_ISOM_REF_HINT = GF_4CC( 'h', 'i', 'n', 't' ), /*ref type for QT Chapter tracks*/ - GF_ISOM_REF_CHAP = GF_4CC( 'c', 'h', 'a', 'p' ) + GF_ISOM_REF_CHAP = GF_4CC( 'c', 'h', 'a', 'p' ), + /*ref type for the SVC tracks*/ + GF_ISOM_REF_BASE = GF_4CC( 's', 'b', 'a', 's' ), + GF_ISOM_REF_SCAL = GF_4CC( 's', 'c', 'a', 'l' ) }; /*Track Edition flag*/ @@ -162,6 +129,7 @@ enum GF_ISOM_MEDIA_HINT = GF_4CC( 'h', 'i', 'n', 't' ), GF_ISOM_MEDIA_META = GF_4CC( 'm', 'e', 't', 'a' ), GF_ISOM_MEDIA_TEXT = GF_4CC( 't', 'e', 'x', 't' ), + GF_ISOM_MEDIA_SUBM = GF_4CC( 's', 'u', 'b', 'm' ), /*subtitle code point used on ipod - same as text*/ GF_ISOM_MEDIA_SUBT = GF_4CC( 's', 'b', 't', 'l' ), GF_ISOM_MEDIA_SUBPIC = GF_4CC( 's', 'u', 'b', 'p' ), @@ -189,6 +157,13 @@ enum GF_ISOM_ISMACRYP_SCHEME = GF_4CC( 'i', 'A', 'E', 'C' ) }; +/* Encryption Scheme Type in the SchemeTypeInfoBox */ +enum +{ + GF_ISOM_OMADRM_SCHEME = GF_4CC('o','d','k','m') +}; + + /*specific media sub-types - you shall make sure the media sub type is what you expect*/ enum { @@ -278,6 +253,8 @@ enum GF_ISOM_BRAND_AVC1 = GF_4CC('a', 'v', 'c', '1'), /* file complying to ISO/IEC 21000-9:2005 (MPEG-21 spec)*/ GF_ISOM_BRAND_MP21 = GF_4CC('m', 'p', '2', '1'), + /*file complying to the generic ISO Media File (base specification ISO/IEC 14496-12) + support for version 1*/ + GF_ISOM_BRAND_ISO4 = GF_4CC( 'i', 's', 'o', '4' ) }; @@ -294,6 +271,41 @@ enum GF_ISOM_PL_INLINE, }; +#ifndef GPAC_DISABLE_ISOM + +#include + +/*the isomedia file*/ +typedef struct __tag_isom GF_ISOFile; + +/*media sample object*/ +typedef struct +{ + /*data size*/ + u32 dataLength; + /*data with padding if requested*/ + char *data; + /*decoding time*/ + u64 DTS; + /*relative offset for composition if needed*/ + s32 CTS_Offset; + /*Random Access Point flag: + 0: not random access + 1: regular RAP, + 2: sample is a redundant RAP. If set when adding the sample, this will create a sample dependency entry + */ + u8 IsRAP; +} GF_ISOSample; + + +/*creates a new empty sample*/ +GF_ISOSample *gf_isom_sample_new(); + +/*delete a sample. NOTE:the buffer content will be destroyed by default. +if you wish to keep the buffer, set dataLength to 0 in the sample +before deleting it +the pointer is set to NULL after deletion*/ +void gf_isom_sample_del(GF_ISOSample **samp); /******************************************************************** GENERAL API FUNCTIONS @@ -329,6 +341,11 @@ u64 gf_isom_get_file_size(GF_ISOFile *the_file); Bool gf_isom_moov_first(GF_ISOFile *movie); +/*sets write cache size for files when creating them. If size is 0, writing +only relies on the underlying OS fwrite/fgetc +If movie is NULL, assigns the default write cache size for any new movie*/ +GF_Err gf_isom_set_output_buffering(GF_ISOFile *movie, u32 size); + /******************************************************************** STREAMING API FUNCTIONS ********************************************************************/ @@ -555,8 +572,12 @@ u8 gf_isom_has_sync_points(GF_ISOFile *the_file, u32 trackNumber); /*returns number of sync points*/ u32 gf_isom_get_sync_point_count(GF_ISOFile *the_file, u32 trackNumber); -/*returns 1 if one sample of the track is found to have a composition time offset (DTS0) this sample to have a complete refresh of the decoded data (used by GDR in AVC) - currently sample group info MUST be added in order (no insertion in the tables)*/ GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *movie, u32 track, u32 sample_number, s16 roll_distance); + +GF_Err gf_isom_set_composition_offset_mode(GF_ISOFile *file, u32 track, Bool use_negative_offsets); + #endif + + #endif /*GPAC_DISABLE_ISOM*/ #ifdef __cplusplus diff --git a/include/gpac/laser.h b/include/gpac/laser.h index 3ad8289..76eb9f2 100644 --- a/include/gpac/laser.h +++ b/include/gpac/laser.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2006-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/include/gpac/list.h b/include/gpac/list.h index 9187fdc..04ffcf9 100644 --- a/include/gpac/list.h +++ b/include/gpac/list.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/math.h b/include/gpac/math.h index 3c61046..ddeb809 100644 --- a/include/gpac/math.h +++ b/include/gpac/math.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/media_tools.h b/include/gpac/media_tools.h index b2fe236..f860a7c 100644 --- a/include/gpac/media_tools.h +++ b/include/gpac/media_tools.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Authoring Tools sub-project @@ -32,6 +33,7 @@ extern "C" { #include #include +#include /*computes file hash. If file is ISO-based, computre hash according to OMA (P)DCF (without MutableDRMInformation box)*/ GF_Err gf_media_get_file_hash(const char *file, u8 hash[20]); @@ -206,7 +208,8 @@ typedef struct __track_import /*for text import*/ u32 fontSize; char *fontName; - u32 twidth, theight; + u32 text_track_width, text_track_height, text_width, text_height; + s32 text_x, text_y; /*Initial offset of the first AU to import*/ Double initial_time_offset; @@ -251,19 +254,53 @@ GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level); /*rewrite AVC samples if nalu size_length has to be changed*/ GF_Err gf_media_avc_rewrite_samples(GF_ISOFile *file, u32 track, u32 prev_size_in_bits, u32 new_size_in_bits); +/* Split SVC layers */ +GF_Err gf_media_split_svc(GF_ISOFile *file, u32 track, Bool splitAll); + +/* Merge SVC layers*/ +GF_Err gf_media_merge_svc(GF_ISOFile *file, u32 track, Bool mergeAll); + #endif /*GPAC_DISABLE_MEDIA_IMPORT*/ -#ifndef GPAC_DISABLE_ISOM_WRITE +typedef struct +{ + char *file_name; + char representationID[100]; + char periodID[100]; + u32 bandwidth; +} GF_DashSegmenterInput; + +typedef enum +{ + GF_DASH_PROFILE_FULL = 0, + /*live for ISOFF, SIMPLE for M2TS*/ + GF_DASH_PROFILE_LIVE, + GF_DASH_PROFILE_ONDEMAND, + GF_DASH_PROFILE_MAIN, + + /*internal use only*/ + GF_DASH_PROFILE_UNKNOWN +} GF_DashProfile; + +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 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); + +/*returns time to wait until end of currently generated segments*/ +u32 gf_dasher_next_update_time(GF_Config *dash_ctx, u32 mpd_update_time); -/*starts MPD file */ -GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, GF_ISOFile *init_segment, Double period_duration); -GF_Err gf_media_mpd_end(char *mpd_name); +#ifndef GPAC_DISABLE_ISOM_WRITE #ifndef GPAC_DISABLE_ISOM_FRAGMENTS -/*save file as fragmented movie -@dash_mode: 0 = DASH not used, 1 = DASH used without GOP spliting, 2 = DASH used with GOP spliting, */ -GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file_radical, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool use_single_segment, const char *dash_ctx, GF_ISOFile *sample_descs, u32 rep_id); +/*save file as fragmented movie*/ +GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file, Double max_duration_sec); + + #endif #endif @@ -403,7 +440,10 @@ GF_Err gf_saf_mux_add_au(GF_SAFMuxer *mux, u32 stream_id, u32 CTS, char *data, u if force_end_of_session is set, this flushes the SAF Session - no more operations will be allowed on the muxer*/ GF_Err gf_saf_mux_for_time(GF_SAFMuxer *mux, u32 time_ms, Bool force_end_of_session, char **out_data, u32 *out_size); - +/*reduces input width/height to common aspect ration num/denum values*/ +void gf_media_reduce_aspect_ratio(u32 *width, u32 *height); +/*reduces input FPS to a more compact value (eg 25000/1000 -> 25/1)*/ +void gf_media_get_reduced_frame_rate(u32 *timescale, u32 *sample_dur); #ifdef __cplusplus } diff --git a/include/gpac/mediaobject.h b/include/gpac/mediaobject.h index fd330eb..7358fdd 100644 --- a/include/gpac/mediaobject.h +++ b/include/gpac/mediaobject.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Stream Management sub-project diff --git a/include/gpac/module.h b/include/gpac/module.h index 6418403..14332b5 100644 --- a/include/gpac/module.h +++ b/include/gpac/module.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/modules/audio_out.h b/include/gpac/modules/audio_out.h index 94bbf8d..7153b77 100644 --- a/include/gpac/modules/audio_out.h +++ b/include/gpac/modules/audio_out.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces @@ -102,7 +103,7 @@ typedef struct _audiooutput /*if not using private thread, this should perform sleep & fill of HW buffer the audio render loop in this case is: while (run) {driver->WriteAudio(); if (reconf) Reconfig();} the driver must therefore give back the hand to the renderer as often as possible - the usual way is: - gf_sleep untill hw data can be written + gf_sleep until hw data can be written write HW data return */ diff --git a/include/gpac/modules/codec.h b/include/gpac/modules/codec.h index 14bb2cf..7a0cbbd 100644 --- a/include/gpac/modules/codec.h +++ b/include/gpac/modules/codec.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/modules/font.h b/include/gpac/modules/font.h index 1b8e40d..f8822e1 100644 --- a/include/gpac/modules/font.h +++ b/include/gpac/modules/font.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/modules/hardcoded_proto.h b/include/gpac/modules/hardcoded_proto.h index 10f0f15..addb6f1 100644 --- a/include/gpac/modules/hardcoded_proto.h +++ b/include/gpac/modules/hardcoded_proto.h @@ -1,7 +1,7 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Ivica Arsov, Jean Le Feuvre + * Authors: Jean Le Feuvre * Copyright (c) Telecom ParisTech 2012 * All rights reserved * @@ -36,23 +36,24 @@ extern "C" { #include /*interface name and version for Built-in proto User Extensions*/ -#define GF_HARDCODED_PROTO_INTERFACE GF_4CC('G','H','P', '1') +#define GF_HARDCODED_PROTO_INTERFACE GF_4CC('G','H','P', '2') typedef struct _hc_proto_mod { /* interface declaration*/ GF_DECL_MODULE_INTERFACE - /*load hardcoded proto - compositor: compositor used for loading - node: proto node to be loaded + /*Initialize hardcoded proto node. + compositor: GPAC compositor + node: node to be loaded - this node is always a PROTO instance + proto_uri: the proto URI */ - Bool (*init)(GF_Compositor* compositor, GF_Node* node); + Bool (*init)(GF_Compositor* compositor, GF_Node* node, const char *proto_uri); /*check if the module can load a proto - url: url to check + uri: proto uri to check for support */ - Bool (*can_load_proto)(const char* url); + Bool (*can_load_proto)(const char* uri); /*module private*/ void *udta; diff --git a/include/gpac/modules/ipmp.h b/include/gpac/modules/ipmp.h index 0b561db..de0342c 100644 --- a/include/gpac/modules/ipmp.h +++ b/include/gpac/modules/ipmp.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/modules/js_usr.h b/include/gpac/modules/js_usr.h index 4d92f4b..a84e08e 100644 --- a/include/gpac/modules/js_usr.h +++ b/include/gpac/modules/js_usr.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/modules/raster2d.h b/include/gpac/modules/raster2d.h index 9fd1702..750d19d 100644 --- a/include/gpac/modules/raster2d.h +++ b/include/gpac/modules/raster2d.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/modules/service.h b/include/gpac/modules/service.h index bff5805..388079f 100644 --- a/include/gpac/modules/service.h +++ b/include/gpac/modules/service.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces @@ -33,6 +34,7 @@ extern "C" { #include #include #include +#include /*handle to service*/ typedef struct _net_service GF_ClientService; @@ -322,6 +324,9 @@ typedef struct 2: time discontinuity - seeking has occured and some segments were skipped */ u32 discontinuity_type; + /*out: initialization/switching segment of next URL to play, if different from previous init segment*/ + const char *next_url_init_or_switch_segment; + u64 switch_start_range, switch_end_range; } GF_NetURLQuery; /*GF_NET_SERVICE_QUALITY_SWITCH*/ diff --git a/include/gpac/modules/term_ext.h b/include/gpac/modules/term_ext.h index 4fd0e0d..3a18fbf 100644 --- a/include/gpac/modules/term_ext.h +++ b/include/gpac/modules/term_ext.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/modules/video_out.h b/include/gpac/modules/video_out.h index 4c37692..3376517 100644 --- a/include/gpac/modules/video_out.h +++ b/include/gpac/modules/video_out.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / modules interfaces diff --git a/include/gpac/mpeg4_odf.h b/include/gpac/mpeg4_odf.h index 9bc29fa..a31acfb 100644 --- a/include/gpac/mpeg4_odf.h +++ b/include/gpac/mpeg4_odf.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 Object Descriptor sub-project @@ -102,6 +103,8 @@ enum /*internal descriptor for LASeR config input description*/ GF_ODF_LASER_CFG_TAG = GF_ODF_USER_BEGIN_TAG + 6, + GF_ODF_GEN_SUB_CFG_TAG = GF_ODF_USER_BEGIN_TAG + 7, + GF_ODF_USER_END_TAG = 0xFE, GF_ODF_OCI_BEGIN_TAG = 0x40, @@ -487,6 +490,35 @@ typedef struct s16 vert_offset; } GF_TextConfig; +typedef struct +{ + /*this is defined as a descriptor for parsing*/ + BASE_DESCRIPTOR + + /*unused in isomedia but needed for streamingText*/ + u8 sample_index; +} GF_GenericSubtitleSampleDescriptor; + +typedef struct +{ + BASE_DESCRIPTOR + u32 timescale; + /*More negative layer values are towards the viewer*/ + s16 layer; + /*text track width & height*/ + u16 text_width; + u16 text_height; + /*defined in isomedia.h*/ + GF_List *sample_descriptions; + + /*if true info below are valid (cf 3GPP for their meaning)*/ + Bool has_vid_info; + u16 video_width; + u16 video_height; + s16 horiz_offset; + s16 vert_offset; +} GF_GenericSubtitleConfig; + /*MuxInfo descriptor - parsing only, stored in ESD:extDescr*/ typedef struct { @@ -838,6 +870,13 @@ typedef struct /*for SVC*/ u8 complete_representation; + + /*for high profiles*/ + u8 chroma_format; + u8 luma_bit_depth; + u8 chroma_bit_depth; + /*may be NULL*/ + GF_List *sequenceParameterSetExtensions; } GF_AVCConfig; diff --git a/include/gpac/mpegts.h b/include/gpac/mpegts.h index 9bc55da..6bf26ac 100644 --- a/include/gpac/mpegts.h +++ b/include/gpac/mpegts.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Walid B.H - Jean Le Feuvre - * Copyright (c)2006-200X ENST - All rights reserved + * Authors: Jean Le Feuvre, Cyril Concolato, Romain Bouqueau + * Copyright (c) Telecom ParisTech 2006-2012 * * This file is part of GPAC / MPEG2-TS sub-project * @@ -27,31 +27,159 @@ #define _GF_MPEG_TS_H_ #include - -#ifndef GPAC_DISABLE_MPEG2TS - -#include #include -#include #include -#include +#include -typedef struct tag_m2ts_demux GF_M2TS_Demuxer; -typedef struct tag_m2ts_es GF_M2TS_ES; -typedef struct tag_m2ts_section_es GF_M2TS_SECTION_ES; -#ifdef GPAC_HAS_LINUX_DVB -typedef struct __gf_dvb_tuner GF_Tuner; -#endif -/*Maximum number of streams in a TS*/ -#define GF_M2TS_MAX_STREAMS 8192 +/*MPEG-2 Descriptor tags*/ +enum +{ + /* ... */ + GF_M2TS_VIDEO_STREAM_DESCRIPTOR = 0x02, + GF_M2TS_AUDIO_STREAM_DESCRIPTOR = 0x03, + GF_M2TS_HIERARCHY_DESCRIPTOR = 0x04, + GF_M2TS_REGISTRATION_DESCRIPTOR = 0x05, + GF_M2TS_DATA_STREAM_ALIGNEMENT_DESCRIPTOR = 0x06, + GF_M2TS_TARGET_BACKGROUND_GRID_DESCRIPTOR = 0x07, + GF_M2TS_VIEW_WINDOW_DESCRIPTOR = 0x08, + GF_M2TS_CA_DESCRIPTOR = 0x09, + GF_M2TS_ISO_639_LANGUAGE_DESCRIPTOR = 0x0A, + GF_M2TS_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR = 0x0C, + GF_M2TS_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR = 0x0D, + GF_M2TS_DVB_TARGET_IP_SLASH_DESCRIPTOR = 0x0F, + /* ... */ + GF_M2TS_DVB_STREAM_LOCATION_DESCRIPTOR =0x13, + /* ... */ + GF_M2TS_STD_DESCRIPTOR = 0x17, + /* ... */ + GF_M2TS_MPEG4_VIDEO_DESCRIPTOR = 0x1B, + GF_M2TS_MPEG4_AUDIO_DESCRIPTOR = 0x1C, + GF_M2TS_MPEG4_IOD_DESCRIPTOR = 0x1D, + GF_M2TS_MPEG4_SL_DESCRIPTOR = 0x1E, + GF_M2TS_MPEG4_FMC_DESCRIPTOR = 0x1F, + /* ... */ + GF_M2TS_AVC_VIDEO_DESCRIPTOR = 0x28, + /* ... */ + GF_M2TS_AVC_TIMING_HRD_DESCRIPTOR = 0x2A, + /* ... */ + GF_M2TS_MPEG4_ODUPDATE_DESCRIPTOR = 0x35, -/*Maximum number of service in a TS*/ -#define GF_M2TS_MAX_SERVICES 65535 + /* 0x2D - 0x3F - ISO/IEC 13818-6 values */ + /* 0x40 - 0xFF - User Private values */ + GF_M2TS_DVB_NETWORK_NAME_DESCRIPTOR = 0x40, + GF_M2TS_DVB_SERVICE_LIST_DESCRIPTOR = 0x41, + GF_M2TS_DVB_STUFFING_DESCRIPTOR = 0x42, + GF_M2TS_DVB_SAT_DELIVERY_SYSTEM_DESCRIPTOR = 0x43, + GF_M2TS_DVB_CABLE_DELIVERY_SYSTEM_DESCRIPTOR = 0x44, + GF_M2TS_DVB_VBI_DATA_DESCRIPTOR = 0x45, + GF_M2TS_DVB_VBI_TELETEXT_DESCRIPTOR = 0x46, + GF_M2TS_DVB_BOUQUET_NAME_DESCRIPTOR = 0x47, + GF_M2TS_DVB_SERVICE_DESCRIPTOR = 0x48, + GF_M2TS_DVB_COUNTRY_AVAILABILITY_DESCRIPTOR = 0x49, + GF_M2TS_DVB_LINKAGE_DESCRIPTOR = 0x4A, + GF_M2TS_DVB_NVOD_REFERENCE_DESCRIPTOR = 0x4B, + GF_M2TS_DVB_TIME_SHIFTED_SERVICE_DESCRIPTOR = 0x4C, + GF_M2TS_DVB_SHORT_EVENT_DESCRIPTOR = 0x4D, + GF_M2TS_DVB_EXTENDED_EVENT_DESCRIPTOR = 0x4E, + GF_M2TS_DVB_TIME_SHIFTED_EVENT_DESCRIPTOR = 0x4F, + GF_M2TS_DVB_COMPONENT_DESCRIPTOR = 0x50, + GF_M2TS_DVB_MOSAIC_DESCRIPTOR = 0x51, + GF_M2TS_DVB_STREAM_IDENTIFIER_DESCRIPTOR = 0x52, + GF_M2TS_DVB_CA_IDENTIFIER_DESCRIPTOR = 0x53, + GF_M2TS_DVB_CONTENT_DESCRIPTOR = 0x54, + GF_M2TS_DVB_PARENTAL_RATING_DESCRIPTOR = 0x55, + GF_M2TS_DVB_TELETEXT_DESCRIPTOR = 0x56, + /* ... */ + GF_M2TS_DVB_LOCAL_TIME_OFFSET_DESCRIPTOR = 0x58, + GF_M2TS_DVB_SUBTITLING_DESCRIPTOR = 0x59, + GF_M2TS_DVB_PRIVATE_DATA_SPECIFIER_DESCRIPTOR = 0x5F, + /* ... */ + GF_M2TS_DVB_DATA_BROADCAST_DESCRIPTOR = 0x64, + /* ... */ + GF_M2TS_DVB_DATA_BROADCAST_ID_DESCRIPTOR = 0x66, + /* ... */ + GF_M2TS_DVB_AC3_DESCRIPTOR = 0x6A, + /* ... */ + GF_M2TS_DVB_TIME_SLICE_FEC_DESCRIPTOR = 0x77, + /* ... */ + GF_M2TS_DVB_EAC3_DESCRIPTOR = 0x7A, + GF_M2TS_DVB_LOGICAL_CHANNEL_DESCRIPTOR = 0x83, +}; -/*Maximum size of the buffer in UDP */ -#define UDP_BUFFER_SIZE 0x40000 +/* Reserved PID values */ +enum { + GF_M2TS_PID_PAT = 0x0000, + GF_M2TS_PID_CAT = 0x0001, + GF_M2TS_PID_TSDT = 0x0002, + /* reserved 0x0003 to 0x000F */ + GF_M2TS_PID_NIT_ST = 0x0010, + GF_M2TS_PID_SDT_BAT_ST = 0x0011, + GF_M2TS_PID_EIT_ST_CIT = 0x0012, + GF_M2TS_PID_RST_ST = 0x0013, + GF_M2TS_PID_TDT_TOT_ST = 0x0014, + GF_M2TS_PID_NET_SYNC = 0x0015, + GF_M2TS_PID_RNT = 0x0016, + /* reserved 0x0017 to 0x001B */ + GF_M2TS_PID_IN_SIG = 0x001C, + GF_M2TS_PID_MEAS = 0x001D, + GF_M2TS_PID_DIT = 0x001E, + GF_M2TS_PID_SIT = 0x001F +}; + +/* max size includes first header, second header, payload and CRC */ +enum { + GF_M2TS_TABLE_ID_PAT = 0x00, + GF_M2TS_TABLE_ID_CAT = 0x01, + GF_M2TS_TABLE_ID_PMT = 0x02, + GF_M2TS_TABLE_ID_TSDT = 0x03, /* max size for section 1024 */ + GF_M2TS_TABLE_ID_MPEG4_BIFS = 0x04, /* max size for section 4096 */ + GF_M2TS_TABLE_ID_MPEG4_OD = 0x05, /* max size for section 4096 */ + GF_M2TS_TABLE_ID_METADATA = 0x06, + GF_M2TS_TABLE_ID_IPMP_CONTROL = 0x07, + /* 0x08 - 0x37 reserved */ + /* 0x38 - 0x3D DSM-CC defined */ + GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA = 0x3A, + GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE = 0x3B, /* used for MPE (only, not MPE-FEC) */ + GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE = 0x3C, /* used for MPE (only, not MPE-FEC) */ + GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION = 0x3D, /* used for MPE (only, not MPE-FEC) */ + GF_M2TS_TABLE_ID_DSM_CC_PRIVATE = 0x3E, /* used for MPE (only, not MPE-FEC) */ + /* 0x3F DSM-CC defined */ + GF_M2TS_TABLE_ID_NIT_ACTUAL = 0x40, /* max size for section 1024 */ + GF_M2TS_TABLE_ID_NIT_OTHER = 0x41, + GF_M2TS_TABLE_ID_SDT_ACTUAL = 0x42, /* max size for section 1024 */ + /* 0x43 - 0x45 reserved */ + GF_M2TS_TABLE_ID_SDT_OTHER = 0x46, /* max size for section 1024 */ + /* 0x47 - 0x49 reserved */ + GF_M2TS_TABLE_ID_BAT = 0x4a, /* max size for section 1024 */ + /* 0x4b reserved */ + GF_M2TS_TABLE_ID_INT = 0x4c, /* max size for section 4096 */ + /* 0x4d reserved */ + + GF_M2TS_TABLE_ID_EIT_ACTUAL_PF = 0x4E, /* max size for section 4096 */ + GF_M2TS_TABLE_ID_EIT_OTHER_PF = 0x4F, + /* 0x50 - 0x6f EIT SCHEDULE */ + GF_M2TS_TABLE_ID_EIT_SCHEDULE_MIN = 0x50, + GF_M2TS_TABLE_ID_EIT_SCHEDULE_ACTUAL_MAX= 0x5F, + GF_M2TS_TABLE_ID_EIT_SCHEDULE_MAX = 0x6F, + + GF_M2TS_TABLE_ID_TDT = 0x70, /* max size for section 1024 */ + GF_M2TS_TABLE_ID_RST = 0x71, /* max size for section 1024 */ + GF_M2TS_TABLE_ID_ST = 0x72, /* max size for section 4096 */ + GF_M2TS_TABLE_ID_TOT = 0x73, /* max size for section 1024 */ + GF_M2TS_TABLE_ID_AIT = 0x74, + GF_M2TS_TABLE_ID_CONT = 0x75, + GF_M2TS_TABLE_ID_RC = 0x76, + GF_M2TS_TABLE_ID_CID = 0x77, + GF_M2TS_TABLE_ID_MPE_FEC = 0x78, + GF_M2TS_TABLE_ID_RES_NOT = 0x79, + /* 0x7A - 0x7D reserved */ + GF_M2TS_TABLE_ID_DIT = 0x7E, + GF_M2TS_TABLE_ID_SIT = 0x7F, /* max size for section 4096 */ + /* 0x80 - 0xfe reserved */ + /* 0xff reserved */ +}; /*MPEG-2 TS Media types*/ enum @@ -91,9 +219,46 @@ enum GF_M2TS_DVB_VBI = 0x153, GF_M2TS_DVB_SUBTITLE = 0x154, }; + + +#define SECTION_HEADER_LENGTH 3 /* header till the last bit of the section_length field */ +#define SECTION_ADDITIONAL_HEADER_LENGTH 5 /* header from the last bit of the section_length field to the payload */ +#define CRC_LENGTH 4 + + + +#ifndef GPAC_DISABLE_MPEG2TS + +#include + +typedef struct tag_m2ts_demux GF_M2TS_Demuxer; +typedef struct tag_m2ts_es GF_M2TS_ES; +typedef struct tag_m2ts_section_es GF_M2TS_SECTION_ES; + +#ifdef GPAC_HAS_LINUX_DVB +typedef struct __gf_dvb_tuner GF_Tuner; +#endif + +/*Maximum number of streams in a TS*/ +#define GF_M2TS_MAX_STREAMS 8192 + +/*Maximum number of service in a TS*/ +#define GF_M2TS_MAX_SERVICES 65535 + +/*Maximum size of the buffer in UDP */ +#define UDP_BUFFER_SIZE 0x40000 + /*returns readable name for given stream type*/ const char *gf_m2ts_get_stream_name(u32 streamType); +/*returns 1 if file is an MPEG-2 TS */ +Bool gf_m2ts_probe_file(const char *fileName); + +/*shifts all timing by the given value +@is_pes: array of GF_M2TS_MAX_STREAMS u8 set to 1 for PES PIDs to be restamped +*/ +GF_Err gf_m2ts_restamp(char *buffer, u32 size, s64 ts_shift, u8 *is_pes); + /*PES data framing modes*/ enum { @@ -192,6 +357,7 @@ enum GF_M2TS_EVT_AIT_FOUND, /*DSCM-CC has been found (carousel) */ GF_M2TS_EVT_DSMCC_FOUND, + GF_M2TS_EVT_EOS, }; @@ -300,16 +466,18 @@ typedef struct /*ES flags*/ enum { + /*ES is a PES stream*/ + GF_M2TS_ES_IS_PES = 1, /*ES is a section stream*/ - GF_M2TS_ES_IS_SECTION = 1, + GF_M2TS_ES_IS_SECTION = 1<<1, /*ES is an mpeg-4 flexmux stream*/ - GF_M2TS_ES_IS_FMC = 1<<1, + GF_M2TS_ES_IS_FMC = 1<<2, /*ES is an mpeg-4 SL-packetized stream*/ - GF_M2TS_ES_IS_SL = 1<<2, + GF_M2TS_ES_IS_SL = 1<<3, /*ES is an mpeg-4 Object Descriptor SL-packetized stream*/ - GF_M2TS_ES_IS_MPEG4_OD = 1<<3, + GF_M2TS_ES_IS_MPEG4_OD = 1<<4, /*ES is a DVB MPE stream*/ - GF_M2TS_ES_IS_MPE = 1<<4, + GF_M2TS_ES_IS_MPE = 1<<5, /*all flags above this mask are used by importers & co*/ GF_M2TS_ES_STATIC_FLAGS_MASK = 0x0000FFFF, @@ -625,6 +793,7 @@ struct tag_m2ts_demux Bool direct_mpe; Bool dvb_h_demux; + Bool notify_pes_timing; /*user callback - MUST NOT BE NULL*/ void (*on_mpe_event)(struct tag_m2ts_demux *ts, u32 evt_type, void *par); @@ -665,159 +834,7 @@ void gf_m2ts_demux_dmscc_init(GF_M2TS_Demuxer *ts); u32 gf_m2ts_crc32_check(char *data, u32 len); -/*MPEG-2 Descriptor tags*/ -enum -{ - /* ... */ - GF_M2TS_VIDEO_STREAM_DESCRIPTOR = 0x02, - GF_M2TS_AUDIO_STREAM_DESCRIPTOR = 0x03, - GF_M2TS_HIERARCHY_DESCRIPTOR = 0x04, - GF_M2TS_REGISTRATION_DESCRIPTOR = 0x05, - GF_M2TS_DATA_STREAM_ALIGNEMENT_DESCRIPTOR = 0x06, - GF_M2TS_TARGET_BACKGROUND_GRID_DESCRIPTOR = 0x07, - GF_M2TS_VIEW_WINDOW_DESCRIPTOR = 0x08, - GF_M2TS_CA_DESCRIPTOR = 0x09, - GF_M2TS_ISO_639_LANGUAGE_DESCRIPTOR = 0x0A, - GF_M2TS_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR = 0x0C, - GF_M2TS_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR = 0x0D, - GF_M2TS_DVB_TARGET_IP_SLASH_DESCRIPTOR = 0x0F, - /* ... */ - GF_M2TS_DVB_STREAM_LOCATION_DESCRIPTOR =0x13, - /* ... */ - GF_M2TS_STD_DESCRIPTOR = 0x17, - /* ... */ - GF_M2TS_MPEG4_VIDEO_DESCRIPTOR = 0x1B, - GF_M2TS_MPEG4_AUDIO_DESCRIPTOR = 0x1C, - GF_M2TS_MPEG4_IOD_DESCRIPTOR = 0x1D, - GF_M2TS_MPEG4_SL_DESCRIPTOR = 0x1E, - GF_M2TS_MPEG4_FMC_DESCRIPTOR = 0x1F, - /* ... */ - GF_M2TS_AVC_VIDEO_DESCRIPTOR = 0x28, - /* ... */ - GF_M2TS_AVC_TIMING_HRD_DESCRIPTOR = 0x2A, - /* ... */ - GF_M2TS_MPEG4_ODUPDATE_DESCRIPTOR = 0x35, - /* 0x2D - 0x3F - ISO/IEC 13818-6 values */ - /* 0x40 - 0xFF - User Private values */ - GF_M2TS_DVB_NETWORK_NAME_DESCRIPTOR = 0x40, - GF_M2TS_DVB_SERVICE_LIST_DESCRIPTOR = 0x41, - GF_M2TS_DVB_STUFFING_DESCRIPTOR = 0x42, - GF_M2TS_DVB_SAT_DELIVERY_SYSTEM_DESCRIPTOR = 0x43, - GF_M2TS_DVB_CABLE_DELIVERY_SYSTEM_DESCRIPTOR = 0x44, - GF_M2TS_DVB_VBI_DATA_DESCRIPTOR = 0x45, - GF_M2TS_DVB_VBI_TELETEXT_DESCRIPTOR = 0x46, - GF_M2TS_DVB_BOUQUET_NAME_DESCRIPTOR = 0x47, - GF_M2TS_DVB_SERVICE_DESCRIPTOR = 0x48, - GF_M2TS_DVB_COUNTRY_AVAILABILITY_DESCRIPTOR = 0x49, - GF_M2TS_DVB_LINKAGE_DESCRIPTOR = 0x4A, - GF_M2TS_DVB_NVOD_REFERENCE_DESCRIPTOR = 0x4B, - GF_M2TS_DVB_TIME_SHIFTED_SERVICE_DESCRIPTOR = 0x4C, - GF_M2TS_DVB_SHORT_EVENT_DESCRIPTOR = 0x4D, - GF_M2TS_DVB_EXTENDED_EVENT_DESCRIPTOR = 0x4E, - GF_M2TS_DVB_TIME_SHIFTED_EVENT_DESCRIPTOR = 0x4F, - GF_M2TS_DVB_COMPONENT_DESCRIPTOR = 0x50, - GF_M2TS_DVB_MOSAIC_DESCRIPTOR = 0x51, - GF_M2TS_DVB_STREAM_IDENTIFIER_DESCRIPTOR = 0x52, - GF_M2TS_DVB_CA_IDENTIFIER_DESCRIPTOR = 0x53, - GF_M2TS_DVB_CONTENT_DESCRIPTOR = 0x54, - GF_M2TS_DVB_PARENTAL_RATING_DESCRIPTOR = 0x55, - GF_M2TS_DVB_TELETEXT_DESCRIPTOR = 0x56, - /* ... */ - GF_M2TS_DVB_LOCAL_TIME_OFFSET_DESCRIPTOR = 0x58, - GF_M2TS_DVB_SUBTITLING_DESCRIPTOR = 0x59, - GF_M2TS_DVB_PRIVATE_DATA_SPECIFIER_DESCRIPTOR = 0x5F, - /* ... */ - GF_M2TS_DVB_DATA_BROADCAST_DESCRIPTOR = 0x64, - /* ... */ - GF_M2TS_DVB_DATA_BROADCAST_ID_DESCRIPTOR = 0x66, - /* ... */ - GF_M2TS_DVB_AC3_DESCRIPTOR = 0x6A, - /* ... */ - GF_M2TS_DVB_TIME_SLICE_FEC_DESCRIPTOR = 0x77, - /* ... */ - GF_M2TS_DVB_EAC3_DESCRIPTOR = 0x7A, - GF_M2TS_DVB_LOGICAL_CHANNEL_DESCRIPTOR = 0x83, -}; - -/* Reserved PID values */ -enum { - GF_M2TS_PID_PAT = 0x0000, - GF_M2TS_PID_CAT = 0x0001, - GF_M2TS_PID_TSDT = 0x0002, - /* reserved 0x0003 to 0x000F */ - GF_M2TS_PID_NIT_ST = 0x0010, - GF_M2TS_PID_SDT_BAT_ST = 0x0011, - GF_M2TS_PID_EIT_ST_CIT = 0x0012, - GF_M2TS_PID_RST_ST = 0x0013, - GF_M2TS_PID_TDT_TOT_ST = 0x0014, - GF_M2TS_PID_NET_SYNC = 0x0015, - GF_M2TS_PID_RNT = 0x0016, - /* reserved 0x0017 to 0x001B */ - GF_M2TS_PID_IN_SIG = 0x001C, - GF_M2TS_PID_MEAS = 0x001D, - GF_M2TS_PID_DIT = 0x001E, - GF_M2TS_PID_SIT = 0x001F -}; - -/* max size includes first header, second header, payload and CRC */ -enum { - GF_M2TS_TABLE_ID_PAT = 0x00, - GF_M2TS_TABLE_ID_CAT = 0x01, - GF_M2TS_TABLE_ID_PMT = 0x02, - GF_M2TS_TABLE_ID_TSDT = 0x03, /* max size for section 1024 */ - GF_M2TS_TABLE_ID_MPEG4_BIFS = 0x04, /* max size for section 4096 */ - GF_M2TS_TABLE_ID_MPEG4_OD = 0x05, /* max size for section 4096 */ - GF_M2TS_TABLE_ID_METADATA = 0x06, - GF_M2TS_TABLE_ID_IPMP_CONTROL = 0x07, - /* 0x08 - 0x37 reserved */ - /* 0x38 - 0x3D DSM-CC defined */ - GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA = 0x3A, - GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE = 0x3B, /* used for MPE (only, not MPE-FEC) */ - GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE = 0x3C, /* used for MPE (only, not MPE-FEC) */ - GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION = 0x3D, /* used for MPE (only, not MPE-FEC) */ - GF_M2TS_TABLE_ID_DSM_CC_PRIVATE = 0x3E, /* used for MPE (only, not MPE-FEC) */ - /* 0x3F DSM-CC defined */ - GF_M2TS_TABLE_ID_NIT_ACTUAL = 0x40, /* max size for section 1024 */ - GF_M2TS_TABLE_ID_NIT_OTHER = 0x41, - GF_M2TS_TABLE_ID_SDT_ACTUAL = 0x42, /* max size for section 1024 */ - /* 0x43 - 0x45 reserved */ - GF_M2TS_TABLE_ID_SDT_OTHER = 0x46, /* max size for section 1024 */ - /* 0x47 - 0x49 reserved */ - GF_M2TS_TABLE_ID_BAT = 0x4a, /* max size for section 1024 */ - /* 0x4b reserved */ - GF_M2TS_TABLE_ID_INT = 0x4c, /* max size for section 4096 */ - /* 0x4d reserved */ - - GF_M2TS_TABLE_ID_EIT_ACTUAL_PF = 0x4E, /* max size for section 4096 */ - GF_M2TS_TABLE_ID_EIT_OTHER_PF = 0x4F, - /* 0x50 - 0x6f EIT SCHEDULE */ - GF_M2TS_TABLE_ID_EIT_SCHEDULE_MIN = 0x50, - GF_M2TS_TABLE_ID_EIT_SCHEDULE_ACTUAL_MAX= 0x5F, - GF_M2TS_TABLE_ID_EIT_SCHEDULE_MAX = 0x6F, - - GF_M2TS_TABLE_ID_TDT = 0x70, /* max size for section 1024 */ - GF_M2TS_TABLE_ID_RST = 0x71, /* max size for section 1024 */ - GF_M2TS_TABLE_ID_ST = 0x72, /* max size for section 4096 */ - GF_M2TS_TABLE_ID_TOT = 0x73, /* max size for section 1024 */ - GF_M2TS_TABLE_ID_AIT = 0x74, - GF_M2TS_TABLE_ID_CONT = 0x75, - GF_M2TS_TABLE_ID_RC = 0x76, - GF_M2TS_TABLE_ID_CID = 0x77, - GF_M2TS_TABLE_ID_MPE_FEC = 0x78, - GF_M2TS_TABLE_ID_RES_NOT = 0x79, - /* 0x7A - 0x7D reserved */ - GF_M2TS_TABLE_ID_DIT = 0x7E, - GF_M2TS_TABLE_ID_SIT = 0x7F, /* max size for section 4096 */ - /* 0x80 - 0xfe reserved */ - /* 0xff reserved */ -}; - - - -#define SECTION_HEADER_LENGTH 3 /* header till the last bit of the section_length field */ -#define SECTION_ADDITIONAL_HEADER_LENGTH 5 /* header from the last bit of the section_length field to the payload */ -#define CRC_LENGTH 4 typedef struct { @@ -865,8 +882,14 @@ typedef struct void gf_m2ts_print_info(GF_M2TS_Demuxer *ts); + +#endif /*GPAC_DISABLE_MPEG2TS*/ + + #ifndef GPAC_DISABLE_MPEG2TS_MUX +#include + /* MPEG-2 TS Multiplexer */ @@ -978,7 +1001,7 @@ typedef struct __m2ts_mux_stream { /*avg bitrate compute*/ u64 last_br_time; u32 bytes_since_last_time, pes_since_last_time; - + u64 last_dts; /*MPEG-4 over MPEG-2*/ u8 table_id; GF_SLHeader sl_header; @@ -1147,11 +1170,13 @@ struct __gf_dvb_tuner { }; -#define DVB_BUFFER_SIZE 3760 // DVB buffer size 188x20 +// DVB buffer size 188x20 +#define DVB_BUFFER_SIZE 3760 -#endif +#endif //GPAC_HAS_LINUX_DVB +#ifndef GPAC_DISABLE_MPEG2TS GF_Err TSDemux_Demux_Setup(GF_M2TS_Demuxer *ts, const char *url, Bool loop); GF_Err TSDemux_DemuxPlay(GF_M2TS_Demuxer *ts); GF_Err TSDemux_CloseDemux(GF_M2TS_Demuxer *ts); diff --git a/include/gpac/network.h b/include/gpac/network.h index b2292ea..5343007 100644 --- a/include/gpac/network.h +++ b/include/gpac/network.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -95,6 +96,26 @@ char *gf_url_percent_encode(const char *path); */ void gf_url_to_fs_path(char *url); + +/*! + *\brief Extract resource name from URL + * + *Ectracts the reource name from the URL + *\param url input url + *\return resource name. + */ +const char *gf_url_get_resource_name(const char *url); + +/*! + *\brief Extract resource path from URL + * + *Ectracts the reource path from the URL + *\param url input url + *\param res_path buffer for resulting path storage + *\return 1 if path was extracted, 0 if url is a single file name. + */ +Bool gf_url_get_resource_path(const char *url, char *res_path); + /*! *\brief gets UTC time * diff --git a/include/gpac/nodes_mpeg4.h b/include/gpac/nodes_mpeg4.h index 5520c08..f2371cb 100644 --- a/include/gpac/nodes_mpeg4.h +++ b/include/gpac/nodes_mpeg4.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/include/gpac/nodes_svg.h b/include/gpac/nodes_svg.h index ed2f2e3..26175bf 100644 --- a/include/gpac/nodes_svg.h +++ b/include/gpac/nodes_svg.h @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c)2004-200X ENST - All rights reserved + * Copyright (c)2004-2012 Telecom ParisTech - All rights reserved * * This file is part of GPAC / XML-based Scene Graph sub-project * diff --git a/include/gpac/nodes_x3d.h b/include/gpac/nodes_x3d.h index b3a1fc1..096b345 100644 --- a/include/gpac/nodes_x3d.h +++ b/include/gpac/nodes_x3d.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / X3D Scene Graph sub-project diff --git a/include/gpac/nodes_xbl.h b/include/gpac/nodes_xbl.h index 742f525..cfcd057 100644 --- a/include/gpac/nodes_xbl.h +++ b/include/gpac/nodes_xbl.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c)2004-200X ENST - All rights reserved + * Authors: Cyril Concolato + * Copyright (c)2004-2012 Telecom ParisTech - All rights reserved * * This file is part of GPAC / XBL Elements * diff --git a/include/gpac/options.h b/include/gpac/options.h index 9fbcba1..e6c92ec 100644 --- a/include/gpac/options.h +++ b/include/gpac/options.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Stream Management sub-project diff --git a/include/gpac/path2d.h b/include/gpac/path2d.h index ed767f6..9a30ec1 100644 --- a/include/gpac/path2d.h +++ b/include/gpac/path2d.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/ringbuffer.h b/include/gpac/ringbuffer.h index d6d1f67..c7d4c2f 100644 --- a/include/gpac/ringbuffer.h +++ b/include/gpac/ringbuffer.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Pierre Souchay + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/rtp_streamer.h b/include/gpac/rtp_streamer.h index 77584f3..a25e198 100644 --- a/include/gpac/rtp_streamer.h +++ b/include/gpac/rtp_streamer.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2008- + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / media tools sub-project diff --git a/include/gpac/scene_engine.h b/include/gpac/scene_engine.h index 56a99d5..4a9a54a 100644 --- a/include/gpac/scene_engine.h +++ b/include/gpac/scene_engine.h @@ -2,7 +2,7 @@ * GPAC Multimedia Framework * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC diff --git a/include/gpac/scene_manager.h b/include/gpac/scene_manager.h index 368af1e..2fa534a 100644 --- a/include/gpac/scene_manager.h +++ b/include/gpac/scene_manager.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Authoring Tools sub-project @@ -184,6 +185,8 @@ enum GF_SM_SWF_REUSE_APPEARANCE = (1<<9), /*enable IndexedCurve2D proto*/ GF_SM_SWF_USE_IC2D = (1<<10), + /*enable SVG output*/ + GF_SM_SWF_USE_SVG = (1<<11), }; /*general loader flags*/ diff --git a/include/gpac/scenegraph.h b/include/gpac/scenegraph.h index 7d933dc..73211ad 100644 --- a/include/gpac/scenegraph.h +++ b/include/gpac/scenegraph.h @@ -2,7 +2,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/include/gpac/scenegraph_svg.h b/include/gpac/scenegraph_svg.h index 168fc06..d676256 100644 --- a/include/gpac/scenegraph_svg.h +++ b/include/gpac/scenegraph_svg.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004 + * Authors: Jean Le Feuvre - Cyril COncolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph sub-project diff --git a/include/gpac/scenegraph_vrml.h b/include/gpac/scenegraph_vrml.h index fe99993..54d891b 100644 --- a/include/gpac/scenegraph_vrml.h +++ b/include/gpac/scenegraph_vrml.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/include/gpac/setup.h b/include/gpac/setup.h index 59dd39f..cbf8d09 100644 --- a/include/gpac/setup.h +++ b/include/gpac/setup.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / general OS configuration file diff --git a/include/gpac/svg_types.h b/include/gpac/svg_types.h index 43f8ae4..8b5a73b 100644 --- a/include/gpac/svg_types.h +++ b/include/gpac/svg_types.h @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c) 2004-200X ENST + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/include/gpac/sync_layer.h b/include/gpac/sync_layer.h index 3c3284c..57debcb 100644 --- a/include/gpac/sync_layer.h +++ b/include/gpac/sync_layer.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / SL header file diff --git a/include/gpac/term_info.h b/include/gpac/term_info.h index 8d75a04..ffbd673 100644 --- a/include/gpac/term_info.h +++ b/include/gpac/term_info.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Stream Management sub-project diff --git a/include/gpac/terminal.h b/include/gpac/terminal.h index 9e3ccb7..9930755 100644 --- a/include/gpac/terminal.h +++ b/include/gpac/terminal.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Stream Management sub-project diff --git a/include/gpac/thread.h b/include/gpac/thread.h index 0dddee6..8d5c20c 100644 --- a/include/gpac/thread.h +++ b/include/gpac/thread.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/token.h b/include/gpac/token.h index 2ac86f6..651074e 100644 --- a/include/gpac/token.h +++ b/include/gpac/token.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/tools.h b/include/gpac/tools.h index f4e50d3..bd99679 100644 --- a/include/gpac/tools.h +++ b/include/gpac/tools.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -30,6 +31,7 @@ extern "C" { #endif #include +#include /*! \file "gpac/tools.h" @@ -51,32 +53,6 @@ extern "C" { * @{ */ -/*! - * \brief GPAC Version - * \hideinitializer - * - * Macro giving GPAC version expressed as a printable string -*/ -/* KEEP SPACE SEPARATORS FOR MAKE / GREP (SEE MAIN MAKEFILE) - * NO SPACE in GPAC_VERSION for proper install - * SONAME versions must be digits (not strings) - */ -#define GPAC_VERSION "0.5.0" -#define GPAC_VERSION_MAJOR 2 -#define GPAC_VERSION_MINOR 0 -#define GPAC_VERSION_MICRO 0 - -#include -#define GPAC_FULL_VERSION GPAC_VERSION"-rev"GPAC_SVN_REVISION - -/*! - * \brief GPAC Version - * \hideinitializer - * - * Macro giving GPAC version expressed as an integer, where version X.Y.Z is coded as 0x00XXYYZZ -*/ -#define GPAC_VERSION_INT 0x00000406 - /*! * \brief Stringizer * \hideinitializer @@ -376,8 +352,12 @@ enum GF_LOG_MODULE, /*! Log for threads and mutexes */ GF_LOG_MUTEX, + /*! Log for all HTTP streaming */ + GF_LOG_DASH, /*! Log for all messages coming from GF_Terminal or script alert()*/ GF_LOG_CONSOLE, + /*! Log for all messages coming the application, not used by libgpac or the modules*/ + GF_LOG_APP, /*! special value used to set a level for all tools*/ GF_LOG_ALL, @@ -397,7 +377,7 @@ void gf_log_set_tool_level(u32 tool, u32 level); /*! * \brief Log Message Callback * - * The gf_log_cbk type is the type for the callback of the \ref gf_log_set_callback function. By default all logs are redirected to stdout + * The gf_log_cbk type is the type for the callback of the \ref gf_log_set_callback function. By default all logs are redirected to stderr * \param cbck Opaque user data. * \param log_level level of the log. This value is not guaranteed in multi-threaded context. * \param log_tool tool emitting the log. This value is not guaranteed in multi-threaded context. @@ -410,7 +390,7 @@ typedef void (*gf_log_cbk)(void *cbck, u32 log_level, u32 log_tool, const char* /*! * \brief Log overwrite * - * Assigns a user-defined callback for printing log messages. By default all logs are redirected to stdout + * Assigns a user-defined callback for printing log messages. By default all logs are redirected to stderr * \param usr_cbk Opaque user data * \param cbk callback log function * \return previous callback function @@ -558,7 +538,7 @@ GF_Err gf_delete_file(const char *fileName); * \param fileName absolute path of the file / directory to move or rename * \param newFileName absolute new path/name of the file / directory */ -void gf_move_file(const char *fileName, const char *newFileName); +GF_Err gf_move_file(const char *fileName, const char *newFileName); /*! * \brief Temporary File Creation @@ -605,7 +585,7 @@ typedef void (*gf_on_progress_cbk)(const void *cbck, const char *title, u64 done * * Iverwrites the progress signaling function by a user-defined one. * \param user_cbk Opaque user data - * \param prog_cbk new callback function to use. Passing NULL restore default GPAC stdout notification. + * \param prog_cbk new callback function to use. Passing NULL restore default GPAC stderr notification. */ void gf_set_progress_callback(void *user_cbk, gf_on_progress_cbk prog_cbk); diff --git a/include/gpac/unicode.h b/include/gpac/unicode.h index e2019fb..c94bfca 100644 --- a/include/gpac/unicode.h +++ b/include/gpac/unicode.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/user.h b/include/gpac/user.h index 4357231..571a23a 100644 --- a/include/gpac/user.h +++ b/include/gpac/user.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Stream Management sub-project diff --git a/include/gpac/utf.h b/include/gpac/utf.h index 0863b1a..3008d7b 100644 --- a/include/gpac/utf.h +++ b/include/gpac/utf.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/gpac/version.h b/include/gpac/version.h new file mode 100644 index 0000000..c68da7f --- /dev/null +++ b/include/gpac/version.h @@ -0,0 +1,48 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2012 + * All rights reserved + * + * This file is part of GPAC + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _GF_VERSION_H + +/*! + * \brief GPAC Version + * \hideinitializer + * + * Macro giving GPAC version expressed as a printable string +*/ +/* KEEP SPACE SEPARATORS FOR MAKE / GREP (SEE MAIN MAKEFILE & CONFIGURE & CO) + * NO SPACE in GPAC_VERSION / GPAC_FULL_VERSION for proper install + * SONAME versions must be digits (not strings) + */ +#define GPAC_VERSION "0.5.1-DEV" +#define GPAC_VERSION_MAJOR 2 +#define GPAC_VERSION_MINOR 0 +#define GPAC_VERSION_MICRO 0 + +#include +#define GPAC_FULL_VERSION GPAC_VERSION"-rev"GPAC_SVN_REVISION + + +#endif //_GF_VERSION_H + diff --git a/include/gpac/xml.h b/include/gpac/xml.h index 41d1374..465957e 100644 --- a/include/gpac/xml.h +++ b/include/gpac/xml.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/include/win32/inttypes.h b/include/win32/inttypes.h index 921f0b2..4db18db 100644 --- a/include/win32/inttypes.h +++ b/include/win32/inttypes.h @@ -14,9 +14,4 @@ typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; - -#ifdef __cplusplus -} -#endif - #endif /* ndef _INTTYPES_H */ diff --git a/mkdmg.sh b/mkdmg.sh index 89f83c6..df18492 100755 --- a/mkdmg.sh +++ b/mkdmg.sh @@ -65,7 +65,7 @@ echo Copying GUI rsync -r --exclude=.svn $source_path/gui ./tmpdmg/Osmo4.app/Contents/MacOS/ echo Building DMG -version=`grep '#define GPAC_VERSION ' $source_path/include/gpac/tools.h | cut -d '"' -f 2` +version=`grep '#define GPAC_VERSION ' $source_path/include/gpac/version.h | cut -d '"' -f 2` cur_dir=`pwd` cd $source_path diff --git a/modules/Makefile b/modules/Makefile index 7e313c2..6b5a461 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -1,7 +1,15 @@ include ../config.mak #all OS and lib independent -PLUGDIRS=aac_in ac3_in audio_filter bifs_dec dummy_in soft_raster mp3_in isom_in odf_dec rtp_in timedtext img_in saf_in mpegts_in ismacryp mpd_in +PLUGDIRS=aac_in ac3_in audio_filter bifs_dec dummy_in soft_raster mp3_in isom_in odf_dec rtp_in timedtext img_in saf_in ismacryp + +ifeq ($(DISABLE_DASH_CLIENT), no) +PLUGDIRS+=mpd_in +endif + +ifeq ($(DISABLE_MEDIA_IMPORT), no) +PLUGDIRS+=mpegts_in +endif ifeq ($(DISABLE_SMGR), no) PLUGDIRS+=ctx_load svg_in diff --git a/modules/aac_in/Makefile b/modules/aac_in/Makefile index 980c110..01ebf20 100644 --- a/modules/aac_in/Makefile +++ b/modules/aac_in/Makefile @@ -47,11 +47,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_aac_in-static.$(DYN_LIB_SUFFIX) $(OBJS) -L../../bin/gcc -lgpac_static $(EXTRALIBS) endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/aac_in/aac_in.c b/modules/aac_in/aac_in.c index 3a74968..01c450e 100644 --- a/modules/aac_in/aac_in.c +++ b/modules/aac_in/aac_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AAC reader module diff --git a/modules/aac_in/faad_dec.c b/modules/aac_in/faad_dec.c index fd5c029..f064014 100644 --- a/modules/aac_in/faad_dec.c +++ b/modules/aac_in/faad_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AAC reader module @@ -100,14 +101,13 @@ static GF_Err FAAD_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd) case GF_M4A_AAC_PS: s_base_object_type = gf_stringizer(GF_M4A_AAC_PS); base_object_type_error: /*error case*/ - GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error: unsupported %s format for stream %d\n", s_base_object_type, esd->ESID)); - return GF_NOT_SUPPORTED; + GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error: unsupported %s format for stream %d - defaulting to AAC LC\n", s_base_object_type, esd->ESID)); default: break; } a_cfg.base_object_type = GF_M4A_AAC_LC; a_cfg.has_sbr = 0; - a_cfg.nb_chan = 1; + a_cfg.nb_chan = a_cfg.nb_chan > 2 ? 1 : a_cfg.nb_chan; gf_m4a_write_config(&a_cfg, &dsi, &dsi_len); res = faacDecInit2(ctx->codec, (unsigned char *) dsi, dsi_len, (unsigned long *) &ctx->sample_rate, (u8 *) &ctx->num_channels); diff --git a/modules/ac3_in/Makefile b/modules/ac3_in/Makefile index f7c146f..59bb66f 100644 --- a/modules/ac3_in/Makefile +++ b/modules/ac3_in/Makefile @@ -44,11 +44,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/gcc -lgpac $(EXTRALIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ac3_in/ac3_in.c b/modules/ac3_in/ac3_in.c index df933f7..401886f 100644 --- a/modules/ac3_in/ac3_in.c +++ b/modules/ac3_in/ac3_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AC3 reader module diff --git a/modules/ac3_in/liba52_dec.c b/modules/ac3_in/liba52_dec.c index 265f088..ac07500 100644 --- a/modules/ac3_in/liba52_dec.c +++ b/modules/ac3_in/liba52_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AAC reader module @@ -300,7 +301,7 @@ static u32 AC3_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, GF_ESD *esd, /*media type query*/ if (!esd) return GF_CODEC_STREAM_TYPE_SUPPORTED; switch (esd->decoderConfig->objectTypeIndication) { - case 0xA5: + case GPAC_OTI_AUDIO_AC3: return GF_CODEC_SUPPORTED; } return GF_CODEC_NOT_SUPPORTED; diff --git a/modules/alsa/Makefile b/modules/alsa/Makefile index 9f617d2..b34d1c8 100644 --- a/modules/alsa/Makefile +++ b/modules/alsa/Makefile @@ -29,10 +29,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -lasound -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/alsa/alsa.c b/modules/alsa/alsa.c index 2f5f809..840b526 100644 --- a/modules/alsa/alsa.c +++ b/modules/alsa/alsa.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / alsa audio output module diff --git a/modules/amr_dec/Makefile b/modules/amr_dec/Makefile index 77ef22c..32e6707 100644 --- a/modules/amr_dec/Makefile +++ b/modules/amr_dec/Makefile @@ -57,10 +57,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/amr_dec/amr_dec.c b/modules/amr_dec/amr_dec.c index 15f1146..d0fb638 100644 --- a/modules/amr_dec/amr_dec.c +++ b/modules/amr_dec/amr_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AMR decoder module diff --git a/modules/amr_dec/amr_in.c b/modules/amr_dec/amr_in.c index bce7442..02fcf2a 100644 --- a/modules/amr_dec/amr_in.c +++ b/modules/amr_dec/amr_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AMR&EVRC&SMV reader module diff --git a/modules/amr_float_dec/Makefile b/modules/amr_float_dec/Makefile index dac45b9..aef75dc 100644 --- a/modules/amr_float_dec/Makefile +++ b/modules/amr_float_dec/Makefile @@ -47,11 +47,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/amr_float_dec/amr_float_dec.c b/modules/amr_float_dec/amr_float_dec.c index 682d205..997738c 100644 --- a/modules/amr_float_dec/amr_float_dec.c +++ b/modules/amr_float_dec/amr_float_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AMR decoder module diff --git a/modules/audio_filter/Makefile b/modules/audio_filter/Makefile index 123176b..390e421 100644 --- a/modules/audio_filter/Makefile +++ b/modules/audio_filter/Makefile @@ -27,10 +27,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/audio_filter/audio_filter.c b/modules/audio_filter/audio_filter.c index b1830cc..73251fc 100644 --- a/modules/audio_filter/audio_filter.c +++ b/modules/audio_filter/audio_filter.c @@ -1,10 +1,10 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Telecom ParisTech 20010- + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * - * Authors: Jean Le Feuvre * * This file is part of GPAC / sample audio filter module * diff --git a/modules/avcap/Makefile b/modules/avcap/Makefile index 81456ee..b78b7bc 100644 --- a/modules/avcap/Makefile +++ b/modules/avcap/Makefile @@ -31,11 +31,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CXX) -w $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKLIBS) - -%.o: %.cpp - $(CXX) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/avcap/avcap.cpp b/modules/avcap/avcap.cpp index 8d69650..43f181a 100644 --- a/modules/avcap/avcap.cpp +++ b/modules/avcap/avcap.cpp @@ -24,12 +24,24 @@ */ +#include + + +#ifdef __cplusplus +extern "C" { +#endif + #include #include /*for GF_STREAM_PRIVATE_SCENE definition*/ #include #include +#ifdef __cplusplus +} +#endif + + #if !defined(__GNUC__)&& (defined(_WIN32_WCE) || defined (WIN32)) # pragma comment(lib, "strmiids") #ifdef _DEBUG @@ -43,8 +55,6 @@ #endif - -#include using namespace avcap; class GPACCaptureHandler : public CaptureHandler diff --git a/modules/bifs_dec/Makefile b/modules/bifs_dec/Makefile index 516bd85..3218e4d 100644 --- a/modules/bifs_dec/Makefile +++ b/modules/bifs_dec/Makefile @@ -35,10 +35,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/bifs_dec/bifs_dec.c b/modules/bifs_dec/bifs_dec.c index ea08deb..3f9bf35 100644 --- a/modules/bifs_dec/bifs_dec.c +++ b/modules/bifs_dec/bifs_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS decoder module diff --git a/modules/ctx_load/Makefile b/modules/ctx_load/Makefile index ac62a0b..b322030 100644 --- a/modules/ctx_load/Makefile +++ b/modules/ctx_load/Makefile @@ -34,11 +34,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_ctx_load-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ctx_load/ctx_load.c b/modules/ctx_load/ctx_load.c index 0a273e8..87e7082 100644 --- a/modules/ctx_load/ctx_load.c +++ b/modules/ctx_load/ctx_load.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GPAC Scene Context loader module diff --git a/modules/demo_is/Makefile b/modules/demo_is/Makefile index 6c389b0..8acb0a4 100644 --- a/modules/demo_is/Makefile +++ b/modules/demo_is/Makefile @@ -31,11 +31,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/demo_is/demo_is.c b/modules/demo_is/demo_is.c index 06e4209..5846395 100644 --- a/modules/demo_is/demo_is.c +++ b/modules/demo_is/demo_is.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Dummy input module diff --git a/modules/directfb_out/Makefile b/modules/directfb_out/Makefile index 48ec61c..764f435 100644 --- a/modules/directfb_out/Makefile +++ b/modules/directfb_out/Makefile @@ -32,10 +32,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LDFLAGS) -L../../bin/gcc -lgpac - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/directfb_out/directfb_out.c b/modules/directfb_out/directfb_out.c index 174f934..622df2f 100755 --- a/modules/directfb_out/directfb_out.c +++ b/modules/directfb_out/directfb_out.c @@ -1,7 +1,8 @@ /* * GPAC Multimedia Framework * - * Copyright (c) 2005-20XX Telecom-Paristech + * Authors: Romain Bouqueau - Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / DirectFB video output module diff --git a/modules/directfb_out/directfb_out.h b/modules/directfb_out/directfb_out.h index 30ac3cf..2dfa1fa 100755 --- a/modules/directfb_out/directfb_out.h +++ b/modules/directfb_out/directfb_out.h @@ -1,7 +1,8 @@ /* * GPAC Multimedia Framework * - * Copyright (c) 2005-20XX Telecom-Paristech + * Authors: Romain Bouqueau - Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / DirectFB video output module diff --git a/modules/directfb_out/directfb_wrapper.c b/modules/directfb_out/directfb_wrapper.c index fa536ed..e87906c 100644 --- a/modules/directfb_out/directfb_wrapper.c +++ b/modules/directfb_out/directfb_wrapper.c @@ -1,7 +1,8 @@ /* * GPAC Multimedia Framework * - * Copyright (c) 2005-20XX Telecom-Paristech + * Authors: Romain Bouqueau - Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / DirectFB video output module @@ -552,7 +553,7 @@ u32 DirectFBVid_ProcessMessageQueueWrapper(DirectFBVidCtx *ctx, u8 *type, u32 *f *button = GF_MOUSE_MIDDLE; break; default: - printf("in here for others\n"); + //fprintf(stderr, "in here for others\n"); break; } break; @@ -617,47 +618,47 @@ u32 DirectFBVid_TranslatePixelFormatFromGPAC(u32 gpacpf) **/ void directfb_translate_key(DFBInputDeviceKeyIdentifier DirectFBkey, u32 *flags, u32 *key_code) { - //~ printf("DirectFBkey=%d\n", DirectFBkey); + //~ fprintf(stderr, "DirectFBkey=%d\n", DirectFBkey); switch (DirectFBkey) { case DIKI_BACKSPACE: *key_code = GF_KEY_BACKSPACE; - //~ printf("DIKI_BACKSPACE\n"); + //~ fprintf(stderr, "DIKI_BACKSPACE\n"); break; case DIKI_TAB: *key_code = GF_KEY_TAB; - //~ printf("DIKI_TAB\n"); + //~ fprintf(stderr, "DIKI_TAB\n"); break; case DIKI_ENTER: *key_code = GF_KEY_ENTER; - //~ printf("DIKI_ENTER\n"); + //~ fprintf(stderr, "DIKI_ENTER\n"); break; case DIKI_ESCAPE: *key_code = GF_KEY_ESCAPE; - //~ printf("DIKI_ESCAPE\n"); + //~ fprintf(stderr, "DIKI_ESCAPE\n"); break; case DIKI_SPACE: *key_code = GF_KEY_SPACE; - //~ printf("DIKI_SPACE\n"); + //~ fprintf(stderr, "DIKI_SPACE\n"); break; case DIKI_SHIFT_L: case DIKI_SHIFT_R: *key_code = GF_KEY_SHIFT; - //~ printf("DIKI_SHIFT_R/DIKI_SHIFT_L\n"); + //~ fprintf(stderr, "DIKI_SHIFT_R/DIKI_SHIFT_L\n"); break; case DIKI_CONTROL_L: case DIKI_CONTROL_R: *key_code = GF_KEY_CONTROL; - //~ printf("DIKI_CONTROL_L/DIKI_CONTROL_R\n"); + //~ fprintf(stderr, "DIKI_CONTROL_L/DIKI_CONTROL_R\n"); break; case DIKI_ALT_L: case DIKI_ALT_R: *key_code = GF_KEY_ALT; - //~ printf("DIKI_ALT_L/DIKI_ALT_R\n"); + //~ fprintf(stderr, "DIKI_ALT_L/DIKI_ALT_R\n"); break; case DIKI_CAPS_LOCK: *key_code = GF_KEY_CAPSLOCK; - //~ printf("DIKI_CAPS_LOCK\n"); + //~ fprintf(stderr, "DIKI_CAPS_LOCK\n"); break; case DIKI_META_L: case DIKI_META_R: @@ -671,23 +672,23 @@ void directfb_translate_key(DFBInputDeviceKeyIdentifier DirectFBkey, u32 *flags, /* alphabets */ case DIKI_A: *key_code = GF_KEY_A; - //~ printf("DIKI_A\n"); + //~ fprintf(stderr, "DIKI_A\n"); break; case DIKI_B: *key_code = GF_KEY_B; - //~ printf("DIKI_B\n"); + //~ fprintf(stderr, "DIKI_B\n"); break; case DIKI_C: *key_code = GF_KEY_C; - //~ printf("DIKI_C\n"); + //~ fprintf(stderr, "DIKI_C\n"); break; case DIKI_D: *key_code = GF_KEY_D; - //~ printf("DIKI_D\n"); + //~ fprintf(stderr, "DIKI_D\n"); break; case DIKI_E: *key_code = GF_KEY_E; - //~ printf("DIKI_E\n"); + //~ fprintf(stderr, "DIKI_E\n"); break; case DIKI_F: *key_code = GF_KEY_F; break; diff --git a/modules/droid_audio/droidaudio.c b/modules/droid_audio/droidaudio.c index 1b9def0..c16547c 100644 --- a/modules/droid_audio/droidaudio.c +++ b/modules/droid_audio/droidaudio.c @@ -1,13 +1,10 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- * All rights reserved * - * Created by NGO Van Luyen / ARTEMIS / Telecom SudParis /Institut TELECOM on Oct, 2010 - * nvluyen81@gmail.com - * * This file is part of GPAC / Wrapper * * GPAC is free software; you can redistribute it and/or modify diff --git a/modules/droid_audio/javaenv.c b/modules/droid_audio/javaenv.c index 26148bf..291f108 100644 --- a/modules/droid_audio/javaenv.c +++ b/modules/droid_audio/javaenv.c @@ -1,12 +1,10 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- * All rights reserved * - * Created by Arsov Ivica / ARTEMIS / Telecom SudParis /Institut TELECOM on Oct, 2010 - * * This file is part of GPAC / Wrapper * * GPAC is free software; you can redistribute it and/or modify diff --git a/modules/droid_audio/javaenv.h b/modules/droid_audio/javaenv.h index 813ee82..dc80f31 100644 --- a/modules/droid_audio/javaenv.h +++ b/modules/droid_audio/javaenv.h @@ -1,12 +1,10 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- * All rights reserved * - * Created by Arsov Ivica / ARTEMIS / Telecom SudParis /Institut TELECOM on Oct, 2010 - * * This file is part of GPAC / Wrapper * * GPAC is free software; you can redistribute it and/or modify diff --git a/modules/droid_cam/droid_cam.c b/modules/droid_cam/droid_cam.c index ec6cbd7..bf210a3 100644 --- a/modules/droid_cam/droid_cam.c +++ b/modules/droid_cam/droid_cam.c @@ -1,715 +1,715 @@ -/* - * GPAC - Multimedia Framework C SDK - * - * Authors: Ivica Arsov - * Copyright (c) Institut Telecom 2011-20XX - * All rights reserved - * - * This file is part of GPAC / Android camera module - * - * GPAC is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * GPAC is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define LOG_TAG "ANDROID_CAMERA" -#ifdef ANDROID -# define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -# define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#else -# define QUOTEME_(x) #x -# define QUOTEME(x) QUOTEME_(x) -# define LOGI(...) printf("I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__) -# define LOGE(...) printf("E/" LOG_TAG "(" ")" __VA_ARGS__) -#endif - -static JavaVM* javaVM = 0; -static jclass camCtrlClass; -static jmethodID cid; -static jmethodID startCamera; -static jmethodID stopCamera; -static jmethodID startProcessing; -static jmethodID stopProcessing; -static jmethodID getImageFormat; -static jmethodID getImageHeight; -static jmethodID getImageWidth; - -jint JNI_OnLoad(JavaVM* vm, void* reserved) -{ - JNIEnv* env = 0; - javaVM = vm; - - if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) - return -1; - - // Get the class and its methods in the main env - - // Get the CameraController class - // This is just a local refenrece. Cannot be used in the other JNI calls. - camCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/Preview"); - if (camCtrlClass == 0) - { - LOGE("CameraController class = null [myCamera.c, startCameraNative()]"); - return -1; - } - - // Get Global Reference to be able to use the class - camCtrlClass = (*env)->NewGlobalRef(env, camCtrlClass); - if ( camCtrlClass == 0 ) - { - LOGE("[MPEG-V_IN] Cannot create Global Reference\n"); - return -1; - } - - // Get the method ID for the CameraController constructor. - cid = (*env)->GetMethodID(env, camCtrlClass, "", "()V"); - if (cid == 0) - { - LOGE("Method ID for CameraController constructor is null [myCamera.c, startCameraNative()]"); - return -1; - } - - // Get startCamera() method from class CameraController - startCamera = (*env)->GetMethodID(env, camCtrlClass, "initializeCamera", "(Z)Z"); - if (startCamera == 0) - { - LOGE("[ANDROID_CAMERA] Function startCamera not found"); - return -1; - } - - stopCamera = (*env)->GetMethodID(env, camCtrlClass, "stopCamera", "()V"); - if (stopCamera == 0) - { - LOGE("[ANDROID_CAMERA] Function stopCamera not found"); - return -1; - } - - startProcessing = (*env)->GetMethodID(env, camCtrlClass, "resumePreview", "()V"); - if (startProcessing == 0) - { - LOGE("[ANDROID_CAMERA] Function startProcessing not found"); - return -1; - } - - stopProcessing = (*env)->GetMethodID(env, camCtrlClass, "pausePreview", "()V"); - if (stopProcessing == 0) - { - LOGE("[ANDROID_CAMERA] Function stopProcessing not found"); - return -1; - } - - getImageFormat = (*env)->GetMethodID(env, camCtrlClass, "getPreviewFormat", "()I"); - if (getImageFormat == 0) - { - LOGE("[ANDROID_CAMERA] Function getImageFormat not found"); - return -1; - } - - getImageHeight = (*env)->GetMethodID(env, camCtrlClass, "getImageHeight", "()I"); - if (getImageHeight == 0) - { - LOGE("[ANDROID_CAMERA] Function getImageHeight not found"); - return -1; - } - - getImageWidth = (*env)->GetMethodID(env, camCtrlClass, "getImageWidth", "()I"); - if (getImageWidth == 0) - { - LOGE("[ANDROID_CAMERA] Function getImageWidth not found"); - return -1; - } - - return JNI_VERSION_1_2; -} -//---------------------------------------------------------------------- -JavaVM* GetJavaVM() -{ - return javaVM; -} - -JNIEnv* GetEnv() -{ - JNIEnv* env; - if ( (*GetJavaVM())->GetEnv(GetJavaVM(), (void**)&env, JNI_VERSION_1_2) != JNI_OK ) - return NULL; - - return env; -} - -void JNI_OnUnload(JavaVM *vm, void *reserved) -{ - JNIEnv* env = 0; - - if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) - return; - - (*env)->DeleteGlobalRef(env, camCtrlClass); -} -//---------------------------------------------------------------------- - - -#define CAM_PIXEL_FORMAT GF_PIXEL_NV21 -//GF_PIXEL_RGB_32 -#define CAM_PIXEL_SIZE 1.5f -//4 -#define CAM_WIDTH 640 -#define CAM_HEIGHT 480 - -//GF_PIXEL_RGB_24; - -typedef struct -{ - GF_InputService *input; - /*the service we're responsible for*/ - GF_ClientService *service; - LPNETCHANNEL* channel; - - /*input file*/ - u32 time_scale; - - u32 base_track_id; - - struct _tag_terminal *term; - - u32 cntr; - - u32 width; - u32 height; - - Bool started; - - JNIEnv* env; - u8 isAttached; - jclass camCtrlClass; - jmethodID cid; - jobject camCtrlObj; - jmethodID startCamera; - jmethodID stopCamera; - jmethodID startProcessing; - jmethodID stopProcessing; - jmethodID getImageFormat; - jmethodID getImageHeight; - jmethodID getImageWidth; - -} ISOMReader; - -ISOMReader* globReader; - -void loadCameraControler(ISOMReader *read); -void camStartCamera(ISOMReader *read); -void camStopCamera(ISOMReader *read); - -Bool CAM_CanHandleURL(GF_InputService *plug, const char *url) -{ - if (!strnicmp(url, "hw://camera", 11)) return 1; - - return 0; -} - -void unloadCameraControler(ISOMReader *read) -{ - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] unloadCameraControler: %d\n", gf_th_id())); - if ( read->isAttached ) - { - //(*rc->env)->PopLocalFrame(rc->env, NULL); - (*GetJavaVM())->DetachCurrentThread(GetJavaVM()); - read->isAttached = 0; - } - - read->env = NULL; -} - -u32 unregisterFunc(void* data) -{ - unloadCameraControler(globReader); -} - -void loadCameraControler(ISOMReader *read) -{ - JNIEnv* env = NULL; - jint res = 0; - - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] loadCameraControler: %d\n", gf_th_id())); - - // Get the JNI interface pointer - res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2); - if ( res == JNI_EDETACHED ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The current thread is not attached to the VM, assuming native thread\n")); - if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] Attach current thread failed: %d\n", res)); - return; - } - gf_register_before_exit_function(gf_th_current(), unregisterFunc); - read->isAttached = 1; - //(*rc->env)->PushLocalFrame(rc->env, 2); - } - else - if ( res == JNI_EVERSION ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The specified version is not supported\n")); - return; - } - - read->env = env; - read->camCtrlClass = camCtrlClass; - read->cid = cid; - read->startCamera = startCamera; - read->stopCamera = stopCamera; - read->startProcessing = startProcessing; - read->stopProcessing = stopProcessing; - read->getImageFormat = getImageFormat; - read->getImageHeight = getImageHeight; - read->getImageWidth = getImageWidth; - - // Create the object. - read->camCtrlObj = (*env)->NewObject(env, read->camCtrlClass, read->cid); - if (read->camCtrlObj == 0) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("CameraController object creation failed. [myCamera.c, startCameraNative()]")); - return; - } -} - -GF_Err CAM_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) -{ - ISOMReader *read; - if (!plug || !plug->priv || !serv) return GF_SERVICE_ERROR; - read = (ISOMReader *) plug->priv; - - read->input = plug; - read->service = serv; - read->base_track_id = 1; - read->time_scale = 1000; - - read->term = serv->term; - - loadCameraControler(read); - - /*reply to user*/ - gf_term_on_connect(serv, NULL, GF_OK); - //if (read->no_service_desc) isor_declare_objects(read); - - return GF_OK; -} - -GF_Err CAM_CloseService(GF_InputService *plug) -{ - GF_Err reply; - ISOMReader *read; - if (!plug || !plug->priv) return GF_SERVICE_ERROR; - read = (ISOMReader *) plug->priv; - reply = GF_OK; - - (*GetEnv())->DeleteLocalRef( GetEnv(), read->camCtrlObj ); - - //unloadCameraControler(read); - - gf_term_on_disconnect(read->service, NULL, reply); - return GF_OK; -} - -u32 getWidth(ISOMReader *read); -u32 getHeight(ISOMReader *read); - -static GF_Descriptor *CAM_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url) -{ - u32 trackID; - GF_ESD *esd; - ISOMReader *read; - GF_ObjectDescriptor *od; - GF_BitStream *bs; - char *buf; - u32 buf_size; - if (!plug || !plug->priv) return NULL; - read = (ISOMReader *) plug->priv; - - trackID = 0; - trackID = read->base_track_id; - read->base_track_id = 0; - - if (trackID && (expect_type==GF_MEDIA_OBJECT_VIDEO) ) { - od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); - od->objectDescriptorID = 1; - - esd = gf_odf_desc_esd_new(0); - esd->slConfig->timestampResolution = 1000; - esd->decoderConfig->streamType = GF_STREAM_VISUAL; - esd->ESID = 1; - esd->decoderConfig->objectTypeIndication = GPAC_OTI_RAW_MEDIA_STREAM; - - bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); - - read->width = getWidth(read); - read->height = getHeight(read); - - gf_bs_write_u32(bs, CAM_PIXEL_FORMAT); // fourcc - gf_bs_write_u16(bs, read->width); // width - gf_bs_write_u16(bs, read->height); // height - gf_bs_write_u32(bs, read->width * read->height * CAM_PIXEL_SIZE); // framesize - gf_bs_write_u32(bs, read->width * CAM_PIXEL_SIZE); // stride - - gf_bs_align(bs); - gf_bs_get_content(bs, &buf, &buf_size); - gf_bs_del(bs); - - esd->decoderConfig->decoderSpecificInfo->data = buf; - esd->decoderConfig->decoderSpecificInfo->dataLength = buf_size; - - gf_list_add(od->ESDescriptors, esd); - return (GF_Descriptor *) od; - } - - return NULL; -} - - - - -GF_Err CAM_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream) -{ - GF_Err e; - ISOMReader *read; - if (!plug || !plug->priv) return GF_SERVICE_ERROR; - read = (ISOMReader *) plug->priv; - - e = GF_OK; - if (upstream) { - e = GF_ISOM_INVALID_FILE; - } - - read->channel = channel; - - camStartCamera(read); - - gf_term_on_connect(read->service, channel, e); - return e; -} - -GF_Err CAM_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel) -{ - GF_Err e; - ISOMReader *read; - if (!plug || !plug->priv) return GF_SERVICE_ERROR; - read = (ISOMReader *) plug->priv; - - e = GF_OK; - - camStopCamera(read); - - gf_term_on_disconnect(read->service, channel, e); - return e; -} - -int* decodeYUV420SP( char* yuv420sp, int width, int height) -{ - int frameSize = width * height; - int j, yp, uvp, i, y, y1192, r, g, b, u, v; - int ti, tj; - - int* rgb = (int*)gf_malloc(width*height*4); - for (j = 0, yp = 0, tj=height-1; j < height; j++, tj--) - { - uvp = frameSize + (j >> 1) * width, u = 0, v = 0; - for (i = 0, ti=0; i < width; i++, yp++, ti+=width) - { - y = (0xff & ((int) yuv420sp[yp])) - 16; - if (y < 0) y = 0; - if ((i & 1) == 0) - { - v = (0xff & yuv420sp[uvp++]) - 128; - u = (0xff & yuv420sp[uvp++]) - 128; - } - - y1192 = 1192 * y; - r = (y1192 + 1634 * v); - g = (y1192 - 833 * v - 400 * u); - b = (y1192 + 2066 * u); - - if (r < 0) - r = 0; - else if (r > 262143) - r = 262143; - if (g < 0) - g = 0; - else if (g > 262143) - g = 262143; - if (b < 0) - b = 0; - else if (b > 262143) - b = 262143; - - rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) - | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); -// rgb[ti+tj] = 0xff000000 | ((r << 6) & 0xff0000) -// | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); - } - } - return rgb; -} - -void Java_com_gpac_Osmo4_Preview_processFrameBuf( JNIEnv* env, jobject thiz, jbyteArray arr) -{ - u8* data; - u32 datasize; - ISOMReader* ctx = globReader; - GF_SLHeader hdr; - u32 cts = 0; - u32 convTime = 0; - u32 j = 0; - jbyte *jdata; - jsize len; - - if ( ctx->started ) - { - len = (*env)->GetArrayLength(env, arr); - jdata = (*env)->GetByteArrayElements(env,arr,0); - - convTime = gf_term_get_time(ctx->term); - - data = (u8*)jdata;//(u8*)decodeYUV420SP((char*)jdata, ctx->width, ctx->height); // - datasize = len;//ctx->width * ctx->height * CAM_PIXEL_SIZE;// - - cts = gf_term_get_time(ctx->term); - - convTime = cts - convTime; - - memset(&hdr, 0, sizeof(hdr)); - hdr.compositionTimeStampFlag = 1; - hdr.compositionTimeStamp = cts; - gf_term_on_sl_packet(ctx->service, ctx->channel, (void*)data, datasize, &hdr, GF_OK); - - //gf_free(data); - - (*env)->ReleaseByteArrayElements(env,arr,jdata,JNI_ABORT); - - //GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Camera Frame Sent %d\n", gf_sys_clock())); - } -} - -void CallCamMethod(ISOMReader *read, jmethodID methodID) -{ - JNIEnv* env = NULL; - jint res = 0; - u8 isAttached = 0; - - // Get the JNI interface pointer - res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2); - if ( res == JNI_EDETACHED ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The current thread is not attached to the VM, assuming native thread\n")); - if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] Attach current thread failed: %d\n", res)); - return; - } - if ( env != read->env ) - isAttached = 1; - } - - (*env)->CallNonvirtualVoidMethod(env, read->camCtrlObj, read->camCtrlClass, methodID); - - if (isAttached) - { - (*GetJavaVM())->DetachCurrentThread(GetJavaVM()); - } -} - -void camStartCamera(ISOMReader *read) -{ - JNIEnv* env = NULL; - jboolean isPortrait = JNI_FALSE; - - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] startCamera: %d\n", gf_th_id())); - - // Get the JNI interface pointer - env = read->env; - - (*env)->CallNonvirtualBooleanMethod(env, read->camCtrlObj, read->camCtrlClass, read->startCamera, isPortrait); -} - -void camStopCamera(ISOMReader *read) -{ - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] stopCamera: %d\n", gf_th_id())); - - CallCamMethod(read, read->stopCamera); -} - -void pauseCamera(ISOMReader *read) -{ - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] pauseCamera: %d\n", gf_th_id())); - - read->started = 0; - CallCamMethod(read, read->stopProcessing); -} - -void resumeCamera(ISOMReader *read) -{ - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] resumeCamera: %d\n", gf_th_id())); - - read->started = 1; - CallCamMethod(read, read->startProcessing); -} - -u32 getWidth(ISOMReader *read) -{ - JNIEnv* env = NULL; - - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] getWidth: %d\n", gf_th_id())); - - // Get the JNI interface pointer - env = read->env; - - return (*env)->CallNonvirtualIntMethod(env, read->camCtrlObj, read->camCtrlClass, read->getImageWidth); -} - -u32 getHeight(ISOMReader *read) -{ - JNIEnv* env = NULL; - - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] getHeight: %d\n", gf_th_id())); - - // Get the JNI interface pointer - env = read->env; - - return (*env)->CallNonvirtualIntMethod(env, read->camCtrlObj, read->camCtrlClass, read->getImageHeight); -} - -GF_Err CAM_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) -{ - ISOMReader *read; - GF_BitStream *bs; - char *buf; - u32 buf_size; - if (!plug || !plug->priv || !com) return GF_SERVICE_ERROR; - read = (ISOMReader *) plug->priv; - - if (com->command_type==GF_NET_SERVICE_INFO) { - return GF_OK; - } - if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) { - return GF_NOT_SUPPORTED; - } - if (!com->base.on_channel) return GF_NOT_SUPPORTED; - - switch (com->command_type) { - case GF_NET_CHAN_INTERACTIVE: - return GF_OK; - case GF_NET_CHAN_BUFFER: - com->buffer.max = com->buffer.min = 0; - return GF_OK; - case GF_NET_CHAN_PLAY: - resumeCamera(read); - return GF_OK; - case GF_NET_CHAN_STOP: - pauseCamera(read); - return GF_OK; - /*nothing to do on MP4 for channel config*/ - case GF_NET_CHAN_CONFIG: - return GF_OK; - case GF_NET_CHAN_GET_PIXEL_AR: - return 1<<16;//gf_isom_get_pixel_aspect_ratio(read->mov, ch->track, 1, &com->par.hSpacing, &com->par.vSpacing); - case GF_NET_CHAN_GET_DSI: - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cam get DSI\n")); - /*it may happen that there are conflicting config when using ESD URLs...*/ - bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); - - read->width = getWidth(read); - read->height = getHeight(read); - - gf_bs_write_u32(bs, CAM_PIXEL_FORMAT); // fourcc - gf_bs_write_u16(bs, read->width); // width - gf_bs_write_u16(bs, read->height); // height - gf_bs_write_u32(bs, read->width * read->height * CAM_PIXEL_SIZE); // framesize - gf_bs_write_u32(bs, read->width * CAM_PIXEL_SIZE); // stride - - gf_bs_align(bs); - gf_bs_get_content(bs, &buf, &buf_size); - gf_bs_del(bs); - - com->get_dsi.dsi = buf; - com->get_dsi.dsi_len = buf_size; - return GF_OK; - } - } - return GF_NOT_SUPPORTED; -} - -GF_InputService *CAM_client_load() -{ - ISOMReader *reader; - GF_InputService *plug; - GF_SAFEALLOC(plug, GF_InputService); - GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC Camera Plugin", "gpac distribution") - plug->CanHandleURL = CAM_CanHandleURL; - plug->ConnectService = CAM_ConnectService; - plug->CloseService = CAM_CloseService; - plug->GetServiceDescriptor = CAM_GetServiceDesc; - plug->ConnectChannel = CAM_ConnectChannel; - plug->DisconnectChannel = CAM_DisconnectChannel; - plug->ServiceCommand = CAM_ServiceCommand; - - GF_SAFEALLOC(reader, ISOMReader); - plug->priv = reader; - globReader = reader; - return plug; -} - -void CAM_client_del(GF_BaseInterface *bi) -{ - GF_InputService *plug = (GF_InputService *) bi; - ISOMReader *read = (ISOMReader *)plug->priv; - - gf_free(read); - gf_free(bi); -} - -GF_EXPORT -const u32 *QueryInterfaces() -{ - static u32 si [] = { - GF_NET_CLIENT_INTERFACE, - 0 - }; - return si; -} - -GF_EXPORT -GF_BaseInterface *LoadInterface(u32 InterfaceType) -{ - if (InterfaceType == GF_NET_CLIENT_INTERFACE) - return (GF_BaseInterface *)CAM_client_load(); - return NULL; -} - -GF_EXPORT -void ShutdownInterface(GF_BaseInterface *ifce) -{ - switch (ifce->InterfaceType) { - case GF_NET_CLIENT_INTERFACE: CAM_client_del(ifce); break; - } -} +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- + * All rights reserved + * + * This file is part of GPAC / Android camera module + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define LOG_TAG "ANDROID_CAMERA" +#ifdef ANDROID +# define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +# define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +#else +# define QUOTEME_(x) #x +# define QUOTEME(x) QUOTEME_(x) +# define LOGI(...) fprintf(stderr, "I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__) +# define LOGE(...) fprintf(stderr, "E/" LOG_TAG "(" ")" __VA_ARGS__) +#endif + +static JavaVM* javaVM = 0; +static jclass camCtrlClass; +static jmethodID cid; +static jmethodID startCamera; +static jmethodID stopCamera; +static jmethodID startProcessing; +static jmethodID stopProcessing; +static jmethodID getImageFormat; +static jmethodID getImageHeight; +static jmethodID getImageWidth; + +jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = 0; + javaVM = vm; + + if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) + return -1; + + // Get the class and its methods in the main env + + // Get the CameraController class + // This is just a local refenrece. Cannot be used in the other JNI calls. + camCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/Preview"); + if (camCtrlClass == 0) + { + LOGE("CameraController class = null [myCamera.c, startCameraNative()]"); + return -1; + } + + // Get Global Reference to be able to use the class + camCtrlClass = (*env)->NewGlobalRef(env, camCtrlClass); + if ( camCtrlClass == 0 ) + { + LOGE("[MPEG-V_IN] Cannot create Global Reference\n"); + return -1; + } + + // Get the method ID for the CameraController constructor. + cid = (*env)->GetMethodID(env, camCtrlClass, "", "()V"); + if (cid == 0) + { + LOGE("Method ID for CameraController constructor is null [myCamera.c, startCameraNative()]"); + return -1; + } + + // Get startCamera() method from class CameraController + startCamera = (*env)->GetMethodID(env, camCtrlClass, "initializeCamera", "(Z)Z"); + if (startCamera == 0) + { + LOGE("[ANDROID_CAMERA] Function startCamera not found"); + return -1; + } + + stopCamera = (*env)->GetMethodID(env, camCtrlClass, "stopCamera", "()V"); + if (stopCamera == 0) + { + LOGE("[ANDROID_CAMERA] Function stopCamera not found"); + return -1; + } + + startProcessing = (*env)->GetMethodID(env, camCtrlClass, "resumePreview", "()V"); + if (startProcessing == 0) + { + LOGE("[ANDROID_CAMERA] Function startProcessing not found"); + return -1; + } + + stopProcessing = (*env)->GetMethodID(env, camCtrlClass, "pausePreview", "()V"); + if (stopProcessing == 0) + { + LOGE("[ANDROID_CAMERA] Function stopProcessing not found"); + return -1; + } + + getImageFormat = (*env)->GetMethodID(env, camCtrlClass, "getPreviewFormat", "()I"); + if (getImageFormat == 0) + { + LOGE("[ANDROID_CAMERA] Function getImageFormat not found"); + return -1; + } + + getImageHeight = (*env)->GetMethodID(env, camCtrlClass, "getImageHeight", "()I"); + if (getImageHeight == 0) + { + LOGE("[ANDROID_CAMERA] Function getImageHeight not found"); + return -1; + } + + getImageWidth = (*env)->GetMethodID(env, camCtrlClass, "getImageWidth", "()I"); + if (getImageWidth == 0) + { + LOGE("[ANDROID_CAMERA] Function getImageWidth not found"); + return -1; + } + + return JNI_VERSION_1_2; +} +//---------------------------------------------------------------------- +JavaVM* GetJavaVM() +{ + return javaVM; +} + +JNIEnv* GetEnv() +{ + JNIEnv* env; + if ( (*GetJavaVM())->GetEnv(GetJavaVM(), (void**)&env, JNI_VERSION_1_2) != JNI_OK ) + return NULL; + + return env; +} + +void JNI_OnUnload(JavaVM *vm, void *reserved) +{ + JNIEnv* env = 0; + + if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) + return; + + (*env)->DeleteGlobalRef(env, camCtrlClass); +} +//---------------------------------------------------------------------- + + +#define CAM_PIXEL_FORMAT GF_PIXEL_NV21 +//GF_PIXEL_RGB_32 +#define CAM_PIXEL_SIZE 1.5f +//4 +#define CAM_WIDTH 640 +#define CAM_HEIGHT 480 + +//GF_PIXEL_RGB_24; + +typedef struct +{ + GF_InputService *input; + /*the service we're responsible for*/ + GF_ClientService *service; + LPNETCHANNEL* channel; + + /*input file*/ + u32 time_scale; + + u32 base_track_id; + + struct _tag_terminal *term; + + u32 cntr; + + u32 width; + u32 height; + + Bool started; + + JNIEnv* env; + u8 isAttached; + jclass camCtrlClass; + jmethodID cid; + jobject camCtrlObj; + jmethodID startCamera; + jmethodID stopCamera; + jmethodID startProcessing; + jmethodID stopProcessing; + jmethodID getImageFormat; + jmethodID getImageHeight; + jmethodID getImageWidth; + +} ISOMReader; + +ISOMReader* globReader; + +void loadCameraControler(ISOMReader *read); +void camStartCamera(ISOMReader *read); +void camStopCamera(ISOMReader *read); + +Bool CAM_CanHandleURL(GF_InputService *plug, const char *url) +{ + if (!strnicmp(url, "hw://camera", 11)) return 1; + + return 0; +} + +void unloadCameraControler(ISOMReader *read) +{ + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] unloadCameraControler: %d\n", gf_th_id())); + if ( read->isAttached ) + { + //(*rc->env)->PopLocalFrame(rc->env, NULL); + (*GetJavaVM())->DetachCurrentThread(GetJavaVM()); + read->isAttached = 0; + } + + read->env = NULL; +} + +u32 unregisterFunc(void* data) +{ + unloadCameraControler(globReader); +} + +void loadCameraControler(ISOMReader *read) +{ + JNIEnv* env = NULL; + jint res = 0; + + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] loadCameraControler: %d\n", gf_th_id())); + + // Get the JNI interface pointer + res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2); + if ( res == JNI_EDETACHED ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The current thread is not attached to the VM, assuming native thread\n")); + if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] Attach current thread failed: %d\n", res)); + return; + } + gf_register_before_exit_function(gf_th_current(), unregisterFunc); + read->isAttached = 1; + //(*rc->env)->PushLocalFrame(rc->env, 2); + } + else + if ( res == JNI_EVERSION ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The specified version is not supported\n")); + return; + } + + read->env = env; + read->camCtrlClass = camCtrlClass; + read->cid = cid; + read->startCamera = startCamera; + read->stopCamera = stopCamera; + read->startProcessing = startProcessing; + read->stopProcessing = stopProcessing; + read->getImageFormat = getImageFormat; + read->getImageHeight = getImageHeight; + read->getImageWidth = getImageWidth; + + // Create the object. + read->camCtrlObj = (*env)->NewObject(env, read->camCtrlClass, read->cid); + if (read->camCtrlObj == 0) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("CameraController object creation failed. [myCamera.c, startCameraNative()]")); + return; + } +} + +GF_Err CAM_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) +{ + ISOMReader *read; + if (!plug || !plug->priv || !serv) return GF_SERVICE_ERROR; + read = (ISOMReader *) plug->priv; + + read->input = plug; + read->service = serv; + read->base_track_id = 1; + read->time_scale = 1000; + + read->term = serv->term; + + loadCameraControler(read); + + /*reply to user*/ + gf_term_on_connect(serv, NULL, GF_OK); + //if (read->no_service_desc) isor_declare_objects(read); + + return GF_OK; +} + +GF_Err CAM_CloseService(GF_InputService *plug) +{ + GF_Err reply; + ISOMReader *read; + if (!plug || !plug->priv) return GF_SERVICE_ERROR; + read = (ISOMReader *) plug->priv; + reply = GF_OK; + + (*GetEnv())->DeleteLocalRef( GetEnv(), read->camCtrlObj ); + + //unloadCameraControler(read); + + gf_term_on_disconnect(read->service, NULL, reply); + return GF_OK; +} + +u32 getWidth(ISOMReader *read); +u32 getHeight(ISOMReader *read); + +static GF_Descriptor *CAM_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url) +{ + u32 trackID; + GF_ESD *esd; + ISOMReader *read; + GF_ObjectDescriptor *od; + GF_BitStream *bs; + char *buf; + u32 buf_size; + if (!plug || !plug->priv) return NULL; + read = (ISOMReader *) plug->priv; + + trackID = 0; + trackID = read->base_track_id; + read->base_track_id = 0; + + if (trackID && (expect_type==GF_MEDIA_OBJECT_VIDEO) ) { + od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); + od->objectDescriptorID = 1; + + esd = gf_odf_desc_esd_new(0); + esd->slConfig->timestampResolution = 1000; + esd->decoderConfig->streamType = GF_STREAM_VISUAL; + esd->ESID = 1; + esd->decoderConfig->objectTypeIndication = GPAC_OTI_RAW_MEDIA_STREAM; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + + read->width = getWidth(read); + read->height = getHeight(read); + + gf_bs_write_u32(bs, CAM_PIXEL_FORMAT); // fourcc + gf_bs_write_u16(bs, read->width); // width + gf_bs_write_u16(bs, read->height); // height + gf_bs_write_u32(bs, read->width * read->height * CAM_PIXEL_SIZE); // framesize + gf_bs_write_u32(bs, read->width * CAM_PIXEL_SIZE); // stride + + gf_bs_align(bs); + gf_bs_get_content(bs, &buf, &buf_size); + gf_bs_del(bs); + + esd->decoderConfig->decoderSpecificInfo->data = buf; + esd->decoderConfig->decoderSpecificInfo->dataLength = buf_size; + + gf_list_add(od->ESDescriptors, esd); + return (GF_Descriptor *) od; + } + + return NULL; +} + + + + +GF_Err CAM_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream) +{ + GF_Err e; + ISOMReader *read; + if (!plug || !plug->priv) return GF_SERVICE_ERROR; + read = (ISOMReader *) plug->priv; + + e = GF_OK; + if (upstream) { + e = GF_ISOM_INVALID_FILE; + } + + read->channel = channel; + + camStartCamera(read); + + gf_term_on_connect(read->service, channel, e); + return e; +} + +GF_Err CAM_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel) +{ + GF_Err e; + ISOMReader *read; + if (!plug || !plug->priv) return GF_SERVICE_ERROR; + read = (ISOMReader *) plug->priv; + + e = GF_OK; + + camStopCamera(read); + + gf_term_on_disconnect(read->service, channel, e); + return e; +} + +int* decodeYUV420SP( char* yuv420sp, int width, int height) +{ + int frameSize = width * height; + int j, yp, uvp, i, y, y1192, r, g, b, u, v; + int ti, tj; + + int* rgb = (int*)gf_malloc(width*height*4); + for (j = 0, yp = 0, tj=height-1; j < height; j++, tj--) + { + uvp = frameSize + (j >> 1) * width, u = 0, v = 0; + for (i = 0, ti=0; i < width; i++, yp++, ti+=width) + { + y = (0xff & ((int) yuv420sp[yp])) - 16; + if (y < 0) y = 0; + if ((i & 1) == 0) + { + v = (0xff & yuv420sp[uvp++]) - 128; + u = (0xff & yuv420sp[uvp++]) - 128; + } + + y1192 = 1192 * y; + r = (y1192 + 1634 * v); + g = (y1192 - 833 * v - 400 * u); + b = (y1192 + 2066 * u); + + if (r < 0) + r = 0; + else if (r > 262143) + r = 262143; + if (g < 0) + g = 0; + else if (g > 262143) + g = 262143; + if (b < 0) + b = 0; + else if (b > 262143) + b = 262143; + + rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) + | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); +// rgb[ti+tj] = 0xff000000 | ((r << 6) & 0xff0000) +// | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); + } + } + return rgb; +} + +void Java_com_gpac_Osmo4_Preview_processFrameBuf( JNIEnv* env, jobject thiz, jbyteArray arr) +{ + u8* data; + u32 datasize; + ISOMReader* ctx = globReader; + GF_SLHeader hdr; + u32 cts = 0; + u32 convTime = 0; + u32 j = 0; + jbyte *jdata; + jsize len; + + if ( ctx->started ) + { + len = (*env)->GetArrayLength(env, arr); + jdata = (*env)->GetByteArrayElements(env,arr,0); + + convTime = gf_term_get_time(ctx->term); + + data = (u8*)jdata;//(u8*)decodeYUV420SP((char*)jdata, ctx->width, ctx->height); // + datasize = len;//ctx->width * ctx->height * CAM_PIXEL_SIZE;// + + cts = gf_term_get_time(ctx->term); + + convTime = cts - convTime; + + memset(&hdr, 0, sizeof(hdr)); + hdr.compositionTimeStampFlag = 1; + hdr.compositionTimeStamp = cts; + gf_term_on_sl_packet(ctx->service, ctx->channel, (void*)data, datasize, &hdr, GF_OK); + + //gf_free(data); + + (*env)->ReleaseByteArrayElements(env,arr,jdata,JNI_ABORT); + + //GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Camera Frame Sent %d\n", gf_sys_clock())); + } +} + +void CallCamMethod(ISOMReader *read, jmethodID methodID) +{ + JNIEnv* env = NULL; + jint res = 0; + u8 isAttached = 0; + + // Get the JNI interface pointer + res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2); + if ( res == JNI_EDETACHED ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] The current thread is not attached to the VM, assuming native thread\n")); + if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] Attach current thread failed: %d\n", res)); + return; + } + if ( env != read->env ) + isAttached = 1; + } + + (*env)->CallNonvirtualVoidMethod(env, read->camCtrlObj, read->camCtrlClass, methodID); + + if (isAttached) + { + (*GetJavaVM())->DetachCurrentThread(GetJavaVM()); + } +} + +void camStartCamera(ISOMReader *read) +{ + JNIEnv* env = NULL; + jboolean isPortrait = JNI_FALSE; + + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] startCamera: %d\n", gf_th_id())); + + // Get the JNI interface pointer + env = read->env; + + (*env)->CallNonvirtualBooleanMethod(env, read->camCtrlObj, read->camCtrlClass, read->startCamera, isPortrait); +} + +void camStopCamera(ISOMReader *read) +{ + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] stopCamera: %d\n", gf_th_id())); + + CallCamMethod(read, read->stopCamera); +} + +void pauseCamera(ISOMReader *read) +{ + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] pauseCamera: %d\n", gf_th_id())); + + read->started = 0; + CallCamMethod(read, read->stopProcessing); +} + +void resumeCamera(ISOMReader *read) +{ + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] resumeCamera: %d\n", gf_th_id())); + + read->started = 1; + CallCamMethod(read, read->startProcessing); +} + +u32 getWidth(ISOMReader *read) +{ + JNIEnv* env = NULL; + + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] getWidth: %d\n", gf_th_id())); + + // Get the JNI interface pointer + env = read->env; + + return (*env)->CallNonvirtualIntMethod(env, read->camCtrlObj, read->camCtrlClass, read->getImageWidth); +} + +u32 getHeight(ISOMReader *read) +{ + JNIEnv* env = NULL; + + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[ANDROID_CAMERA] getHeight: %d\n", gf_th_id())); + + // Get the JNI interface pointer + env = read->env; + + return (*env)->CallNonvirtualIntMethod(env, read->camCtrlObj, read->camCtrlClass, read->getImageHeight); +} + +GF_Err CAM_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) +{ + ISOMReader *read; + GF_BitStream *bs; + char *buf; + u32 buf_size; + if (!plug || !plug->priv || !com) return GF_SERVICE_ERROR; + read = (ISOMReader *) plug->priv; + + if (com->command_type==GF_NET_SERVICE_INFO) { + return GF_OK; + } + if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) { + return GF_NOT_SUPPORTED; + } + if (!com->base.on_channel) return GF_NOT_SUPPORTED; + + switch (com->command_type) { + case GF_NET_CHAN_INTERACTIVE: + return GF_OK; + case GF_NET_CHAN_BUFFER: + com->buffer.max = com->buffer.min = 0; + return GF_OK; + case GF_NET_CHAN_PLAY: + resumeCamera(read); + return GF_OK; + case GF_NET_CHAN_STOP: + pauseCamera(read); + return GF_OK; + /*nothing to do on MP4 for channel config*/ + case GF_NET_CHAN_CONFIG: + return GF_OK; + case GF_NET_CHAN_GET_PIXEL_AR: + return 1<<16;//gf_isom_get_pixel_aspect_ratio(read->mov, ch->track, 1, &com->par.hSpacing, &com->par.vSpacing); + case GF_NET_CHAN_GET_DSI: + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Cam get DSI\n")); + /*it may happen that there are conflicting config when using ESD URLs...*/ + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + + read->width = getWidth(read); + read->height = getHeight(read); + + gf_bs_write_u32(bs, CAM_PIXEL_FORMAT); // fourcc + gf_bs_write_u16(bs, read->width); // width + gf_bs_write_u16(bs, read->height); // height + gf_bs_write_u32(bs, read->width * read->height * CAM_PIXEL_SIZE); // framesize + gf_bs_write_u32(bs, read->width * CAM_PIXEL_SIZE); // stride + + gf_bs_align(bs); + gf_bs_get_content(bs, &buf, &buf_size); + gf_bs_del(bs); + + com->get_dsi.dsi = buf; + com->get_dsi.dsi_len = buf_size; + return GF_OK; + } + } + return GF_NOT_SUPPORTED; +} + +GF_InputService *CAM_client_load() +{ + ISOMReader *reader; + GF_InputService *plug; + GF_SAFEALLOC(plug, GF_InputService); + GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC Camera Plugin", "gpac distribution") + plug->CanHandleURL = CAM_CanHandleURL; + plug->ConnectService = CAM_ConnectService; + plug->CloseService = CAM_CloseService; + plug->GetServiceDescriptor = CAM_GetServiceDesc; + plug->ConnectChannel = CAM_ConnectChannel; + plug->DisconnectChannel = CAM_DisconnectChannel; + plug->ServiceCommand = CAM_ServiceCommand; + + GF_SAFEALLOC(reader, ISOMReader); + plug->priv = reader; + globReader = reader; + return plug; +} + +void CAM_client_del(GF_BaseInterface *bi) +{ + GF_InputService *plug = (GF_InputService *) bi; + ISOMReader *read = (ISOMReader *)plug->priv; + + gf_free(read); + gf_free(bi); +} + +GF_EXPORT +const u32 *QueryInterfaces() +{ + static u32 si [] = { + GF_NET_CLIENT_INTERFACE, + 0 + }; + return si; +} + +GF_EXPORT +GF_BaseInterface *LoadInterface(u32 InterfaceType) +{ + if (InterfaceType == GF_NET_CLIENT_INTERFACE) + return (GF_BaseInterface *)CAM_client_load(); + return NULL; +} + +GF_EXPORT +void ShutdownInterface(GF_BaseInterface *ifce) +{ + switch (ifce->InterfaceType) { + case GF_NET_CLIENT_INTERFACE: CAM_client_del(ifce); break; + } +} diff --git a/modules/droid_mpegv/droid_mpegv.c b/modules/droid_mpegv/droid_mpegv.c index b4d6797..73b35d2 100644 --- a/modules/droid_mpegv/droid_mpegv.c +++ b/modules/droid_mpegv/droid_mpegv.c @@ -1,391 +1,391 @@ -/* - * GPAC - Multimedia Framework C SDK - * - * Authors: Ivica Arsov - * Copyright (c) Institut Telecom 2011-20XX - * All rights reserved - * - * This file is part of GPAC / MPEG-V Input sensor for android - * - * GPAC is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * GPAC is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include - -/*driver interfaces*/ - -#include -#include - -#include - -#include -#include - -#include - -#define LOG_TAG "MPEG-V_IN" -#ifdef ANDROID -# define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -# define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#else -# define QUOTEME_(x) #x -# define QUOTEME(x) QUOTEME_(x) -# define LOGI(...) printf("I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__) -# define LOGE(...) printf("E/" LOG_TAG "(" ")" __VA_ARGS__) -#endif - -JNIEXPORT void JNICALL Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data); - -static JavaVM* javaVM = 0; -static jclass sensCtrlClass; -static jmethodID cid; -static jmethodID startSensor; -static jmethodID stopSensor; - -//---------------------------------------------------------------------- -jint JNI_OnLoad(JavaVM* vm, void* reserved) -{ - JNIEnv* env = 0; - javaVM = vm; - - if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) - return -1; - - // Get the class and its methods in the main env - - // Get the CameraController class - // This is just a local refenrece. Cannot be used in the other JNI calls. - sensCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/MPEGVSensor"); - if (sensCtrlClass == 0) - { - LOGE("[MPEG-V_IN] Class MPEGVSensor not found\n"); - return -1; - } - - // Get Global Reference to be able to use the class - sensCtrlClass = (*env)->NewGlobalRef(env, sensCtrlClass); - if ( sensCtrlClass == 0 ) - { - LOGE("[MPEG-V_IN] Caanot create Global Reference\n"); - return -1; - } - - // Get the method ID for the CameraController constructor. - cid = (*env)->GetMethodID(env, sensCtrlClass, "", "()V"); - if (cid == 0) - { - LOGE("[MPEG-V_IN] MPEGVSensor Constructor not found\n"); - return -1; - } - - // Get startCamera() method from class CameraController - startSensor = (*env)->GetMethodID(env, sensCtrlClass, "startSensor", "(II)V"); - if (startSensor == 0) - { - LOGE("[MPEG-V_IN] Function startSensor not found\n"); - return -1; - } - - stopSensor = (*env)->GetMethodID(env, sensCtrlClass, "stopSensor", "()V"); - if (stopSensor == 0) - { - LOGE("[MPEG-V_IN] Function stopSensor not found\n"); - return -1; - } - - return JNI_VERSION_1_2; -} - -void JNI_OnUnload(JavaVM *vm, void *reserved) -{ - JNIEnv* env = 0; - - if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) - return; - - (*env)->DeleteGlobalRef(env, sensCtrlClass); -} -//---------------------------------------------------------------------- -JavaVM* GetJavaVM() -{ - return javaVM; -} -//---------------------------------------------------------------------- - -typedef struct -{ - char sensor[50]; - u16 sensorAndroidType; - u8 isAttached; - - GF_Thread *trd; - u8 stop; - - JNIEnv* env; - jclass sensCtrlClass; - jmethodID cid; - jobject sensCtrlObj; - jmethodID startSensor; - jmethodID stopSensor; -} MPEGVSensorContext; - -#define MPEGVSCTX MPEGVSensorContext *rc = (MPEGVSensorContext *)dr->udta - -void unloadSensorController(MPEGVSensorContext *rc) -{ - if ( rc->isAttached ) - { - (*rc->env)->PopLocalFrame(rc->env, NULL); - (*GetJavaVM())->DetachCurrentThread(GetJavaVM()); - rc->isAttached = 0; - } - - rc->env = NULL; -} - -void loadSensorControler(MPEGVSensorContext *rc) -{ - JNIEnv* env = NULL; - jint res = 0; - - // Here we can be in a thread - - res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2); - if ( res == JNI_EDETACHED ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The current thread is not attached to the VM, assuming native thread\n")); - if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Attach current thread failed: %d\n", res)); - return; - } - rc->isAttached = 1; - (*env)->PushLocalFrame(env, 2); - } - else - if ( res == JNI_EVERSION ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The specified version is not supported\n")); - return; - } - - rc->env = env; - rc->sensCtrlClass = sensCtrlClass; - rc->cid = cid; - rc->startSensor = startSensor; - rc->stopSensor = stopSensor; - - // Create the sensor object in the thread - rc->sensCtrlObj = (*rc->env)->NewObject(rc->env, rc->sensCtrlClass, rc->cid); - if (rc->sensCtrlObj == 0) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Cannot create MPEGVSensor object\n")); - return; - } -} - -Bool MPEGVS_RegisterDevice(struct __input_device *dr, const char *urn, GF_BitStream *dsi, void (*AddField)(struct __input_device *_this, u32 fieldType, const char *name)) -{ - MPEGVSCTX; - - //"MPEG-V:siv:OrientationSensorType" - - if ( strnicmp(urn, "MPEG-V", 6) ) - return 0; - - if ( strlen(urn) <= 6 ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] No sensor type specified\n")); - return 0; - } - - if ( strnicmp(urn+6, ":siv:", 5) ) - { - GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] Not valid sensor type specified\n")); - return 0; - } - - strcpy(rc->sensor, urn+11); - - if ( !strcmp(rc->sensor, "OrientationSensorType") ) - { - AddField(dr, GF_SG_VRML_SFVEC3F, "Orientation"); - - rc->sensorAndroidType = 3; - - AddField(dr, GF_SG_VRML_SFVEC3F, "pos"); - - return 1; - } - else - { - GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V_IN] Unsupported sensor type: %s\n", rc->sensor)); - return 0; - } -} - -u32 MPEGVS_OnData(struct __input_device * dr, const char* data) -{ - GF_BitStream *bs; - char *buf; - u32 buf_size; - float x, y, z; - - bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); - - sscanf(data, "%f;%f;%f;", &x, &y, &z); - - gf_bs_write_int(bs, 1, 1); - gf_bs_write_float(bs, x); - gf_bs_write_float(bs, y); - gf_bs_write_float(bs, z); - - gf_bs_align(bs); - gf_bs_get_content(bs, &buf, &buf_size); - gf_bs_del(bs); - - dr->DispatchFrame(dr, (u8*)buf, buf_size); - gf_free(buf); - - return GF_OK; -} - -JNIEXPORT void Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data) -{ - jboolean isCopy; - const char * cData = (*env)->GetStringUTFChars(env, data, &isCopy); - - MPEGVS_OnData((struct __input_device *)ptr, cData); - - (*env)->ReleaseStringUTFChars(env, data, cData); -} - -u32 ThreadRun(void* param) -{ - struct __input_device * dr = (struct __input_device *)param; - MPEGVSCTX; - - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Start: %d\n", gf_th_id())); - - loadSensorControler(rc); - - if (!rc->env || !rc->sensCtrlObj) - return; - - (*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->startSensor, (s32)dr, rc->sensorAndroidType); - - while (!rc->stop) - gf_sleep(10); - - GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Stop: %d\n", gf_th_id())); - - if (!rc->env) - return; - - if ( rc->sensCtrlObj ) - { - (*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->stopSensor); - - (*rc->env)->DeleteLocalRef( rc->env, rc->sensCtrlObj ); - } - - unloadSensorController(rc); -} - -void MPEGVS_Start(struct __input_device * dr) -{ - MPEGVSCTX; - - rc->trd = gf_th_new("MPEG-V_IN"); - gf_th_run(rc->trd, ThreadRun, dr); -} - -void MPEGVS_Stop(struct __input_device * dr) -{ - MPEGVSCTX; - - if ( rc->trd ) - { - rc->stop = 1; - while ( gf_th_status(rc->trd) == GF_THREAD_STATUS_RUN ) - gf_sleep(5); - - gf_th_del(rc->trd); - rc->trd = NULL; - rc->stop = 0; - } -} - -GF_InputSensorDevice* NewMPEGVSInputSesor() -{ - MPEGVSensorContext* ctx = NULL; - GF_InputSensorDevice* driv = NULL; - - driv = (GF_InputSensorDevice *) gf_malloc(sizeof(GF_InputSensorDevice)); - memset(driv, 0, sizeof(GF_InputSensorDevice)); - GF_REGISTER_MODULE_INTERFACE(driv, GF_INPUT_DEVICE_INTERFACE, "MPEG-V Sensors Input Module", "gpac distribution"); - - driv->RegisterDevice = MPEGVS_RegisterDevice; - driv->Start = MPEGVS_Start; - driv->Stop = MPEGVS_Stop; - - ctx = (MPEGVSensorContext*) gf_malloc (sizeof(MPEGVSensorContext)); - memset(ctx, 0, sizeof(MPEGVSensorContext)); - - driv->udta = (void*)ctx; - - return driv; -} - -void DeleteMPEGVSInputSensor(GF_InputSensorDevice* dev) -{ - MPEGVS_Stop(dev); - gf_free(dev->udta); - gf_free(dev); -} - -/*interface query*/ -GF_EXPORT -const u32 *QueryInterfaces() -{ - static u32 si [] = { - GF_INPUT_DEVICE_INTERFACE, - 0 - }; - return si; -} - -/*interface create*/ -GF_EXPORT -GF_BaseInterface *LoadInterface(u32 InterfaceType) -{ - if (InterfaceType == GF_INPUT_DEVICE_INTERFACE) return (GF_BaseInterface *) NewMPEGVSInputSesor(); - return NULL; -} - -/*interface destroy*/ -GF_EXPORT -void ShutdownInterface(GF_BaseInterface *ifce) -{ - switch (ifce->InterfaceType) { - case GF_INPUT_DEVICE_INTERFACE: - DeleteMPEGVSInputSensor((GF_InputSensorDevice *)ifce); - break; - } -} - +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- + * All rights reserved + * + * This file is part of GPAC / MPEG-V Input sensor for android + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include + +/*driver interfaces*/ + +#include +#include + +#include + +#include +#include + +#include + +#define LOG_TAG "MPEG-V_IN" +#ifdef ANDROID +# define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +# define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +#else +# define QUOTEME_(x) #x +# define QUOTEME(x) QUOTEME_(x) +# define LOGI(...) fprintf(stderr, "I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__) +# define LOGE(...) fprintf(stderr, "E/" LOG_TAG "(" ")" __VA_ARGS__) +#endif + +JNIEXPORT void JNICALL Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data); + +static JavaVM* javaVM = 0; +static jclass sensCtrlClass; +static jmethodID cid; +static jmethodID startSensor; +static jmethodID stopSensor; + +//---------------------------------------------------------------------- +jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = 0; + javaVM = vm; + + if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) + return -1; + + // Get the class and its methods in the main env + + // Get the CameraController class + // This is just a local refenrece. Cannot be used in the other JNI calls. + sensCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/MPEGVSensor"); + if (sensCtrlClass == 0) + { + LOGE("[MPEG-V_IN] Class MPEGVSensor not found\n"); + return -1; + } + + // Get Global Reference to be able to use the class + sensCtrlClass = (*env)->NewGlobalRef(env, sensCtrlClass); + if ( sensCtrlClass == 0 ) + { + LOGE("[MPEG-V_IN] Caanot create Global Reference\n"); + return -1; + } + + // Get the method ID for the CameraController constructor. + cid = (*env)->GetMethodID(env, sensCtrlClass, "", "()V"); + if (cid == 0) + { + LOGE("[MPEG-V_IN] MPEGVSensor Constructor not found\n"); + return -1; + } + + // Get startCamera() method from class CameraController + startSensor = (*env)->GetMethodID(env, sensCtrlClass, "startSensor", "(II)V"); + if (startSensor == 0) + { + LOGE("[MPEG-V_IN] Function startSensor not found\n"); + return -1; + } + + stopSensor = (*env)->GetMethodID(env, sensCtrlClass, "stopSensor", "()V"); + if (stopSensor == 0) + { + LOGE("[MPEG-V_IN] Function stopSensor not found\n"); + return -1; + } + + return JNI_VERSION_1_2; +} + +void JNI_OnUnload(JavaVM *vm, void *reserved) +{ + JNIEnv* env = 0; + + if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK ) + return; + + (*env)->DeleteGlobalRef(env, sensCtrlClass); +} +//---------------------------------------------------------------------- +JavaVM* GetJavaVM() +{ + return javaVM; +} +//---------------------------------------------------------------------- + +typedef struct +{ + char sensor[50]; + u16 sensorAndroidType; + u8 isAttached; + + GF_Thread *trd; + u8 stop; + + JNIEnv* env; + jclass sensCtrlClass; + jmethodID cid; + jobject sensCtrlObj; + jmethodID startSensor; + jmethodID stopSensor; +} MPEGVSensorContext; + +#define MPEGVSCTX MPEGVSensorContext *rc = (MPEGVSensorContext *)dr->udta + +void unloadSensorController(MPEGVSensorContext *rc) +{ + if ( rc->isAttached ) + { + (*rc->env)->PopLocalFrame(rc->env, NULL); + (*GetJavaVM())->DetachCurrentThread(GetJavaVM()); + rc->isAttached = 0; + } + + rc->env = NULL; +} + +void loadSensorControler(MPEGVSensorContext *rc) +{ + JNIEnv* env = NULL; + jint res = 0; + + // Here we can be in a thread + + res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2); + if ( res == JNI_EDETACHED ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The current thread is not attached to the VM, assuming native thread\n")); + if ( res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL) ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Attach current thread failed: %d\n", res)); + return; + } + rc->isAttached = 1; + (*env)->PushLocalFrame(env, 2); + } + else + if ( res == JNI_EVERSION ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The specified version is not supported\n")); + return; + } + + rc->env = env; + rc->sensCtrlClass = sensCtrlClass; + rc->cid = cid; + rc->startSensor = startSensor; + rc->stopSensor = stopSensor; + + // Create the sensor object in the thread + rc->sensCtrlObj = (*rc->env)->NewObject(rc->env, rc->sensCtrlClass, rc->cid); + if (rc->sensCtrlObj == 0) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Cannot create MPEGVSensor object\n")); + return; + } +} + +Bool MPEGVS_RegisterDevice(struct __input_device *dr, const char *urn, GF_BitStream *dsi, void (*AddField)(struct __input_device *_this, u32 fieldType, const char *name)) +{ + MPEGVSCTX; + + //"MPEG-V:siv:OrientationSensorType" + + if ( strnicmp(urn, "MPEG-V", 6) ) + return 0; + + if ( strlen(urn) <= 6 ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] No sensor type specified\n")); + return 0; + } + + if ( strnicmp(urn+6, ":siv:", 5) ) + { + GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] Not valid sensor type specified\n")); + return 0; + } + + strcpy(rc->sensor, urn+11); + + if ( !strcmp(rc->sensor, "OrientationSensorType") ) + { + AddField(dr, GF_SG_VRML_SFVEC3F, "Orientation"); + + rc->sensorAndroidType = 3; + + AddField(dr, GF_SG_VRML_SFVEC3F, "pos"); + + return 1; + } + else + { + GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V_IN] Unsupported sensor type: %s\n", rc->sensor)); + return 0; + } +} + +u32 MPEGVS_OnData(struct __input_device * dr, const char* data) +{ + GF_BitStream *bs; + char *buf; + u32 buf_size; + float x, y, z; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + + sscanf(data, "%f;%f;%f;", &x, &y, &z); + + gf_bs_write_int(bs, 1, 1); + gf_bs_write_float(bs, x); + gf_bs_write_float(bs, y); + gf_bs_write_float(bs, z); + + gf_bs_align(bs); + gf_bs_get_content(bs, &buf, &buf_size); + gf_bs_del(bs); + + dr->DispatchFrame(dr, (u8*)buf, buf_size); + gf_free(buf); + + return GF_OK; +} + +JNIEXPORT void Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data) +{ + jboolean isCopy; + const char * cData = (*env)->GetStringUTFChars(env, data, &isCopy); + + MPEGVS_OnData((struct __input_device *)ptr, cData); + + (*env)->ReleaseStringUTFChars(env, data, cData); +} + +u32 ThreadRun(void* param) +{ + struct __input_device * dr = (struct __input_device *)param; + MPEGVSCTX; + + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Start: %d\n", gf_th_id())); + + loadSensorControler(rc); + + if (!rc->env || !rc->sensCtrlObj) + return; + + (*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->startSensor, (s32)dr, rc->sensorAndroidType); + + while (!rc->stop) + gf_sleep(10); + + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Stop: %d\n", gf_th_id())); + + if (!rc->env) + return; + + if ( rc->sensCtrlObj ) + { + (*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->stopSensor); + + (*rc->env)->DeleteLocalRef( rc->env, rc->sensCtrlObj ); + } + + unloadSensorController(rc); +} + +void MPEGVS_Start(struct __input_device * dr) +{ + MPEGVSCTX; + + rc->trd = gf_th_new("MPEG-V_IN"); + gf_th_run(rc->trd, ThreadRun, dr); +} + +void MPEGVS_Stop(struct __input_device * dr) +{ + MPEGVSCTX; + + if ( rc->trd ) + { + rc->stop = 1; + while ( gf_th_status(rc->trd) == GF_THREAD_STATUS_RUN ) + gf_sleep(5); + + gf_th_del(rc->trd); + rc->trd = NULL; + rc->stop = 0; + } +} + +GF_InputSensorDevice* NewMPEGVSInputSesor() +{ + MPEGVSensorContext* ctx = NULL; + GF_InputSensorDevice* driv = NULL; + + driv = (GF_InputSensorDevice *) gf_malloc(sizeof(GF_InputSensorDevice)); + memset(driv, 0, sizeof(GF_InputSensorDevice)); + GF_REGISTER_MODULE_INTERFACE(driv, GF_INPUT_DEVICE_INTERFACE, "MPEG-V Sensors Input Module", "gpac distribution"); + + driv->RegisterDevice = MPEGVS_RegisterDevice; + driv->Start = MPEGVS_Start; + driv->Stop = MPEGVS_Stop; + + ctx = (MPEGVSensorContext*) gf_malloc (sizeof(MPEGVSensorContext)); + memset(ctx, 0, sizeof(MPEGVSensorContext)); + + driv->udta = (void*)ctx; + + return driv; +} + +void DeleteMPEGVSInputSensor(GF_InputSensorDevice* dev) +{ + MPEGVS_Stop(dev); + gf_free(dev->udta); + gf_free(dev); +} + +/*interface query*/ +GF_EXPORT +const u32 *QueryInterfaces() +{ + static u32 si [] = { + GF_INPUT_DEVICE_INTERFACE, + 0 + }; + return si; +} + +/*interface create*/ +GF_EXPORT +GF_BaseInterface *LoadInterface(u32 InterfaceType) +{ + if (InterfaceType == GF_INPUT_DEVICE_INTERFACE) return (GF_BaseInterface *) NewMPEGVSInputSesor(); + return NULL; +} + +/*interface destroy*/ +GF_EXPORT +void ShutdownInterface(GF_BaseInterface *ifce) +{ + switch (ifce->InterfaceType) { + case GF_INPUT_DEVICE_INTERFACE: + DeleteMPEGVSInputSensor((GF_InputSensorDevice *)ifce); + break; + } +} + diff --git a/modules/droid_out/droid_vout-bitmap.c b/modules/droid_out/droid_vout-bitmap.c index c177145..c47afcb 100644 --- a/modules/droid_out/droid_vout-bitmap.c +++ b/modules/droid_out/droid_vout-bitmap.c @@ -1,12 +1,10 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- * All rights reserved * - * Created by NGO Van Luyen, Ivica ARSOV / ARTEMIS / Telecom SudParis /Institut TELECOM on Oct, 2010 - * * This file is part of GPAC / Wrapper * * GPAC is free software; you can redistribute it and/or modify diff --git a/modules/droid_out/droid_vout.c b/modules/droid_out/droid_vout.c index f63e9ab..a32d45d 100644 --- a/modules/droid_out/droid_vout.c +++ b/modules/droid_out/droid_vout.c @@ -1,12 +1,10 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Ivica Arsov, Jean Le Feuvre + * Copyright (c) Mines-Telecom 2009- * All rights reserved * - * Created by NGO Van Luyen, Ivica ARSOV / ARTEMIS / Telecom SudParis /Institut TELECOM on Oct, 2010 - * * This file is part of GPAC / Wrapper * * GPAC is free software; you can redistribute it and/or modify diff --git a/modules/dummy_in/Makefile b/modules/dummy_in/Makefile index 2576530..d7a7ad2 100644 --- a/modules/dummy_in/Makefile +++ b/modules/dummy_in/Makefile @@ -34,11 +34,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_dummy_in-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/dummy_in/dummy_in.c b/modules/dummy_in/dummy_in.c index 6dc2605..7146d25 100644 --- a/modules/dummy_in/dummy_in.c +++ b/modules/dummy_in/dummy_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Dummy input module @@ -42,6 +43,7 @@ typedef struct GF_ClientService *service; char *url; u32 oti; + Bool is_views_url; GF_List *channels; /*file downloader*/ @@ -123,6 +125,9 @@ Bool DC_CanHandleURL(GF_InputService *plug, const char *url) if (cgi_par) cgi_par[0] = '?'; if (ok) return 1; } + /*views:// internal URI*/ + if (!strnicmp(url, "views://", 8)) + return 1; if (!strncmp(url, "\\\\", 2)) return 0; @@ -226,6 +231,13 @@ GF_Err DC_ConnectService(GF_InputService *plug, GF_ClientService *serv, const ch } read->service = serv; + if (!strnicmp(url, "views://", 8)) { + read->is_views_url = 1; + gf_term_on_connect(serv, NULL, GF_OK); + read->is_service_connected = 1; + return GF_OK; + } + if (ext) { char *cgi_par = NULL; ext += 1; @@ -319,6 +331,11 @@ static GF_Descriptor *DC_GetServiceDesc(GF_InputService *plug, u32 expect_type, iod->visual_profileAndLevel = 0xFE; iod->objectDescriptorID = 1; + if (read->is_views_url) { + iod->URLString = gf_strdup(read->url); + return (GF_Descriptor *)iod; + } + esd = gf_odf_desc_esd_new(0); esd->slConfig->timestampResolution = 1000; esd->slConfig->useTimestampsFlag = 1; diff --git a/modules/dx_hw/Makefile b/modules/dx_hw/Makefile index 1425f82..5676c66 100644 --- a/modules/dx_hw/Makefile +++ b/modules/dx_hw/Makefile @@ -41,10 +41,6 @@ $(LIB): $(OBJS) windres "$(SRC_PATH)/modules/dx_hw/dx_hw.rc" dw_hw.o $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) dw_hw.o $(LDFLAGS_DX) -L../../bin/gcc -lgpac $(EXTRALIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) ifeq ($(CONFIG_WIN32),yes) diff --git a/modules/dx_hw/copy_pixels.c b/modules/dx_hw/copy_pixels.c index 9e39708..24ee473 100644 --- a/modules/dx_hw/copy_pixels.c +++ b/modules/dx_hw/copy_pixels.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / 2D rendering module diff --git a/modules/dx_hw/dx_2d.c b/modules/dx_hw/dx_2d.c index 6a21969..199d91d 100644 --- a/modules/dx_hw/dx_2d.c +++ b/modules/dx_hw/dx_2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module @@ -402,7 +403,13 @@ static GF_Err DD_BlitSurface(DDContext *dd, DDSurface *src, GF_Window *src_wnd, if (src->is_yuv && dd->force_video_mem_for_yuv && dd->systems_memory) return GF_IO_ERR; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DX Out] Hardware blit src w=%d,h=%d to dst w=%d,h=%d - result: %08x\n", src_w, src_h, dst_w, dst_h, hr)); +#ifndef GPAC_DISABLE_LOG + if (hr) { + GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DX Out] Failed blitting %s %s memory: error %08x\n", src->is_yuv ? "YUV" : "RGB", dd->systems_memory ? "systems" : "hardware", hr)); + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DX Out] %s blit %s memory %dx%d -> %dx%d\n", src->is_yuv ? "YUV" : "RGB", dd->systems_memory ? "systems" : "hardware", src_w, src_h, dst_w, dst_h)); + } +#endif return FAILED(hr) ? GF_IO_ERR : GF_OK; } @@ -439,7 +446,8 @@ static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 p ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; - if (dr->hw_caps & GF_VIDEO_HW_HAS_YUV_OVERLAY) + + if (!dd->offscreen_yuv_to_rgb && (dr->hw_caps & GF_VIDEO_HW_HAS_YUV_OVERLAY)) ddsd.ddsCaps.dwCaps |= DDSCAPS_OVERLAY; ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; @@ -451,7 +459,21 @@ static DDSurface *DD_GetSurface(GF_VideoOutput *dr, u32 width, u32 height, u32 p if (FAILED(hr) ) { if (!check_caps) return NULL; - /*try withou overlay cap*/ + /*try without offscreen yuv->rgbcap*/ + if (dd->offscreen_yuv_to_rgb) { + dd->offscreen_yuv_to_rgb = 0; + if (dr->hw_caps & GF_VIDEO_HW_HAS_YUV_OVERLAY) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_OVERLAY; + hr = dd->pDD->lpVtbl->CreateSurface(dd->pDD, &ddsd, &yuvp->pSurface, NULL); + if( FAILED(hr) ) { + return NULL; + } + } else { + return NULL; + } + } + + /*try without overlay cap*/ if (dr->hw_caps & GF_VIDEO_HW_HAS_YUV_OVERLAY) { dr->hw_caps &= ~GF_VIDEO_HW_HAS_YUV_OVERLAY; ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; @@ -784,7 +806,7 @@ rem_fmt: gf_modules_set_option((GF_BaseInterface *)dr, "Video", "EnableOffscreenYUV", "yes"); } if (opt && strcmp(opt, "yes")) dr->hw_caps &= ~GF_VIDEO_HW_HAS_YUV; - + else dd->offscreen_yuv_to_rgb = 1; /*get YUV overlay key*/ opt = gf_modules_get_option((GF_BaseInterface *)dr, "Video", "OverlayColorKey"); diff --git a/modules/dx_hw/dx_audio.c b/modules/dx_hw/dx_audio.c index 3c5f02f..a6d48c4 100644 --- a/modules/dx_hw/dx_audio.c +++ b/modules/dx_hw/dx_audio.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module @@ -328,14 +329,14 @@ void DS_WriteAudio(GF_AudioOutput *dr) /*wait for end of current play buffer*/ if (ctx->pOutput->lpVtbl->GetCurrentPosition(ctx->pOutput, &in_play, NULL) != DS_OK ) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] error getting sound buffer poitions\n")); + GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] error getting sound buffer positions\n")); return; } in_play = (in_play / ctx->buffer_size); retry = 6; while (retry) { if (ctx->pOutput->lpVtbl->GetCurrentPosition(ctx->pOutput, &cur_play, NULL) != DS_OK ) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] error getting sound buffer poitions\n")); + GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[DirectSound] error getting sound buffer positions\n")); return; } cur_play = (cur_play / ctx->buffer_size); diff --git a/modules/dx_hw/dx_hw.h b/modules/dx_hw/dx_hw.h index 12bb34a..bd59d81 100644 --- a/modules/dx_hw/dx_hw.h +++ b/modules/dx_hw/dx_hw.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module @@ -125,6 +126,7 @@ typedef struct Bool fullscreen; Bool systems_memory; Bool force_alpha; + Bool offscreen_yuv_to_rgb; u32 width, height; u32 fs_width, fs_height; diff --git a/modules/dx_hw/dx_video.c b/modules/dx_hw/dx_video.c index 7f9b190..e84cf14 100644 --- a/modules/dx_hw/dx_video.c +++ b/modules/dx_hw/dx_video.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module @@ -542,6 +543,11 @@ static GF_Err DD_SetFullScreen(GF_VideoOutput *dr, Bool bOn, u32 *outWidth, u32 if (!dd->fullscreen && (dd->os_hwnd==dd->fs_hwnd)) { SetWindowPos(dd->os_hwnd, NULL, 0, 0, dd->store_width+dd->off_w, dd->store_height+dd->off_h, SWP_NOZORDER | SWP_NOMOVE | SWP_ASYNCWINDOWPOS); } + /*first time FS, store*/ + if (!dd->store_width) { + dd->store_width = dd->width; + dd->store_height = dd->height; + } e = InitDirectDraw(dr, dd->store_width, dd->store_height); } diff --git a/modules/dx_hw/dx_window.c b/modules/dx_hw/dx_window.c index 3939c4c..9f5b678 100644 --- a/modules/dx_hw/dx_window.c +++ b/modules/dx_hw/dx_window.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module diff --git a/modules/epoc_hw/epoc_aout.cpp b/modules/epoc_hw/epoc_aout.cpp index 4aef8dc..42adc86 100644 --- a/modules/epoc_hw/epoc_aout.cpp +++ b/modules/epoc_hw/epoc_aout.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / wave audio render module diff --git a/modules/epoc_hw/epoc_codec.cpp b/modules/epoc_hw/epoc_codec.cpp index ca4b6ef..4171ad4 100644 --- a/modules/epoc_hw/epoc_codec.cpp +++ b/modules/epoc_hw/epoc_codec.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / AAC reader module diff --git a/modules/epoc_hw/epoc_vout.cpp b/modules/epoc_hw/epoc_vout.cpp index 5e748a8..b6afacb 100644 --- a/modules/epoc_hw/epoc_vout.cpp +++ b/modules/epoc_hw/epoc_vout.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / EPOC video output module diff --git a/modules/ffmpeg_in/Makefile b/modules/ffmpeg_in/Makefile index bcff766..10dc9e0 100644 --- a/modules/ffmpeg_in/Makefile +++ b/modules/ffmpeg_in/Makefile @@ -62,11 +62,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/gcc $(LOCAL_LIB) $(LINKLIBS) $(EXTRALIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ffmpeg_in/ffmpeg_decode.c b/modules/ffmpeg_in/ffmpeg_decode.c index db7d65e..592cee2 100644 --- a/modules/ffmpeg_in/ffmpeg_decode.c +++ b/modules/ffmpeg_in/ffmpeg_decode.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / FFMPEG module diff --git a/modules/ffmpeg_in/ffmpeg_demux.c b/modules/ffmpeg_in/ffmpeg_demux.c index 0f8ee50..77a9efe 100644 --- a/modules/ffmpeg_in/ffmpeg_demux.c +++ b/modules/ffmpeg_in/ffmpeg_demux.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / FFMPEG module @@ -260,6 +261,7 @@ static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url) /*note we forbid ffmpeg to handle files we support*/ if (!strcmp(szExt, "mp4") || !strcmp(szExt, "mpg4") || !strcmp(szExt, "m4a") || !strcmp(szExt, "m21") || !strcmp(szExt, "m4v") || !strcmp(szExt, "m4a") + || !strcmp(szExt, "m4s") || !strcmp(szExt, "3gs") || !strcmp(szExt, "3gp") || !strcmp(szExt, "3gpp") || !strcmp(szExt, "3gp2") || !strcmp(szExt, "3g2") || !strcmp(szExt, "mp3") || !strcmp(szExt, "ac3") @@ -698,6 +700,7 @@ static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv, ffd->seekable = (av_seek_frame(ffd->ctx, -1, 0, AVSEEK_FLAG_BACKWARD)<0) ? 0 : 1; if (!ffd->seekable) { av_close_input_file(ffd->ctx); + ffd->ctx = NULL; open_file(&ffd->ctx, szName, av_in); av_find_stream_info(ffd->ctx); } diff --git a/modules/ffmpeg_in/ffmpeg_in.h b/modules/ffmpeg_in/ffmpeg_in.h index 4b2bdf5..5f90198 100644 --- a/modules/ffmpeg_in/ffmpeg_in.h +++ b/modules/ffmpeg_in/ffmpeg_in.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MP4 reader module diff --git a/modules/ffmpeg_in/ffmpeg_load.c b/modules/ffmpeg_in/ffmpeg_load.c index 2724f14..4c97498 100644 --- a/modules/ffmpeg_in/ffmpeg_load.c +++ b/modules/ffmpeg_in/ffmpeg_load.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / FFMPEG module diff --git a/modules/freenect/Makefile b/modules/freenect/Makefile index cb4810c..16cef5d 100644 --- a/modules/freenect/Makefile +++ b/modules/freenect/Makefile @@ -39,11 +39,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CXX) -w $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKLIBS) - -%.o: %.cpp - $(CXX) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/freenect/freenect.c b/modules/freenect/freenect.c index d7dcdd3..b8cfee7 100644 --- a/modules/freenect/freenect.c +++ b/modules/freenect/freenect.c @@ -38,8 +38,8 @@ #include -#ifndef FREENECT_RESOLUTION_MEDIUM -#define FREENECT_MINIMAL +#ifndef FREENECT_RESOLUTION_HIGH +//#define FREENECT_MINIMAL #endif diff --git a/modules/ft_font/Makefile b/modules/ft_font/Makefile index 1b5fa80..ff52be0 100644 --- a/modules/ft_font/Makefile +++ b/modules/ft_font/Makefile @@ -42,10 +42,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ft_font/ft_font.c b/modules/ft_font/ft_font.c index 22f8036..e90f5cf 100644 --- a/modules/ft_font/ft_font.c +++ b/modules/ft_font/ft_font.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / FreeType font engine module diff --git a/modules/ft_font/ft_font.h b/modules/ft_font/ft_font.h index 689976e..4fc6531 100644 --- a/modules/ft_font/ft_font.h +++ b/modules/ft_font/ft_font.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / FreeType font engine module diff --git a/modules/gapi/gapi.cpp b/modules/gapi/gapi.cpp index 37231fd..7230a09 100644 --- a/modules/gapi/gapi.cpp +++ b/modules/gapi/gapi.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GAPI WinCE-iPaq video render module diff --git a/modules/gapi/gapi.h b/modules/gapi/gapi.h index 13bd738..565ccac 100644 --- a/modules/gapi/gapi.h +++ b/modules/gapi/gapi.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module diff --git a/modules/gdip_raster/gdip_font.cpp b/modules/gdip_raster/gdip_font.cpp index 343a748..f795efd 100644 --- a/modules/gdip_raster/gdip_font.cpp +++ b/modules/gdip_raster/gdip_font.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GDIplus rasterizer module diff --git a/modules/gdip_raster/gdip_grad.cpp b/modules/gdip_raster/gdip_grad.cpp index 7ab52fe..f20425d 100644 --- a/modules/gdip_raster/gdip_grad.cpp +++ b/modules/gdip_raster/gdip_grad.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GDIplus rasterizer module diff --git a/modules/gdip_raster/gdip_priv.h b/modules/gdip_raster/gdip_priv.h index c144cd7..e2817f0 100644 --- a/modules/gdip_raster/gdip_priv.h +++ b/modules/gdip_raster/gdip_priv.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GDIplus rasterizer module diff --git a/modules/gdip_raster/gdip_rend.cpp b/modules/gdip_raster/gdip_rend.cpp index a481f8d..7a49653 100644 --- a/modules/gdip_raster/gdip_rend.cpp +++ b/modules/gdip_raster/gdip_rend.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GDIplus rasterizer module diff --git a/modules/gdip_raster/gdip_texture.cpp b/modules/gdip_raster/gdip_texture.cpp index e0d4b62..58a81a4 100644 --- a/modules/gdip_raster/gdip_texture.cpp +++ b/modules/gdip_raster/gdip_texture.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / GDIplus rasterizer module diff --git a/modules/gpac_js/Makefile b/modules/gpac_js/Makefile index c9258f8..73ba409 100644 --- a/modules/gpac_js/Makefile +++ b/modules/gpac_js/Makefile @@ -48,11 +48,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/gpac_js/gpac_js.c b/modules/gpac_js/gpac_js.c index cca3b5b..2144838 100644 --- a/modules/gpac_js/gpac_js.c +++ b/modules/gpac_js/gpac_js.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2007-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2007-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -60,9 +60,9 @@ typedef struct u32 nb_loaded; GF_Terminal *term; - JSClass gpacClass; - JSClass gpacEvtClass; - JSClass anyClass; + GF_JSClass gpacClass; + GF_JSClass gpacEvtClass; + GF_JSClass anyClass; jsval evt_fun; GF_TermEventFilter evt_filter; @@ -83,8 +83,8 @@ static GF_Terminal *gpac_get_term(JSContext *c, JSObject *obj) return ext ? ext->term : NULL; } -static JSBool gpac_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( gpac_getProperty) + const char *res; char *prop_name; GF_Terminal *term = gpac_get_term(c, obj); @@ -201,8 +201,8 @@ static JSBool gpac_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js SMJS_FREE(c, prop_name); return JS_TRUE; } -static JSBool gpac_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( gpac_setProperty) + char *prop_name, *prop_val; GF_Terminal *term = gpac_get_term(c, obj); if (!term) return JS_FALSE; @@ -662,8 +662,8 @@ static JSBool SMJS_FUNCTION(gpac_migrate_url) return JS_TRUE; } -static JSBool gpacevt_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( gpacevt_getProperty) + GF_GPACJSExt *gjs = SMJS_GET_PRIVATE(c, obj); GF_Event *evt = gjs->evt; if (!evt) return 0; @@ -834,7 +834,7 @@ static JSBool SMJS_FUNCTION(gpac_get_scene) if (!scene) return JS_TRUE; - scene_obj = JS_NewObject(c, &gjs->anyClass, 0, 0); + scene_obj = JS_NewObject(c, &gjs->anyClass._class, 0, 0); SMJS_SET_PRIVATE(c, scene_obj, scene); gf_sg_get_scene_size_info(scene->graph, &w, &h); JS_DefineProperty(c, scene_obj, "width", INT_TO_JSVAL(w), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -910,8 +910,8 @@ static void gjs_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext JS_SETUP_CLASS(gjs->gpacClass, "GPAC", JSCLASS_HAS_PRIVATE, gpac_getProperty, gpac_setProperty, JS_FinalizeStub); if (!gjs->gpac_obj) { - JS_InitClass(c, global, 0, &gjs->gpacClass, 0, 0, gpacClassProps, gpacClassFuncs, 0, 0); - gjs->gpac_obj = JS_DefineObject(c, global, "gpac", &gjs->gpacClass, 0, 0); + GF_JS_InitClass(c, global, 0, &gjs->gpacClass, 0, 0, gpacClassProps, gpacClassFuncs, 0, 0); + gjs->gpac_obj = JS_DefineObject(c, global, "gpac", &gjs->gpacClass._class, 0, 0); if (scene->script_action) { if (scene->script_action(scene->script_action_cbck, GF_JSAPI_OP_GET_TERM, scene->RootNode, &par)) { @@ -925,8 +925,8 @@ static void gjs_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext if (!gjs->evt_obj) { JS_SETUP_CLASS(gjs->gpacEvtClass, "GPACEVT", JSCLASS_HAS_PRIVATE, gpacevt_getProperty, JS_PropertyStub_forSetter, JS_FinalizeStub); - JS_InitClass(c, global, 0, &gjs->gpacEvtClass, 0, 0, gpacEvtClassProps, gpacEvtClassFuncs, 0, 0); - gjs->evt_obj = JS_DefineObject(c, global, "gpacevt", &gjs->gpacEvtClass, 0, 0); + GF_JS_InitClass(c, global, 0, &gjs->gpacEvtClass, 0, 0, gpacEvtClassProps, gpacEvtClassFuncs, 0, 0); + gjs->evt_obj = JS_DefineObject(c, global, "gpacevt", &gjs->gpacEvtClass._class, 0, 0); #define DECLARE_GPAC_CONST(name) \ JS_DefineProperty(c, global, #name, INT_TO_JSVAL(name), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -959,7 +959,7 @@ static void gjs_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext DECLARE_GPAC_CONST(GF_NAVIGATE_TYPE_3D); JS_SETUP_CLASS(gjs->anyClass, "GPACOBJECT", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub); - JS_InitClass(c, global, 0, &gjs->anyClass, 0, 0, 0, 0, 0, 0); + GF_JS_InitClass(c, global, 0, &gjs->anyClass, 0, 0, 0, 0, 0, 0); gjs->evt_fun = JSVAL_NULL; } diff --git a/modules/hyb_in/Makefile b/modules/hyb_in/Makefile index bdc9531..244305f 100644 --- a/modules/hyb_in/Makefile +++ b/modules/hyb_in/Makefile @@ -31,11 +31,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_hyb_in-static.$(DYN_LIB_SUFFIX) $(OBJS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/img_in/Makefile b/modules/img_in/Makefile index f085be1..6c89a0e 100644 --- a/modules/img_in/Makefile +++ b/modules/img_in/Makefile @@ -63,11 +63,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_img_in-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/img_in/bmp_dec.c b/modules/img_in/bmp_dec.c index 6dc1e21..5918c8c 100644 --- a/modules/img_in/bmp_dec.c +++ b/modules/img_in/bmp_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module diff --git a/modules/img_in/img_dec.c b/modules/img_in/img_dec.c index 69c5ddc..88189df 100644 --- a/modules/img_in/img_dec.c +++ b/modules/img_in/img_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module diff --git a/modules/img_in/img_in.c b/modules/img_in/img_in.c index 7ce064f..9abe261 100644 --- a/modules/img_in/img_in.c +++ b/modules/img_in/img_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module @@ -69,10 +70,12 @@ GF_ESD *IMG_GetESD(IMGLoader *read) if (read->img_type == IMG_BMP) esd->decoderConfig->objectTypeIndication = GPAC_BMP_OTI; else { - u8 OTI; + u8 OTI=0; u32 mtype, w, h; GF_BitStream *bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ); +#ifndef GPAC_DISABLE_AV_PARSERS gf_img_parse(bs, &OTI, &mtype, &w, &h, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength); +#endif gf_bs_del(bs); if (!OTI) { diff --git a/modules/img_in/img_in.h b/modules/img_in/img_in.h index 6f870ca..3374235 100644 --- a/modules/img_in/img_in.h +++ b/modules/img_in/img_in.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module diff --git a/modules/img_in/jp2_dec.c b/modules/img_in/jp2_dec.c index e3a13c9..5d46c2d 100644 --- a/modules/img_in/jp2_dec.c +++ b/modules/img_in/jp2_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * -* Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module diff --git a/modules/img_in/jpeg_dec.c b/modules/img_in/jpeg_dec.c index 3676913..7f12799 100644 --- a/modules/img_in/jpeg_dec.c +++ b/modules/img_in/jpeg_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module @@ -101,6 +102,7 @@ static GF_Err JPEG_ProcessData(GF_MediaDecoder *ifcg, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { +#ifndef GPAC_DISABLE_AV_PARSERS GF_Err e; JPEGCTX(); @@ -111,6 +113,9 @@ static GF_Err JPEG_ProcessData(GF_MediaDecoder *ifcg, } ctx->out_size = *outBufferLength; return e; +#else + return GF_NOT_SUPPORTED; +#endif //GPAC_DISABLE_AV_PARSERS } static const char *JPEG_GetCodecName(GF_BaseDecoder *dec) diff --git a/modules/img_in/png_dec.c b/modules/img_in/png_dec.c index 4f5a1a4..55d4583 100644 --- a/modules/img_in/png_dec.c +++ b/modules/img_in/png_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / image format module @@ -115,6 +116,7 @@ static GF_Err PNG_ProcessData(GF_MediaDecoder *ifcg, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { +#ifndef GPAC_DISABLE_AV_PARSERS GF_Err e; PNGCTX(); @@ -137,6 +139,9 @@ static GF_Err PNG_ProcessData(GF_MediaDecoder *ifcg, } ctx->out_size = *outBufferLength; return e; +#else + return GF_NOT_SUPPORTED; +#endif //GPAC_DISABLE_AV_PARSERS } static const char *PNG_GetCodecName(GF_BaseDecoder *dec) diff --git a/modules/ismacryp/Makefile b/modules/ismacryp/Makefile index d83c52d..0b49d73 100644 --- a/modules/ismacryp/Makefile +++ b/modules/ismacryp/Makefile @@ -33,11 +33,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_ismacryp-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ismacryp/ismacryp.c b/modules/ismacryp/ismacryp.c index db86ff8..8d05469 100644 --- a/modules/ismacryp/ismacryp.c +++ b/modules/ismacryp/ismacryp.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / LASeR decoder module diff --git a/modules/isom_in/Makefile b/modules/isom_in/Makefile index df8f591..fab86c7 100644 --- a/modules/isom_in/Makefile +++ b/modules/isom_in/Makefile @@ -34,11 +34,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_isom_in-static.$(DYN_LIB_SUFFIX) $(OBJS) -L../../bin/gcc -lgpac_static $(EXTRALIBS) endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/isom_in/cache.c b/modules/isom_in/cache.c index 714ca8e..e640fc1 100644 --- a/modules/isom_in/cache.c +++ b/modules/isom_in/cache.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MP4 cache module diff --git a/modules/isom_in/isom_in.h b/modules/isom_in/isom_in.h index 2ef8bbd..18945a1 100644 --- a/modules/isom_in/isom_in.h +++ b/modules/isom_in/isom_in.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MP4 reader module @@ -73,8 +74,7 @@ typedef struct ISOMReader *owner; u64 duration; - Bool wait_for_segment_switch; - + Bool wait_for_segment_switch, needs_codec_update; /*current sample*/ GF_ISOSample *sample; GF_SLHeader current_slh; diff --git a/modules/isom_in/load.c b/modules/isom_in/load.c index 3bc504d..02405ab 100644 --- a/modules/isom_in/load.c +++ b/modules/isom_in/load.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MP4 reader module diff --git a/modules/isom_in/read.c b/modules/isom_in/read.c index e844cb2..24c688a 100644 --- a/modules/isom_in/read.c +++ b/modules/isom_in/read.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IsoMedia reader module diff --git a/modules/isom_in/read_ch.c b/modules/isom_in/read_ch.c index 3011102..744a69d 100644 --- a/modules/isom_in/read_ch.c +++ b/modules/isom_in/read_ch.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MP4 reader module @@ -66,7 +67,7 @@ static void check_segment_switch(ISOMReader *read) } /*close current segment*/ gf_isom_release_segment(read->mov, 1); - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Done playing segment - querying new one\n")); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Done playing segment - querying new one\n")); /*update current fragment if any*/ param.command_type = GF_NET_SERVICE_QUERY_NEXT; @@ -74,27 +75,38 @@ static void check_segment_switch(ISOMReader *read) if (param.url_query.discontinuity_type==2) gf_isom_reset_fragment_info(read->mov); + if (param.url_query.next_url_init_or_switch_segment) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Switching between files - opening new init segment %s\n", param.url_query.next_url_init_or_switch_segment)); + if (read->mov) gf_isom_close(read->mov); + e = gf_isom_open_progressive(param.url_query.next_url_init_or_switch_segment, param.url_query.switch_start_range, param.url_query.switch_end_range, &read->mov, &read->missing_bytes); + } + e = gf_isom_open_segment(read->mov, param.url_query.next_url, param.url_query.start_range, param.url_query.end_range); #ifndef GPAC_DISABLE_LOG if (e<0) { - GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[IsoMedia] Error opening new segment %s: %s\n", param.url_query.next_url, gf_error_to_string(e) )); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[IsoMedia] Error opening new segment %s: %s\n", param.url_query.next_url, gf_error_to_string(e) )); } else if (param.url_query.end_range) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Playing new range in %s: "LLU"-"LLU"\n", param.url_query.next_url, param.url_query.start_range, param.url_query.end_range )); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Playing new range in %s: "LLU"-"LLU"\n", param.url_query.next_url, param.url_query.start_range, param.url_query.end_range )); } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] playing new segment %s\n", param.url_query.next_url)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] playing new segment %s\n", param.url_query.next_url)); } #endif for (i=0; ichannels, i); ch->wait_for_segment_switch = 0; - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[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) )); + 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; + /*we changed our moov structure, sample_num now starts from 0*/ + ch->sample_num = 0; + } } } else { /*consider we are done*/ read->frag_type = 2; - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] No more segments - done playing file\n")); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] No more segments - done playing file\n")); } gf_mx_v(read->segment_mutex); } @@ -262,17 +274,17 @@ fetch_next: if (ch->owner->frag_type==1) { if (!ch->wait_for_segment_switch) { ch->wait_for_segment_switch = 1; - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Track #%d end of segment reached - waiting for sample %d - current count %d\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track) )); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Track #%d end of segment reached - waiting for sample %d - current count %d\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track) )); } /*if sample cannot be found and file is fragmented, rewind sample*/ if (ch->sample_num) ch->sample_num--; ch->last_state = GF_OK; } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Track #%d end of stream reached\n", ch->track)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Track #%d end of stream reached\n", ch->track)); ch->last_state = GF_EOS; } } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] Track #%d fail to fetch sample %d / %d: %s\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track), gf_error_to_string(gf_isom_last_error(ch->owner->mov)) )); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Track #%d fail to fetch sample %d / %d: %s\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track), gf_error_to_string(gf_isom_last_error(ch->owner->mov)) )); } if (ch->wait_for_segment_switch) check_segment_switch(ch->owner); @@ -294,7 +306,7 @@ fetch_next: ch->current_slh.randomAccessPointFlag = ch->sample->IsRAP; if (ch->end && (ch->end < ch->sample->DTS + ch->sample->CTS_Offset)) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] End of Channel "LLD" (CTS "LLD")\n", ch->end, ch->sample->DTS + ch->sample->CTS_Offset)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] End of Channel "LLD" (CTS "LLD")\n", ch->end, ch->sample->DTS + ch->sample->CTS_Offset)); ch->last_state = GF_EOS; } @@ -313,6 +325,62 @@ 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; isequenceParameterSets); 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; ipictureParameterSets); 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; isequenceParameterSets); 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; ipictureParameterSets); 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) diff --git a/modules/jack/Makefile b/modules/jack/Makefile index 0037f67..0902d64 100644 --- a/modules/jack/Makefile +++ b/modules/jack/Makefile @@ -27,11 +27,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -L/usr/lib -ljack - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/jack/jack.c b/modules/jack/jack.c index 3eb5891..106aa80 100644 --- a/modules/jack/jack.c +++ b/modules/jack/jack.c @@ -1,8 +1,6 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 - * All rights reserved * Copyright (c) Pierre Souchay 2008 * History: * diff --git a/modules/laser_dec/Makefile b/modules/laser_dec/Makefile index f457f73..e695b19 100644 --- a/modules/laser_dec/Makefile +++ b/modules/laser_dec/Makefile @@ -35,10 +35,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/laser_dec/laser_dec.c b/modules/laser_dec/laser_dec.c index 5469af5..c73cdfa 100644 --- a/modules/laser_dec/laser_dec.c +++ b/modules/laser_dec/laser_dec.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / LASeR decoder module diff --git a/modules/libplayer/Makefile b/modules/libplayer/Makefile index 3266c90..916e644 100644 --- a/modules/libplayer/Makefile +++ b/modules/libplayer/Makefile @@ -28,10 +28,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -lplayer -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/libplayer/libplayer.c b/modules/libplayer/libplayer.c index 57dda91..1ab9b67 100644 --- a/modules/libplayer/libplayer.c +++ b/modules/libplayer/libplayer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Dummy input module @@ -347,9 +348,9 @@ GF_Err LIBPLAYER_CloseService(GF_InputService *plug) // only disconnect if if (read->player_type == PLAYER_FILE) { player_playback_stop(read->player); - printf("[LibPlayerIN]player_playback_stop for instance %d\n", read->player_id); + fprintf(stderr, "[LibPlayerIN]player_playback_stop for instance %d\n", read->player_id); player_uninit(read->player); - printf("[LibPlayerIN]player_uninit for instance %d\n", read->player_id); + fprintf(stderr, "[LibPlayerIN]player_uninit for instance %d\n", read->player_id); read->player = NULL; libplayer_id--; @@ -538,7 +539,7 @@ static GF_Err LIBPLAYER_Control(GF_PrivateMediaDecoder *dec, Bool mute, GF_Windo //! unfortunately, saving data would not be a good solution for Mosaic Mode in ESG Application since the position changes everytime user //! uses the navigation button //~ if (read->player_id == 1 && save_data_instance1 == 1) { - //~ printf("in here for save data instance\n"); + //~ fprintf(stderr, "in here for save data instance\n"); //~ player_video_io_windows_set(read->player, &in_instance1, &out_instance1); //~ //~ return GF_OK; @@ -551,8 +552,8 @@ static GF_Err LIBPLAYER_Control(GF_PrivateMediaDecoder *dec, Bool mute, GF_Windo if((width != read->width) || (height != read->height)) { - printf("in here for video size changed\t"); - printf("width %d read->width %d height %d read->height %d\n", width, read->width, height, read->height); + fprintf(stderr, "in here for video size changed\t"); + fprintf(stderr, "width %d read->width %d height %d read->height %d\n", width, read->width, height, read->height); GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[LibPlayerDEC] video size changed to width %d - height %d\n", width, height)); if (width && height) { read->width = width; diff --git a/modules/modules_export.cpp b/modules/modules_export.cpp index 4b050bf..08d077e 100644 --- a/modules/modules_export.cpp +++ b/modules/modules_export.cpp @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 - * Copyright (c) ENST 2008 - + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC diff --git a/modules/mp3_in/Makefile b/modules/mp3_in/Makefile index d77f42f..5dbdf5e 100644 --- a/modules/mp3_in/Makefile +++ b/modules/mp3_in/Makefile @@ -50,10 +50,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/mp3_in/mad_dec.c b/modules/mp3_in/mad_dec.c index 2ccd017..dff0711 100644 --- a/modules/mp3_in/mad_dec.c +++ b/modules/mp3_in/mad_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / codec pack module diff --git a/modules/mp3_in/mp3_in.c b/modules/mp3_in/mp3_in.c index 6ae3255..4269701 100644 --- a/modules/mp3_in/mp3_in.c +++ b/modules/mp3_in/mp3_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / MP3 reader module diff --git a/modules/mpd_in/Makefile b/modules/mpd_in/Makefile index 22bb385..af0718d 100644 --- a/modules/mpd_in/Makefile +++ b/modules/mpd_in/Makefile @@ -31,11 +31,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_mpegts_in-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/mpd_in/mpd_in.c b/modules/mpd_in/mpd_in.c index 4dcc2ac..7c4bbe9 100644 --- a/modules/mpd_in/mpd_in.c +++ b/modules/mpd_in/mpd_in.c @@ -24,526 +24,79 @@ */ #include -#include -#include -#include -#include -#include -#include -#include - -/*set to 1 if you want MPD to use SegmentTemplate if possible instead of SegmentList*/ -#define M3U8_TO_MPD_USE_TEMPLATE 0 - -/*! - * All the possible Mime-types for MPD files - */ -static const char * MPD_MIME_TYPES[] = { "application/dash+xml", "video/vnd.3gpp.mpd", "audio/vnd.3gpp.mpd", NULL }; - -/*! - * All the possible Mime-types for M3U8 files - */ -static const char * M3U8_MIME_TYPES[] = { "video/x-mpegurl", "audio/x-mpegurl", "application/x-mpegurl", "application/vnd.apple.mpegurl", NULL}; -typedef enum { - MPD_STATE_STOPPED = 0, - MPD_STATE_RUNNING, - MPD_STATE_CONNECTING, -} MPD_STATE; +#ifndef GPAC_DISABLE_DASH_CLIENT -GF_Err MPD_downloadWithRetry( GF_ClientService * service, GF_DownloadSession ** sess, const char *url, gf_dm_user_io user_io, void *usr_cbk, u64 start_range, u64 end_range, Bool persistent); +#include +#include -typedef struct -{ - char *cache; - char *url; - u64 start_range, end_range; -} segment_cache_entry; -/*this structure Group is the implementation of the adaptationSet element of the MPD.*/ -typedef struct __mpd_group +typedef struct __mpd_module { - /*pointer to adaptation set*/ - GF_MPD_AdaptationSet *adaptation_set; - /*pointer to active period*/ - GF_MPD_Period *period; - - /*active representation index in adaptation_set->representations*/ - u32 active_rep_index; - - Bool selected; - Bool done; - Bool force_switch_bandwidth, min_bandwidth_selected; - u32 nb_bw_check; - u32 active_bitrate, max_bitrate, min_bitrate; - - u32 nb_segments_in_rep; - Double segment_duration; - - /*local file playback, do not delete them*/ - Bool local_files; - /*next segment to download for this group*/ - u32 download_segment_index; - - /*next file (cached) to delete at next GF_NET_SERVICE_QUERY_NEXT for this group*/ - char * urlToDeleteNext; - volatile u32 max_cached_segments, nb_cached_segments; - segment_cache_entry *cached; - - GF_DownloadSession *segment_dnload; - const char *segment_local_url; - /*usually 0-0 (no range) but can be non-zero when playing local MPD/DASH sessions*/ - u64 local_url_start_range, local_url_end_range; - - u32 nb_segments_done; - - Bool segment_must_be_streamed; - - /* Service really managing the segments */ - GF_InputService *input_module; - char *service_mime; - Bool service_connected, service_descriptor_fetched; - - struct __mpd_module *mpd_in; - - u32 force_representation_idx_plus_one; - - Bool force_segment_switch; - - /*set when switching segment, indicates the current downloaded segment duration*/ - u64 current_downloaded_segment_duration; -} GF_MPD_Group; - -typedef struct __mpd_module { /* GPAC Service object (i.e. how this module is seen by the terminal)*/ GF_ClientService *service; - /* URL to which this service is connected - Used to detect when audio service connection request is made on the same URL as video */ - char *url; + GF_InputService *plug; + + GF_DashClient *dash; /*interface to mpd parser*/ - GF_FileDownload getter; - - u32 option_max_cached; - u32 auto_switch_count; - Bool keep_files, disable_switching; - - /* MPD downloader*/ - GF_DownloadSession *mpd_dnload; - /* MPD */ - GF_MPD *mpd; - /* number of time the MPD has been reloaded and last update time*/ - u32 reload_count, last_update_time; - /*signature of last MPD*/ - u8 lastMPDSignature[20]; - /*mime used by M3U8 server*/ - char *mimeTypeForM3U8Segments; - - /* active period in MPD (only one currently supported) */ - u32 active_period_index; - u32 request_period_switch; - - u64 start_time_in_active_period; - - /*list of groups in the active period*/ - GF_List *groups; - /*group 0 if present, NULL otherwise*/ - GF_MPD_Group *group_zero_selected; - - /*Main MPD Thread handling segment downloads and MPD/M3U8 update*/ - GF_Thread *mpd_thread; - /*mutex for group->cache file name access and MPD update*/ - GF_Mutex *dl_mutex; - - /* 0 not started, 1 download in progress */ - MPD_STATE mpd_is_running; - Bool mpd_stop_request; - Bool in_period_setup; - - /* TODO - handle playback status for SPEED/SEEK through SIDX */ - Double playback_speed, playback_start_range, previous_start_range; - Double start_range_in_segment_at_next_period; + GF_DASHFileIO dash_io; + + Bool connection_ack_sent; Bool in_seek; + Double previous_start_range; } GF_MPD_In; -void MPD_ResetGroups(GF_MPD_In *mpdin); -GF_Err MPD_SetupPeriod(GF_MPD_In *mpdin); - - - -static const char *MPD_GetMimeType(GF_MPD_SubRepresentation *subrep, GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set) +typedef struct { - if (subrep && subrep->mime_type) return subrep->mime_type; - if (rep && rep->mime_type) return rep->mime_type; - if (set && set->mime_type) return set->mime_type; - return NULL; -} + GF_InputService *segment_ifce; + Bool service_connected; + Bool service_descriptor_fetched; +} GF_MPDGroup; +const char * MPD_MPD_DESC = "MPEG-DASH Streaming"; +const char * MPD_MPD_EXT = "3gm mpd"; +const char * MPD_M3U8_DESC = "Apple HLS Streaming"; +const char * MPD_M3U8_EXT = "m3u8 m3u"; -static Bool MPD_CheckRootType(const char *local_url) +static u32 MPD_RegisterMimeTypes(const GF_InputService *plug) { - if (local_url) { - char *rtype = gf_xml_get_root_type(local_url, NULL); - if (rtype) { - Bool handled = 0; - if (!strcmp(rtype, "MPD")) { - handled = 1; - } - gf_free(rtype); - return handled; - } - } - return 0; + u32 i, c; + for (i = 0 ; GF_DASH_MPD_MIME_TYPES[i]; i++) + gf_term_register_mime_type (plug, GF_DASH_MPD_MIME_TYPES[i], MPD_MPD_EXT, MPD_MPD_DESC); + c = i; + for (i = 0 ; GF_DASH_M3U8_MIME_TYPES[i]; i++) + gf_term_register_mime_type(plug, GF_DASH_M3U8_MIME_TYPES[i], MPD_M3U8_EXT, MPD_M3U8_DESC); + return c+i; } -/** - * NET IO for MPD, we don't need this anymore since mime-type can be given by session - */ -void MPD_NetIO_Segment(void *cbk, GF_NETIO_Parameter *param) +Bool MPD_CanHandleURL(GF_InputService *plug, const char *url) { - GF_Err e; - u32 download_rate; - GF_MPD_Group *group= (GF_MPD_Group*) cbk; - - /*handle service message*/ - gf_term_download_update_stats(group->segment_dnload); - if (group->done) { - gf_dm_sess_abort(group->segment_dnload); - return; - } - - if ((param->msg_type == GF_NETIO_PARSE_HEADER) && !strcmp(param->name, "Content-Type")) { - if (!group->service_mime) { - group->service_mime = gf_strdup(param->value); - } else if (stricmp(group->service_mime, param->value)) { - GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); - if (! MPD_GetMimeType(NULL, rep, group->adaptation_set) ) rep->mime_type = gf_strdup(param->value); - rep->disabled = 1; - GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, - ("[MPD_IN] Disabling representation since mime does not match: expected %s, but had %s for %s!\n", group->service_mime, param->value, gf_dm_sess_get_resource_name(group->segment_dnload))); - group->force_switch_bandwidth = 1; - gf_dm_sess_abort(group->segment_dnload); - return; - } - } - - e = param->error; - if (param->msg_type == GF_NETIO_PARSE_REPLY) { - if (! gf_dm_sess_can_be_cached_on_disk(group->segment_dnload)) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, - ("[MPD_IN] Segment %s cannot be cached on disk, will use direct streaming\n", gf_dm_sess_get_resource_name(group->segment_dnload))); - group->segment_must_be_streamed = 1; - gf_dm_sess_abort(group->segment_dnload); - } else { - group->segment_must_be_streamed = 0; - } - } - else if ((param->msg_type == GF_NETIO_DATA_EXCHANGE) || (param->msg_type == GF_NETIO_DATA_TRANSFERED)) { - if (!group->mpd_in->disable_switching && (gf_dm_sess_get_stats(group->segment_dnload, NULL, NULL, NULL, NULL, &download_rate, NULL) == GF_OK)) { - if (download_rate) { - download_rate *= 8; - if (download_ratemin_bitrate) group->min_bitrate = download_rate; - if (download_rate>group->max_bitrate) group->max_bitrate = download_rate; - - if (download_rate && (download_rate < group->active_bitrate)) { - u32 set_idx = gf_list_find(group->period->adaptation_sets, group->adaptation_set)+1; - group->nb_bw_check ++; - if (group->min_bandwidth_selected) { - fprintf(stdout, "Downloading from set #%d at rate %d kbps but media bitrate is %d kbps - no lower bitrate available ...\n", set_idx, download_rate/1024, group->active_bitrate/1024); - } else if (group->nb_bw_check>2) { - fprintf(stdout, "Downloading from set #%d at rate %d kbps but media bitrate is %d kbps - switching\n", set_idx, download_rate/1024, group->active_bitrate/1024); - group->force_switch_bandwidth = 1; - gf_dm_sess_abort(group->segment_dnload); - } else { - fprintf(stdout, "Downloading from set #%ds at rate %d kbps but media bitrate is %d kbps\n", set_idx, download_rate/1024, group->active_bitrate/1024); - } - } else { - group->nb_bw_check = 0; - } - } - } - } -} - -/*! - * Returns true if given mime type is a MPD file - * \param mime the mime-type to check - * \return true if mime-type if MPD-OK - */ -static Bool MPD_is_MPD_mime(const char * mime) { u32 i; - if (!mime) - return 0; - for (i = 0 ; MPD_MIME_TYPES[i] ; i++){ - if ( !stricmp(mime, MPD_MIME_TYPES[i])) + char *sExt; + if (!plug || !url) + return 0; + sExt = strrchr(url, '.'); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Can Handle URL request from terminal for %s\n", url)); + for (i = 0 ; GF_DASH_MPD_MIME_TYPES[i]; i++) { + if (gf_term_check_extension(plug, GF_DASH_MPD_MIME_TYPES[i], MPD_MPD_EXT, MPD_MPD_DESC, sExt)) return 1; } - return 0; -} - -/*! - * Returns true if mime type is an M3U8 mime-type - * \param mime The mime-type to check - * \return true if mime-type is OK for M3U8 - */ -static Bool MPD_isM3U8_mime(const char * mime) { - u32 i; - if (!mime) - return 0; - for (i = 0 ; M3U8_MIME_TYPES[i] ; i++) { - if ( !stricmp(mime, M3U8_MIME_TYPES[i])) + for (i = 0 ; GF_DASH_M3U8_MIME_TYPES[i]; i++) { + if (gf_term_check_extension(plug, GF_DASH_M3U8_MIME_TYPES[i], MPD_M3U8_EXT, MPD_M3U8_DESC, sExt)) return 1; } - return 0; -} - -void MPD_NetIO(void *cbk, GF_NETIO_Parameter *param) -{ - GF_Err e; - GF_MPD_In *mpdin = (GF_MPD_In*) cbk; - - /*handle service message*/ - gf_term_download_update_stats(mpdin->mpd_dnload); - e = param->error; -} - -static GF_Err MPD_UpdatePlaylist(GF_MPD_In *mpdin) -{ - GF_Err e; - u32 group_idx, rep_idx, i, j; - Bool seg_found = 0; - GF_DOMParser *mpd_parser; - GF_MPD_Period *period, *new_period; - const char *local_url; - char mime[128]; - char * purl; - Bool is_m3u8 = 0; - u32 oldUpdateTime = mpdin->mpd->minimum_update_period; - /*reset update time - if any error occurs, we will no longer attempt to update the MPD*/ - mpdin->mpd->minimum_update_period = 0; - - if (!mpdin->mpd_dnload) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing downloader\n")); - return GF_BAD_PARAM; - } - - local_url = gf_dm_sess_get_cache_name(mpdin->mpd_dnload); - if (!local_url) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: wrong cache file %s\n", local_url)); - return GF_IO_ERR; - } - gf_delete_file(local_url); - purl = gf_strdup(gf_dm_sess_get_resource_name(mpdin->mpd_dnload)); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Updating Playlist %s...\n", purl)); - /*use non-persistent connection for MPD*/ - e = MPD_downloadWithRetry(mpdin->service, &(mpdin->mpd_dnload), purl, MPD_NetIO, mpdin, 0, 0, 0); - if (e!=GF_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: download problem %s for MPD file\n", gf_error_to_string(e))); - gf_free(purl); - return gf_dm_sess_last_error(mpdin->mpd_dnload); - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Playlist %s updated with success\n", purl)); - } - strncpy(mime, gf_dm_sess_mime_type(mpdin->mpd_dnload), sizeof(mime)); - strlwr(mime); - - /*in case the session has been restarted, local_url may have been destroyed - get it back*/ - local_url = gf_dm_sess_get_cache_name(mpdin->mpd_dnload); - - /* Some servers, for instance http://tv.freebox.fr, serve m3u8 as text/plain */ - if (MPD_isM3U8_mime(mime) || strstr(purl, ".m3u8")) { - gf_m3u8_to_mpd(local_url, purl, NULL, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments, 0, M3U8_TO_MPD_USE_TEMPLATE, &mpdin->getter); - } else if (!MPD_is_MPD_mime(mime)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] mime '%s' should be m3u8 or mpd\n", mime)); - gf_term_on_connect(mpdin->service, NULL, GF_BAD_PARAM); - gf_free(purl); - purl = NULL; - return GF_BAD_PARAM; - } - - gf_free(purl); - purl = NULL; - - if (!MPD_CheckRootType(local_url)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: MPD file type is not correct %s\n", local_url)); - return GF_NON_COMPLIANT_BITSTREAM; - } - { - u8 signature[sizeof(mpdin->lastMPDSignature)]; - if (gf_sha1_file( local_url, signature)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] : cannot SHA1 file %s\n", local_url)); - } else { - if (! memcmp( signature, mpdin->lastMPDSignature, sizeof(mpdin->lastMPDSignature))) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] MPD file did not change\n")); - mpdin->reload_count++; - mpdin->mpd->minimum_update_period = oldUpdateTime; - } else { - GF_MPD *new_mpd; - mpdin->reload_count = 0; - memccpy(mpdin->lastMPDSignature, signature, sizeof(char), sizeof(mpdin->lastMPDSignature)); - - /* It means we have to reparse the file ... */ - /* parse the MPD */ - mpd_parser = gf_xml_dom_new(); - e = gf_xml_dom_parse(mpd_parser, local_url, NULL, NULL); - if (e != GF_OK) { - gf_xml_dom_del(mpd_parser); - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: error in XML parsing %s\n", gf_error_to_string(e))); - return GF_NON_COMPLIANT_BITSTREAM; - } - new_mpd = gf_mpd_new(); - e = gf_mpd_init_from_dom(gf_xml_dom_get_root(mpd_parser), new_mpd, purl); - gf_xml_dom_del(mpd_parser); - if (e) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: error in MPD creation %s\n", gf_error_to_string(e))); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - - /*TODO - check periods are the same*/ - period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index); - new_period = gf_list_get(new_mpd->periods, mpdin->active_period_index); - if (!new_period) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing period\n")); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - - if (gf_list_count(period->adaptation_sets) != gf_list_count(new_period->adaptation_sets)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing AdaptationSet\n")); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - - for (group_idx=0; group_idxgroups); group_idx++) { - GF_MPD_AdaptationSet *set, *new_set; - GF_MPD_Group *group = gf_list_get(mpdin->groups, group_idx); - if (!group->selected) continue; - set = group->adaptation_set; - new_set = gf_list_get(new_period->adaptation_sets, group_idx); - - if (gf_list_count(new_set->representations) != gf_list_count(group->adaptation_set->representations)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: missing representation in adaptation set\n")); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - - /*get all representations in both periods*/ - for (rep_idx = 0; rep_idx adaptation_set->representations); rep_idx++) { - GF_List *segments, *new_segments; - GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_idx); - GF_MPD_Representation *new_rep = gf_list_get(new_set->representations, rep_idx); - - if (rep->segment_base || group->adaptation_set->segment_base || period->segment_base) { - if (!new_rep->segment_base && !new_set->segment_base && !new_period->segment_base) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: representation does not use segment base as previous version\n")); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - /*what else should we check ??*/ - - /*OK, this rep is fine*/ - } - - else if (rep->segment_template || group->adaptation_set->segment_template || period->segment_template) { - if (!new_rep->segment_template && !new_set->segment_template && !new_period->segment_template) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: representation does not use segment template as previous version\n")); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - /*what else should we check ??*/ - - /*OK, this rep is fine*/ - } - - else { - /*we're using segment list*/ - assert(rep->segment_list || group->adaptation_set->segment_list || period->segment_list); - - if (!new_rep->segment_list && !new_set->segment_list && !new_period->segment_list) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot update playlist: representation does not use segment list as previous version\n")); - gf_mpd_del(new_mpd); - return GF_NON_COMPLIANT_BITSTREAM; - } - /*what else should we check ??*/ - - /*get the segment list*/ - segments = new_segments = NULL; - if (period->segment_list && period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs; - if (set->segment_list && set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs; - if (rep->segment_list && rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs; - - if (new_period->segment_list && new_period->segment_list->segment_URLs) new_segments = new_period->segment_list->segment_URLs; - if (new_set->segment_list && new_set->segment_list->segment_URLs) new_segments = new_set->segment_list->segment_URLs; - if (new_rep->segment_list && new_rep->segment_list->segment_URLs) new_segments = new_rep->segment_list->segment_URLs; - - - for (i=0; imedia && new_seg->media && !strcmp(seg->media, new_seg->media)) { - found=1; - break; - } - if (seg->media_range && new_seg->media_range && (seg->media_range->start_range==new_seg->media_range->start_range) && (seg->media_range->end_range==new_seg->media_range->end_range) ) { - found=1; - break; - } - } - /*this is a new segment, merge it: we remove from new list and push to old one, before doing a final swap - this ensures that indexing in the segment_list is still correct after merging*/ - if (!found) { - gf_list_rem(new_segments, i); - i--; - gf_list_add(segments, new_seg); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Representation #%d: Adding new segment %s\n", rep_idx+1, new_seg->media)); - } - } - - /*what else should we check ?*/ - - /*swap segment list content*/ - gf_list_swap(new_segments, segments); - - /*current representation is the active one in the group - update the number of segments*/ - if (group->active_rep_index==rep_idx) { - group->nb_segments_in_rep = gf_list_count(new_segments); - } - } - - /*copy over a few things from former rep*/ - new_rep->disabled = rep->disabled; - if (!new_rep->mime_type) { - new_rep->mime_type = rep->mime_type; - rep->mime_type = NULL; - } - } - /*update group/period to new period*/ - j = gf_list_find(group->period->adaptation_sets, group->adaptation_set); - group->adaptation_set = gf_list_get(new_period->adaptation_sets, j); - group->period = new_period; - } - /*swap representations - we don't need to update download_segment_index as it still points to the right entry in the merged list*/ - if (mpdin->mpd) - gf_mpd_del(mpdin->mpd); - mpdin->mpd = new_mpd; - mpdin->last_update_time = gf_sys_clock(); - } - } - } - return GF_OK; + return gf_dash_check_mpd_root_type(url); } static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param) { u32 i; - GF_MPD_Group *group = NULL; GF_MPD_In *mpdin = (GF_MPD_In *) ifce->proxy_udta; if (!param || !ifce || !ifce->proxy_udta) return GF_BAD_PARAM; + /*gets byte range of init segment (for local validation)*/ if (param->command_type==GF_NET_SERVICE_QUERY_INIT_RANGE) { param->url_query.next_url = NULL; param->url_query.start_range = 0; @@ -551,23 +104,28 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param) mpdin->in_seek = 0; - for (i=0; igroups); i++) { - group = gf_list_get(mpdin->groups, i); - if (group->selected && (group->input_module == ifce)) break; - group = NULL; - } - - if (!group) return GF_SERVICE_ERROR; - param->url_query.start_range = group->local_url_start_range; - param->url_query.end_range = group->local_url_end_range; - - return GF_OK; + for (i=0; idash); i++) { + GF_MPDGroup *group; + if (!gf_dash_is_group_selected(mpdin->dash, i)) continue; + group = gf_dash_get_group_udta(mpdin->dash, i); + if (group->segment_ifce == ifce) { + gf_dash_group_get_segment_init_url(mpdin->dash, i, ¶m->url_query.start_range, ¶m->url_query.end_range); + return GF_OK; + } + } + return GF_SERVICE_ERROR; } + + /*gets URL and byte range of next segment - if needed, adds butstream switching segment info*/ if (param->command_type==GF_NET_SERVICE_QUERY_NEXT) { + Bool group_done; + u32 nb_segments_cached; + u32 group_idx=0; + GF_MPDGroup *group=NULL; + const char *src_url; Bool discard_first_cache_entry = 1; u32 timer = gf_sys_clock(); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Service Query Next request from terminal\n")); - gf_mx_p(mpdin->dl_mutex); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Service Query Next request from input service %s\n", ifce->module_name)); param->url_query.discontinuity_type = 0; @@ -576,31 +134,35 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param) param->url_query.discontinuity_type = 2; discard_first_cache_entry = 0; } - - for (i=0; igroups); i++) { - group = gf_list_get(mpdin->groups, i); - if (group->selected && (group->input_module == ifce)) break; - group = NULL; - } + for (i=0; idash); i++) { + if (!gf_dash_is_group_selected(mpdin->dash, i)) continue; + group = gf_dash_get_group_udta(mpdin->dash, i); + if (group->segment_ifce == ifce) { + group_idx = i; + break; + } + group=NULL; + } if (!group) { - gf_mx_v(mpdin->dl_mutex); return GF_SERVICE_ERROR; } - group->force_segment_switch = 0; - /* Wait until no file is scheduled to be downloaded */ - while (mpdin->mpd_is_running && group->nb_cached_segments<2) { - gf_mx_v(mpdin->dl_mutex); - if (group->done) { - if (!mpdin->request_period_switch && (mpdin->active_period_index+1 < gf_list_count(mpdin->mpd->periods))) { + while (gf_dash_is_running(mpdin->dash) ) { + group_done=0; + nb_segments_cached = gf_dash_group_get_num_segments_ready(mpdin->dash, group_idx, &group_done); + if (nb_segments_cached>=2) + break; + + if (group_done) { + if (!gf_dash_get_period_switch_status(mpdin->dash) && !gf_dash_in_last_period(mpdin->dash) ) { GF_NetworkCommand com; memset(&com, 0, sizeof(GF_NetworkCommand)); com.command_type = GF_NET_BUFFER_QUERY; - while (mpdin->request_period_switch != 1) { + while (gf_dash_get_period_switch_status(mpdin->dash) != 1) { gf_term_on_command(mpdin->service, &com, GF_OK); if (!com.buffer.occupancy) { - mpdin->request_period_switch = 1; + gf_dash_request_period_switch(mpdin->dash); break; } gf_sleep(20); @@ -609,61 +171,49 @@ static GF_Err MPD_ClientQuery(GF_InputService *ifce, GF_NetworkCommand *param) return GF_EOS; } gf_sleep(16); - gf_mx_p(mpdin->dl_mutex); } - if (group->nb_cached_segments<2) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] No more file in cache, EOS\n")); - gf_mx_v(mpdin->dl_mutex); + + nb_segments_cached = gf_dash_group_get_num_segments_ready(mpdin->dash, group_idx, &group_done); + if (nb_segments_cached < 2) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[MPD_IN] No more file in cache, EOS\n")); return GF_EOS; } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Had to wait for %u ms for the only cache file to be downloaded\n", (gf_sys_clock() - timer))); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Had to wait for %u ms for the only cache file to be downloaded\n", (gf_sys_clock() - timer))); } if (discard_first_cache_entry) { - if (group->cached[0].cache) { - if (group->urlToDeleteNext) { - if (!group->local_files && !mpdin->keep_files) - gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext); - - gf_free( group->urlToDeleteNext); - group->urlToDeleteNext = NULL; - } - assert( group->cached[0].url ); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] deleting cache file %s : %s\n", group->cached[0].url, group->cached[0].cache)); - group->urlToDeleteNext = gf_strdup( group->cached[0].url ); - gf_free(group->cached[0].cache); - gf_free(group->cached[0].url); - group->cached[0].url = NULL; - group->cached[0].cache = NULL; - } - memmove(&group->cached[0], &group->cached[1], sizeof(segment_cache_entry)*(group->nb_cached_segments-1)); - memset(&(group->cached[group->nb_cached_segments-1]), 0, sizeof(segment_cache_entry)); - group->nb_cached_segments--; + gf_dash_group_discard_segment(mpdin->dash, group_idx); } - param->url_query.next_url = group->cached[0].cache; - param->url_query.start_range = group->cached[0].start_range; - param->url_query.end_range = group->cached[0].end_range; - gf_mx_v(mpdin->dl_mutex); + gf_dash_group_get_next_segment_location(mpdin->dash, group_idx, ¶m->url_query.next_url, ¶m->url_query.start_range, ¶m->url_query.end_range, + ¶m->url_query.next_url_init_or_switch_segment, ¶m->url_query.switch_start_range , ¶m->url_query.switch_end_range, + &src_url); + { u32 timer2 = gf_sys_clock() - timer ; if (timer2 > 1000) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] We were stuck waiting for download to end during too much time : %u ms !\n", timer2)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Waiting for download to end took a long time : %u ms\n", timer2)); } - if (group->cached[0].end_range) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching segment playback to \n\tURL: %s in %u ms\n\tMedia Range: "LLD"-"LLD"\n\tElements in cache: %u/%u\n", group->cached[0].url, timer2, group->cached[0].start_range, group->cached[0].end_range, group->nb_cached_segments, group->max_cached_segments)); + if (param->url_query.end_range) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[MPD_IN] Switching segment playback to %s (Media Range: "LLD"-"LLD")\n", src_url, param->url_query.start_range, param->url_query.end_range)); } else { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching segment playback to \n\tURL: %s in %u ms\n\tCache: %s\n\tElements in cache: %u/%u\n", group->cached[0].url, timer2, group->cached[0].cache, group->nb_cached_segments, group->max_cached_segments)); + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[MPD_IN] Switching segment playback to %s\n", src_url)); } + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[MPD_IN] segment start time %g sec\n", gf_dash_group_current_segment_start_time(mpdin->dash, group_idx) )); + + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Waited %d ms - Elements in cache: %u/%u\n\tCache file name %s\n", timer2, gf_dash_group_get_num_segments_ready(mpdin->dash, group_idx, &group_done), gf_dash_group_get_max_segments_in_cache(mpdin->dash, group_idx), param->url_query.next_url )); } - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Client Query request (%d) from terminal\n", param->command_type)); + return GF_OK; } + + return GF_OK; } -static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, GF_MPD_Group *group, const char *mime, const char *init_segment_name) +/*locates input service (demuxer) based on mime type or segment name*/ +static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, u32 group_index, const char *mime, const char *init_segment_name) { + GF_InputService *segment_ifce; u32 i; const char *sPlug; if (mime) { @@ -672,10 +222,14 @@ static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, GF_MPD_Group *group, const if (sPlug) sPlug = strrchr(sPlug, '"'); if (sPlug) { sPlug += 2; - group->input_module = (GF_InputService *) gf_modules_load_interface_by_name(mpdin->service->term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); - if (group->input_module) { - group->input_module->proxy_udta = mpdin; - group->input_module->query_proxy = MPD_ClientQuery; + segment_ifce = (GF_InputService *) gf_modules_load_interface_by_name(mpdin->service->term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); + if (segment_ifce) { + GF_MPDGroup *group; + GF_SAFEALLOC(group, GF_MPDGroup); + group->segment_ifce = segment_ifce; + group->segment_ifce->proxy_udta = mpdin; + group->segment_ifce->query_proxy = MPD_ClientQuery; + gf_dash_set_group_udta(mpdin->dash, group_index, group); return GF_OK; } } @@ -686,1216 +240,51 @@ static GF_Err MPD_LoadMediaService(GF_MPD_In *mpdin, GF_MPD_Group *group, const if (!ifce) continue; if (ifce->CanHandleURL && ifce->CanHandleURL(ifce, init_segment_name)) { - group->input_module = ifce; - group->input_module->proxy_udta = mpdin; - group->input_module->query_proxy = MPD_ClientQuery; - return GF_OK; - } - gf_modules_close_interface((GF_BaseInterface *) ifce); - } - } - - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error locating plugin for segment - mime type %s - name %s\n", mime, init_segment_name)); - return GF_CODEC_NOT_FOUND; -} - -/*! - * Download a file with possible retry if GF_IP_CONNECTION_FAILURE|GF_IP_NETWORK_FAILURE - * (I discovered that with my WIFI connection, I had many issues with BFM-TV downloads) - * Similar to gf_term_download_new() and gf_dm_sess_process(). - * Parameters are identical to the ones of gf_term_download_new. - * \see gf_term_download_new() - */ -GF_Err MPD_downloadWithRetry( GF_ClientService * service, GF_DownloadSession **sess, const char *url, gf_dm_user_io user_io, void *usr_cbk, u64 start_range, u64 end_range, Bool persistent) -{ - Bool had_sess = 0; - GF_Err e; - - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Downloading %s...\n", url)); - - if (! *sess) { - u32 flags = GF_NETIO_SESSION_NOT_THREADED; - if (persistent) flags |= GF_NETIO_SESSION_PERSISTENT; - *sess = gf_term_download_new(service, url, flags, user_io, usr_cbk); - if (!(*sess)){ - assert(0); - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Cannot try to download %s... OUT of memory ?\n", url)); - return GF_OUT_OF_MEM; - } - } else { - had_sess = 1; - e = gf_dm_sess_setup_from_url(*sess, url); - if (e) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Cannot resetup session for url %s: %s\n", url, gf_error_to_string(e) )); - return e; - } - - } - if (end_range) { - e = gf_dm_sess_set_range(*sess, start_range, end_range); - if (e) { - if (had_sess) { - gf_term_download_del(*sess); - *sess = NULL; - return MPD_downloadWithRetry(service, sess, url, user_io, usr_cbk, start_range, end_range, persistent); - } - - - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Cannot setup byte-range download for %s: %s\n", url, gf_error_to_string(e) )); - return e; - } - } - e = gf_dm_sess_process(*sess); - switch (e) { - case GF_IP_CONNECTION_FAILURE: - case GF_IP_NETWORK_FAILURE: - { - gf_term_download_del(*sess); - GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, - ("[MPD_IN] failed to download, retrying once with %s...\n", url)); - *sess = gf_term_download_new(service, url, GF_NETIO_SESSION_NOT_THREADED, user_io, usr_cbk); - if (!(*sess)){ - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Cannot retry to download %s... OUT of memory ?\n", url)); - return GF_OUT_OF_MEM; - } - e = gf_dm_sess_process(*sess); - if (e != GF_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, - ("[MPD_IN] two consecutive failures, aborting the download %s.\n", url)); - } - return e; - } - case GF_OK: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] OK, Download %s complete\n", url)); - return e; - default: - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] FAILED to download %s = %s...\n", url, gf_error_to_string(e))); - return e; - } -} - -static void MPD_GetTimelineDuration(GF_MPD_SegmentTimeline *timeline, u32 *nb_segments, Double *seg_duration) -{ - u32 i, count; - - *nb_segments = 0; - *seg_duration = 0; - count = gf_list_count(timeline->entries); - for (i=0; ientries, i); - *nb_segments += 1 + ent->repeat_count; - if (*seg_duration < ent->duration) *seg_duration = ent->duration; - } -} - -static void MPD_GetSegmentDuration(GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, GF_MPD *mpd, u32 *nb_segments, Double *seg_duration) -{ - Double mediaDuration; - u32 timescale; - u64 duration; - GF_MPD_SegmentTimeline *timeline = NULL; - *nb_segments = timescale = 0; - duration = 0; - - /*single segment*/ - if (rep->segment_base || set->segment_base || period->segment_base) { - return; - } - if (rep->segment_list || set->segment_list || period->segment_list) { - GF_List *segments = NULL; - if (period->segment_list) { - if (period->segment_list->duration) duration = period->segment_list->duration; - if (period->segment_list->timescale) timescale = period->segment_list->timescale; - if (period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs; - if (period->segment_list->segment_timeline) timeline = period->segment_list->segment_timeline; - } - if (set->segment_list) { - if (set->segment_list->duration) duration = set->segment_list->duration; - if (set->segment_list->timescale) timescale = set->segment_list->timescale; - if (set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs; - if (set->segment_list->segment_timeline) timeline = set->segment_list->segment_timeline; - } - if (rep->segment_list) { - if (rep->segment_list->duration) duration = rep->segment_list->duration; - if (rep->segment_list->timescale) timescale = rep->segment_list->timescale; - if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs; - if (rep->segment_list->segment_timeline) timeline = rep->segment_list->segment_timeline; - } - if (! timescale) timescale=1; - - if (timeline) { - MPD_GetTimelineDuration(timeline, nb_segments, seg_duration); - *seg_duration /= timescale; - } else { - if (segments) - *nb_segments = gf_list_count(segments); - *seg_duration = (Double) duration; - *seg_duration /= timescale; - } - return; - } - - if (period->segment_template) { - if (period->segment_template->duration) duration = period->segment_template->duration; - if (period->segment_template->timescale) timescale = period->segment_template->timescale; - if (period->segment_template->segment_timeline) timeline = period->segment_template->segment_timeline; - } - if (set->segment_template) { - if (set->segment_template->duration) duration = set->segment_template->duration; - if (set->segment_template->timescale) timescale = set->segment_template->timescale; - if (set->segment_template->segment_timeline) timeline = set->segment_template->segment_timeline; - } - if (rep->segment_template) { - if (rep->segment_template->duration) duration = rep->segment_template->duration; - if (rep->segment_template->timescale) timescale = rep->segment_template->timescale; - if (rep->segment_template->segment_timeline) timeline = rep->segment_template->segment_timeline; - } - if (!timescale) timescale=1; - - if (timeline) { - MPD_GetTimelineDuration(timeline, nb_segments, seg_duration); - *seg_duration /= timescale; - } else { - *seg_duration = (Double) duration; - *seg_duration /= timescale; - mediaDuration = period->duration; - if (!mediaDuration) mediaDuration = mpd->media_presentation_duration; - if (mediaDuration && duration) { - Double nb_seg = (Double) mediaDuration; - /*duration is given in ms*/ - nb_seg /= 1000; - nb_seg *= timescale; - nb_seg /= duration; - *nb_segments = (u32) ceil(nb_seg); - } - } -} - - -static void MPD_SetGroupRepresentation(GF_MPD_Group *group, GF_MPD_Representation *rep) -{ - u64 duration = 0; - u64 mediaDuration = 0; -#ifndef GPAC_DISABLE_LOG - u32 width=0, height=0, samplerate=0; - GF_MPD_Fractional *framerate=NULL; -#endif - u32 k, timescale = 1; - GF_MPD_AdaptationSet *set; - GF_MPD_Period *period; - u32 i = gf_list_find(group->adaptation_set->representations, rep); - assert((s32) i >= 0); - - group->active_rep_index = i; - group->active_bitrate = rep->bandwidth; - group->nb_segments_in_rep = 1; - - group->min_bandwidth_selected = 1; - for (k=0; kadaptation_set->representations); k++) { - GF_MPD_Representation *arep = gf_list_get(group->adaptation_set->representations, k); - if (group->active_bitrate > arep->bandwidth) { - group->min_bandwidth_selected = 0; - break; - } - } - - set = group->adaptation_set; - period = group->period; - -#ifndef GPAC_DISABLE_LOG - -#define GET_REP_ATTR(_a) _a = rep->_a; if (!_a) _a = set->_a; - - GET_REP_ATTR(width); - GET_REP_ATTR(height); - GET_REP_ATTR(samplerate); - GET_REP_ATTR(framerate); - - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPDIn] Switched to representation bandwidth %d kbps\n", rep->bandwidth/1024)); - if (group->max_bitrate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tmax download bandwidth: %d kbps\n", group->max_bitrate/1024)); - if (width&&height) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tWidth %d Height %d", width, height)); - if (framerate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("framerate %d/%d", framerate->num, framerate->den)); - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\n")); - } else if (samplerate) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tsamplerate %d\n", samplerate)); - } -#endif - - - MPD_GetSegmentDuration(rep, set, period, group->mpd_in->mpd, &group->nb_segments_in_rep, &group->segment_duration); -} - -static void MPD_SwitchGroupRepresentation(GF_MPD_In *mpd, GF_MPD_Group *group) -{ - u32 i, bandwidth, min_bandwidth; - GF_MPD_Representation *rep_sel = NULL; - GF_MPD_Representation *min_rep_sel = NULL; - Bool min_bandwidth_selected = 0; - bandwidth = 0; - min_bandwidth = (u32) -1; - - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPDIn] Checking representations between %d and %d kbps\n", group->min_bitrate/1024, group->max_bitrate/1024)); - - if (group->force_representation_idx_plus_one) { - rep_sel = gf_list_get(group->adaptation_set->representations, group->force_representation_idx_plus_one - 1); - group->force_representation_idx_plus_one = 0; - } - - if (!rep_sel) { - for (i=0; iadaptation_set->representations); i++) { - GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, i); - if (rep->disabled) continue; - if ((rep->bandwidth > bandwidth) && (rep->bandwidth < group->max_bitrate )) { - rep_sel = rep; - bandwidth = rep->bandwidth; - } - if (rep->bandwidth < min_bandwidth) { - min_rep_sel = rep; - min_bandwidth = rep->bandwidth; - } - } - } - - if (!rep_sel) { - rep_sel = min_rep_sel; - min_bandwidth_selected = 1; - } - assert(rep_sel); - i = gf_list_find(group->adaptation_set->representations, rep_sel); - - assert((s32) i >= 0); - - group->force_switch_bandwidth = 0; - group->max_bitrate = 0; - group->min_bitrate = (u32) -1; - - if (i != group->active_rep_index) { - if (min_bandwidth_selected) { - GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[MPDIn] No representation found with bandwidth below %d kbps - using representation @ %d kbps\n", group->max_bitrate/1024, rep_sel->bandwidth/1024)); - } - MPD_SetGroupRepresentation(group, rep_sel); - } -} - - -static void MPD_ResolveDuration(GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, u64 *out_duration, u32 *out_timescale) -{ - u32 timescale = 0; - GF_MPD_SegmentTimeline *segment_timeline; - GF_MPD_MultipleSegmentBase *mbase_rep, *mbase_set, *mbase_period; - /*single media segment - duration is not known unless indicated in period*/ - if (rep->segment_base || set->segment_base || period->segment_base) { - *out_duration = period ? period->duration : 0; - *out_timescale = 1000; - return; - } - /*we have a segment template list or template*/ - mbase_rep = rep->segment_list ? (GF_MPD_MultipleSegmentBase *) rep->segment_list : (GF_MPD_MultipleSegmentBase *) rep->segment_template; - mbase_set = set->segment_list ? (GF_MPD_MultipleSegmentBase *)set->segment_list : (GF_MPD_MultipleSegmentBase *)set->segment_template; - mbase_period = period->segment_list ? (GF_MPD_MultipleSegmentBase *)period->segment_list : (GF_MPD_MultipleSegmentBase *)period->segment_template; - - segment_timeline = NULL; - if (mbase_period) segment_timeline = mbase_period->segment_timeline; - if (mbase_set) segment_timeline = mbase_set->segment_timeline; - if (mbase_rep) segment_timeline = mbase_rep->segment_timeline; - - timescale = mbase_rep ? mbase_rep->timescale : 0; - if (!timescale && mbase_set && mbase_set->timescale) timescale = mbase_set->timescale; - if (!timescale && mbase_period && mbase_period->timescale) timescale = mbase_period->timescale; - if (!timescale) timescale = 1; - *out_timescale = timescale; - - if (mbase_rep && mbase_rep->duration) *out_duration = mbase_rep->duration; - else if (mbase_set && mbase_set->duration) *out_duration = mbase_set->duration; - else if (mbase_period && mbase_period->duration) *out_duration = mbase_period->duration; - -} - -typedef enum -{ - GF_MPD_RESOLVE_URL_MEDIA, - GF_MPD_RESOLVE_URL_INIT, - GF_MPD_RESOLVE_URL_INDEX, -} GF_MPDURLResolveType; - - -GF_Err MPD_ResolveURL(GF_MPD *mpd, GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, char *mpd_url, GF_MPDURLResolveType resolve_type, u32 item_index, char **out_url, u64 *out_range_start, u64 *out_range_end, u64 *segment_duration) -{ - GF_MPD_BaseURL *url_child; - GF_MPD_SegmentTimeline *timeline = NULL; - u32 start_number = 1; - u32 timescale; - char *url; - char *url_to_solve, *solved_template, *first_sep, *media_url; - char *init_template, *index_template; - - *out_range_start = *out_range_end = 0; - *out_url = NULL; - - /*resolve base URLs from document base (download location) to representation (media)*/ - url = gf_strdup(mpd_url); - url_child = gf_list_get(mpd->base_URLs, 0); - if (url_child) { - char *t_url = gf_url_concatenate(url, url_child->URL); - gf_free(url); - url = t_url; - } - - url_child = gf_list_get(period->base_URLs, 0); - if (url_child) { - char *t_url = gf_url_concatenate(url, url_child->URL); - gf_free(url); - url = t_url; - } - - url_child = gf_list_get(set->base_URLs, 0); - if (url_child) { - char *t_url = gf_url_concatenate(url, url_child->URL); - gf_free(url); - url = t_url; - } - - url_child = gf_list_get(rep->base_URLs, 0); - if (url_child) { - char *t_url = gf_url_concatenate(url, url_child->URL); - gf_free(url); - url = t_url; - } - - MPD_ResolveDuration(rep, set, period, segment_duration, ×cale); - *segment_duration = (u32) ((Double) (*segment_duration) * 1000.0 / timescale); - - /*single URL*/ - if (rep->segment_base || set->segment_base || period->segment_base) { - GF_MPD_URL *res_url; - if (item_index>0) return GF_EOS; - switch (resolve_type) { - case GF_MPD_RESOLVE_URL_MEDIA: - if (!url) return GF_NON_COMPLIANT_BITSTREAM; - *out_url = url; - return GF_OK; - case GF_MPD_RESOLVE_URL_INIT: - case GF_MPD_RESOLVE_URL_INDEX: - res_url = NULL; - if (resolve_type == GF_MPD_RESOLVE_URL_INDEX) { - if (period->segment_base) res_url = period->segment_base->representation_index; - if (set->segment_base) res_url = set->segment_base->representation_index; - if (rep->segment_base) res_url = rep->segment_base->representation_index; - } else { - if (period->segment_base) res_url = period->segment_base->initialization_segment; - if (set->segment_base) res_url = set->segment_base->initialization_segment; - if (rep->segment_base) res_url = rep->segment_base->initialization_segment; - } - /*no initialization segment / index*/ - if (!res_url) { - gf_free(url); + GF_MPDGroup *group; + GF_SAFEALLOC(group, GF_MPDGroup); + group->segment_ifce = ifce; + group->segment_ifce->proxy_udta = mpdin; + group->segment_ifce->query_proxy = MPD_ClientQuery; + gf_dash_set_group_udta(mpdin->dash, group_index, group); return GF_OK; } - if (res_url->sourceURL) { - *out_url = gf_url_concatenate(url, res_url->sourceURL); - gf_free(url); - } else { - *out_url = url; - } - if (res_url->byte_range) { - *out_range_start = res_url->byte_range->start_range; - *out_range_end = res_url->byte_range->end_range; - } - return GF_OK; - default: - break; - } - gf_free(url); - return GF_BAD_PARAM; - } - - /*segmentList*/ - if (rep->segment_list || set->segment_list || period->segment_list) { - GF_MPD_URL *init_url, *index_url; - GF_MPD_SegmentURL *segment; - GF_List *segments = NULL; - u32 segment_count; - - init_url = index_url = NULL; - - /*apply inheritance of attributes, lowest level having preceedence*/ - if (period->segment_list) { - if (period->segment_list->initialization_segment) init_url = period->segment_list->initialization_segment; - if (period->segment_list->representation_index) index_url = period->segment_list->representation_index; - if (period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs; - if (period->segment_list->start_number != (u32) -1) start_number = period->segment_list->start_number; - if (period->segment_list->segment_timeline) timeline = period->segment_list->segment_timeline; - } - if (set->segment_list) { - if (set->segment_list->initialization_segment) init_url = set->segment_list->initialization_segment; - if (set->segment_list->representation_index) index_url = set->segment_list->representation_index; - if (set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs; - if (set->segment_list->start_number != (u32) -1) start_number = set->segment_list->start_number; - if (set->segment_list->segment_timeline) timeline = set->segment_list->segment_timeline; - } - if (rep->segment_list) { - if (rep->segment_list->initialization_segment) init_url = rep->segment_list->initialization_segment; - if (rep->segment_list->representation_index) index_url = rep->segment_list->representation_index; - if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs; - if (rep->segment_list->start_number != (u32) -1) start_number = rep->segment_list->start_number; - if (rep->segment_list->segment_timeline) timeline = rep->segment_list->segment_timeline; - } - - - segment_count = gf_list_count(segments); - - switch (resolve_type) { - case GF_MPD_RESOLVE_URL_INIT: - - if (init_url) { - if (init_url->sourceURL) { - *out_url = gf_url_concatenate(url, init_url->sourceURL); - gf_free(url); - } else { - *out_url = url; - } - if (init_url->byte_range) { - *out_range_start = init_url->byte_range->start_range; - *out_range_end = init_url->byte_range->end_range; - } - } else { - gf_free(url); - } - return GF_OK; - case GF_MPD_RESOLVE_URL_MEDIA: - if (!url) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Media URL is not set in segment list\n")); - return GF_SERVICE_ERROR; - } - if (item_index >= segment_count) { - gf_free(url); - return GF_EOS; - } - *out_url = url; - segment = gf_list_get(segments, item_index); - if (segment->media) { - *out_url = gf_url_concatenate(url, segment->media); - gf_free(url); - } - if (segment->media_range) { - *out_range_start = segment->media_range->start_range; - *out_range_end = segment->media_range->end_range; - } - return GF_OK; - case GF_MPD_RESOLVE_URL_INDEX: - if (item_index >= segment_count) { - gf_free(url); - return GF_EOS; - } - *out_url = url; - segment = gf_list_get(segments, item_index); - if (segment->index) { - *out_url = gf_url_concatenate(url, segment->index); - gf_free(url); - } - if (segment->index_range) { - *out_range_start = segment->index_range->start_range; - *out_range_end = segment->index_range->end_range; - } - return GF_OK; - default: - break; - } - gf_free(url); - return GF_BAD_PARAM; - } - - /*segmentTemplate*/ - media_url = init_template = index_template = NULL; - - /*apply inheritance of attributes, lowest level having preceedence*/ - if (period->segment_template) { - if (period->segment_template->initialization) init_template = period->segment_template->initialization; - if (period->segment_template->index) index_template = period->segment_template->index; - if (period->segment_template->media) media_url = period->segment_template->media; - if (period->segment_template->start_number != (u32) -1) start_number = period->segment_template->start_number; - if (period->segment_template->segment_timeline) timeline = period->segment_template->segment_timeline; - } - if (set->segment_template) { - if (set->segment_template->initialization) init_template = set->segment_template->initialization; - if (set->segment_template->index) index_template = set->segment_template->index; - if (set->segment_template->media) media_url = set->segment_template->media; - if (set->segment_template->start_number != (u32) -1) start_number = set->segment_template->start_number; - if (set->segment_template->segment_timeline) timeline = set->segment_template->segment_timeline; - } - if (rep->segment_template) { - if (rep->segment_template->initialization) init_template = rep->segment_template->initialization; - if (rep->segment_template->index) index_template = rep->segment_template->index; - if (rep->segment_template->media) media_url = rep->segment_template->media; - if (rep->segment_template->start_number != (u32) -1) start_number = rep->segment_template->start_number; - if (rep->segment_template->segment_timeline) timeline = rep->segment_template->segment_timeline; - } - if (!media_url) { - GF_MPD_BaseURL *base = gf_list_get(rep->base_URLs, 0); - media_url = base->URL; - } - url_to_solve = NULL; - switch (resolve_type) { - case GF_MPD_RESOLVE_URL_INIT: - url_to_solve = init_template; - break; - case GF_MPD_RESOLVE_URL_MEDIA: - url_to_solve = media_url; - break; - case GF_MPD_RESOLVE_URL_INDEX: - url_to_solve = index_template; - break; - default: - gf_free(url); - return GF_BAD_PARAM; - } - if (!url_to_solve) { - gf_free(url); - return GF_OK; - } - /*let's solve the template*/ - solved_template = gf_malloc(sizeof(char)*strlen(url_to_solve)*2); - solved_template[0] = 0; - strcpy(solved_template, url_to_solve); - first_sep = strchr(solved_template, '$'); - if (first_sep) first_sep[0] = 0; - - first_sep = strchr(url_to_solve, '$'); - while (first_sep) { - char szFormat[100]; - char *format_tag; - char *second_sep = strchr(first_sep+1, '$'); - if (!second_sep) { - gf_free(url); - gf_free(solved_template); - return GF_NON_COMPLIANT_BITSTREAM; - } - second_sep[0] = 0; - format_tag = strchr(first_sep+1, '%'); - if (format_tag) format_tag[0] = 0; - /* identifier is $$ -> replace by $*/ - if (!strlen(first_sep+1)) { - strcat(solved_template, "$"); - } - else if (!strcmp(first_sep+1, "RepresentationID")) { - strcat(solved_template, rep->id); - } - else if (!strcmp(first_sep+1, "Number")) { - if (format_tag) { - char szPrintFormat[20]; - strcpy(szPrintFormat, "%"); - strcat(szPrintFormat, format_tag+1); - strcat(szPrintFormat, "d"); - sprintf(szFormat, szPrintFormat, start_number + item_index); - } else { - sprintf(szFormat, "%d", start_number + item_index); - } - strcat(solved_template, szFormat); - } - else if (!strcmp(first_sep+1, "Bandwidth")) { - if (format_tag) { - char szPrintFormat[20]; - strcpy(szPrintFormat, "%"); - strcat(szPrintFormat, format_tag+1); - strcat(szPrintFormat, "d"); - sprintf(szFormat, format_tag+1, rep->bandwidth); - } else { - sprintf(szFormat, "%d", rep->bandwidth); - } - strcat(solved_template, szFormat); - } - else if (!strcmp(first_sep+1, "Time")) { - if (timeline) { - /*uses segment timeline*/ - u32 k, nb_seg, cur_idx, nb_repeat; - u64 time, start_time; - nb_seg = gf_list_count(timeline->entries); - cur_idx = 0; - start_time=0; - for (k=0; kentries, k); - if (item_index>cur_idx+ent->repeat_count) { - cur_idx += 1 + ent->repeat_count; - start_time += ent->duration * (1 + ent->repeat_count); - continue; - } - *segment_duration = ent->duration; - *segment_duration = (u32) ((Double) (*segment_duration) * 1000.0 / timescale); - nb_repeat = item_index - cur_idx; - time = ent->start_time ? ent->start_time : start_time; - time += nb_repeat * ent->duration; - sprintf(szFormat, ""LLD"", time); - strcat(solved_template, szFormat); - break; - } - } - } - if (format_tag) format_tag[0] = '%'; - second_sep[0] = '$'; - /*look for next keyword - copy over remaining text if any*/ - first_sep = strchr(second_sep+1, '$'); - if (first_sep) first_sep[0] = 0; - if (strlen(second_sep+1)) - strcat(solved_template, second_sep+1); - if (first_sep) first_sep[0] = '$'; - } - *out_url = gf_url_concatenate(url, solved_template); - gf_free(url); - gf_free(solved_template); - return GF_OK; -} - -static GF_Err MPD_DownloadInitSegment(GF_MPD_In *mpdin, GF_MPD_Group *group) -{ - GF_Err e; - char *base_init_url; - GF_MPD_Representation *rep; - u64 start_range, end_range; - /* This variable is 0 if there is a initURL, the index of first segment downloaded otherwise */ - u32 nb_segment_read = 0; - if (!mpdin || !group) - return GF_BAD_PARAM; - gf_mx_p(mpdin->dl_mutex); - - assert( group->adaptation_set && group->adaptation_set->representations ); - rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); - if (!rep) { - gf_mx_v(mpdin->dl_mutex); - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Unable to find any representation, aborting.\n")); - return GF_IO_ERR; - } - start_range = end_range = 0; - - e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_INIT, 0, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration); - if (e) { - gf_mx_v(mpdin->dl_mutex); - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Unable to resolve initialization URL: %s\n", gf_error_to_string(e) )); - return e; - } - - /*no error and no init segment, go for media segment*/ - if (!base_init_url) { - e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_MEDIA, group->download_segment_index, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration); - if (e) { - gf_mx_v(mpdin->dl_mutex); - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Unable to resolve media URL: %s\n", gf_error_to_string(e) )); - return e; - } - nb_segment_read = 1; - } - - if (!strstr(base_init_url, "://") || !strnicmp(base_init_url, "file://", 7)) { - assert(!group->nb_cached_segments); - group->cached[0].cache = gf_strdup(base_init_url); - group->cached[0].url = gf_strdup(base_init_url); - group->nb_cached_segments = 1; - /*do not erase local files*/ - group->local_files = 1; - group->download_segment_index += nb_segment_read; - group->segment_local_url = group->cached[0].cache; - group->local_url_start_range = start_range; - group->local_url_end_range = end_range; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Setup initialization segment %s \n", group->segment_local_url)); - if (!group->input_module) { - const char *mime_type = MPD_GetMimeType(NULL, rep, group->adaptation_set); - e = MPD_LoadMediaService(mpdin, group, mime_type, group->segment_local_url); - } - gf_mx_v(mpdin->dl_mutex); - gf_free(base_init_url); - return GF_OK; - } - - group->max_bitrate = 0; - group->min_bitrate = (u32)-1; - /*use persistent connection for segment downloads*/ - e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), base_init_url, MPD_NetIO_Segment, group, start_range, end_range, 1); - - if ((e==GF_OK) && group->force_switch_bandwidth && !mpdin->auto_switch_count) { - MPD_SwitchGroupRepresentation(mpdin, group); - gf_mx_v(mpdin->dl_mutex); - return MPD_DownloadInitSegment(mpdin, group); - } - - - if (e == GF_URL_ERROR && !base_init_url) { /* We have a 404 and started with segments */ - /* It is possible that the first segment has been deleted while we made the first request... - * so we try with the next segment on some M3U8 servers */ - - gf_free(base_init_url); - - e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_MEDIA, group->download_segment_index + 1, &base_init_url, &start_range, &end_range, &group->current_downloaded_segment_duration); - if (!e) { - gf_mx_v(mpdin->dl_mutex); - return e; - } - GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("Download of first segment failed... retrying with second one : %s\n", base_init_url)); - nb_segment_read = 2; - /*use persistent connection for segment downloads*/ - e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), base_init_url, MPD_NetIO_Segment, group, 0, 0, 1); - } /* end of 404 */ - - if (e!= GF_OK && !group->segment_must_be_streamed) { - mpdin->mpd_stop_request = 1; - gf_mx_v(mpdin->dl_mutex); - gf_free(base_init_url); - return e; - } else { - char mime[128]; - const char *mime_type; - u32 count = group->nb_segments_in_rep + 1; - if (count < group->max_cached_segments) { - if (count < 1) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] 0 representations, aborting\n")); - gf_free(base_init_url); - gf_mx_v(mpdin->dl_mutex); - return GF_BAD_PARAM; - } - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Resizing to %u max_cached_segments elements instead of %u.\n", count, group->max_cached_segments)); - /* OK, we have a problem, it may ends download */ - group->max_cached_segments = count; - } - e = gf_dm_sess_process(group->segment_dnload); - /* Mime-Type check */ - strncpy(mime, gf_dm_sess_mime_type(group->segment_dnload), sizeof(mime)); - strlwr(mime); - if (mime && group->input_module == NULL) { - GF_Err e; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Searching an input plugin for mime type : %s...\n", mime)); - gf_free( mpdin->mimeTypeForM3U8Segments); - mpdin->mimeTypeForM3U8Segments = gf_strdup( mime ); - if (rep->mime_type) gf_free( rep->mime_type); - rep->mime_type = gf_strdup( mime ); - e = MPD_LoadMediaService(mpdin, group, mime, base_init_url); - if (e != GF_OK) { - gf_mx_v(mpdin->dl_mutex); - return e; - } - } - mime_type = MPD_GetMimeType(NULL, rep, group->adaptation_set); - if (!mime || (stricmp(mime, mime_type))) { - Bool valid = 0; - char *stype1, *stype2; - stype1 = strchr(mime_type, '/'); - stype2 = mime ? strchr(mime, '/') : NULL; - if (stype1 && stype2 && !strcmp(stype1, stype2)) valid = 1; - - if (!valid && 0) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Mime '%s' is not correct for '%s', it should be '%s'\n", mime, base_init_url, mime_type)); - mpdin->mpd_stop_request = 0; - gf_mx_v(mpdin->dl_mutex); - gf_free(base_init_url); - base_init_url = NULL; - return GF_BAD_PARAM; - } - } - if (group->segment_must_be_streamed ) { - group->segment_local_url = gf_dm_sess_get_resource_name(group->segment_dnload); - e = GF_OK; - } else { - group->segment_local_url = gf_dm_sess_get_cache_name(group->segment_dnload); - } - - if ((e!=GF_OK) || !group->segment_local_url) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error with initialization segment: download result:%s, cache file:%s\n", gf_error_to_string(e), group->segment_local_url)); - mpdin->mpd_stop_request = 1; - gf_mx_v(mpdin->dl_mutex); - gf_free(base_init_url); - return GF_BAD_PARAM; - } else { - assert(!group->nb_cached_segments); - group->cached[0].cache = gf_strdup(group->segment_local_url); - group->cached[0].url = gf_strdup(gf_dm_sess_get_resource_name(group->segment_dnload)); - group->nb_cached_segments = 1; - group->download_segment_index += nb_segment_read; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Adding initialization segment %s to cache: %s\n", group->segment_local_url, group->cached[0].url )); - gf_mx_v(mpdin->dl_mutex); - gf_free(base_init_url); - return GF_OK; - } - } -} - -static void MPDIn_skip_disabled_rep(GF_MPD_Group *group, GF_MPD_Representation *rep) -{ - s32 rep_idx = gf_list_find(group->adaptation_set->representations, rep); - while (1) { - rep_idx++; - if (rep_idx==gf_list_count(group->adaptation_set->representations)) rep_idx = 0; - rep = gf_list_get(group->adaptation_set->representations, rep_idx); - if (!rep->disabled) break; - } - assert(rep && !rep->disabled); - MPD_SetGroupRepresentation(group, rep); - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Switching to representation %d - BW %d\n", group->active_rep_index, group->active_bitrate )); -} - - -static u32 download_segments(void *par) -{ - GF_Err e; - GF_MPD_In *mpdin = (GF_MPD_In*) par; - GF_MPD_Period *period; - GF_MPD_Representation *rep; - u32 i, group_count, ret = 0; - Bool go_on = 1; - char *new_base_seg_url; - assert(mpdin); - if (!mpdin->mpd){ - GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[MPD_IN] Incorrect state, no mpdin->mpd for URL=%s, already stopped ?\n", mpdin->url)); - return 1; - } - - /* Setting the download status in exclusive code */ - gf_mx_p(mpdin->dl_mutex); - mpdin->mpd_is_running = MPD_STATE_CONNECTING; - gf_mx_v(mpdin->dl_mutex); - -restart_period: - mpdin->in_period_setup = 1; - e = GF_OK; - period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index); - group_count = gf_list_count(mpdin->groups); - for (i=0; igroups, i); - if (!group->selected) continue; - e = MPD_DownloadInitSegment(mpdin, group); - if (e) break; - } - mpdin->mpd_stop_request=0; - - if (e != GF_OK) { - gf_term_on_connect(mpdin->service, NULL, e); - ret = 1; - goto exit; - } - - mpdin->last_update_time = gf_sys_clock(); - - gf_mx_p(mpdin->dl_mutex); - mpdin->mpd_is_running = MPD_STATE_CONNECTING; - gf_mx_v(mpdin->dl_mutex); - - for (i=0; igroups, i); - if (!group->selected) continue; - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Connecting initial service... %s\n", group->segment_local_url)); - if (! group->input_module) { - e = GF_SERVICE_ERROR; - gf_term_on_connect(mpdin->service, NULL, e); - ret = 1; - goto exit; - } - e = group->input_module->ConnectService(group->input_module, mpdin->service, group->segment_local_url); - if (e) { - ret = 1; - goto exit; - } - group->service_connected = 1; - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Connecting initial service DONE\n", group->segment_local_url)); - } - - gf_mx_p(mpdin->dl_mutex); - mpdin->in_period_setup = 0; - mpdin->mpd_is_running = MPD_STATE_RUNNING; - gf_mx_v(mpdin->dl_mutex); - - while (go_on) { - const char *local_file_name = NULL; - const char *resource_name = NULL; - /*wait until next segment is needed*/ - while (!mpdin->mpd_stop_request) { - u32 timer = gf_sys_clock() - mpdin->last_update_time; - Bool shouldParsePlaylist = mpdin->mpd->minimum_update_period && (timer > mpdin->mpd->minimum_update_period); - - if (shouldParsePlaylist) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Next segment in cache, but it is time to update the playlist (%u ms/%u)\n", timer, mpdin->mpd->minimum_update_period)); - e = MPD_UpdatePlaylist(mpdin); - group_count = gf_list_count(mpdin->groups); - if (e) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error updating MPD %s\n", gf_error_to_string(e))); - } - } else { - Bool all_groups_done = 1; - Bool cache_full = 1; - gf_mx_p(mpdin->dl_mutex); - for (i=0; igroups, i); - if (!group->selected || group->done) continue; - all_groups_done = 0; - if (group->nb_cached_segmentsmax_cached_segments) { - cache_full = 0; - break; - } - } - gf_mx_v(mpdin->dl_mutex); - if (!cache_full) break; - - if (mpdin->request_period_switch==2) all_groups_done = 1; - - if (all_groups_done && mpdin->request_period_switch) { - MPD_ResetGroups(mpdin); - if (mpdin->request_period_switch == 1) - mpdin->active_period_index++; - - MPD_SetupPeriod(mpdin); - mpdin->request_period_switch = 0; - - goto restart_period; - } - - gf_sleep(16); - } - } - - /* stop the thread if requested */ - if (mpdin->mpd_stop_request) { - go_on = 0; - break; - } - - /* Continue the processing (no stop request) */ - period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index); - - /*for each selected groups*/ - for (i=0; igroups, i); - if (! group->selected) continue; - if (group->done) continue; - - - if (group->nb_cached_segments>=group->max_cached_segments) { - continue; - } - - rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); - - /* if the index of the segment to be downloaded is greater or equal to the last segment (as seen in the playlist), - we need to check if a new playlist is ready */ - if (group->download_segment_index>=group->nb_segments_in_rep) { - u32 timer = gf_sys_clock() - mpdin->last_update_time; - /* update of the playlist, only if indicated */ - if (mpdin->mpd->minimum_update_period && timer > mpdin->mpd->minimum_update_period) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Last segment in current playlist downloaded, checking updates after %u ms\n", timer)); - e = MPD_UpdatePlaylist(mpdin); - if (e) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error updating MPD %s\n", gf_error_to_string(e))); - } - group_count = gf_list_count(mpdin->groups); - period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index); - rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); - } else { - gf_sleep(16); - } - /* Now that the playlist is up to date, we can check again */ - if (group->download_segment_index >= group->nb_segments_in_rep) { - if (mpdin->mpd->minimum_update_period) { - /* if there is a specified update period, we redo the whole process */ - continue; - } else { - /* if not, we are really at the end of the playlist, we can quit */ - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] End of playlist reached... downloading remaining elements...")); - group->done = 1; - break; - } - } - } - gf_mx_p(mpdin->dl_mutex); - - /* At this stage, there are some segments left to be downloaded */ - e = MPD_ResolveURL(mpdin->mpd, rep, group->adaptation_set, group->period, mpdin->url, GF_MPD_RESOLVE_URL_MEDIA, group->download_segment_index, &new_base_seg_url, &start_range, &end_range, &group->current_downloaded_segment_duration); - gf_mx_v(mpdin->dl_mutex); - if (e) { - /*do something!!*/ - break; - } - use_byterange = (start_range || end_range) ? 1 : 0; - - if (use_byterange) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Downloading new segment: %s (range: "LLD"-"LLD")\n", new_base_seg_url, start_range, end_range)); - } - - /*local file*/ - if (!strstr(new_base_seg_url, "://") || !strnicmp(new_base_seg_url, "file://", 7)) { - resource_name = local_file_name = (char *) new_base_seg_url; - e = GF_OK; - /*do not erase local files*/ - group->local_files = 1; - if (group->force_switch_bandwidth && !mpdin->auto_switch_count) { - MPD_SwitchGroupRepresentation(mpdin, group); - /*restart*/ - i--; - continue; - } - - } else { - u32 total_size, bytes_per_sec; - - group->max_bitrate = 0; - group->min_bitrate = (u32)-1; - /*use persistent connection for segment downloads*/ - if (use_byterange) { - e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), new_base_seg_url, MPD_NetIO_Segment, group, start_range, end_range, 1); - } else { - e = MPD_downloadWithRetry(mpdin->service, &(group->segment_dnload), new_base_seg_url, MPD_NetIO_Segment, group, 0, 0, 1); - } - - if ((e==GF_OK) && group->force_switch_bandwidth) { - if (!mpdin->auto_switch_count) { - MPD_SwitchGroupRepresentation(mpdin, group); - /*restart*/ - i--; - continue; - } - if (rep->disabled) { - MPDIn_skip_disabled_rep(group, rep); - /*restart*/ - i--; - continue; - } - } - - if (group->segment_must_be_streamed) local_file_name = gf_dm_sess_get_resource_name(group->segment_dnload); - else local_file_name = gf_dm_sess_get_cache_name(group->segment_dnload); - - resource_name = gf_dm_sess_get_resource_name(group->segment_dnload); - - gf_dm_sess_get_stats(group->segment_dnload, NULL, NULL, &total_size, NULL, &bytes_per_sec, NULL); - if (total_size && bytes_per_sec && group->current_downloaded_segment_duration) { - Double bitrate, time; - bitrate = 8*total_size; - bitrate *= 1000; - bitrate /= group->current_downloaded_segment_duration; - bitrate /= 1024; - time = total_size; - time /= bytes_per_sec; - - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Downloaded segment %d bytes in %g seconds - duration %g sec - Bandwidth (kbps): indicated %d - computed %d - download %d\n", total_size, time, group->current_downloaded_segment_duration/1000.0, rep->bandwidth/1024, (u32) bitrate, 8*bytes_per_sec/1024)); - - if (rep->bandwidth < 8*bytes_per_sec) { - u32 k; - /*find highest bandwidth that fits our bitrate*/ - GF_MPD_Representation *new_rep = NULL; - for (k=0; kadaptation_set->representations); k++) { - GF_MPD_Representation *arep = gf_list_get(group->adaptation_set->representations, k); - if (8*bytes_per_sec > arep->bandwidth) { - if (!new_rep) new_rep = arep; - else if (arep->bandwidth > new_rep->bandwidth) { - new_rep = arep; - } - } - } - if (new_rep) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("Switching to new representation bitrate %d kbps\n", new_rep->bandwidth/1024)); - MPD_SetGroupRepresentation(group, new_rep); - } - } - } - } - - if (local_file_name && (e == GF_OK || group->segment_must_be_streamed )) { - gf_mx_p(mpdin->dl_mutex); - assert(group->nb_cached_segmentsmax_cached_segments); - assert( local_file_name ); - group->cached[group->nb_cached_segments].cache = gf_strdup(local_file_name); - group->cached[group->nb_cached_segments].url = gf_strdup( resource_name ); - group->cached[group->nb_cached_segments].start_range = 0; - group->cached[group->nb_cached_segments].end_range = 0; - if (group->local_files && use_byterange) { - group->cached[group->nb_cached_segments].start_range = start_range; - group->cached[group->nb_cached_segments].end_range = end_range; - } - if (!group->local_files) { - GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPD_IN] Added file to cache\n\tURL: %s\n\tCache: %s\n\tElements in cache: %u/%u\n", group->cached[group->nb_cached_segments].url, group->cached[group->nb_cached_segments].cache, group->nb_cached_segments+1, group->max_cached_segments)); - } - group->nb_cached_segments++; - group->download_segment_index++; - if (mpdin->auto_switch_count) { - group->nb_segments_done++; - if (group->nb_segments_done==mpdin->auto_switch_count) { - group->nb_segments_done=0; - MPDIn_skip_disabled_rep(group, rep); - } - } - gf_mx_v(mpdin->dl_mutex); - } - gf_free(new_base_seg_url); - new_base_seg_url = NULL; - if (e != GF_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error in downloading new segment: %s %s\n", new_base_seg_url, gf_error_to_string(e))); - go_on=0; - break; - } - } - } - -exit: - /* Signal that the download thread has ended */ - gf_mx_p(mpdin->dl_mutex); - mpdin->mpd_is_running = MPD_STATE_STOPPED; - gf_mx_v(mpdin->dl_mutex); - return ret; -} - -const char * MPD_MPD_DESC = "HTTP MPD Streaming"; - -const char * MPD_MPD_EXT = "3gm mpd"; - -const char * MPD_M3U8_DESC = "HTTP M3U8 Playlist Streaming"; - -const char * MPD_M3U8_EXT = "m3u8 m3u"; - -static u32 MPD_RegisterMimeTypes(const GF_InputService *plug) -{ - u32 i, c; - for (i = 0 ; MPD_MIME_TYPES[i]; i++) - gf_term_register_mime_type (plug, MPD_MIME_TYPES[i], MPD_MPD_EXT, MPD_MPD_DESC); - c = i; - for (i = 0 ; M3U8_MIME_TYPES[i]; i++) - gf_term_register_mime_type(plug, M3U8_MIME_TYPES[i], MPD_M3U8_EXT, MPD_M3U8_DESC); - return c+i; -} - -Bool MPD_CanHandleURL(GF_InputService *plug, const char *url) -{ - u32 i; - char *sExt; - if (!plug || !url) - return 0; - sExt = strrchr(url, '.'); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Can Handle URL request from terminal for %s\n", url)); - for (i = 0 ; MPD_MIME_TYPES[i]; i++) { - if (gf_term_check_extension(plug, MPD_MIME_TYPES[i], MPD_MPD_EXT, MPD_MPD_DESC, sExt)) - return 1; - } - for (i = 0 ; M3U8_MIME_TYPES[i]; i++) { - if (gf_term_check_extension(plug, M3U8_MIME_TYPES[i], MPD_M3U8_EXT, MPD_M3U8_DESC, sExt)) - return 1; - } - return MPD_CheckRootType(url); + gf_modules_close_interface((GF_BaseInterface *) ifce); + } + } + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error locating plugin for segment - mime type %s - name %s\n", mime, init_segment_name)); + return GF_CODEC_NOT_FOUND; } + GF_InputService *MPD_GetInputServiceForChannel(GF_MPD_In *mpdin, LPNETCHANNEL channel) { GF_Channel *ch; - if (mpdin->group_zero_selected) return mpdin->group_zero_selected->input_module; - ch = (GF_Channel *) channel; - assert(ch && ch->odm && ch->odm->OD); + if (!channel) { + if (gf_dash_is_group_selected(mpdin->dash, 0)) { + GF_MPDGroup *mudta = gf_dash_get_group_udta(mpdin->dash, 0); + return mudta ? mudta->segment_ifce : NULL; + } + return NULL; + } + ch = (GF_Channel *) channel; + assert(ch->odm && ch->odm->OD); return (GF_InputService *) ch->odm->OD->service_ifce; } -GF_MPD_Group *MPD_GetGroupForInputService(GF_MPD_In *mpdin, GF_InputService *ifce) +s32 MPD_GetGroupIndexForChannel(GF_MPD_In *mpdin, LPNETCHANNEL channel) { u32 i; - for (i=0; igroups); i++) { - GF_MPD_Group *group = gf_list_get(mpdin->groups, i); - if (group->input_module==ifce) return group; + GF_InputService *ifce = MPD_GetInputServiceForChannel(mpdin, channel); + if (!ifce) return -1; + + for (i=0; idash); i++) { + GF_MPDGroup *group = gf_dash_get_group_udta(mpdin->dash, i); + if (!group) continue; + if (group->segment_ifce == ifce) return i; } - return NULL; + return -1; } GF_Err MPD_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream) @@ -1903,7 +292,7 @@ GF_Err MPD_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const cha GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; GF_InputService *segment_ifce = MPD_GetInputServiceForChannel(mpdin, channel); if (!plug || !plug->priv || !segment_ifce) return GF_SERVICE_ERROR; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Channel Connection (%p) request from terminal for %s\n", channel, url)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Channel Connection (%p) request from terminal for %s\n", channel, url)); return segment_ifce->ConnectChannel(segment_ifce, channel, url, upstream); } @@ -1912,628 +301,275 @@ GF_Err MPD_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel) GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; GF_InputService *segment_ifce = MPD_GetInputServiceForChannel(mpdin, channel); if (!plug || !plug->priv || !segment_ifce) return GF_SERVICE_ERROR; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Disconnect channel (%p) request from terminal \n", channel)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Disconnect channel (%p) request from terminal \n", channel)); return segment_ifce->DisconnectChannel(segment_ifce, channel); } -static u32 MPD_GetPeriodIndexFromTime(GF_MPD_In *mpdin, u32 time) +void mpdin_dash_io_delete_cache_file(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, const char *cache_url) { - u32 i, count; - GF_MPD_Period *period; - count = gf_list_count(mpdin->mpd->periods); - for (i = 0; impd->periods, i); - if (period->start > time) { - break; - } - } - return (i-1 >= 0 ? (i-1) : 0); + gf_dm_delete_cached_file_entry_session((GF_DownloadSession *)session, cache_url); } -static void MPD_DownloadStop(GF_MPD_In *mpdin) +GF_DASHFileIOSession mpdin_dash_io_create(GF_DASHFileIO *dashio, Bool persistent, const char *url) { - u32 i; - assert( mpdin ); - if (mpdin->groups) { - for (i=0; igroups); i++) { - GF_MPD_Group *group = gf_list_get(mpdin->groups, i); - assert( group ); - if (group->selected && group->segment_dnload) { - gf_dm_sess_abort(group->segment_dnload); - group->done = 1; - } - } - } - /* stop the download thread */ - gf_mx_p(mpdin->dl_mutex); - if (mpdin->mpd_is_running != MPD_STATE_STOPPED) { - mpdin->mpd_stop_request = 1; - gf_mx_v(mpdin->dl_mutex); - while (1) { - /* waiting for the download thread to stop */ - gf_sleep(16); - gf_mx_p(mpdin->dl_mutex); - if (mpdin->mpd_is_running != MPD_STATE_RUNNING) { - /* it's stopped we can continue */ - gf_mx_v(mpdin->dl_mutex); - break; - } - gf_mx_v(mpdin->dl_mutex); - } - } else { - gf_mx_v(mpdin->dl_mutex); - } -} + u32 flags = GF_NETIO_SESSION_NOT_THREADED; + GF_MPD_In *mpdin = (GF_MPD_In *)dashio->udta; + GF_DownloadSession *sess; -Bool MPD_SeekPeriods(GF_MPD_In *mpdin) + if (persistent) flags |= GF_NETIO_SESSION_PERSISTENT; + sess = gf_term_download_new(mpdin->service, url, flags, NULL, NULL); + return (GF_DASHFileIOSession ) sess; +} +void mpdin_dash_io_del(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) { - Double start_time; - u32 i, period_idx; - - gf_mx_p(mpdin->dl_mutex); - - mpdin->start_range_in_segment_at_next_period = 0; - start_time = 0; - period_idx = 0; - for (i=0; i<=gf_list_count(mpdin->mpd->periods); i++) { - GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, i); - Double dur = period->duration; - dur /= 1000; - if (mpdin->playback_start_range >= start_time) { - if ((i+1==gf_list_count(mpdin->mpd->periods)) || (mpdin->playback_start_range < start_time + dur) ) { - period_idx = i; - break; - } - } - start_time += dur; - } - if (period_idx != mpdin->active_period_index) { - mpdin->playback_start_range -= start_time; - mpdin->active_period_index = period_idx; - mpdin->request_period_switch = 2; - - /*figure out default segment duration and substract from our start range request*/ - if (mpdin->playback_start_range) { - Double duration; - u32 nb_segs; - GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, period_idx); - GF_MPD_AdaptationSet *set = gf_list_get(period->adaptation_sets, 0); - GF_MPD_Representation *rep = gf_list_get(set->representations, 0); - - MPD_GetSegmentDuration(rep, set, period, mpdin->mpd, &nb_segs, &duration); - - if (duration) { - while (mpdin->playback_start_range - mpdin->start_range_in_segment_at_next_period >= duration) - mpdin->start_range_in_segment_at_next_period += duration; - } - - } - } - gf_mx_v(mpdin->dl_mutex); - - return mpdin->request_period_switch ? 1 : 0; + gf_term_download_del((GF_DownloadSession *)session); } - -void MPD_SeekGroup(GF_MPD_In *mpdin, GF_MPD_Group *group) +void mpdin_dash_io_abort(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) { - Double seg_start; - u32 first_downloaded, last_downloaded, segment_idx; - - group->force_segment_switch = 0; - if (!group->segment_duration) return; - - /*figure out where to seek*/ - segment_idx = 0; - seg_start = 0.0; - while (1) { - if ((mpdin->playback_start_range >= seg_start) && (mpdin->playback_start_range < seg_start + group->segment_duration)) - break; - seg_start += group->segment_duration; - segment_idx++; - } - /*todo - seek to given duration*/ - mpdin->playback_start_range -= seg_start; - - first_downloaded = last_downloaded = group->download_segment_index; - if (group->download_segment_index +1 >= group->nb_cached_segments) { - first_downloaded = group->download_segment_index + 1 - group->nb_cached_segments; - } - /*we are seeking in our download range, just go on*/ - if ((segment_idx >= first_downloaded) && (segment_idx<=last_downloaded)) return; - - group->force_segment_switch = 1; - group->download_segment_index = segment_idx; - - if (group->segment_dnload) - gf_dm_sess_abort(group->segment_dnload); - - if (group->urlToDeleteNext) { - if (!mpdin->keep_files && !group->local_files) - gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext); - - gf_free(group->urlToDeleteNext); - group->urlToDeleteNext = NULL; - } - if (group->segment_dnload) { - gf_term_download_del(group->segment_dnload); - group->segment_dnload = NULL; - } - while (group->nb_cached_segments) { - group->nb_cached_segments --; - if (!mpdin->keep_files && !group->local_files) - gf_delete_file(group->cached[group->nb_cached_segments].cache); - - gf_free(group->cached[group->nb_cached_segments].cache); - gf_free(group->cached[group->nb_cached_segments].url); - memset(&group->cached[group->nb_cached_segments], 0, sizeof(segment_cache_entry)); - } + gf_dm_sess_abort((GF_DownloadSession *)session); } - -void MPD_SeekGroupsDownloads(GF_MPD_In *mpdin) +GF_Err mpdin_dash_io_setup_from_url(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, const char *url) { - u32 i; - - gf_mx_p(mpdin->dl_mutex); - - if (mpdin->active_period_index) { - Double dur = 0; - u32 i; - for (i=0; iactive_period_index; i++) { - GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index-1); - dur += period->duration/1000.0; - } - mpdin->playback_start_range -= dur; - } - for (i=0; igroups); i++) { - GF_MPD_Group *group = gf_list_get(mpdin->groups, i); - MPD_SeekGroup(mpdin, group); - } - gf_mx_v(mpdin->dl_mutex); + return gf_dm_sess_setup_from_url((GF_DownloadSession *)session, url); } - - -void MPD_ResetGroups(GF_MPD_In *mpdin) +GF_Err mpdin_dash_io_set_range(GF_DASHFileIO *dashio, GF_DASHFileIOSession session, u64 start_range, u64 end_range) { - mpdin->service->subservice_disconnect = 1; - gf_term_on_disconnect(mpdin->service, NULL, GF_OK); - - mpdin->service->subservice_disconnect = 2; - while (gf_list_count(mpdin->groups)) { - GF_MPD_Group *group = gf_list_last(mpdin->groups); - gf_list_rem_last(mpdin->groups); - - if (group->urlToDeleteNext) { - if (!mpdin->keep_files && !group->local_files) - gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext); - - gf_free(group->urlToDeleteNext); - group->urlToDeleteNext = NULL; - } - if (group->segment_dnload) { - gf_term_download_del(group->segment_dnload); - group->segment_dnload = NULL; - } - while (group->nb_cached_segments) { - group->nb_cached_segments --; - if (!mpdin->keep_files && !group->local_files) - gf_delete_file(group->cached[group->nb_cached_segments].cache); - - gf_free(group->cached[group->nb_cached_segments].cache); - gf_free(group->cached[group->nb_cached_segments].url); - } - gf_free(group->cached); - - if (group->input_module) { - if (group->service_connected) { - group->input_module->CloseService(group->input_module); - group->service_connected = 0; - } - gf_modules_close_interface((GF_BaseInterface *) group->input_module); - group->input_module = NULL; - } - - gf_free(group); - } - gf_list_del(mpdin->groups); - mpdin->groups = NULL; - mpdin->service->subservice_disconnect = 0; + return gf_dm_sess_set_range((GF_DownloadSession *)session, start_range, end_range); +} +GF_Err mpdin_dash_io_init(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + return gf_dm_sess_process_headers((GF_DownloadSession *)session); +} +GF_Err mpdin_dash_io_run(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + return gf_dm_sess_process((GF_DownloadSession *)session); +} +const char *mpdin_dash_io_get_url(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + return gf_dm_sess_get_resource_name((GF_DownloadSession *)session); +} +const char *mpdin_dash_io_get_cache_name(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + return gf_dm_sess_get_cache_name((GF_DownloadSession *)session); +} +const char *mpdin_dash_io_get_mime(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + return gf_dm_sess_mime_type((GF_DownloadSession *)session); +} +u32 mpdin_dash_io_get_bytes_per_sec(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + u32 bps=0; + GF_DownloadSession *sess = (GF_DownloadSession *)session; + gf_dm_sess_get_stats((GF_DownloadSession *)session, NULL, NULL, NULL, NULL, &bps, NULL); + return bps; +} +u32 mpdin_dash_io_get_total_size(GF_DASHFileIO *dashio, GF_DASHFileIOSession session) +{ + u32 size=0; + GF_DownloadSession *sess = (GF_DownloadSession *)session; + gf_dm_sess_get_stats((GF_DownloadSession *)session, NULL, NULL, &size, NULL, NULL, NULL); + return size; } -/* create groups (implemntation of adaptations set) */ -GF_Err MPD_SetupGroups(GF_MPD_In *mpdin) +GF_Err mpdin_dash_io_on_dash_event(GF_DASHFileIO *dashio, GF_DASHEventType dash_evt, GF_Err error_code) { GF_Err e; - u32 i, j, count; - GF_MPD_Period *period; - if (!mpdin->groups) { - mpdin->groups = gf_list_new(); - if (!mpdin->groups) return GF_OUT_OF_MEM; - } + u32 i; + GF_MPD_In *mpdin = (GF_MPD_In *)dashio->udta; - period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index); - if (!period) return GF_BAD_PARAM; - - count = gf_list_count(period->adaptation_sets); - for (i=0; iadaptation_sets, i); - for (j=0; jgroups); j++) { - GF_MPD_Group *group = gf_list_get(mpdin->groups, j); - if (group->adaptation_set==set) { - found = 1; - break; - } - } - if (!found) { - GF_MPD_Group *group; - GF_SAFEALLOC(group, GF_MPD_Group); - if (!group) return GF_OUT_OF_MEM; - group->mpd_in = mpdin; - group->adaptation_set = set; - group->period = period; - group->period = period; - group->max_cached_segments = mpdin->option_max_cached; - group->cached = gf_malloc(sizeof(segment_cache_entry)*group->max_cached_segments); - memset(group->cached, 0, sizeof(segment_cache_entry)*group->max_cached_segments); - if (!group->cached) { - gf_free(group); - return GF_OUT_OF_MEM; - } - e = gf_list_add(mpdin->groups, group); - if (e) { - gf_free(group->cached); - gf_free(group); - return e; - } + if (dash_evt==GF_DASH_EVENT_PERIOD_SETUP_ERROR) { + if (!mpdin->connection_ack_sent) { + gf_term_on_connect(mpdin->service, NULL, error_code); + mpdin->connection_ack_sent=1; } + return GF_OK; } - return GF_OK; -} -GF_Err MPD_SetupPeriod(GF_MPD_In *mpdin) -{ - GF_Err e; - u32 rep_i, group_i; - - /*setup all groups*/ - MPD_SetupGroups(mpdin); - mpdin->group_zero_selected = NULL; - - for (group_i=0; group_igroups); group_i++) { - GF_MPD_Representation *rep_sel; - u32 active_rep; - const char *mime_type; - GF_MPD_Group *group = gf_list_get(mpdin->groups, group_i); - - if (group->adaptation_set->group==0) { - mpdin->group_zero_selected = group; - } else if (mpdin->group_zero_selected) { - /* if this group is not the group 0 and we have found the group 0, - we can safely ignore this group. */ - break; + if (dash_evt==GF_DASH_EVENT_SELECT_GROUPS) { + const char *opt; + for (i=0; idash); i++) { + /*todo: select groups based on user criteria*/ + gf_dash_group_select(mpdin->dash, i, 1); } + opt = gf_modules_get_option((GF_BaseInterface *)mpdin->plug, "Systems", "Language3CC"); + if (opt && strcmp(opt, "und")) + gf_dash_groups_set_language(mpdin->dash, opt); - /* Select the appropriate representation in the given period */ - active_rep = 0; - for (rep_i = 0; rep_i < gf_list_count(group->adaptation_set->representations); rep_i++) { - GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_i); - rep_sel = gf_list_get(group->adaptation_set->representations, active_rep); + return GF_OK; + } - if (rep_i && ( !rep->codecs || !rep_sel->codecs || strcmp(rep->codecs, rep_sel->codecs) ) ) continue; + /*for all selected groups, create input service and connect to init/first segment*/ + if (dash_evt==GF_DASH_EVENT_CREATE_PLAYBACK) { - /*by default tune to best quality and/or full bandwith*/ - if (rep->quality_ranking > rep_sel->quality_ranking) { - active_rep = rep_i; - } else if (rep->bandwidth < rep_sel->bandwidth) { - active_rep = rep_i; - } + /*select input services if possible*/ + for (i=0; idash); i++) { + const char *mime, *init_segment; + + if (!gf_dash_is_group_selected(mpdin->dash, i)) + continue; + mime = gf_dash_group_get_segment_mime(mpdin->dash, i); + init_segment = gf_dash_group_get_segment_init_url(mpdin->dash, i, NULL, NULL); + e = MPD_LoadMediaService(mpdin, i, mime, init_segment); + if (e != GF_OK) { + gf_dash_group_select(mpdin->dash, i, 0); + } else { + /*connect our media service*/ + GF_MPDGroup *group = gf_dash_get_group_udta(mpdin->dash, i); + e = group->segment_ifce->ConnectService(group->segment_ifce, mpdin->service, init_segment); + if (e) { + 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 { + group->service_connected = 1; + } + } } - rep_sel = gf_list_get(group->adaptation_set->representations, active_rep); - MPD_SetGroupRepresentation(group, rep_sel); - - if (mpdin->playback_start_range>=0) - MPD_SeekGroup(mpdin, group); - - mime_type = MPD_GetMimeType(NULL, rep_sel, group->adaptation_set); - - if (!mime_type) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: missing mime\n")); - return GF_NON_COMPLIANT_BITSTREAM; + if (!mpdin->connection_ack_sent) { + gf_term_on_connect(mpdin->service, NULL, GF_OK); + mpdin->connection_ack_sent=1; } + return GF_OK; + } - /* TODO: Generate segment names if urltemplates are used */ - if (!rep_sel->segment_base && !rep_sel->segment_list && !rep_sel->segment_template - && !group->adaptation_set->segment_base && !group->adaptation_set->segment_list && !group->adaptation_set->segment_template - && !group->period->segment_base && !group->period->segment_list && !group->period->segment_template - && !gf_list_count(rep_sel->base_URLs) - - ) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: missing segments\n")); - return GF_NON_COMPLIANT_BITSTREAM; - } + /*for all running services, stop service*/ + if (dash_evt==GF_DASH_EVENT_DESTROY_PLAYBACK) { - group->input_module = NULL; - if (strcmp(M3U8_UNKOWN_MIME_TYPE, mime_type)) { - e = MPD_LoadMediaService(mpdin, group, mime_type, NULL); - if (e != GF_OK) return e; - } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Ignoring mime type %s, wait for first file...\n", mime_type)); + mpdin->service->subservice_disconnect = 1; + gf_term_on_disconnect(mpdin->service, NULL, GF_OK); + mpdin->service->subservice_disconnect = 2; + + for (i=0; idash); i++) { + GF_MPDGroup *group = gf_dash_get_group_udta(mpdin->dash, i); + if (!group) continue; + if (group->segment_ifce) { + if (group->service_connected) { + group->segment_ifce->CloseService(group->segment_ifce); + group->service_connected = 0; + } + gf_modules_close_interface((GF_BaseInterface *) group->segment_ifce); + } + gf_free(group); + gf_dash_set_group_udta(mpdin->dash, i, NULL); } - group->selected = 1; + mpdin->service->subservice_disconnect = 0; } - /*and seek if needed*/ return GF_OK; } -static GF_Err MPD_SegmentsProcessStart(GF_MPD_In *mpdin, u32 time) -{ - GF_Err e = GF_BAD_PARAM; - GF_MPD_Period *period; - - MPD_ResetGroups(mpdin); - - /* Get the right period from the given time */ - mpdin->active_period_index = MPD_GetPeriodIndexFromTime(mpdin, time); - period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index); - if (!period || !gf_list_count(period->adaptation_sets) ) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot start: not enough periods or representations in MPD\n")); - goto exit; - } - - e = MPD_SetupPeriod(mpdin); - if (e) goto exit; - - gf_th_run(mpdin->mpd_thread, download_segments, mpdin); - return GF_OK; - -exit: - gf_term_on_connect(mpdin->service, NULL, e); - return e; -} - - -static GF_Err http_ifce_get(GF_FileDownload *getter, char *url) -{ - GF_MPD_In *mpdin = (GF_MPD_In*) getter->udta; - GF_DownloadSession *sess = gf_term_download_new(mpdin->service, url, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL); - if (!sess) return GF_IO_ERR; - getter->session = sess; - return gf_dm_sess_process(sess); -} - -static void http_ifce_clean(GF_FileDownload *getter) -{ - GF_MPD_In *mpdin = (GF_MPD_In*) getter->udta; - if (getter->session) gf_term_download_del(getter->session); -} - -static const char *http_ifce_cache_name(GF_FileDownload *getter) -{ - GF_MPD_In *mpdin = (GF_MPD_In*) getter->udta; - if (getter->session) return gf_dm_sess_get_cache_name(getter->session); - return NULL; -} GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; - char local_path[GF_MAX_PATH]; - const char *local_url, *opt; + const char *opt; GF_Err e; - GF_DOMParser *mpd_parser; - Bool is_m3u8 = 0; - Bool is_local = 0; + u32 max_cache_duration, auto_switch_count; + GF_DASHInitialSelectionMode first_select_mode; + Bool keep_files, disable_switching; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Service Connection request (%p) from terminal for %s\n", serv, url)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Service Connection request (%p) from terminal for %s\n", serv, url)); if (!mpdin|| !serv || !url) return GF_BAD_PARAM; mpdin->service = serv; - memset( mpdin->lastMPDSignature, 0, sizeof(mpdin->last_update_time)); - mpdin->reload_count = 0; - if (mpdin->url) - gf_free(mpdin->url); - mpdin->url = gf_strdup(url); - mpdin->option_max_cached = 0; - - mpdin->getter.udta = mpdin; - mpdin->getter.new_session = http_ifce_get; - mpdin->getter.del_session = http_ifce_clean; - mpdin->getter.get_cache_name = http_ifce_cache_name; - mpdin->getter.session = NULL; - - - opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "MaxCachedSegments"); - if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "MaxCachedSegments", "3"); - if (opt) mpdin->option_max_cached = atoi(opt); - if (!mpdin->option_max_cached) mpdin->option_max_cached = 1; - /*we need one more entry for the current segment being played*/ - mpdin->option_max_cached++; - - mpdin->auto_switch_count = 0; + + mpdin->dash_io.udta = mpdin; + mpdin->dash_io.delete_cache_file = mpdin_dash_io_delete_cache_file; + mpdin->dash_io.create = mpdin_dash_io_create; + mpdin->dash_io.del = mpdin_dash_io_del; + mpdin->dash_io.abort = mpdin_dash_io_abort; + mpdin->dash_io.setup_from_url = mpdin_dash_io_setup_from_url; + mpdin->dash_io.set_range = mpdin_dash_io_set_range; + mpdin->dash_io.init = mpdin_dash_io_init; + mpdin->dash_io.run = mpdin_dash_io_run; + mpdin->dash_io.get_url = mpdin_dash_io_get_url; + mpdin->dash_io.get_cache_name = mpdin_dash_io_get_cache_name; + mpdin->dash_io.get_mime = mpdin_dash_io_get_mime; + mpdin->dash_io.get_bytes_per_sec = mpdin_dash_io_get_bytes_per_sec; + mpdin->dash_io.get_total_size = mpdin_dash_io_get_total_size; + mpdin->dash_io.on_dash_event = mpdin_dash_io_on_dash_event; + + max_cache_duration = 30; + opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "MaxCacheDuration"); + if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "MaxCacheDuration", "30"); + if (opt) max_cache_duration = atoi(opt); + + auto_switch_count = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "AutoSwitchCount"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "AutoSwitchCount", "0"); - if (opt) mpdin->auto_switch_count = atoi(opt); + if (opt) auto_switch_count = atoi(opt); + keep_files = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "KeepFiles"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "KeepFiles", "no"); - if (opt && !strcmp(opt, "yes")) mpdin->keep_files = 1; + if (opt && !strcmp(opt, "yes")) keep_files = 1; + disable_switching = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "DisableSwitching"); - if (opt && !strcmp(opt, "yes")) mpdin->disable_switching = 1; + if (opt && !strcmp(opt, "yes")) disable_switching = 1; + + first_select_mode = 0; + opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "StartRepresentation"); + if (!opt) { + gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "StartRepresentation", "minBandwidth"); + opt = "minBandwidth"; + } + if (opt && !strcmp(opt, "maxBandwidth")) first_select_mode = GF_DASH_SELECT_BANDWIDTH_HIGHEST; + 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; - if (mpdin->mpd_dnload) gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; mpdin->in_seek = 0; mpdin->previous_start_range = -1; + mpdin->dash = gf_dash_new(&mpdin->dash_io, max_cache_duration, auto_switch_count, keep_files, disable_switching, first_select_mode); - if (!strnicmp(url, "file://", 7)) { - local_url = url + 7; - is_local = 1; - if (strstr(url, ".m3u8")) { - is_m3u8 = 1; - } - } else if (strstr(url, "://")) { - /*use non-persistent connection for MPD downloads*/ - e = MPD_downloadWithRetry(mpdin->service, &(mpdin->mpd_dnload), url, MPD_NetIO, mpdin, 0, 0, 1); - if (e!=GF_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: MPD downloading problem %s for %s\n", gf_error_to_string(e), url)); - gf_term_on_connect(mpdin->service, NULL, GF_IO_ERR); - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - return e; - } - { - const char *url; - char mime[128]; - strncpy(&(mime[0]), gf_dm_sess_mime_type(mpdin->mpd_dnload), sizeof(mime)); - strlwr(mime); - url = gf_dm_sess_get_resource_name(mpdin->mpd_dnload); - /* Some servers, for instance http://tv.freebox.fr, serve m3u8 as text/plain */ - if (MPD_isM3U8_mime(mime) || strstr(url, ".m3u8")) { - is_m3u8 = 1; - } else if (!MPD_is_MPD_mime(mime) && !strstr(url, ".mpd")) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] mime '%s' for '%s' should be m3u8 or mpd\n", mime, url)); - gf_term_on_connect(mpdin->service, NULL, GF_BAD_PARAM); - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - return GF_CODEC_NOT_FOUND; - } - } - local_url = gf_dm_sess_get_cache_name(mpdin->mpd_dnload); - if (!local_url) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: cache problem %s\n", local_url)); - gf_term_on_connect(mpdin->service, NULL, GF_IO_ERR); - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - return GF_OK; - } - } else { - local_url = url; - is_local = 1; - if (strstr(url, ".m3u8")) - is_m3u8 = 1; - } - - if (is_local) { - FILE *f = fopen(local_url, "rt"); - if (!f) { - gf_term_on_connect(mpdin->service, NULL, GF_URL_ERROR); - return GF_OK; - } - fclose(f); + if (!mpdin->dash) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error - cannot create DASH Client for %s\n", url)); + gf_term_on_connect(mpdin->service, NULL, GF_IO_ERR); + return GF_OK; } - if (is_m3u8) { - if (is_local) { - char *sep; - strcpy(local_path, local_url); - sep = strrchr(local_path, '.'); - if (sep) sep[0]=0; - strcat(local_path, ".mpd"); - - gf_m3u8_to_mpd(local_url, url, local_path, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments, 0, M3U8_TO_MPD_USE_TEMPLATE, &mpdin->getter); - local_url = local_path; - } else { - gf_m3u8_to_mpd(local_url, url, NULL, mpdin->reload_count, mpdin->mimeTypeForM3U8Segments, 0, M3U8_TO_MPD_USE_TEMPLATE, &mpdin->getter); - } - } - - if (!MPD_CheckRootType(local_url)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: wrong file type %s\n", local_url)); - gf_term_on_connect(mpdin->service, NULL, GF_BAD_PARAM); - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - return GF_OK; - } - - /* parse the MPD */ - mpd_parser = gf_xml_dom_new(); - e = gf_xml_dom_parse(mpd_parser, local_url, NULL, NULL); - if (e != GF_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: MPD parsing problem %s\n", gf_xml_dom_get_error(mpd_parser) )); - gf_xml_dom_del(mpd_parser); - gf_term_on_connect(mpdin->service, NULL, e); - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - return GF_OK; - } - if (mpdin->mpd) - gf_mpd_del(mpdin->mpd); - mpdin->mpd = gf_mpd_new(); - if (!mpdin->mpd) { - e = GF_OUT_OF_MEM; - } else { - e = gf_mpd_init_from_dom(gf_xml_dom_get_root(mpd_parser), mpdin->mpd, url); - } - gf_xml_dom_del(mpd_parser); - if (e != GF_OK) { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot connect service: MPD creation problem %s\n", gf_error_to_string(e))); + /*dash thread starts at the end of gf_dash_open */ + e = gf_dash_open(mpdin->dash, url); + if (!mpdin->dash) { + 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); - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - if (mpdin->mpd) - gf_mpd_del(mpdin->mpd); - mpdin->mpd = NULL; - return e; - } - - e = MPD_SegmentsProcessStart(mpdin, 0); - return e; + return GF_OK; + } + return GF_OK; } static GF_Descriptor *MPD_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url) { - GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Service Description request from terminal for %s\n", sub_url)); - if (mpdin->group_zero_selected) { - if (mpdin->group_zero_selected->input_module) { - return mpdin->group_zero_selected->input_module->GetServiceDescriptor(mpdin->group_zero_selected->input_module, expect_type, sub_url); - } else { - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD_IN] Error - cannot provide service description: no segment service hanlder created\n")); - return NULL; - } - } else { - u32 i; - for (i=0; igroups); i++) { - GF_MPD_Group *group = gf_list_get(mpdin->groups, i); - if (!group->selected) continue; - if (group->service_descriptor_fetched) continue; - group->service_descriptor_fetched = 1; - return group->input_module->GetServiceDescriptor(group->input_module, expect_type, sub_url); - } - return NULL; + u32 i; + 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; idash); i++) { + 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); } + return NULL; } -void MPD_Stop(GF_MPD_In *mpdin) -{ - assert( mpdin ); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Stopping service %p\n", mpdin->service)); - MPD_DownloadStop(mpdin); - MPD_ResetGroups(mpdin); - - if (mpdin->mpd_dnload) { - gf_term_download_del(mpdin->mpd_dnload); - mpdin->mpd_dnload = NULL; - } - if (mpdin->mpd) - gf_mpd_del(mpdin->mpd); - mpdin->mpd = NULL; -} GF_Err MPD_CloseService(GF_InputService *plug) { GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; assert( mpdin ); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Close Service (%p) request from terminal\n", mpdin->service)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Close Service (%p) request from terminal\n", mpdin->service)); - MPD_Stop(mpdin); + if (mpdin->dash) + gf_dash_close(mpdin->dash); gf_term_on_disconnect(mpdin->service, NULL, GF_OK); @@ -2542,18 +578,19 @@ GF_Err MPD_CloseService(GF_InputService *plug) GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) { + s32 idx; GF_Err e; GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; GF_InputService *segment_ifce = NULL; - GF_MPD_Group *group = NULL; - if (!plug || !plug->priv || !com ) return GF_SERVICE_ERROR; - if (mpdin->group_zero_selected) segment_ifce = mpdin->group_zero_selected->input_module; + if (!plug || !plug->priv || !com ) return GF_SERVICE_ERROR; + + segment_ifce = MPD_GetInputServiceForChannel(mpdin, com->base.on_channel); switch (com->command_type) { case GF_NET_SERVICE_INFO: { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Info command from terminal on Service (%p)\n", mpdin->service)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Info command from terminal on Service (%p)\n", mpdin->service)); e = GF_OK; if (segment_ifce) { @@ -2562,18 +599,13 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) } if (e!= GF_OK || !com->info.name || 2 > strlen(com->info.name)) { - GF_MPD_ProgramInfo *info = gf_list_get(mpdin->mpd->program_infos, 0); - if (info) { - com->info.name = info->title; - com->info.comment = info->source; - } - if (!com->info.name && mpdin->group_zero_selected) - com->info.name = mpdin->group_zero_selected->cached[0].url; + gf_dash_get_info(mpdin->dash, &com->info.name, &com->info.comment); } return GF_OK; } + /*we could get it from MPD*/ case GF_NET_SERVICE_HAS_AUDIO: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Has Audio command from terminal on Service (%p)\n", mpdin->service)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Has Audio command from terminal on Service (%p)\n", mpdin->service)); if (segment_ifce) { /* defer to the real input service */ return segment_ifce->ServiceCommand(segment_ifce, com); @@ -2581,44 +613,7 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) return GF_NOT_SUPPORTED; case GF_NET_SERVICE_QUALITY_SWITCH: - { - u32 i; - - for (i=0; igroups); i++) { - Bool do_switch = 0; - GF_MPD_Group *group = gf_list_get(mpdin->groups, i); - u32 current_idx = group->active_rep_index; - if (! group->selected) continue; - - if (group->force_representation_idx_plus_one) current_idx = group->force_representation_idx_plus_one - 1; - if (com->switch_quality.up) { - if (current_idx + 1 < gf_list_count(group->adaptation_set->representations)) { - group->force_representation_idx_plus_one = 1 + current_idx+1; - do_switch = 1; - } - } else { - if (current_idx) { - group->force_representation_idx_plus_one = 1 + current_idx - 1; - do_switch = 1; - } - } - if (do_switch) { - gf_mx_p(mpdin->dl_mutex); - group->force_switch_bandwidth = 1; - /*in local playback just switch at the end of the current segment*/ - while (group->local_files && (group->nb_cached_segments>1)) { - group->nb_cached_segments--; - gf_free(group->cached[group->nb_cached_segments].url); - group->cached[group->nb_cached_segments].url = NULL; - group->cached[group->nb_cached_segments].start_range = 0; - group->cached[group->nb_cached_segments].end_range = 0; - assert(group->download_segment_index>1); - group->download_segment_index--; - } - gf_mx_v(mpdin->dl_mutex); - } - } - } + gf_dash_switch_quality(mpdin->dash, com->switch_quality.up); return GF_OK; } /*not supported*/ @@ -2626,205 +621,125 @@ GF_Err MPD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) segment_ifce = MPD_GetInputServiceForChannel(mpdin, com->base.on_channel); if (!segment_ifce) return GF_NOT_SUPPORTED; - group = MPD_GetGroupForInputService(mpdin, segment_ifce); - switch (com->command_type) { - case GF_NET_CHAN_SET_PADDING: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Set Padding command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - /* for padding settings, the MPD level should not change anything */ - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_SET_PULL: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Set Pull command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - /* defer to the real input service */ - return segment_ifce->ServiceCommand(segment_ifce, com); - break; case GF_NET_CHAN_INTERACTIVE: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Interactive command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); /* we are interactive (that's the whole point of MPD) */ return GF_OK; + /*we should get it from MPD minBufferTime*/ case GF_NET_CHAN_BUFFER: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Buffer query command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_BUFFER_QUERY: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received buffer query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); return segment_ifce->ServiceCommand(segment_ifce, com); break; - case GF_NET_CHAN_DURATION: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Duration query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - /* Ignore the duration given by the input service and use the one given in the MPD - Note: the duration of the initial segment will be 0 anyway (in MP4).*/ - { - Double duration; - duration = (Double)mpdin->mpd->media_presentation_duration; - if (!duration) { - u32 i; - for (i=0; impd->periods); i++) { - GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, i); - duration += (Double)period->duration; - } + + case GF_NET_CHAN_DURATION: + /* Ignore the duration given by the input service and use the one given in the MPD + Note: the duration of the initial segment will be 0 anyway (in MP4).*/ + com->duration.duration = gf_dash_get_duration(mpdin->dash); + return GF_OK; + + case GF_NET_CHAN_PLAY: + /*don't seek if this command is the first PLAY request of objects declared by the subservice*/ + if (!com->play.initial_broadcast_play) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Play command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); + + if (!gf_dash_in_period_setup(mpdin->dash) && !com->play.dash_segment_switch && ! mpdin->in_seek) { + Bool skip_seek; + + mpdin->in_seek = 1; + + /*if start range request is the same as previous one, don't process it + - this happens at period switch when new objects are declared*/ + skip_seek = (mpdin->previous_start_range==com->play.start_range) ? 1 : 0; + mpdin->previous_start_range = com->play.start_range; + + gf_dash_seek(mpdin->dash, com->play.start_range); + } + /*For MPEG-2 TS or formats not using Init Seg: since objects are declared and started once the first + segment is playing, we will stay in playback_start_range!=-1 until next segment (because we won't have a query_next), + which will prevent seeking until then ... we force a reset of playback_start_range to allow seeking asap*/ + else if (mpdin->in_seek && (com->play.start_range==0)) { +// mpdin->in_seek = 0; + } + else if (gf_dash_in_period_setup(mpdin->dash) && (com->play.start_range==0)) { + com->play.start_range = gf_dash_get_playback_start_range(mpdin->dash); } - duration /= 1000; - com->duration.duration = duration; - return GF_OK; - } - break; - case GF_NET_CHAN_PLAY: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Play command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - if (! mpdin->in_period_setup && !com->play.dash_segment_switch && ! mpdin->in_seek) { - Bool skip_seek; - - mpdin->in_seek = 1; - - /*if start range request is the same as previous one, don't process it - - this happens at period switch when new objects are declared*/ - skip_seek = (mpdin->previous_start_range==com->play.start_range) ? 1 : 0; - mpdin->previous_start_range = com->play.start_range; - - mpdin->playback_speed = com->play.speed; - mpdin->playback_start_range = com->play.start_range; - - /*first check if we seek to another period*/ - if (! MPD_SeekPeriods(mpdin)) { - /*if no, seek in group*/ - MPD_SeekGroupsDownloads(mpdin); + idx = MPD_GetGroupIndexForChannel(mpdin, com->play.on_channel); + if (idx>=0) { + gf_dash_set_group_done(mpdin->dash, idx, 0); + com->play.dash_segment_switch = gf_dash_group_segment_switch_forced(mpdin->dash, idx); } - } - /*For MPEG-2 TS or formats not using Init Seg: since objects are declared and started once the first - segment is playing, we will stay in playback_start_range!=-1 until next segment (because we won't have a query_next), - which will prevent seeking until then ... we force a reset of playback_start_range to allow seeking asap*/ - else if (mpdin->in_seek && (com->play.start_range==0)) { -// mpdin->in_seek = 0; - } - else if (mpdin->in_period_setup && (com->play.start_range==0)) { - com->play.start_range = mpdin->playback_start_range; - } - group->done = 0; - com->play.dash_segment_switch = group->force_segment_switch; - /*don't forward commands, we are killing the service anyway ...*/ - if (mpdin->request_period_switch) return GF_OK; + /*don't forward commands, we are killing the service anyway ...*/ + if (gf_dash_get_period_switch_status(mpdin->dash) ) return GF_OK; + } return segment_ifce->ServiceCommand(segment_ifce, com); case GF_NET_CHAN_STOP: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Stop command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - group->done = 1; - return segment_ifce->ServiceCommand(segment_ifce, com); - case GF_NET_CHAN_PAUSE: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Pause command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - case GF_NET_CHAN_RESUME: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Resume command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - case GF_NET_CHAN_SET_SPEED: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Set Speed command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - /* recording the speed, to change the segment download speed */ - mpdin->playback_speed = com->play.speed; - return segment_ifce->ServiceCommand(segment_ifce, com); + { + s32 idx = MPD_GetGroupIndexForChannel(mpdin, com->play.on_channel); + if (idx>=0) { + gf_dash_set_group_done(mpdin->dash, (u32) idx, 1); + } + } + return segment_ifce->ServiceCommand(segment_ifce, com); - case GF_NET_CHAN_CONFIG: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Set Config command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - /* defer to the real input service */ - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_GET_PIXEL_AR: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Pixel Aspect Ratio query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); + /*we could get it from MPD*/ + case GF_NET_CHAN_GET_PIXEL_AR: /* defer to the real input service */ return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_GET_DSI: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Decoder Specific Info query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_MAP_TIME: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Map Time query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_RECONFIG: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Reconfig command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_DRM_CFG: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received DRM query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_CHAN_GET_ESD: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Elementary Stream Descriptor query from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_BUFFER_QUERY: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Global Buffer query from terminal on Service (%p)\n", mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_GET_STATS: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Statistics query from terminal on Service (%p)\n", mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_IS_CACHABLE: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Cachable query from terminal on Service (%p)\n", mpdin->service)); - return segment_ifce->ServiceCommand(segment_ifce, com); - break; - case GF_NET_SERVICE_MIGRATION_INFO: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Migration info query from terminal on Service (%p)\n", mpdin->service)); + + case GF_NET_CHAN_SET_SPEED: return segment_ifce->ServiceCommand(segment_ifce, com); - break; + default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received unknown command (%d) on Service (%p)\n",com->command_type, mpdin->service)); - return GF_SERVICE_ERROR; + return segment_ifce->ServiceCommand(segment_ifce, com); } } GF_Err MPD_ChannelGetSLP(GF_InputService *plug, LPNETCHANNEL channel, char **out_data_ptr, u32 *out_data_size, GF_SLHeader *out_sl_hdr, Bool *sl_compressed, GF_Err *out_reception_status, Bool *is_new_data) { - GF_Err e; GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; GF_InputService *segment_ifce = MPD_GetInputServiceForChannel(mpdin, channel); if (!plug || !plug->priv || !segment_ifce) return GF_SERVICE_ERROR; - -// gf_mx_p(mpdin->dl_mutex); - e = segment_ifce->ChannelGetSLP(segment_ifce, channel, out_data_ptr, out_data_size, out_sl_hdr, sl_compressed, out_reception_status, is_new_data); -// gf_mx_v(mpdin->dl_mutex); - return e; + return segment_ifce->ChannelGetSLP(segment_ifce, channel, out_data_ptr, out_data_size, out_sl_hdr, sl_compressed, out_reception_status, is_new_data); } GF_Err MPD_ChannelReleaseSLP(GF_InputService *plug, LPNETCHANNEL channel) { - GF_Err e; GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; GF_InputService *segment_ifce = MPD_GetInputServiceForChannel(mpdin, channel); if (!plug || !plug->priv || !segment_ifce) return GF_SERVICE_ERROR; - -// gf_mx_p(mpdin->dl_mutex); - e = segment_ifce->ChannelReleaseSLP(segment_ifce, channel); -// gf_mx_v(mpdin->dl_mutex); - return e; + return segment_ifce->ChannelReleaseSLP(segment_ifce, channel); } Bool MPD_CanHandleURLInService(GF_InputService *plug, const char *url) { /** - * May arrive when using pid:// URLs into a TS stream - */ + * May arrive when using pid:// URLs into a TS stream + */ GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Can Handle URL In Service (%p) request from terminal for %s\n", mpdin->service, url)); - if (!plug || !plug->priv) return GF_SERVICE_ERROR; - if (mpdin->url && !strcmp(mpdin->url, url)) { - return 1; - } else { - GF_InputService *segment_ifce = NULL; - GF_MPD_Group *group = NULL; - if (mpdin->group_zero_selected) - segment_ifce = mpdin->group_zero_selected->input_module; - if (segment_ifce && segment_ifce->CanHandleURLInService){ - return segment_ifce->CanHandleURLInService(plug, url); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Can Handle URL In Service (%p) request from terminal for %s\n", mpdin->service, url)); + if (!plug || !plug->priv) return GF_SERVICE_ERROR; + if (gf_dash_get_url(mpdin->dash) && !strcmp(gf_dash_get_url(mpdin->dash) , url)) { + return 1; + } else { + GF_MPDGroup *mudta; + GF_InputService *segment_ifce = NULL; + u32 i; + for (i=0;idash); i++) { + if (!gf_dash_is_group_selected(mpdin->dash, i)) continue; + + mudta = gf_dash_get_group_udta(mpdin->dash, i); + segment_ifce = mudta->segment_ifce; + if (mudta && mudta->segment_ifce && mudta->segment_ifce->CanHandleURLInService) { + return mudta->segment_ifce->CanHandleURLInService(plug, url); + } + } + return 0; } - return 0; - } } GF_EXPORT @@ -2859,36 +774,25 @@ GF_BaseInterface *LoadInterface(u32 InterfaceType) plug->ChannelReleaseSLP = MPD_ChannelReleaseSLP; GF_SAFEALLOC(mpdin, GF_MPD_In); plug->priv = mpdin; - mpdin->mpd_thread = gf_th_new("MPD Segment Downloader Thread"); - mpdin->dl_mutex = gf_mx_new("MPD Segment Downloader Mutex"); - mpdin->mimeTypeForM3U8Segments = gf_strdup( M3U8_UNKOWN_MIME_TYPE ); + mpdin->plug = plug; return (GF_BaseInterface *)plug; } GF_EXPORT void ShutdownInterface(GF_BaseInterface *bi) { - GF_InputService *ifcn = (GF_InputService*)bi; - if (ifcn->InterfaceType==GF_NET_CLIENT_INTERFACE) { - GF_MPD_In *mpdin = (GF_MPD_In*)ifcn->priv; + GF_MPD_In *mpdin; + + if (bi->InterfaceType!=GF_NET_CLIENT_INTERFACE) return; + + mpdin = (GF_MPD_In*) ((GF_InputService*)bi)->priv; assert( mpdin ); - if (mpdin->mpd) - gf_mpd_del(mpdin->mpd); - mpdin->mpd = NULL; - if (mpdin->url) - gf_free(mpdin->url); - mpdin->url = NULL; - if (mpdin->mpd_thread) - gf_th_del(mpdin->mpd_thread); - mpdin->mpd_thread = NULL; - if (mpdin->dl_mutex) - gf_mx_del(mpdin->dl_mutex); - mpdin->dl_mutex = NULL; - if (mpdin->mimeTypeForM3U8Segments) - gf_free(mpdin->mimeTypeForM3U8Segments); - mpdin->mimeTypeForM3U8Segments = NULL; - gf_free(mpdin); - ifcn->priv = NULL; - gf_free(bi); - } + + if (mpdin->dash) + gf_dash_del(mpdin->dash); + + gf_free(mpdin); + gf_free(bi); } + +#endif //GPAC_DISABLE_DASH_CLIENT diff --git a/modules/mpegts_in/Makefile b/modules/mpegts_in/Makefile index f9245ac..e8ce986 100644 --- a/modules/mpegts_in/Makefile +++ b/modules/mpegts_in/Makefile @@ -35,10 +35,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/mpegts_in/mpegts_in.c b/modules/mpegts_in/mpegts_in.c index b8b7777..a3e8421 100644 --- a/modules/mpegts_in/mpegts_in.c +++ b/modules/mpegts_in/mpegts_in.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre, Cyril Concolato, Romain Bouqueau + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / M2TS reader module @@ -191,6 +191,9 @@ static GF_ObjectDescriptor *MP2TS_GetOD(M2TSIn *m2ts, GF_M2TS_PES *stream, char break; case GF_M2TS_AUDIO_LATM_AAC: case GF_M2TS_AUDIO_AAC: + case GPAC_OTI_AUDIO_AAC_MPEG2_MP: + case GPAC_OTI_AUDIO_AAC_MPEG2_LCP: + case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP: if (!dsi) { /*turn on parsing to get AAC config NB: we removed "no file regulation" since we may get broken files where PMT declares an AAC stream but no AAC PID is in the MUX @@ -512,6 +515,9 @@ static void M2TS_OnEvent(GF_M2TS_Demuxer *ts, u32 evt_type, void *param) case GF_M2TS_EVT_SL_PCK: MP2TS_SendSLPacket(m2ts, param); break; + case GF_M2TS_EVT_EOS: + gf_term_on_sl_packet(m2ts->service, ((GF_M2TS_PES *)param)->user, NULL, 0, NULL, GF_EOS); + break; case GF_M2TS_EVT_AAC_CFG: { GF_M2TS_PES_PCK *pck = (GF_M2TS_PES_PCK*)param; @@ -787,7 +793,7 @@ static GF_Err M2TS_ConnectService(GF_InputService *plug, GF_ClientService *serv, } opt = gf_modules_get_option((GF_BaseInterface *)m2ts->owner, "DSMCC", "Activated"); - if (opt && !strcmp(opt, "true")) { + if (opt && !strcmp(opt, "yes")) { gf_m2ts_demux_dmscc_init(m2ts->ts); } @@ -1155,8 +1161,8 @@ void DeleteM2TSReader(void *ifce) gf_free(prog); } gf_list_del(m2ts->ts->requested_progs); + m2ts->ts->requested_progs = NULL; } - m2ts->ts->requested_progs = NULL; if( m2ts->ts->requested_pids ){ count = gf_list_count(m2ts->ts->requested_pids); for (i = 0; i < count; i++) { @@ -1164,8 +1170,8 @@ void DeleteM2TSReader(void *ifce) gf_free(prog); } gf_list_del(m2ts->ts->requested_pids); + m2ts->ts->requested_pids = NULL; } - m2ts->ts->requested_pids = NULL; if (m2ts->network_buffer) gf_free(m2ts->network_buffer); m2ts->network_buffer = NULL; diff --git a/modules/odf_dec/Makefile b/modules/odf_dec/Makefile index 4192681..6ef0f04 100644 --- a/modules/odf_dec/Makefile +++ b/modules/odf_dec/Makefile @@ -34,11 +34,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_odf_dec-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/odf_dec/odf_dec.c b/modules/odf_dec/odf_dec.c index c2bd4c4..d39bc9a 100644 --- a/modules/odf_dec/odf_dec.c +++ b/modules/odf_dec/odf_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / OD decoder module diff --git a/modules/ogg/Makefile b/modules/ogg/Makefile index 1e99a8b..76212f2 100644 --- a/modules/ogg/Makefile +++ b/modules/ogg/Makefile @@ -68,11 +68,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ogg/ogg_in.c b/modules/ogg/ogg_in.c index 522557f..a2e3409 100644 --- a/modules/ogg/ogg_in.c +++ b/modules/ogg/ogg_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / XIPH.org module diff --git a/modules/ogg/ogg_in.h b/modules/ogg/ogg_in.h index 2b12b08..82145a6 100644 --- a/modules/ogg/ogg_in.h +++ b/modules/ogg/ogg_in.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / XIPH.org module diff --git a/modules/ogg/ogg_load.c b/modules/ogg/ogg_load.c index c32c916..642a503 100644 --- a/modules/ogg/ogg_load.c +++ b/modules/ogg/ogg_load.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / XIPH.org module diff --git a/modules/ogg/theora_dec.c b/modules/ogg/theora_dec.c index 43df4cf..3c2e921 100644 --- a/modules/ogg/theora_dec.c +++ b/modules/ogg/theora_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / XIPH.org module diff --git a/modules/ogg/vorbis_dec.c b/modules/ogg/vorbis_dec.c index 5200501..8486179 100644 --- a/modules/ogg/vorbis_dec.c +++ b/modules/ogg/vorbis_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / XIPH.org module diff --git a/modules/opencv_is/Makefile b/modules/opencv_is/Makefile index b0b2e5b..8e1b297 100644 --- a/modules/opencv_is/Makefile +++ b/modules/opencv_is/Makefile @@ -34,10 +34,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/opencv_is/opencv_is.c b/modules/opencv_is/opencv_is.c index 643a0a1..49ae1d2 100644 --- a/modules/opencv_is/opencv_is.c +++ b/modules/opencv_is/opencv_is.c @@ -1,11 +1,11 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * - * This file is part of GPAC / Dummy input module + * This file is part of GPAC / OpenCV demo module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -104,7 +104,7 @@ void detect_and_draw_objects(GF_InputSensorDevice *ifce, IplImage* image, (theRealY+theRealHeight)*scale), CV_RGB(0,255,0), 3, 8, 0 ); - fprintf(stdout, "translation selon X : %d - translation selon Y : %d\n", (theRealX - prev_x0), (theRealY -prev_y0) ); + GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[OpenCV] translation selon X : %d - translation selon Y : %d\n", (theRealX - prev_x0), (theRealY -prev_y0) )); /*send data frame to GPAC*/ { diff --git a/modules/opensvc_dec/Makefile b/modules/opensvc_dec/Makefile index fa9e923..4222991 100644 --- a/modules/opensvc_dec/Makefile +++ b/modules/opensvc_dec/Makefile @@ -30,10 +30,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/opensvc_dec/opensvc_dec.c b/modules/opensvc_dec/opensvc_dec.c index 041bb06..0690d0e 100644 --- a/modules/opensvc_dec/opensvc_dec.c +++ b/modules/opensvc_dec/opensvc_dec.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Telecom ParisTech 2010- - * Author(s): Jean Le Feuvre + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / OpenSVC Decoder module diff --git a/modules/osd/Makefile b/modules/osd/Makefile index 2920b65..8f24113 100644 --- a/modules/osd/Makefile +++ b/modules/osd/Makefile @@ -32,10 +32,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/osd/osd.c b/modules/osd/osd.c index f4c6f6c..817da8b 100644 --- a/modules/osd/osd.c +++ b/modules/osd/osd.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2011-20XX ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2011-2012 * All rights reserved * * This file is part of GPAC / User Event Recorder sub-project diff --git a/modules/oss_audio/Makefile b/modules/oss_audio/Makefile index 2deafcd..3ed6f68 100644 --- a/modules/oss_audio/Makefile +++ b/modules/oss_audio/Makefile @@ -40,11 +40,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_oss_audio-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static $(OSS_LDFLAGS) endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/oss_audio/oss.c b/modules/oss_audio/oss.c index ff6a5b6..c243095 100644 --- a/modules/oss_audio/oss.c +++ b/modules/oss_audio/oss.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / linux_oss audio render module diff --git a/modules/platinum/GPACFileMediaServer.cpp b/modules/platinum/GPACFileMediaServer.cpp index cdc337d..2dc9ba2 100644 --- a/modules/platinum/GPACFileMediaServer.cpp +++ b/modules/platinum/GPACFileMediaServer.cpp @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module @@ -497,7 +497,7 @@ void GPAC_FileMediaServer::ShareVirtualResource(const char *res_uri, const char GPAC_VirtualFile vres(the_uri, res_val, res_mime, temporary); m_VirtualFiles.Add(vres); - fprintf(stdout, "sharing virtual file %s as %s\n", res_uri, (const char *)the_uri); + GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[UPnP] sharing virtual file %s as %s\n", res_uri, (const char *)the_uri)); } NPT_Result @@ -518,7 +518,7 @@ GPAC_FileMediaServer::ServeVirtualFile(NPT_HttpResponse& response, return NPT_SUCCESS; } - fprintf(stdout, "Serving virtual file %s\n", vfile->m_Content.GetChars()); + GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[UPnP] Serving virtual file %s\n", vfile->m_Content.GetChars())); NPT_HttpEntity* entity = new NPT_HttpEntity(); entity->SetContentLength(total_len); diff --git a/modules/platinum/GPACFileMediaServer.h b/modules/platinum/GPACFileMediaServer.h index cdb2dfd..160df3d 100644 --- a/modules/platinum/GPACFileMediaServer.h +++ b/modules/platinum/GPACFileMediaServer.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module diff --git a/modules/platinum/GPACMediaController.cpp b/modules/platinum/GPACMediaController.cpp index e91e133..d029265 100644 --- a/modules/platinum/GPACMediaController.cpp +++ b/modules/platinum/GPACMediaController.cpp @@ -2,8 +2,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module diff --git a/modules/platinum/GPACMediaController.h b/modules/platinum/GPACMediaController.h index 5236f58..4db8a69 100644 --- a/modules/platinum/GPACMediaController.h +++ b/modules/platinum/GPACMediaController.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module diff --git a/modules/platinum/GPACMediaRenderer.cpp b/modules/platinum/GPACMediaRenderer.cpp index 6feb58e..7ac2285 100644 --- a/modules/platinum/GPACMediaRenderer.cpp +++ b/modules/platinum/GPACMediaRenderer.cpp @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module diff --git a/modules/platinum/GPACMediaRenderer.h b/modules/platinum/GPACMediaRenderer.h index 3e8e996..afb5d23 100644 --- a/modules/platinum/GPACMediaRenderer.h +++ b/modules/platinum/GPACMediaRenderer.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module diff --git a/modules/platinum/GPACPlatinum.cpp b/modules/platinum/GPACPlatinum.cpp index e998ca3..baa6be9 100644 --- a/modules/platinum/GPACPlatinum.cpp +++ b/modules/platinum/GPACPlatinum.cpp @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module @@ -525,8 +525,13 @@ void GF_UPnP::OnMediaServerAdd(PLT_DeviceDataReference& device, int added) LockJavascript(0); } -static JSBool upnpdevice_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) +static SMJS_DECL_FUNC_PROP_GET( upnpdevice_getProperty) { +#ifdef USE_FFDEV_15 + JSObject *obj = (JSObject *) __hobj; + jsid id = (jsid) __hid; +#endif + char *prop_name; GPAC_DeviceItem *dev = (GPAC_DeviceItem *)SMJS_GET_PRIVATE(c, obj); if (!dev) return JS_FALSE; @@ -625,7 +630,7 @@ void GF_UPnP::OnDeviceAdd(GPAC_DeviceItem *item, int added) if (added) { item->js_ctx = m_pJSCtx; - item->obj = JS_NewObject(m_pJSCtx, &upnpGenericDeviceClass, 0, 0); + item->obj = JS_NewObject(m_pJSCtx, &upnpGenericDeviceClass._class, 0, 0); item->m_pUPnP = this; gf_js_add_root(m_pJSCtx, &item->obj, GF_JSGC_OBJECT); SMJS_SET_PRIVATE(item->js_ctx, item->obj, item); @@ -641,8 +646,14 @@ void GF_UPnP::OnDeviceAdd(GPAC_DeviceItem *item, int added) LockJavascript(0); } -static JSBool upnp_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) +static SMJS_DECL_FUNC_PROP_GET( upnp_getProperty) { +#ifdef USE_FFDEV_15 + JSObject *obj = (JSObject *) __hobj; + jsid id = (jsid) __hid; +#endif + + char *prop_name; GF_UPnP *upnp = (GF_UPnP *)SMJS_GET_PRIVATE(c, obj); if (!upnp) return JS_FALSE; @@ -673,8 +684,12 @@ static JSBool upnp_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js return JS_TRUE; } -static JSBool upnp_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) +static SMJS_DECL_FUNC_PROP_SET(upnp_setProperty) { +#ifdef USE_FFDEV_15 + JSObject *obj = (JSObject *) __hobj; + jsid id = (jsid) __hid; +#endif char *prop_name; GF_UPnP *upnp = (GF_UPnP *)SMJS_GET_PRIVATE(c, obj); if (!upnp) return JS_FALSE; @@ -721,7 +736,7 @@ static JSBool SMJS_FUNCTION(upnp_get_device) if (!device) return JS_FALSE; if (!device->obj) { device->js_ctx = upnp->m_pJSCtx; - device->obj = JS_NewObject(upnp->m_pJSCtx, &upnp->upnpGenericDeviceClass, 0, 0); + device->obj = JS_NewObject(upnp->m_pJSCtx, &upnp->upnpGenericDeviceClass._class, 0, 0); device->m_pUPnP = upnp; gf_js_add_root(upnp->m_pJSCtx, &device->obj, GF_JSGC_OBJECT); SMJS_SET_PRIVATE(device->js_ctx, device->obj, device); @@ -967,7 +982,7 @@ static JSBool SMJS_FUNCTION(upnp_get_renderer) } if (!mr) return JS_FALSE; - s_obj = JS_NewObject(c, &upnp->upnpDeviceClass, 0, 0); + s_obj = JS_NewObject(c, &upnp->upnpDeviceClass._class, 0, 0); SMJS_SET_PRIVATE(c, s_obj, upnp); JS_DefineProperty(c, s_obj, "Name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, mr->m_device->GetFriendlyName()) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1087,7 +1102,7 @@ static JSBool SMJS_FUNCTION(upnp_server_get_file) server->m_BrowseResults->Get(id, mo); if (!mo) return JS_TRUE; - f_obj = JS_NewObject(c, &upnp->upnpDeviceClass, 0, 0); + f_obj = JS_NewObject(c, &upnp->upnpDeviceClass._class, 0, 0); SMJS_SET_PRIVATE(c, f_obj, mo); JS_DefineProperty(c, f_obj, "ObjectID", STRING_TO_JSVAL( JS_NewStringCopyZ(c, mo->m_ObjectID)), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1149,7 +1164,7 @@ static JSBool SMJS_FUNCTION(upnp_get_server) SMJS_FREE(c, uuid); } if (!ms) return JS_FALSE; - s_obj = JS_NewObject(c, &upnp->upnpDeviceClass, 0, 0); + s_obj = JS_NewObject(c, &upnp->upnpDeviceClass._class, 0, 0); SMJS_SET_PRIVATE(c, s_obj, upnp); JS_DefineProperty(c, s_obj, "Name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ms->m_device->GetFriendlyName()) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1374,7 +1389,7 @@ static GPAC_GenericDevice *upnp_create_generic_device(GF_UPnP *upnp, JSObject*gl device->m_pUPnP = upnp; device->js_source = ""; - device->obj = JS_NewObject(upnp->m_pJSCtx, &upnp->upnpDeviceClass, 0, global); + device->obj = JS_NewObject(upnp->m_pJSCtx, &upnp->upnpDeviceClass._class, 0, global); gf_js_add_root(upnp->m_pJSCtx, &device->obj, GF_JSGC_OBJECT); JS_DefineProperty(upnp->m_pJSCtx, device->obj, "Name", STRING_TO_JSVAL( JS_NewStringCopyZ(upnp->m_pJSCtx, name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1499,8 +1514,8 @@ Bool GF_UPnP::LoadJS(GF_TermExtJS *param) /*setup JS bindings*/ JS_SETUP_CLASS(upnpClass, "UPNPMANAGER", JSCLASS_HAS_PRIVATE, upnp_getProperty, upnp_setProperty, JS_FinalizeStub); - JS_InitClass(m_pJSCtx, (JSObject*)param->global, 0, &upnpClass, 0, 0, upnpClassProps, upnpClassFuncs, 0, 0); - m_pObj = JS_DefineObject(m_pJSCtx, (JSObject*)param->global, "UPnP", &upnpClass, 0, 0); + GF_JS_InitClass(m_pJSCtx, (JSObject*)param->global, 0, &upnpClass, 0, 0, upnpClassProps, upnpClassFuncs, 0, 0); + m_pObj = JS_DefineObject(m_pJSCtx, (JSObject*)param->global, "UPnP", &upnpClass._class, 0, 0); SMJS_SET_PRIVATE(m_pJSCtx, m_pObj, this); JS_SETUP_CLASS(upnpDeviceClass, "UPNPAVDEVICE", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub); @@ -1515,10 +1530,10 @@ Bool GF_UPnP::LoadJS(GF_TermExtJS *param) SMJS_FUNCTION_SPEC(0, 0, 0) }; JS_SETUP_CLASS(upnpGenericDeviceClass, "UPNPDEVICE", JSCLASS_HAS_PRIVATE, upnpdevice_getProperty, JS_PropertyStub_forSetter, JS_FinalizeStub); - JS_InitClass(m_pJSCtx, (JSObject*)param->global, 0, &upnpGenericDeviceClass, 0, 0, upnpDeviceClassProps, upnpDeviceClassFuncs, 0, 0); + GF_JS_InitClass(m_pJSCtx, (JSObject*)param->global, 0, &upnpGenericDeviceClass, 0, 0, upnpDeviceClassProps, upnpDeviceClassFuncs, 0, 0); JS_SETUP_CLASS(upnpServiceClass, "UPNPSERVICEDEVICE", JSCLASS_HAS_PRIVATE, upnpservice_getProperty, JS_PropertyStub_forSetter, JS_FinalizeStub); - JS_InitClass(m_pJSCtx, (JSObject*)param->global, 0, &upnpServiceClass, 0, 0, 0, 0, 0, 0); + GF_JS_InitClass(m_pJSCtx, (JSObject*)param->global, 0, &upnpServiceClass, 0, 0, 0, 0, 0, 0); m_nbJSInstances=1; @@ -1583,7 +1598,7 @@ static Bool upnp_process(GF_TermExt *termext, u32 action, void *param) if (!opt) { #ifdef GPAC_CONFIG_DARWIN opt = "no"; - fprintf(stdout, "Disabling UPnP - to enable it, modify section [UPnP] key \"Enabled\" in /Users/yourname/.gpacrc"); + GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[UPnP] Disabling UPnP - to enable it, modify section [UPnP] key \"Enabled\" in /Users/yourname/.gpacrc")); #else opt = "yes"; #endif diff --git a/modules/platinum/GPACPlatinum.h b/modules/platinum/GPACPlatinum.h index e7fceef..74890ff 100644 --- a/modules/platinum/GPACPlatinum.h +++ b/modules/platinum/GPACPlatinum.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module @@ -114,10 +114,10 @@ public: u32 m_nbJSInstances; JSContext *m_pJSCtx; JSObject *m_pObj; - JSClass upnpClass; - JSClass upnpDeviceClass; - JSClass upnpGenericDeviceClass; - JSClass upnpServiceClass; + GF_JSClass upnpClass; + GF_JSClass upnpDeviceClass; + GF_JSClass upnpGenericDeviceClass; + GF_JSClass upnpServiceClass; GF_List *m_Devices; u32 last_time, upnp_init_time; @@ -140,7 +140,7 @@ public: }; #ifdef GPAC_HAS_SPIDERMONKEY -JSBool upnpservice_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp); +SMJS_DECL_FUNC_PROP_GET( upnpservice_getProperty); #endif void format_time_string(char *str, Double dur); diff --git a/modules/platinum/GenericDevice.cpp b/modules/platinum/GenericDevice.cpp index 962acf4..33e077d 100644 --- a/modules/platinum/GenericDevice.cpp +++ b/modules/platinum/GenericDevice.cpp @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module @@ -173,7 +173,6 @@ static JSBool SMJS_FUNCTION(upnp_service_set_listener) return JS_TRUE; } - static JSBool SMJS_FUNCTION(upnp_service_set_action_listener) { PLT_ActionDesc *action; @@ -247,8 +246,12 @@ static JSBool SMJS_FUNCTION(upnp_service_get_scpd) return JS_TRUE; } -JSBool upnpservice_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) +SMJS_DECL_FUNC_PROP_GET( upnpservice_getProperty) { +#ifdef USE_FFDEV_15 + JSObject *obj = (JSObject *) __hobj; + jsid id = (jsid) __hid; +#endif char *prop_name; GPAC_ServiceItem *service = (GPAC_ServiceItem *)SMJS_GET_PRIVATE(c, obj); if (!service) return JS_FALSE; @@ -424,7 +427,7 @@ GPAC_ServiceItem *GPAC_DeviceItem::FindService(const char *type) #ifdef GPAC_HAS_SPIDERMONKEY serv->js_ctx = js_ctx; - serv->obj = JS_NewObject(serv->js_ctx, &m_pUPnP->upnpServiceClass, 0, obj); + serv->obj = JS_NewObject(serv->js_ctx, &m_pUPnP->upnpServiceClass._class, 0, obj); gf_js_add_root(serv->js_ctx, &serv->obj, GF_JSGC_OBJECT); SMJS_SET_PRIVATE(serv->js_ctx, serv->obj, serv); JS_DefineProperty(serv->js_ctx, serv->obj, "Name", STRING_TO_JSVAL( JS_NewStringCopyZ(serv->js_ctx, service->GetServiceID()) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -640,7 +643,7 @@ NPT_Result GPAC_GenericController::OnActionResponse(NPT_Result res, PLT_ActionRe GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[UPnP] Calling handler for response %s\n", (char *) action->GetActionDesc().GetName())); - act_obj = JS_NewObject(serv->js_ctx, &item->m_pUPnP->upnpDeviceClass, 0, item->obj); + act_obj = JS_NewObject(serv->js_ctx, &item->m_pUPnP->upnpDeviceClass._class, 0, item->obj); SMJS_SET_PRIVATE(serv->js_ctx, act_obj, (void *)action.AsPointer() ); JS_DefineFunction(serv->js_ctx, act_obj, "GetArgumentValue", upnp_action_get_argument_value, 1, 0); JS_DefineFunction(serv->js_ctx, act_obj, "GetErrorCode", upnp_action_get_error_code, 1, 0); @@ -782,7 +785,7 @@ static JSBool SMJS_FUNCTION(upnp_service_set_state_variable) void GPAC_Service::SetupJS(JSContext *c, GF_UPnP *upnp, JSObject *parent) { m_pCtx = c; - m_pObj = JS_NewObject(c, &upnp->upnpDeviceClass, 0, parent); + m_pObj = JS_NewObject(c, &upnp->upnpDeviceClass._class, 0, parent); gf_js_add_root(m_pCtx, &m_pObj, GF_JSGC_OBJECT); SMJS_SET_PRIVATE(c, m_pObj, this); JS_DefineFunction(c, m_pObj, "SetStateVariable", upnp_service_set_state_variable, 2, 0); @@ -963,7 +966,7 @@ GPAC_GenericDevice::OnAction(PLT_ActionReference& action, m_pUPnP->LockJavascript(1); - JSObject *js_action = JS_NewObject(m_pUPnP->m_pJSCtx, &m_pUPnP->upnpDeviceClass, 0, 0); + JSObject *js_action = JS_NewObject(m_pUPnP->m_pJSCtx, &m_pUPnP->upnpDeviceClass._class, 0, 0); argv[0] = OBJECT_TO_JSVAL(js_action); SMJS_SET_PRIVATE(m_pUPnP->m_pJSCtx, js_action, this); diff --git a/modules/platinum/GenericDevice.h b/modules/platinum/GenericDevice.h index e498684..70e38a9 100644 --- a/modules/platinum/GenericDevice.h +++ b/modules/platinum/GenericDevice.h @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2009- Telecom ParisTech + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Platinum UPnP module diff --git a/modules/platinum/Makefile b/modules/platinum/Makefile index f5f8dda..cc49c88 100644 --- a/modules/platinum/Makefile +++ b/modules/platinum/Makefile @@ -18,7 +18,7 @@ LINKLIBS= -lgpac -lPlatinum -lPltMediaServer -lPltMediaConnect -lPltMediaRendere LOCAL_LIB=../../bin/gcc -L../../extra_lib/lib/gcc #common objects -OBJS=GPACFileMediaServer.o GPACMediaController.o GPACMediaRenderer.o GenericDevice.o GPACPlatinum.o +OBJS=GPACFileMediaServer.o GPACMediaController.o GPACMediaRenderer.o GenericDevice.o GPACPlatinum.o ifeq ($(CONFIG_JS),no) else @@ -44,11 +44,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CXX) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) - -%.o: %.cpp - $(CXX) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/pulseaudio/Makefile b/modules/pulseaudio/Makefile index cc50a42..639807d 100644 --- a/modules/pulseaudio/Makefile +++ b/modules/pulseaudio/Makefile @@ -27,11 +27,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -L/usr/lib -lpulse-simple - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/pulseaudio/pulseaudio.c b/modules/pulseaudio/pulseaudio.c index 073fcc4..ff09b94 100644 --- a/modules/pulseaudio/pulseaudio.c +++ b/modules/pulseaudio/pulseaudio.c @@ -1,8 +1,6 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 - * All rights reserved * Copyright (c) Pierre Souchay 2008 * * History: diff --git a/modules/raw_out/Makefile b/modules/raw_out/Makefile index ed6e0dd..e518da1 100644 --- a/modules/raw_out/Makefile +++ b/modules/raw_out/Makefile @@ -43,10 +43,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/raw_out/raw_video.c b/modules/raw_out/raw_video.c index ad73a88..875e94b 100644 --- a/modules/raw_out/raw_video.c +++ b/modules/raw_out/raw_video.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module diff --git a/modules/redirect_av/Makefile b/modules/redirect_av/Makefile index c514a1b..acbec25 100644 --- a/modules/redirect_av/Makefile +++ b/modules/redirect_av/Makefile @@ -33,10 +33,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/redirect_av/ffmpeg_ts_muxer.c b/modules/redirect_av/ffmpeg_ts_muxer.c index 2489fec..85c6360 100644 --- a/modules/redirect_av/ffmpeg_ts_muxer.c +++ b/modules/redirect_av/ffmpeg_ts_muxer.c @@ -1,6 +1,19 @@ #include "ts_muxer.h" #include #include + +#ifdef AVIO_FLAG_WRITE +#include +#define url_fopen avio_open +#define url_fclose avio_close +#define URL_WRONLY AVIO_FLAG_WRITE +#define av_write_header(__a) avformat_write_header(__a, NULL) +#define dump_format av_dump_format + +#define SAMPLE_FMT_S16 AV_SAMPLE_FMT_S16 +#endif + + #define STREAM_FRAME_RATE 25 /* 25 images/s */ #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE)) #define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */ @@ -87,8 +100,7 @@ static Bool ts_interleave_thread_run(void *param) { audioKbps = audioSize * 8000 / (now-start) / 1024; audioSize = videoSize = 0; start = now; - printf("\rPTS audio="LLU" ("LLU"kbps), video="LLU" ("LLU"kbps)", audio_pts, audioKbps, video_pts, videoKbps); - fflush(stdout); + GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("\rPTS audio="LLU" ("LLU"kbps), video="LLU" ("LLU"kbps)", audio_pts, audioKbps, video_pts, videoKbps)); } } /* write interleaved audio and video frames */ @@ -222,13 +234,17 @@ GF_AbstractTSMuxer * ts_amux_new(GF_AVRedirect * avr, u32 videoBitrateInBitsPerS } //av_set_pts_info(ts->audio_st, 33, 1, audioBitRateInBitsPerSec); - /* set the output parameters (must be done even if no + +#ifndef AVIO_FLAG_WRITE + /* set the output parameters (must be done even if no parameters). */ if (av_set_parameters(ts->oc, NULL) < 0) { fprintf(stderr, "Invalid output format parameters\n"); return NULL; } - dump_format(ts->oc, 0, avr->destination, 1); +#endif + + dump_format(ts->oc, 0, avr->destination, 1); GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[AVRedirect] DUMPING to %s...\n", ts->destination)); if (avcodec_open(ts->video_st->codec, avr->videoCodec) < 0) { @@ -325,7 +341,7 @@ Bool ts_encode_audio_frame(GF_AbstractTSMuxer * ts, uint8_t * data, int encoded, pkt->stream_index= ts->audio_st->index; pkt->data = data; pkt->size = encoded; - //printf("AUDIO PTS="LLU" was: "LLU" (%p)\n", pkt->pts, pts, pl); + //fprintf(stderr, "AUDIO PTS="LLU" was: "LLU" (%p)\n", pkt->pts, pts, pl); gf_mx_p(ts->audioMx); if (!ts->audioPackets) ts->audioPackets = pl; @@ -360,7 +376,7 @@ Bool ts_encode_video_frame(GF_AbstractTSMuxer* ts, uint8_t* data, int encoded) { pkt->stream_index= ts->video_st->index; pkt->data= data; pkt->size= encoded; - //printf("VIDEO PTS="LLU" was: "LLU" (%p)\n", pkt->pts, ts->video_st->codec->coded_frame->pts, pl); + //fprintf(stderr, "VIDEO PTS="LLU" was: "LLU" (%p)\n", pkt->pts, ts->video_st->codec->coded_frame->pts, pl); gf_mx_p(ts->videoMx); if (!ts->videoPackets) ts->videoPackets = pl; diff --git a/modules/redirect_av/gpac_ts_muxer.c b/modules/redirect_av/gpac_ts_muxer.c index 9a657a9..8db2619 100644 --- a/modules/redirect_av/gpac_ts_muxer.c +++ b/modules/redirect_av/gpac_ts_muxer.c @@ -74,18 +74,18 @@ static GF_Err void_input_ctrl(GF_ESInterface *ifce, u32 act_type, void *param) /* case GF_ESI_INPUT_DATA_PULL: gf_mx_p(ts->encodingMutex); if (ts->frameTimeEncoded > ts->frameTimeSentOverTS) { - //printf("Data PULL, avr=%p, avr->video=%p, encoded="LLU", sent over TS="LLU"\n", avr, &avr->video, avr->frameTimeEncoded, avr->frameTimeSentOverTS); + //fprintf(stderr, "Data PULL, avr=%p, avr->video=%p, encoded="LLU", sent over TS="LLU"\n", avr, &avr->video, avr->frameTimeEncoded, avr->frameTimeSentOverTS); ts->video->output_ctrl( ts->video, GF_ESI_OUTPUT_DATA_DISPATCH, &(ts->videoCurrentTSPacket)); ts->frameTimeSentOverTS = ts->frameTime; } else { - //printf("Data PULL IGNORED : encoded = "LLU", sent on TS="LLU"\n", avr->frameTimeEncoded, avr->frameTimeSentOverTS); + //fprintf(stderr, "Data PULL IGNORED : encoded = "LLU", sent on TS="LLU"\n", avr->frameTimeEncoded, avr->frameTimeSentOverTS); } gf_mx_v(avr->encodingMutex); break;*/ case GF_ESI_INPUT_DATA_RELEASE: break; default: - printf("Asking unknown : %u\n", act_type); + fprintf(stderr, "Asking unknown : %u\n", act_type); } return GF_OK; } @@ -100,11 +100,8 @@ Bool ts_encode_video_frame(GF_AbstractTSMuxer * ts, AVFrame * encodedFrame, uint ts->videoCurrentTSPacket.dts = ts->videoCurrentTSPacket.cts = gf_m2ts_get_sys_clock(ts->muxer); ts->videoCurrentTSPacket.data = data; ts->videoCurrentTSPacket.data_len = encoded; - //printf("\rSending frame DTS="LLU", CTS="LLU", len=%u, FPS=%u, delta=%u...", ts->videoCurrentTSPacket.dts, avr->videoCurrentTSPacket.cts, avr->videoCurrentTSPacket.data_len, fps, currentFrameTimeProcessed - lastEncodedFrameTime); - fflush(stdout); ts->videoCurrentTSPacket.flags = GF_ESI_DATA_HAS_CTS | GF_ESI_DATA_HAS_DTS; //if (ts_packets_sent == 0) { - // printf("First Packet !\n"); ts->videoCurrentTSPacket.flags|=GF_ESI_DATA_AU_START|GF_ESI_DATA_AU_END ; //} void_input_ctrl(ts->video, GF_ESI_INPUT_DATA_PULL, NULL); diff --git a/modules/redirect_av/redirect_av.c b/modules/redirect_av/redirect_av.c index b89a490..0dd73ab 100644 --- a/modules/redirect_av/redirect_av.c +++ b/modules/redirect_av/redirect_av.c @@ -58,8 +58,9 @@ #include "ts_muxer.h" #define USE_GPAC_MPEG2TS -#undef USE_GPAC_MPEG2TS +#undef USE_GPAC_MPEG2TS +//#define MULTITHREAD_REDIRECT_AV #define REDIRECT_AV_AUDIO_ENABLED 1 #ifdef USE_GPAC_MPEG2TS @@ -149,10 +150,10 @@ static Bool audio_encoding_thread_run(void *param) goto exit; } - printf("******* Audio Codec Context = %d/%d, start="LLU", frame_size=%u\n", ctx->time_base.num, ctx->time_base.den, ctx->timecode_frame_start, ctx->frame_size); + fprintf(stderr, "******* Audio Codec Context = %d/%d, start="LLU", frame_size=%u\n", ctx->time_base.num, ctx->time_base.den, ctx->timecode_frame_start, ctx->frame_size); samplesReaden = ctx->frame_size * ctx->channels; - //printf("SETUP input sample size=%u, output samplesize=%u, buffsize=%u, samplesReaden=%u\n", ctx->input_sample_size, ctx->frame_size, sizeof(outbuf), samplesReaden); + //fprintf(stderr, "SETUP input sample size=%u, output samplesize=%u, buffsize=%u, samplesReaden=%u\n", ctx->input_sample_size, ctx->frame_size, sizeof(outbuf), samplesReaden); // 2 chars are needed for each short toRead = samplesReaden * 2; inBuffSize = toRead; @@ -242,7 +243,7 @@ static Bool video_encoding_thread_run(void *param) if (!ctx) { goto exit; } - printf("******* Video Codec Context = %d/%d, start="LLU"\n", ctx->time_base.num, ctx->time_base.den, ctx->timecode_frame_start); + fprintf(stderr, "******* Video Codec Context = %d/%d, start="LLU"\n", ctx->time_base.num, ctx->time_base.den, ctx->timecode_frame_start); while (avr->is_running) { { gf_mx_p(avr->frameMutex); @@ -257,7 +258,7 @@ static Bool video_encoding_thread_run(void *param) assert( currentFrameTimeProcessed != avr->frameTime); currentFrameTimeProcessed = avr->frameTime; { - avpicture_fill ( ( AVPicture * ) avr->RGBpicture, avr->frame, PIX_FMT_RGB24, avr->srcWidth, avr->srcHeight ); + avpicture_fill ( ( AVPicture * ) avr->RGBpicture, avr->frame, PIX_FMT_RGB24, avr->srcWidth, avr->srcHeight ); assert( avr->swsContext ); sws_scale ( avr->swsContext, #ifdef USE_AVCODEC2 @@ -278,20 +279,20 @@ static Bool video_encoding_thread_run(void *param) if (avr->encode) { int written; - //u32 sysclock = gf_sys_clock(); + u32 sysclock_begin = gf_sys_clock(), sysclock_end=0; avr->YUVpicture->pts = currentFrameTimeProcessed; - //printf("Encoding frame PTS="LLU", frameNum=%u, time=%u...", avr->YUVpicture->pts, avr->YUVpicture->coded_picture_number, currentFrameTimeProcessed); - written = avcodec_encode_video ( ctx, avr->videoOutbuf, avr->videoOutbufSize, avr->YUVpicture ); - //ctx->coded_frame->pts = currentFrameTimeProcessed; - if ( written < 0 ) - { + written = avcodec_encode_video ( ctx, avr->videoOutbuf, avr->videoOutbufSize, avr->YUVpicture); + sysclock_end = gf_sys_clock(); + GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("Encoding frame PTS="LLD", frameNum=%u, time="LLU", size=%d\t in %ums\n", avr->YUVpicture->pts, avr->YUVpicture->coded_picture_number, currentFrameTimeProcessed, written, sysclock_end-sysclock_begin)); + ctx->coded_frame->pts = currentFrameTimeProcessed; + + if (written<0) { GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error while encoding video frame =%d\n", written ) ); - } else - if ( written > 0 ) - { + } else { + if (written>0) ts_encode_video_frame(avr->ts_implementation, avr->videoOutbuf, written); - } - lastEncodedFrameTime = currentFrameTimeProcessed; + lastEncodedFrameTime = currentFrameTimeProcessed; + } } } } @@ -335,7 +336,7 @@ static Bool start_if_needed(GF_AVRedirect *avr) { #endif /* AVR_DUMP_RAW_AVI */ GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[AVRedirect] Initializing...\n")); if (!avr->pcmAudio) - avr->pcmAudio = gf_ringbuffer_new(32768); + avr->pcmAudio = gf_ringbuffer_new(48000*2*2); //1s of 16b stereo 48000Hz /* Setting up the video encoding ... */ { @@ -460,6 +461,7 @@ static void avr_on_video_frame ( void *udta, u32 time ) GF_Err e; GF_VideoSurface fb; GF_AVRedirect *avr = ( GF_AVRedirect * ) udta; + if (start_if_needed(avr)) return; gf_mx_p(avr->frameMutex); @@ -469,20 +471,25 @@ static void avr_on_video_frame ( void *udta, u32 time ) GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error grabing frame buffer %s\n", gf_error_to_string ( e ) ) ); return; } - /*convert frame*/ - for ( i=0; iframe + i * fb.width * 3; - char *src = fb.video_buffer + i * fb.pitch_y; - for ( j=0; j RGB24*/ + for (i=0; iframe + i * fb.width * 3; + char *src = fb.video_buffer + i * fb.pitch_y; + for (j=0; jframe+i*fb.width*3, fb.video_buffer+i*fb.pitch_y, fb.width*3); + } avr->frameTime = time; gf_mx_v(avr->frameMutex); gf_sc_release_screen_buffer ( avr->term->compositor, &fb ); @@ -530,7 +537,7 @@ static Bool ts_thread_run(void *param) gf_sleep(1); gf_mx_p(avr->tsMutex); } - printf("avr->frameTimeEncoded="LLU"\n", avr->frameTimeEncoded); + fprintf(stderr, "avr->frameTimeEncoded="LLU"\n", avr->frameTimeEncoded); while (avr->is_running) { e = sendTSMux(avr); @@ -610,8 +617,10 @@ static Bool avr_process ( GF_TermExt *termext, u32 action, void *param ) GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("Failed to lock global resource 'AVRedirect:output', another GPAC instance must be running, disabling AVRedirect\n")); return 0; } +#ifndef AVIO_FLAG_WRITE /* must be called before using avcodec lib */ avcodec_init(); +#endif /* register all the codecs */ avcodec_register_all(); @@ -680,7 +689,7 @@ static Bool avr_process ( GF_TermExt *termext, u32 action, void *param ) char *endPtr = NULL; unsigned int x = strtoul(opt, &endPtr, 10); if (endPtr == opt || x > 65536) { - printf("Failed to parse : %s\n", opt); + fprintf(stderr, "Failed to parse : %s\n", opt); opt = NULL; } else avr->udp_port = (u16) x; diff --git a/modules/rtp_in/Makefile b/modules/rtp_in/Makefile index ed25165..6009968 100644 --- a/modules/rtp_in/Makefile +++ b/modules/rtp_in/Makefile @@ -36,10 +36,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/rtp_in/rtp_in.c b/modules/rtp_in/rtp_in.c index e1a94a7..d11c25b 100644 --- a/modules/rtp_in/rtp_in.c +++ b/modules/rtp_in/rtp_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rtp_in/rtp_in.h b/modules/rtp_in/rtp_in.h index 1ce20ba..26af97d 100644 --- a/modules/rtp_in/rtp_in.h +++ b/modules/rtp_in/rtp_in.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rtp_in/rtp_session.c b/modules/rtp_in/rtp_session.c index 2f67cf9..de08369 100644 --- a/modules/rtp_in/rtp_session.c +++ b/modules/rtp_in/rtp_session.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rtp_in/rtp_signaling.c b/modules/rtp_in/rtp_signaling.c index e05e3d0..1a90d52 100644 --- a/modules/rtp_in/rtp_signaling.c +++ b/modules/rtp_in/rtp_signaling.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rtp_in/rtp_stream.c b/modules/rtp_in/rtp_stream.c index e7bf1f0..d420ae3 100644 --- a/modules/rtp_in/rtp_stream.c +++ b/modules/rtp_in/rtp_stream.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rtp_in/sdp_fetch.c b/modules/rtp_in/sdp_fetch.c index ec61e42..7ea4d35 100644 --- a/modules/rtp_in/sdp_fetch.c +++ b/modules/rtp_in/sdp_fetch.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rtp_in/sdp_load.c b/modules/rtp_in/sdp_load.c index 6cb2a5c..29a61ce 100644 --- a/modules/rtp_in/sdp_load.c +++ b/modules/rtp_in/sdp_load.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module diff --git a/modules/rvc_dec/Makefile b/modules/rvc_dec/Makefile index b28709b..a60c433 100644 --- a/modules/rvc_dec/Makefile +++ b/modules/rvc_dec/Makefile @@ -31,10 +31,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/rvc_dec/rvc_dec.c b/modules/rvc_dec/rvc_dec.c index a4ec5c8..c39880c 100644 --- a/modules/rvc_dec/rvc_dec.c +++ b/modules/rvc_dec/rvc_dec.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Telecom ParisTech 2010- - * Author(s): Jean Le Feuvre + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / OpenSVC Decoder module diff --git a/modules/saf_in/Makefile b/modules/saf_in/Makefile index a3ed689..4dc0110 100644 --- a/modules/saf_in/Makefile +++ b/modules/saf_in/Makefile @@ -36,10 +36,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/saf_in/saf_in.c b/modules/saf_in/saf_in.c index bfbccc9..3be84fb 100644 --- a/modules/saf_in/saf_in.c +++ b/modules/saf_in/saf_in.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / SAF reader module @@ -119,7 +119,7 @@ static void SAF_Regulate(SAFIn *read) if (com.buffer.occupancy) min_occ = MIN(min_occ, com.buffer.occupancy - ch->buffer_min); } if (min_occ == (u32) -1) break; - //fprintf(stdout, "Regulating SAF demux - sleeping for %d ms\n", min_occ); + GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[SAF] Regulating SAF demux - sleeping for %d ms\n", min_occ)); gf_sleep(min_occ); } } diff --git a/modules/sdl_out/Makefile b/modules/sdl_out/Makefile index 4cbc60d..ba84dda 100644 --- a/modules/sdl_out/Makefile +++ b/modules/sdl_out/Makefile @@ -33,10 +33,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(LINKFLAGS) -L../../bin/gcc -lgpac -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/sdl_out/audio.c b/modules/sdl_out/audio.c index df74c0a..b768886 100644 --- a/modules/sdl_out/audio.c +++ b/modules/sdl_out/audio.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / SDL audio and video module diff --git a/modules/sdl_out/cursors.c b/modules/sdl_out/cursors.c index de25c39..96dc08c 100644 --- a/modules/sdl_out/cursors.c +++ b/modules/sdl_out/cursors.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / DirectX audio and video render module diff --git a/modules/sdl_out/sdl_out.c b/modules/sdl_out/sdl_out.c index 1be2a12..9b02cd3 100644 --- a/modules/sdl_out/sdl_out.c +++ b/modules/sdl_out/sdl_out.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / SDL audio and video module diff --git a/modules/sdl_out/sdl_out.h b/modules/sdl_out/sdl_out.h index 4fa2e94..b34a759 100644 --- a/modules/sdl_out/sdl_out.h +++ b/modules/sdl_out/sdl_out.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / SDL audio and video module diff --git a/modules/sdl_out/video.c b/modules/sdl_out/video.c index 14f892d..5daa6f3 100644 --- a/modules/sdl_out/video.c +++ b/modules/sdl_out/video.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre - Romain Bouqueau + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / SDL audio and video module diff --git a/modules/sdl_out/video2d.c b/modules/sdl_out/video2d.c index b6b91dc..b41481d 100644 --- a/modules/sdl_out/video2d.c +++ b/modules/sdl_out/video2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / SDL audio and video module diff --git a/modules/soft_raster/Makefile b/modules/soft_raster/Makefile index 740dad0..4476cfe 100644 --- a/modules/soft_raster/Makefile +++ b/modules/soft_raster/Makefile @@ -40,11 +40,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_soft_raster-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/soft_raster/rast_soft.h b/modules/soft_raster/rast_soft.h index 34d128f..8ea59f4 100644 --- a/modules/soft_raster/rast_soft.h +++ b/modules/soft_raster/rast_soft.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / software 2D rasterizer module diff --git a/modules/soft_raster/raster_565.c b/modules/soft_raster/raster_565.c index 7e8f996..9527d9c 100644 --- a/modules/soft_raster/raster_565.c +++ b/modules/soft_raster/raster_565.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Rendering sub-project diff --git a/modules/soft_raster/raster_argb.c b/modules/soft_raster/raster_argb.c index f3ab03d..e593555 100644 --- a/modules/soft_raster/raster_argb.c +++ b/modules/soft_raster/raster_argb.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / software 2D rasterizer module diff --git a/modules/soft_raster/raster_load.c b/modules/soft_raster/raster_load.c index d395186..7867fb7 100644 --- a/modules/soft_raster/raster_load.c +++ b/modules/soft_raster/raster_load.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / software 2D rasterizer module diff --git a/modules/soft_raster/raster_rgb.c b/modules/soft_raster/raster_rgb.c index 34fe846..9f2d404 100644 --- a/modules/soft_raster/raster_rgb.c +++ b/modules/soft_raster/raster_rgb.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / software 2D rasterizer module diff --git a/modules/soft_raster/stencil.c b/modules/soft_raster/stencil.c index 70eaed3..b02539b 100644 --- a/modules/soft_raster/stencil.c +++ b/modules/soft_raster/stencil.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / software 2D rasterizer module diff --git a/modules/soft_raster/surface.c b/modules/soft_raster/surface.c index b860c8a..3fe0ad7 100644 --- a/modules/soft_raster/surface.c +++ b/modules/soft_raster/surface.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / software 2D rasterizer module diff --git a/modules/svg_in/Makefile b/modules/svg_in/Makefile index f5cccdd..c5c8ec2 100644 --- a/modules/svg_in/Makefile +++ b/modules/svg_in/Makefile @@ -39,11 +39,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_svg_in-static.$(DYN_LIB_SUFFIX) $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac_static -lz endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/svg_in/svg_in.c b/modules/svg_in/svg_in.c index c810e25..6f84531 100644 --- a/modules/svg_in/svg_in.c +++ b/modules/svg_in/svg_in.c @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / SVG Loader module diff --git a/modules/timedtext/Makefile b/modules/timedtext/Makefile index 67c30a2..74c9a4e 100644 --- a/modules/timedtext/Makefile +++ b/modules/timedtext/Makefile @@ -35,10 +35,6 @@ ifeq ($(STATICBUILD),yes) endif -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/timedtext/timedtext_dec.c b/modules/timedtext/timedtext_dec.c index a674431..78929c1 100644 --- a/modules/timedtext/timedtext_dec.c +++ b/modules/timedtext/timedtext_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / 3GPP/MPEG4 timed text module diff --git a/modules/timedtext/timedtext_in.c b/modules/timedtext/timedtext_in.c index d4a8c5c..ca32829 100644 --- a/modules/timedtext/timedtext_in.c +++ b/modules/timedtext/timedtext_in.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / 3GPP/MPEG4 timed text module diff --git a/modules/ui_rec/Makefile b/modules/ui_rec/Makefile index 41a8199..d9317cd 100644 --- a/modules/ui_rec/Makefile +++ b/modules/ui_rec/Makefile @@ -37,10 +37,6 @@ $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L$(LOCAL_LIB) $(LINKLIBS) -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/ui_rec/ui_rec.c b/modules/ui_rec/ui_rec.c index b34dd7c..3432c5f 100644 --- a/modules/ui_rec/ui_rec.c +++ b/modules/ui_rec/ui_rec.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2007-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2007-2012 * All rights reserved * * This file is part of GPAC / User Event Recorder sub-project diff --git a/modules/validator/validator.c b/modules/validator/validator.c index 7863caf..287e95d 100644 --- a/modules/validator/validator.c +++ b/modules/validator/validator.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - * Copyright (c) 2010 Telecom ParisTech + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / Test Suite Validator Recorder sub-project diff --git a/modules/wav_out/Makefile b/modules/wav_out/Makefile index bd302c6..5733866 100644 --- a/modules/wav_out/Makefile +++ b/modules/wav_out/Makefile @@ -29,11 +29,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/gcc -lgpac $(EXTRALIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/wav_out/wav_out.c b/modules/wav_out/wav_out.c index 3e243f1..49edf61 100644 --- a/modules/wav_out/wav_out.c +++ b/modules/wav_out/wav_out.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / wave audio render module diff --git a/modules/widgetman/Makefile b/modules/widgetman/Makefile index edb93f8..f054337 100644 --- a/modules/widgetman/Makefile +++ b/modules/widgetman/Makefile @@ -49,11 +49,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) $(LOCAL_LIB) $(LINKLIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/widgetman/unzip.c b/modules/widgetman/unzip.c index 71f0e69..c1acc82 100644 --- a/modules/widgetman/unzip.c +++ b/modules/widgetman/unzip.c @@ -1176,7 +1176,7 @@ int makedir (newdir) *p = 0; if ((mymkdir(buffer) == -1) && (errno == ENOENT)) { - printf("couldn't create directory %s\n",buffer); + fprintf(stderr, "couldn't create directory %s\n",buffer); gf_free(buffer); return 0; } @@ -1211,7 +1211,7 @@ int do_extract_currentfile(uf) if (err!=UNZ_OK) { - printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); + fprintf(stderr, "error %d with zipfile in unzGetCurrentFileInfo\n",err); return err; } @@ -1219,7 +1219,7 @@ int do_extract_currentfile(uf) buf = (void*)gf_malloc(size_buf); if (buf==NULL) { - printf("Error allocating memory\n"); + fprintf(stderr, "Error allocating memory\n"); return UNZ_INTERNALERROR; } @@ -1234,7 +1234,7 @@ int do_extract_currentfile(uf) if ((*filename_withoutpath)=='\0') { #ifndef _WIN32_WCE - printf("creating directory: %s\n",filename_inzip); + fprintf(stderr, "creating directory: %s\n",filename_inzip); mymkdir(filename_inzip); #endif } @@ -1248,7 +1248,7 @@ int do_extract_currentfile(uf) err = unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/); if (err!=UNZ_OK) { - printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); + fprintf(stderr, "error %d with zipfile in unzOpenCurrentFilePassword\n",err); } if ((skip==0) && (err==UNZ_OK)) @@ -1267,26 +1267,26 @@ int do_extract_currentfile(uf) if (fout==NULL) { - printf("error opening %s\n",write_filename); + fprintf(stderr, "error opening %s\n",write_filename); } } if (fout!=NULL) { - printf(" extracting: %s\n",write_filename); + fprintf(stderr, " extracting: %s\n",write_filename); do { err = unzReadCurrentFile(uf,buf,size_buf); if (err<0) { - printf("error %d with zipfile in unzReadCurrentFile\n",err); + fprintf(stderr, "error %d with zipfile in unzReadCurrentFile\n",err); break; } if (err>0) if (gf_fwrite(buf,err,1,fout)!=1) { - printf("error in writing extracted file\n"); + fprintf(stderr, "error in writing extracted file\n"); err=UNZ_ERRNO; break; } @@ -1301,7 +1301,7 @@ int do_extract_currentfile(uf) err = unzCloseCurrentFile (uf); if (err!=UNZ_OK) { - printf("error %d with zipfile in unzCloseCurrentFile\n",err); + fprintf(stderr, "error %d with zipfile in unzCloseCurrentFile\n",err); } } else @@ -1324,20 +1324,20 @@ int gf_unzip_archive(const char *zipfilename, const char *dirname) uf = unzOpen2(zipfilename, NULL); if (uf==NULL) { - printf("Cannot open %s\n", zipfilename); + fprintf(stderr, "Cannot open %s\n", zipfilename); return 1; } #ifndef _WIN32_WCE if (chdir(dirname)) { - printf("Error changing into %s, aborting\n", dirname); + fprintf(stderr, "Error changing into %s, aborting\n", dirname); exit(-1); } #endif err = unzGetGlobalInfo (uf,&gi); if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); + fprintf(stderr, "error %d with zipfile in unzGetGlobalInfo \n",err); for (i=0;iifce->messages, i); if (!strcmp(msg->name, msg_name)) { - JSObject *an_obj = JS_NewObject(c, &bifce->wid->widget->wm->widgetAnyClass, 0, 0); + JSObject *an_obj = JS_NewObject(c, &bifce->wid->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, an_obj, msg); JS_DefineProperty(c, an_obj, "msgName", STRING_TO_JSVAL( JS_NewStringCopyZ(c, msg->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineProperty(c, an_obj, "interfaceHandler", OBJECT_TO_JSVAL( obj ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -227,7 +227,7 @@ static JSBool SMJS_FUNCTION(widget_invoke_message_reply) static void widget_interface_js_bind(JSContext *c, GF_WidgetInterfaceInstance *ifce) { if (!ifce->obj) { - ifce->obj = JS_NewObject(c, &ifce->wid->widget->wm->widgetAnyClass, 0, 0); + ifce->obj = JS_NewObject(c, &ifce->wid->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, ifce->obj, ifce); gf_js_add_root(c, &ifce->obj, GF_JSGC_OBJECT); JS_DefineProperty(c, ifce->obj, "type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ifce->ifce->type) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -327,8 +327,8 @@ void widget_on_interface_bind(GF_WidgetInterfaceInstance *ifce, Bool unbind) } -JSBool widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *rval) -{ +SMJS_FUNC_PROP_GET(widget_getProperty) + const char *opt; char *prop_name; GF_WidgetInstance *wid = (GF_WidgetInstance *)SMJS_GET_PRIVATE(c, obj); @@ -339,41 +339,41 @@ JSBool widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval * if (!prop_name) return JS_FALSE; if (!strcmp(prop_name, "viewMode")) { - *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, "floating") ); + *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, "floating") ); } else if (!strcmp(prop_name, "locale")) { opt = gf_cfg_get_key(wid->widget->wm->term->user->config, "Systems", "Language2CC"); if (!opt) opt = "und"; - *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, opt) ); + *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, opt) ); } else if (!strcmp(prop_name, "identifier")) { - if (wid->widget->identifier) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->identifier) ); + if (wid->widget->identifier) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->identifier) ); } else if (!strcmp(prop_name, "authorName")) { - if (wid->widget->authorName) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorName) ); + if (wid->widget->authorName) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorName) ); } else if (!strcmp(prop_name, "authorEmail")) { - if (wid->widget->authorEmail) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorEmail) ); + if (wid->widget->authorEmail) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorEmail) ); } else if (!strcmp(prop_name, "authorHref")) { - if (wid->widget->authorHref) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorHref) ); + if (wid->widget->authorHref) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorHref) ); } else if (!strcmp(prop_name, "name")) { - if (wid->widget->name) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->name) ); + if (wid->widget->name) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->name) ); } else if (!strcmp(prop_name, "version")) { - if (wid->widget->version) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->version) ); + if (wid->widget->version) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->version) ); } else if (!strcmp(prop_name, "description")) { - if (wid->widget->description) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->description) ); + if (wid->widget->description) *vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->description) ); } else if (!strcmp(prop_name, "width")) { opt = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, "width"); - *rval = INT_TO_JSVAL( (opt ? atoi(opt) : 0) ); + *vp = INT_TO_JSVAL( (opt ? atoi(opt) : 0) ); } else if (!strcmp(prop_name, "height")) { opt = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, "height"); - *rval = INT_TO_JSVAL( (opt ? atoi(opt) : 0) ); + *vp = INT_TO_JSVAL( (opt ? atoi(opt) : 0) ); } else if (!strcmp(prop_name, "preferences")) { } @@ -381,8 +381,11 @@ JSBool widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval * return JS_TRUE; } -JSBool widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +SMJS_FUNC_PROP_SET( widget_setProperty) + + /*avoids GCC warning*/ + if (!obj) obj = NULL; + if (!id) id=0; return JS_TRUE; } @@ -431,10 +434,10 @@ void widget_load(GF_WidgetManager *wm, GF_SceneGraph *scene, JSContext *c, JSObj SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(c, global, 0, &wm->widgetClass, 0, 0,widgetClassProps, widgetClassFuncs, 0, 0); + GF_JS_InitClass(c, global, 0, &wm->widgetClass, 0, 0,widgetClassProps, widgetClassFuncs, 0, 0); - wi->scene_obj = JS_DefineObject(c, global, "widget", &wm->widgetClass, 0, 0); + wi->scene_obj = JS_DefineObject(c, global, "widget", &wm->widgetClass._class, 0, 0); //JS_AliasProperty(c, global, "widget", "MPEGWidget"); SMJS_SET_PRIVATE(c, wi->scene_obj, wi); /*and remember the script*/ diff --git a/modules/widgetman/widgetman.c b/modules/widgetman/widgetman.c index 058cc8b..9e25943 100644 --- a/modules/widgetman/widgetman.c +++ b/modules/widgetman/widgetman.c @@ -20,7 +20,7 @@ // //This copyright notice must be included in all copies or derivative works. // -//Copyright (c) 2009. +//Copyright (c) 2009 Telecom ParisTech. // // Alternatively, this software module may be redistributed and/or modified // it under the terms of the GNU Lesser General Public License as published by @@ -1387,7 +1387,7 @@ static JSBool SMJS_FUNCTION(wm_widget_get_message_param) } if (par) { - JSObject *obj = JS_NewObject(c, &msg->ifce->content->widget->wm->widgetAnyClass, 0, 0); + JSObject *obj = JS_NewObject(c, &msg->ifce->content->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, obj, par); JS_DefineProperty(c, obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, par->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineProperty(c, obj, "is_input", BOOLEAN_TO_JSVAL( (par->type == GF_WM_PARAM_OUTPUT) ? JS_FALSE : JS_TRUE), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1432,7 +1432,7 @@ static JSBool SMJS_FUNCTION(wm_widget_get_message) SMJS_FREE(c, name); } if (msg) { - JSObject *obj = JS_NewObject(c, &ifce->content->widget->wm->widgetAnyClass, 0, 0); + JSObject *obj = JS_NewObject(c, &ifce->content->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, obj, msg); JS_DefineProperty(c, obj, "num_params", INT_TO_JSVAL( gf_list_count(msg->params) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineProperty(c, obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, msg->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1503,7 +1503,7 @@ static JSBool SMJS_FUNCTION(wm_widget_get_interface) if (ifce) { if (!ifce->obj) { - ifce->obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0); + ifce->obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, ifce->obj, ifce); JS_DefineProperty(c, ifce->obj, "num_messages", INT_TO_JSVAL( gf_list_count(ifce->messages) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineProperty(c, ifce->obj, "type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ifce->type) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1638,8 +1638,8 @@ static JSBool SMJS_FUNCTION(wm_widget_get_context) } -static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( wm_widget_getProperty) + JSString *s; char *prop_name; const char *opt; @@ -1693,7 +1693,7 @@ static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTE if (icon) { char *abs_reloc_url; jsval icon_obj_val; - JSObject *icon_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0); + JSObject *icon_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, icon_obj, icon); JS_DefineProperty(c, icon_obj, "src", STRING_TO_JSVAL( JS_NewStringCopyZ(c, icon->src) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); if (strlen(icon->relocated_src)) abs_reloc_url = gf_url_concatenate(wid->widget->url, icon->relocated_src); @@ -1717,7 +1717,7 @@ static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTE GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i); if (pref) { jsval pref_obj_val; - JSObject *pref_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0); + JSObject *pref_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, pref_obj, pref); JS_DefineProperty(c, pref_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, pref->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineProperty(c, pref_obj, "value", STRING_TO_JSVAL( JS_NewStringCopyZ(c, pref->value) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1737,7 +1737,7 @@ static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTE GF_WidgetFeature *feat = gf_list_get(wid->widget->features, i); if (feat) { jsval feat_obj_val; - JSObject *feat_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0); + JSObject *feat_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass._class, 0, 0); SMJS_SET_PRIVATE(c, feat_obj, feat); JS_DefineProperty(c, feat_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, feat->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); JS_DefineProperty(c, feat_obj, "required", BOOLEAN_TO_JSVAL( (feat->required? JS_TRUE : JS_FALSE) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1748,7 +1748,7 @@ static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTE params_arr = JS_NewArrayObject(c, pcount, NULL); for (j=0; j < pcount; j++) { GF_WidgetFeatureParam *param = gf_list_get(feat->params, j); - JSObject *param_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0); + JSObject *param_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass._class, 0, 0); jsval param_obj_val; SMJS_SET_PRIVATE(c, param_obj, param); JS_DefineProperty(c, param_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); @@ -1893,8 +1893,9 @@ static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTE SMJS_FREE(c, prop_name); return JS_TRUE; } -static JSBool wm_widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ + +static SMJS_FUNC_PROP_SET( wm_widget_setProperty) + char szVal[32]; jsdouble val; char *prop_name; @@ -2105,7 +2106,7 @@ static void wm_widget_jsbind(GF_WidgetManager *wm, GF_WidgetInstance *wid) { if (wid->obj) return; - wid->obj = JS_NewObject(wm->ctx, &wm->wmWidgetClass, 0, 0); + wid->obj = JS_NewObject(wm->ctx, &wm->wmWidgetClass._class, 0, 0); SMJS_SET_PRIVATE(wm->ctx, wid->obj, wid); /*protect from GC*/ gf_js_add_root(wm->ctx, &wid->obj, GF_JSGC_OBJECT); @@ -2222,7 +2223,7 @@ static JSBool SMJS_FUNCTION(wm_load) url = NULL; if ((argc==2) && ! JSVAL_IS_NULL(argv[1]) && JSVAL_IS_OBJECT(argv[1])) { GF_WidgetInstance *parent_widget; - if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[1]), &wm->wmWidgetClass, NULL) ) return JS_FALSE; + if (!GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[1]), &wm->wmWidgetClass, NULL) ) return JS_FALSE; parent_widget = (GF_WidgetInstance *)SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[1]) ); if (parent_widget->widget->url) url = gf_url_concatenate(parent_widget->widget->url, manifest); @@ -2288,7 +2289,7 @@ static JSBool SMJS_FUNCTION(wm_unload) GF_WidgetManager *wm = (GF_WidgetManager *)SMJS_GET_PRIVATE(c, obj); if (!argc || !JSVAL_IS_OBJECT(argv[0])) return JS_TRUE; - if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &wm->wmWidgetClass, NULL) ) return JS_FALSE; + if (!GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &wm->wmWidgetClass, NULL) ) return JS_FALSE; wid = (GF_WidgetInstance *)SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0]) ); if (!wid) return JS_TRUE; @@ -2304,8 +2305,8 @@ static JSBool SMJS_FUNCTION(wm_unload) -static JSBool wm_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( wm_getProperty) + char *prop_name; GF_WidgetManager *wm = (GF_WidgetManager *)SMJS_GET_PRIVATE(c, obj); if (!wm) return JS_FALSE; @@ -2325,8 +2326,10 @@ static JSBool wm_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsva SMJS_FREE(c, prop_name); return JS_TRUE; } -static JSBool wm_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ + + +static SMJS_FUNC_PROP_SET( wm_setProperty) + char *prop_name; GF_WidgetManager *wm = (GF_WidgetManager *)SMJS_GET_PRIVATE(c, obj); if (!wm) return JS_FALSE; @@ -3534,8 +3537,8 @@ static void widgetmanager_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, /*setup JS bindings*/ JS_SETUP_CLASS(wm->widmanClass, "WIDGETMANAGER", JSCLASS_HAS_PRIVATE, wm_getProperty, wm_setProperty, JS_FinalizeStub); - JS_InitClass(c, global, 0, &wm->widmanClass, 0, 0, wmClassProps, wmClassFuncs, 0, 0); - wm->obj = JS_DefineObject(c, global, "WidgetManager", &wm->widmanClass, 0, 0); + GF_JS_InitClass(c, global, 0, &wm->widmanClass, 0, 0, wmClassProps, wmClassFuncs, 0, 0); + wm->obj = JS_DefineObject(c, global, "WidgetManager", &wm->widmanClass._class, 0, 0); SMJS_SET_PRIVATE(c, wm->obj, wm); gf_js_add_root(c, &wm->obj, GF_JSGC_OBJECT); @@ -3563,10 +3566,10 @@ static void widgetmanager_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, }; /*setup JS bindings*/ JS_SETUP_CLASS(wm->wmWidgetClass, "WMWIDGET", JSCLASS_HAS_PRIVATE, wm_widget_getProperty, wm_widget_setProperty, JS_FinalizeStub); - JS_InitClass(c, global, 0, &wm->wmWidgetClass, 0, 0, wmWidgetClassProps, wmWidgetClassFuncs, 0, 0); + GF_JS_InitClass(c, global, 0, &wm->wmWidgetClass, 0, 0, wmWidgetClassProps, wmWidgetClassFuncs, 0, 0); JS_SETUP_CLASS(wm->widgetAnyClass, "WIDGETANY", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub); - JS_InitClass(c, global, 0, &wm->widgetAnyClass, 0, 0, 0, 0, 0, 0); + GF_JS_InitClass(c, global, 0, &wm->widgetAnyClass, 0, 0, 0, 0, 0, 0); } JS_SETUP_CLASS(wm->widgetClass, "MPEGWidget", JSCLASS_HAS_PRIVATE, widget_getProperty, widget_setProperty, JS_FinalizeStub); diff --git a/modules/widgetman/widgetman.h b/modules/widgetman/widgetman.h index 879cf8b..b7b5195 100644 --- a/modules/widgetman/widgetman.h +++ b/modules/widgetman/widgetman.h @@ -20,7 +20,7 @@ // //This copyright notice must be included in all copies or derivative works. // -//Copyright (c) 2009. +//Copyright (c) 2009 Telecom ParisTech. // // Alternatively, this software module may be redistributed and/or modified // it under the terms of the GNU Lesser General Public License as published by @@ -76,14 +76,14 @@ typedef struct _widget_manager { JSContext *ctx; /*widget manager class*/ - JSClass widmanClass; + GF_JSClass widmanClass; /*widget class used by the widget manager*/ - JSClass wmWidgetClass; + GF_JSClass wmWidgetClass; /*widget class used by the widget scripts*/ - JSClass widgetClass; + GF_JSClass widgetClass; - JSClass widgetAnyClass; + GF_JSClass widgetAnyClass; JSObject *obj; GF_Terminal *term; @@ -336,8 +336,8 @@ JSBool SMJS_FUNCTION(widget_open_url); JSBool SMJS_FUNCTION(widget_get_attention); JSBool SMJS_FUNCTION(widget_show_notification); JSBool SMJS_FUNCTION(widget_get_interface); -JSBool widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp); -JSBool widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp); +SMJS_DECL_FUNC_PROP_GET(widget_getProperty); +SMJS_DECL_FUNC_PROP_SET(widget_setProperty); void widget_on_interface_bind(GF_WidgetInterfaceInstance *ifce, Bool unbind); diff --git a/modules/wiiis/Makefile b/modules/wiiis/Makefile index cd00066..b3f8c59 100644 --- a/modules/wiiis/Makefile +++ b/modules/wiiis/Makefile @@ -34,11 +34,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) -L../../bin/gcc -lgpac - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/wiiis/wiiis.c b/modules/wiiis/wiiis.c index b283984..bed16ba 100644 --- a/modules/wiiis/wiiis.c +++ b/modules/wiiis/wiiis.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) ENST 2009- - * Authors: Jean Le Feuvre + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2009-2012 * All rights reserved * * This file is part of GPAC / Dummy input module @@ -102,7 +102,6 @@ static u32 WII_Run(void *par) /*locate the wiimotes*/ count = wiiuse_find(wii->wiimotes, wii->nb_wiimotes, scan_delay); GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[Wii] Found %d wiimotes\n", count)); - fprintf(stdout, "found %d wiimotes", count); count = wiiuse_connect(wii->wiimotes, wii->nb_wiimotes); if (count) { GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[Wii] Connected to %d connected wiimotes\n", count)); diff --git a/modules/x11_out/Makefile b/modules/x11_out/Makefile index ab00d89..5c6433e 100644 --- a/modules/x11_out/Makefile +++ b/modules/x11_out/Makefile @@ -68,12 +68,6 @@ ifeq ($(STATICBUILD),yes) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_x11_out-static.$(DYN_LIB_SUFFIX) $(OBJS) -lX11 -L../../bin/gcc -lgpac_static $(EXTRALIBS) endif -#static-bin: -# $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_x11_out-static.$(DYN_LIB_SUFFIX) $(OBJS) -lX11 -L../../bin/gcc -lgpac_static - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/x11_out/x11_out.c b/modules/x11_out/x11_out.c index e299352..3ba42c9 100644 --- a/modules/x11_out/x11_out.c +++ b/modules/x11_out/x11_out.c @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * - * Authors: DINH Anh Min - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / X11 video output module @@ -732,7 +732,7 @@ static GF_Err X11_SetupGLPixmap(GF_VideoOutput *vout, u32 width, u32 height) if (!xWin->glx_context) return GF_IO_ERR; XSync(xWin->display, False); - fprintf(stdout, "!! Activating GLContext on GLPixmap - this may crash !!\n"); + GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("[X11] Activating GLContext on GLPixmap - this may crash !!\n")); glXMakeCurrent(xWin->display, xWin->gl_offscreen, xWin->glx_context); } diff --git a/modules/x11_out/x11_out.h b/modules/x11_out/x11_out.h index 2aa88af..d950695 100644 --- a/modules/x11_out/x11_out.h +++ b/modules/x11_out/x11_out.h @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * - * Authors: DINH Anh Min - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / X11 video output module diff --git a/modules/xvid_dec/Makefile b/modules/xvid_dec/Makefile index d105a12..5e1d3b1 100644 --- a/modules/xvid_dec/Makefile +++ b/modules/xvid_dec/Makefile @@ -46,11 +46,6 @@ all: $(LIB) $(LIB): $(OBJS) $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -L../../bin/gcc -lgpac $(EXTRALIBS) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - - clean: rm -f $(OBJS) ../../bin/gcc/$(LIB) diff --git a/modules/xvid_dec/xvid_dec.c b/modules/xvid_dec/xvid_dec.c index 76c44e3..0855647 100644 --- a/modules/xvid_dec/xvid_dec.c +++ b/modules/xvid_dec/xvid_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / codec pack module diff --git a/modules/xvid_dec/xvid_dec_wce.cpp b/modules/xvid_dec/xvid_dec_wce.cpp index acc86e7..24c6dbf 100644 --- a/modules/xvid_dec/xvid_dec_wce.cpp +++ b/modules/xvid_dec/xvid_dec_wce.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / codec pack module diff --git a/regression_tests/bifs/bifs-script-timestamp.bt b/regression_tests/bifs/bifs-script-timestamp.bt index 3756b24..2186a61 100644 --- a/regression_tests/bifs/bifs-script-timestamp.bt +++ b/regression_tests/bifs/bifs-script-timestamp.bt @@ -58,7 +58,8 @@ OrderedGroup { DEF SCRIPT Script { eventIn SFTime act field SFNode n USE TEXT - url ["javascript: function act(value, timestamp) {n.string[0] = 'EventIn Value: ' + value;n.string[1] = 'Script Timestamp: ' + timestamp;n.string[2] = 'Diff: ' + (timestamp-value);}" ] + url ["javascript: function act(value, timestamp) {n.string[0] = 'EventIn Value: ' + value;n.string[1] = 'Script Timestamp: ' + timestamp;n.string[2] = 'Diff: ' + (timestamp-value); +}" ] } ] } diff --git a/src/Makefile b/src/Makefile index c0f4cb2..318b782 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,7 +15,14 @@ LDFLAGS+=-pg endif ## libgpac objects gathering: src/utils -LIBGPAC_UTILS=utils/os_divers.o utils/os_net.o utils/os_module.o utils/os_thread.o utils/os_config_init.o utils/list.o utils/base_encoding.o utils/bitstream.o utils/color.o utils/configfile.o utils/cache.o utils/downloader.o utils/error.o utils/math.o utils/path2d.o utils/path2d_stroker.o utils/module.o utils/token.o utils/uni_bidi.o utils/url.o utils/utf.o utils/xml_parser.o utils/alloc.o utils/ringbuffer.o utils/unicode.o utils/sha1.o +LIBGPAC_UTILS=utils/os_divers.o utils/list.o utils/bitstream.o utils/error.o utils/alloc.o utils/url.o utils/configfile.o +ifeq ($(DISABLE_CORE_TOOLS), no) +LIBGPAC_UTILS+=utils/sha1.o utils/base_encoding.o utils/os_net.o utils/os_thread.o utils/os_config_init.o utils/cache.o utils/downloader.o utils/xml_parser.o utils/utf.o utils/token.o +endif + +ifeq ($(DISABLE_PLAYER), no) +LIBGPAC_UTILS+=utils/color.o utils/os_module.o utils/math.o utils/path2d.o utils/path2d_stroker.o utils/module.o utils/uni_bidi.o utils/ringbuffer.o utils/unicode.o +endif ## libgpac objects gathering: src/ietf LIBGPAC_IETF= @@ -30,13 +37,32 @@ 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_apple.o isomedia/box_code_base.o isomedia/box_code_isma.o isomedia/box_code_meta.o isomedia/box_dump.o isomedia/box_funcs.o isomedia/data_map.o isomedia/isma_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 +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 ifeq ($(DISABLE_ISOFF_HINT), no) LIBGPAC_ISOM+=isomedia/hint_track.o isomedia/hinting.o endif ## libgpac objects gathering: src/odf -LIBGPAC_ODF=odf/desc_private.o odf/descriptors.o odf/ipmpx_code.o odf/ipmpx_dump.o odf/ipmpx_parse.o odf/oci_codec.o odf/odf_code.o odf/odf_codec.o odf/odf_command.o odf/odf_dump.o odf/odf_parse.o odf/qos.o odf/slc.o +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 +ifeq ($(MINIMAL_OD), no) +LIBGPAC_ODF+=odf/ipmpx_code.o odf/oci_codec.o + +ifeq ($(DISABLE_OD_DUMP), no) +LIBGPAC_ODF+=odf/ipmpx_dump.o +endif + +ifeq ($(DISABLE_OD_PARSE), no) +LIBGPAC_ODF+=odf/ipmpx_parse.o +endif + +endif + +ifeq ($(DISABLE_OD_DUMP), no) +LIBGPAC_ODF+=odf/odf_dump.o +endif +ifeq ($(DISABLE_OD_PARSE), no) +LIBGPAC_ODF+=odf/odf_parse.o +endif ## libgpac objects gathering: src/scenegraph LIBGPAC_SCENE=scenegraph/base_scenegraph.o scenegraph/mpeg4_animators.o scenegraph/commands.o scenegraph/mpeg4_nodes.o scenegraph/mpeg4_valuator.o scenegraph/vrml_interpolators.o scenegraph/vrml_proto.o scenegraph/vrml_route.o scenegraph/vrml_script.o scenegraph/vrml_smjs.o scenegraph/vrml_tools.o scenegraph/x3d_nodes.o scenegraph/svg_attributes.o scenegraph/svg_types.o scenegraph/svg_smjs.o scenegraph/smil_anim.o scenegraph/smil_timing.o scenegraph/svg_properties.o scenegraph/dom_events.o scenegraph/dom_smjs.o scenegraph/xbl_process.o scenegraph/xml_ns.o @@ -48,7 +74,28 @@ LIBGPAC_MCRYPT+=mcrypt/cbc.o mcrypt/cfb.o mcrypt/ctr.o mcrypt/des.o mcrypt/ecb.o endif ## libgpac objects gathering: src/media tools -LIBGPAC_MEDIATOOLS=media_tools/av_parsers.o media_tools/img.o media_tools/isom_tools.o media_tools/media_export.o media_tools/media_import.o media_tools/mpegts.o media_tools/m2ts_mux.o media_tools/m3u8.o media_tools/mpd.o +LIBGPAC_MEDIATOOLS=media_tools/isom_tools.o media_tools/dash_segmenter.o media_tools/av_parsers.o +ifeq ($(DISABLE_AV_PARSERS), no) +LIBGPAC_MEDIATOOLS+=media_tools/img.o +endif +ifeq ($(DISABLE_MEDIA_IMPORT), no) +LIBGPAC_MEDIATOOLS+=media_tools/media_import.o +endif +ifeq ($(DISABLE_M2TS), no) +LIBGPAC_MEDIATOOLS+=media_tools/mpegts.o +endif +ifeq ($(DISABLE_MPD), no) +LIBGPAC_MEDIATOOLS+=media_tools/m3u8.o media_tools/mpd.o +endif +ifeq ($(DISABLE_DASH_CLIENT), no) +LIBGPAC_MEDIATOOLS+=media_tools/dash_client.o +endif +ifeq ($(DISABLE_MEDIA_EXPORT), no) +LIBGPAC_MEDIATOOLS+=media_tools/media_export.o +endif +ifeq ($(DISABLE_M2TS_MUX), no) +LIBGPAC_MEDIATOOLS+=media_tools/m2ts_mux.o +endif ifeq ($(DISABLE_STREAMING), no) LIBGPAC_MEDIATOOLS+=media_tools/filestreamer.o endif @@ -69,6 +116,10 @@ LIBGPAC_MEDIATOOLS+=media_tools/ismacryp.o endif ifeq ($(DISABLE_ISOFF_HINT), no) LIBGPAC_MEDIATOOLS+=media_tools/isom_hinter.o +else +ifeq ($(DISABLE_STREAMING), no) +LIBGPAC_MEDIATOOLS+=media_tools/isom_hinter.o +endif endif ifeq ($(DISABLE_SAF), no) LIBGPAC_MEDIATOOLS+=media_tools/saf.o @@ -84,10 +135,10 @@ endif ## libgpac objects gathering: src/scene_manager LIBGPAC_SCENEMANAGER= ifeq ($(DISABLE_SMGR), no) -LIBGPAC_SCENEMANAGER+=scene_manager/scene_manager.o +LIBGPAC_SCENEMANAGER+=scene_manager/scene_manager.o scene_manager/text_to_bifs.o endif ifeq ($(DISABLE_LOADER_BT), no) -LIBGPAC_SCENEMANAGER+=scene_manager/loader_bt.o scene_manager/text_to_bifs.o +LIBGPAC_SCENEMANAGER+=scene_manager/loader_bt.o endif ifeq ($(DISABLE_LOADER_XMT), no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_xmt.o @@ -102,7 +153,7 @@ ifeq ($(DISABLE_SVG), no) LIBGPAC_SCENEMANAGER+=scene_manager/loader_svg.o endif ifeq ($(DISABLE_LOADER_SWF), no) -LIBGPAC_SCENEMANAGER+=scene_manager/swf_parse.o scene_manager/swf_bifs.o +LIBGPAC_SCENEMANAGER+=scene_manager/swf_parse.o scene_manager/swf_bifs.o scene_manager/swf_svg.o endif ifeq ($(DISABLE_SCENE_DUMP), no) LIBGPAC_SCENEMANAGER+=scene_manager/scene_dump.o @@ -147,6 +198,8 @@ LINKLIBS= SCENEGRAPH_CFLAGS= MEDIATOOLS_CFLAGS= +ifeq ($(DISABLE_CORE_TOOLS), no) + #1 - zlib support ifeq ($(CONFIG_ZLIB), local) CFLAGS+= -I"$(LOCAL_INC_PATH)/zlib" @@ -169,6 +222,8 @@ endif LINKLIBS+=$(JS_LIBS) endif +endif + #4 - JPEG support ifeq ($(CONFIG_JPEG), no) else @@ -279,18 +334,16 @@ mediatools: $(LIBGPAC_MEDIATOOLS) compositor: CFLAGS+=$(COMPOSITOR_CFLAGS) compositor: $(LIBGPAC_COMPOSITOR) -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - $(LIB): $(LIBGPAC_UTILS) $(LIBGPAC_IETF) $(LIBGPAC_BIFS) $(LIBGPAC_ODF) $(LIBGPAC_LASER) $(LIBGPAC_ISOM) $(LIBGPAC_SCENEMANAGER) $(LIBGPAC_TERMINAL) compositor scenegraph mediatools mcrypt $(OBJS) + @echo "Linking libgpac" ifeq ($(CONFIG_DARWIN),yes) - libtool -s -o ../bin/gcc/libgpac_static.a $(OBJS) - ranlib ../bin/gcc/libgpac_static.a + $(LIBTOOL) -s -o ../bin/gcc/libgpac_static.a $(OBJS) + $(RANLIB) ../bin/gcc/libgpac_static.a $(CC) $(SHFLAGS) $(LD_SONAME) $(LDFLAGS) -o ../bin/gcc/$@ $(OBJS) $(EXTRALIBS) else - ar cr ../bin/gcc/libgpac_static.a $(OBJS) - ranlib ../bin/gcc/libgpac_static.a + $(AR) cr ../bin/gcc/libgpac_static.a $(OBJS) + $(RANLIB) ../bin/gcc/libgpac_static.a $(CC) $(SHFLAGS) $(LD_SONAME) $(LDFLAGS) -o ../bin/gcc/$@ $(OBJS) $(EXTRALIBS) ifeq (,$(findstring yes, $(CONFIG_WIN32))) mv ../bin/gcc/$@ ../bin/gcc/$@.$(VERSION_SONAME) diff --git a/src/bifs/arith_decoder.c b/src/bifs/arith_decoder.c index b838bb4..331d5dc 100644 --- a/src/bifs/arith_decoder.c +++ b/src/bifs/arith_decoder.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/bifs_codec.c b/src/bifs/bifs_codec.c index c526866..bfff6e9 100644 --- a/src/bifs/bifs_codec.c +++ b/src/bifs/bifs_codec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/bifs_node_tables.c b/src/bifs/bifs_node_tables.c index a024495..987ffde 100644 --- a/src/bifs/bifs_node_tables.c +++ b/src/bifs/bifs_node_tables.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/com_dec.c b/src/bifs/com_dec.c index 21d8f19..bfcd1b6 100644 --- a/src/bifs/com_dec.c +++ b/src/bifs/com_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/com_enc.c b/src/bifs/com_enc.c index 71ba742..7f86875 100644 --- a/src/bifs/com_enc.c +++ b/src/bifs/com_enc.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/conditional.c b/src/bifs/conditional.c index 2016cf6..2a1db48 100644 --- a/src/bifs/conditional.c +++ b/src/bifs/conditional.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/field_decode.c b/src/bifs/field_decode.c index b39422e..6e2aaf6 100644 --- a/src/bifs/field_decode.c +++ b/src/bifs/field_decode.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project @@ -923,10 +924,14 @@ GF_Node *gf_bifs_dec_node(GF_BifsDecoder * codec, GF_BitStream *bs, u32 NDT_Tag) break; } + /*proto is initialized upon the first traversal to have the same behavior as wth BT/XMT loading*/ +#if 0 /*if new node is a proto and we're in the top scene, load proto code*/ if (proto && (codec->scenegraph == codec->current_graph)) { codec->LastError = gf_sg_proto_load_code(new_node); } +#endif + return new_node; } diff --git a/src/bifs/field_encode.c b/src/bifs/field_encode.c index 56e4f92..4b90bdf 100644 --- a/src/bifs/field_encode.c +++ b/src/bifs/field_encode.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/memory_decoder.c b/src/bifs/memory_decoder.c index ae4f9de..3d57eb9 100644 --- a/src/bifs/memory_decoder.c +++ b/src/bifs/memory_decoder.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/predictive_mffield.c b/src/bifs/predictive_mffield.c index 0e32773..8d0c426 100644 --- a/src/bifs/predictive_mffield.c +++ b/src/bifs/predictive_mffield.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/quant.h b/src/bifs/quant.h index b7dd1bc..6d45add 100644 --- a/src/bifs/quant.h +++ b/src/bifs/quant.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/quantize.c b/src/bifs/quantize.c index ece1182..d1e873a 100644 --- a/src/bifs/quantize.c +++ b/src/bifs/quantize.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/script.h b/src/bifs/script.h index b305c88..d60fa97 100644 --- a/src/bifs/script.h +++ b/src/bifs/script.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/script_dec.c b/src/bifs/script_dec.c index 3f5be24..11362de 100644 --- a/src/bifs/script_dec.c +++ b/src/bifs/script_dec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/script_enc.c b/src/bifs/script_enc.c index 77c09fe..75738c1 100644 --- a/src/bifs/script_enc.c +++ b/src/bifs/script_enc.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/bifs/unquantize.c b/src/bifs/unquantize.c index c2b5a36..ec33773 100644 --- a/src/bifs/unquantize.c +++ b/src/bifs/unquantize.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / BIFS codec sub-project diff --git a/src/compositor/audio_input.c b/src/compositor/audio_input.c index c02b232..475d403 100644 --- a/src/compositor/audio_input.c +++ b/src/compositor/audio_input.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -24,10 +25,7 @@ #include -//#define ENABLE_EARLY_FRAME_DETECTION - -/*diff time in ms to consider an audio frame too early and insert silence*/ -#define MIN_RESYNC_TIME 500 +#define ENABLE_EARLY_FRAME_DETECTION /*diff time in ms to consider an audio frame too late and drop it - we should try to dynamically figure this out since the drift may be high on TS for example, where PTS-PCR>500ms is quite common*/ @@ -55,7 +53,7 @@ static char *gf_audio_input_fetch_frame(void *callback, u32 *size, u32 audio_del { char *frame; u32 obj_time, ts; - s32 drift, resync_delay; + s32 drift; Fixed speed; GF_AudioInput *ai = (GF_AudioInput *) callback; /*even if the stream is signaled as finished we must check it, because it may have been restarted by a mediaControl*/ @@ -74,7 +72,6 @@ static char *gf_audio_input_fetch_frame(void *callback, u32 *size, u32 audio_del ai->need_release = 1; speed = gf_mo_get_current_speed(ai->stream); - resync_delay = FIX2INT(speed*ai->is_open); gf_mo_get_object_time(ai->stream, &obj_time); obj_time += audio_delay_ms; @@ -83,8 +80,8 @@ static char *gf_audio_input_fetch_frame(void *callback, u32 *size, u32 audio_del #ifdef ENABLE_EARLY_FRAME_DETECTION /*too early (silence insertions), skip*/ - if (drift + (s32) (audio_delay_ms + resync_delay) < 0) { - GF_LOG(GF_LOG_INFO, GF_LOG_AUDIO, ("[Audio Input] audio too early %d (CTS %d)\n", drift + audio_delay_ms + resync_delay, ts)); + if (drift < 0) { + GF_LOG(GF_LOG_INFO, GF_LOG_AUDIO, ("[Audio Input] audio too early of %d (CTS %d at OTB %d with audio delay %d ms)\n", drift + audio_delay_ms, ts, obj_time, audio_delay_ms)); ai->need_release = 0; gf_mo_release_data(ai->stream, 0, 0); return NULL; @@ -92,7 +89,7 @@ static char *gf_audio_input_fetch_frame(void *callback, u32 *size, u32 audio_del #endif /*adjust drift*/ if (audio_delay_ms) { - resync_delay = FIX2INT(speed * MAX_RESYNC_TIME); + s32 resync_delay = FIX2INT(speed * MAX_RESYNC_TIME); /*CU is way too late, discard and fetch a new one - this usually happen when media speed is more than 1*/ if (drift>resync_delay) { GF_LOG(GF_LOG_INFO, GF_LOG_AUDIO, ("[Audio Input] Audio data too late obj time %d - CTS %d - drift %d ms - resync forced\n", obj_time - audio_delay_ms, ts, drift)); @@ -112,8 +109,6 @@ static void gf_audio_input_release_frame(void *callback, u32 nb_bytes) if (!ai->stream) return; gf_mo_release_data(ai->stream, nb_bytes, 1); ai->need_release = 0; - /*as soon as we have released a frame for this audio stream, update resync tolerance*/ - ai->is_open = MIN_RESYNC_TIME; } static Fixed gf_audio_input_get_speed(void *callback) diff --git a/src/compositor/audio_mixer.c b/src/compositor/audio_mixer.c index 2f1e82b..42010d5 100644 --- a/src/compositor/audio_mixer.c +++ b/src/compositor/audio_mixer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -604,7 +605,7 @@ single_source_mix: buffer_size -= size; ptr += size; single_source->src->ReleaseFrame(single_source->src->callback, size); - delay = 0; + delay += size * 8000 / am->bits_per_sample / am->sample_rate / am->nb_channels; } /*not completely filled*/ @@ -690,7 +691,7 @@ do_mix: for (i=0; isources, i); if (in->out_samples_to_write>in->out_samples_written) { - gf_mixer_fetch_input(am, in, in->out_samples_written ? 0 : delay); + 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++; } } diff --git a/src/compositor/audio_render.c b/src/compositor/audio_render.c index 6fdb997..df3d149 100644 --- a/src/compositor/audio_render.c +++ b/src/compositor/audio_render.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -487,7 +488,7 @@ void gf_sc_ar_del(GF_AudioRenderer *ar) if (ar->audio_out) { /*kill audio thread*/ if (!ar->audio_out->SelfThreaded) { - GF_LOG(GF_LOG_DEBUG, GF_LOG_AUDIO, ("[AudioRender] stoping audio thread\n")); + GF_LOG(GF_LOG_DEBUG, GF_LOG_AUDIO, ("[AudioRender] stopping audio thread\n")); ar->audio_th_state = 2; while (ar->audio_th_state != 3) { gf_sleep(33); @@ -653,7 +654,7 @@ void gf_sc_reload_audio_filters(GF_Compositor *compositor) gf_mixer_lock(ar->mixer, 0); } - +GF_EXPORT GF_Err gf_sc_add_audio_listener(GF_Compositor *compositor, GF_AudioListener *al) { GF_AudioMixer *mixer; @@ -675,6 +676,7 @@ GF_Err gf_sc_add_audio_listener(GF_Compositor *compositor, GF_AudioListener *al) return GF_OK; } +GF_EXPORT GF_Err gf_sc_remove_audio_listener(GF_Compositor *compositor, GF_AudioListener *al) { if (!compositor || !al) return GF_BAD_PARAM; diff --git a/src/compositor/bindable.c b/src/compositor/bindable.c index 5bdf431..e36d21f 100644 --- a/src/compositor/bindable.c +++ b/src/compositor/bindable.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/camera.c b/src/compositor/camera.c index d92ea3e..1a7bb23 100644 --- a/src/compositor/camera.c +++ b/src/compositor/camera.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -184,7 +185,7 @@ void camera_set_2d(GF_Camera *cam) #endif } -void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camera_layout) +void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camera_layout) { Fixed vlen, h, w, ar; SFVec3f corner, center; @@ -201,7 +202,7 @@ void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coor Fixed left, right, top, bottom, shift, wd2, ndfl, viewing_distance; SFVec3f eye, pos, tar, disp; - viewing_distance = (nominal_view_distance + view_distance_offset); + viewing_distance = nominal_view_distance; wd2 = cam->z_near * gf_tan(cam->fieldOfView/2); ndfl = gf_divfix(cam->z_near, viewing_distance); @@ -230,7 +231,6 @@ void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coor gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); - vlen += view_distance_offset * (vlen/nominal_view_distance); shift = horizontal_shift * vlen / viewing_distance; pos = gf_vec_scale(disp, shift); @@ -315,13 +315,12 @@ void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coor if (camera_layout == GF_3D_CAMERA_CIRCULAR) { GF_Matrix mx; - Fixed viewing_distance = nominal_view_distance + view_distance_offset; + Fixed viewing_distance = nominal_view_distance; SFVec3f pos, target; Fixed angle; gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); - vlen += view_distance_offset * (vlen/nominal_view_distance); gf_vec_diff(pos, cam->target, cam->position); gf_vec_norm(&pos); @@ -345,7 +344,7 @@ void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coor gf_vec_diff(center, cam->world_bbox.center, cam->position); vlen = gf_vec_len(center); vlen += view_distance_offset * (vlen/nominal_view_distance); - + gf_vec_diff(eye, cam->target, cam->position); gf_vec_norm(&eye); tar = gf_vec_scale(eye, vlen); @@ -370,6 +369,10 @@ void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coor cam->flags &= ~CAM_IS_DIRTY; } +void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords) +{ + camera_update_stereo(cam, user_transform, center_coords, 0, 0, 0, GF_3D_CAMERA_STRAIGHT); +} void camera_set_vectors(GF_Camera *cam, SFVec3f pos, SFRotation ori, Fixed fov) { Fixed sin_a, cos_a, icos_a, tmp; diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 71b4645..04891c8 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -1267,6 +1268,11 @@ void gf_sc_reload_config(GF_Compositor *compositor) else if (!strcmp(sOpt, "OffAxis")) compositor->visual->camera_layout = GF_3D_CAMERA_OFFAXIS; else compositor->visual->camera_layout = GF_3D_CAMERA_STRAIGHT; + compositor->interoccular_distance = FLT2FIX(6.3f); + sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "EyeSeparation"); + if (sOpt) compositor->interoccular_distance = FLT2FIX( atof(sOpt)) ; + else gf_cfg_set_key(compositor->user->config, "Compositor", "EyeSeparation", "6.3"); + sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "ReverseViews"); if (sOpt && !strcmp(sOpt, "yes")) compositor->visual->reverse_views = 1; @@ -1290,6 +1296,16 @@ void gf_sc_reload_config(GF_Compositor *compositor) sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "ViewDistance"); compositor->video_out->view_distance = FLT2FIX( sOpt ? (Float) atof(sOpt) : 50.0f ); } + +#ifndef GPAC_DISABLE_3D + sOpt = gf_cfg_get_key(compositor->user->config, "Compositor", "FocusDistance"); + compositor->focus_distance = 0; + if (sOpt) + compositor->focus_distance = FLT2FIX( atof(sOpt) ); + else + gf_cfg_set_key(compositor->user->config, "Compositor", "FocusDistance", "0"); +#endif + #endif @@ -2052,7 +2068,7 @@ void gf_sc_simulation_tick(GF_Compositor *compositor) if (gf_sys_get_rti(500, &sys_rti, GF_RTI_ALL_PROCESSES_TIMES)) { evt.type = GF_EVENT_CPU; evt.cpu_percentage = sys_rti.total_cpu_usage; - //printf("%d\n",sys_rti.total_cpu_usage); + //fprintf(stderr, "%d\n",sys_rti.total_cpu_usage); gf_dom_event_fire(root, NULL, &evt); } } else if (l->event.type == GF_EVENT_BATTERY) { //&& l->observer.target == (SVG_SA_Element *)node) { @@ -2192,7 +2208,8 @@ void gf_sc_simulation_tick(GF_Compositor *compositor) flush_time = gf_sys_clock(); #endif - if(compositor->user->init_flags & GF_TERM_INIT_HIDE) compositor->skip_flush = 1; + if(compositor->user->init_flags & GF_TERM_INIT_HIDE) + compositor->skip_flush = 1; if (compositor->skip_flush!=1) { rc.x = rc.y = 0; @@ -2959,6 +2976,7 @@ void gf_sc_check_focus_upon_destroy(GF_Node *n) if (compositor->hit_text==n) compositor->hit_text = NULL; } +GF_EXPORT GF_Err gf_sc_add_video_listener(GF_Compositor *sc, GF_VideoListener *vl) { if (!sc|| !vl || !vl->on_video_frame || !vl->on_video_reconfig) return GF_BAD_PARAM; @@ -2970,6 +2988,7 @@ GF_Err gf_sc_add_video_listener(GF_Compositor *sc, GF_VideoListener *vl) return GF_OK; } +GF_EXPORT GF_Err gf_sc_remove_video_listener(GF_Compositor *sc, GF_VideoListener *vl) { if (!sc|| !vl) return GF_BAD_PARAM; diff --git a/src/compositor/compositor_2d.c b/src/compositor/compositor_2d.c index 2263628..9b27324 100644 --- a/src/compositor/compositor_2d.c +++ b/src/compositor/compositor_2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/compositor_3d.c b/src/compositor/compositor_3d.c index d1c8f27..8a8aa57 100644 --- a/src/compositor/compositor_3d.c +++ b/src/compositor/compositor_3d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/compositor_node_init.c b/src/compositor/compositor_node_init.c index d1ab396..be9fc65 100644 --- a/src/compositor/compositor_node_init.c +++ b/src/compositor/compositor_node_init.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/drawable.c b/src/compositor/drawable.c index cfb1340..94103aa 100644 --- a/src/compositor/drawable.c +++ b/src/compositor/drawable.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -820,7 +821,7 @@ void drawable_finalize_sort_ex(DrawableContext *ctx, GF_TraverseState *tr_state, } else { gf_path_get_bounds(ctx->drawable->path, &store_orig_bounds); } - //if (store_orig_bounds) printf("store_orig_bounds: %d\n", (int) store_orig_bounds.width ); + //if (store_orig_bounds) fprintf(stderr, "store_orig_bounds: %d\n", (int) store_orig_bounds.width ); ctx->bi->unclip = store_orig_bounds; gf_mx2d_apply_rect(&tr_state->transform, &ctx->bi->unclip); diff --git a/src/compositor/drawable.h b/src/compositor/drawable.h index c24ed76..937a272 100644 --- a/src/compositor/drawable.h +++ b/src/compositor/drawable.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/events.c b/src/compositor/events.c index 482c2dc..2ba4548 100644 --- a/src/compositor/events.c +++ b/src/compositor/events.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -165,7 +166,9 @@ static Bool load_text_node(GF_Compositor *compositor, u32 cmd_type) u32 prev_pos, pos=0; s32 caret_pos; Bool append; +#ifndef GPAC_DISABLE_SVG Bool delete_cr = 0; +#endif caret_pos = -1; @@ -177,7 +180,9 @@ static Bool load_text_node(GF_Compositor *compositor, u32 cmd_type) break; /*load prev text chunk*/ case 4: +#ifndef GPAC_DISABLE_SVG delete_cr = 1; +#endif case 1: if (compositor->dom_text_pos ==0) return 0; pos = compositor->dom_text_pos - 1; @@ -335,11 +340,11 @@ static Bool load_text_node(GF_Compositor *compositor, u32 cmd_type) } /* if (1) { GF_ChildNodeItem *child = ((GF_ParentNode *) compositor->focus_node)->children; - fprintf(stdout, "Dumping text tree:\n"); + fprintf(stderr, "Dumping text tree:\n"); while (child) { switch (gf_node_get_tag(child->node)) { - case TAG_SVG_tbreak: fprintf(stdout, "\ttbreak\n"); break; - case TAG_DOMText: fprintf(stdout, "\ttext: %s\n", ((GF_DOMText *)child->node)->textContent); break; + case TAG_SVG_tbreak: fprintf(stderr, "\ttbreak\n"); break; + case TAG_DOMText: fprintf(stderr, "\ttext: %s\n", ((GF_DOMText *)child->node)->textContent); break; } child = child->next; } @@ -613,19 +618,16 @@ static Bool hit_node_editable(GF_Compositor *compositor, Bool check_focus_node) return 1; } +#ifndef GPAC_DISABLE_SVG static GF_Node *get_parent_focus(GF_Node *node, GF_List *hit_use_stack, u32 cur_idx) { GF_Node *parent; -#ifndef GPAC_DISABLE_SVG GF_FieldInfo info; -#endif if (!node) return NULL; -#ifndef GPAC_DISABLE_SVG if (gf_node_get_attribute_by_tag(node, TAG_SVG_ATT_focusable, 0, 0, &info)==GF_OK) { if ( *(SVG_Focusable*)info.far_ptr == SVG_FOCUSABLE_TRUE) return node; } -#endif parent = gf_node_get_parent(node, 0); if (cur_idx) { GF_Node *n = gf_list_get(hit_use_stack, cur_idx-1); @@ -637,6 +639,8 @@ static GF_Node *get_parent_focus(GF_Node *node, GF_List *hit_use_stack, u32 cur_ } return get_parent_focus(parent, hit_use_stack, cur_idx); } +#endif + static Bool exec_event_dom(GF_Compositor *compositor, GF_Event *event) { @@ -1195,17 +1199,14 @@ u32 gf_sc_svg_focus_navigate(GF_Compositor *compositor, u32 key_code) } /*focus management*/ +#ifndef GPAC_DISABLE_SVG static Bool is_focus_target(GF_Node *elt) { -#ifndef GPAC_DISABLE_SVG u32 i, count; -#endif u32 tag = gf_node_get_tag(elt); switch (tag) { -#ifndef GPAC_DISABLE_SVG case TAG_SVG_a: return 1; -#endif #ifndef GPAC_DISABLE_VRML case TAG_MPEG4_Anchor: @@ -1221,7 +1222,6 @@ static Bool is_focus_target(GF_Node *elt) } if (tag<=GF_NODE_FIRST_DOM_NODE_TAG) return 0; -#ifndef GPAC_DISABLE_SVG count = gf_dom_listener_count(elt); for (i=0; ifocus_ancestors, elt); \ @@ -1255,7 +1255,7 @@ static Bool is_focus_target(GF_Node *elt) return NULL; \ } \ - +#ifndef GPAC_DISABLE_SVG static void rebuild_focus_ancestor(GF_Compositor *compositor, GF_Node *elt) { gf_list_reset(compositor->focus_ancestors); @@ -1266,6 +1266,7 @@ static void rebuild_focus_ancestor(GF_Compositor *compositor, GF_Node *elt) elt = par; } } +#endif // GPAC_DISABLE_SVG static GF_Node *set_focus(GF_Compositor *compositor, GF_Node *elt, Bool current_focus, Bool prev_focus) { @@ -1754,15 +1755,20 @@ GF_EXPORT u32 gf_sc_focus_switch_ring(GF_Compositor *compositor, Bool move_prev, GF_Node *focus, u32 force_focus) { Bool current_focus = 1; +#ifndef GPAC_DISABLE_SVG Bool prev_uses_dom_events; + GF_Node *prev_use; +#endif u32 ret = 0; GF_List *cloned_use = NULL; - GF_Node *n, *prev, *prev_use; + GF_Node *n, *prev; + compositor->focus_text_type = 0; prev = compositor->focus_node; +#ifndef GPAC_DISABLE_SVG prev_use = compositor->focus_used; - compositor->focus_text_type = 0; prev_uses_dom_events = compositor->focus_uses_dom_events; +#endif compositor->focus_uses_dom_events = 0; if (!compositor->focus_node) { diff --git a/src/compositor/font_engine.c b/src/compositor/font_engine.c index 26c12e6..11f1018 100644 --- a/src/compositor/font_engine.c +++ b/src/compositor/font_engine.c @@ -2,8 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * - * Copyright (c) ENST 2007-200X + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Rendering sub-project @@ -1177,7 +1176,9 @@ static void gf_font_spans_select(GF_TextSpan *span, GF_TraverseState *tr_state, for (i=0; inb_glyphs; i++) { GF_Rect g_rc; Bool end_of_line = 0; - Fixed advance = sx * span->glyphs[i]->horiz_advance; + Fixed advance; + if (!span->glyphs[i]) continue; + advance = sx * span->glyphs[i]->horiz_advance; if (span->dx) dx = span->dx[i]; if (span->dy) dy = span->dy[i]; if (dx + advance/2 < rc->x) { diff --git a/src/compositor/gl_inc.h b/src/compositor/gl_inc.h index 177e385..62e6f41 100644 --- a/src/compositor/gl_inc.h +++ b/src/compositor/gl_inc.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -78,7 +79,7 @@ #endif -#define GL_CHECK_ERR {s32 res = glGetError(); if (res) fprintf(stdout, "GL Error %d file %s line %d\n", res, __FILE__, __LINE__); } +#define GL_CHECK_ERR {s32 res = glGetError(); if (res) GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, "GL Error %d file %s line %d\n", res, __FILE__, __LINE__)); } /*macros for GL proto and fun declaration*/ #ifdef _WIN32_WCE diff --git a/src/compositor/hardcoded_protos.c b/src/compositor/hardcoded_protos.c index 695cae4..2eff1dc 100644 --- a/src/compositor/hardcoded_protos.c +++ b/src/compositor/hardcoded_protos.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -904,7 +905,7 @@ static void TraverseUntransform(GF_Node *node, void *rs, Bool is_destroy) tr_state->camera->is_3D=0; tr_state->camera->flags |= CAM_NO_LOOKAT; tr_state->camera->end_zoom = FIX_ONE; - camera_update(tr_state->camera, NULL, 1, 0, 0, 0, GF_3D_CAMERA_STRAIGHT); + camera_update(tr_state->camera, NULL, 1); if (tr_state->traversing_mode == TRAVERSE_SORT) { @@ -1043,7 +1044,7 @@ void compositor_init_hardcoded_proto(GF_Compositor *compositor, GF_Node *node) if (compositor->proto_modules) { j = 0; while ( (ifce = (GF_HardcodedProto *)gf_list_enum(compositor->proto_modules, &j) )) { - if ( ifce->can_load_proto(url) && ifce->init(compositor, node) ) { + if ( ifce->can_load_proto(url) && ifce->init(compositor, node, url) ) { return; } } @@ -1052,4 +1053,19 @@ void compositor_init_hardcoded_proto(GF_Compositor *compositor, GF_Node *node) } +Bool gf_sc_uri_is_hardcoded_proto(GF_Compositor *compositor, const char *uri) +{ + /*check proto modules*/ + if (compositor && compositor->proto_modules ) { + u32 j = 0; + GF_HardcodedProto *ifce; + while ( (ifce = (GF_HardcodedProto *)gf_list_enum(compositor->proto_modules, &j) )) { + if ( ifce->can_load_proto(uri)) { + return 1; + } + } + } + return 0; +} + #endif /*GPAC_DISABLE_VRML*/ diff --git a/src/compositor/hc_flash_shape.c b/src/compositor/hc_flash_shape.c index a8e764e..0c9e8fc 100644 --- a/src/compositor/hc_flash_shape.c +++ b/src/compositor/hc_flash_shape.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mesh.c b/src/compositor/mesh.c index 8914608..f9bd6b7 100644 --- a/src/compositor/mesh.c +++ b/src/compositor/mesh.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mesh_collide.c b/src/compositor/mesh_collide.c index 248ecb1..007211b 100644 --- a/src/compositor/mesh_collide.c +++ b/src/compositor/mesh_collide.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mesh_tesselate.c b/src/compositor/mesh_tesselate.c index bb6f3ea..569553b 100644 --- a/src/compositor/mesh_tesselate.c +++ b/src/compositor/mesh_tesselate.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_animstream.c b/src/compositor/mpeg4_animstream.c index 2610899..a19c411 100644 --- a/src/compositor/mpeg4_animstream.c +++ b/src/compositor/mpeg4_animstream.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_audio.c b/src/compositor/mpeg4_audio.c index c83e933..98c361c 100644 --- a/src/compositor/mpeg4_audio.c +++ b/src/compositor/mpeg4_audio.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_background.c b/src/compositor/mpeg4_background.c index b5de7c4..8b0c44c 100644 --- a/src/compositor/mpeg4_background.c +++ b/src/compositor/mpeg4_background.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_background2d.c b/src/compositor/mpeg4_background2d.c index 214330c..bb48311 100644 --- a/src/compositor/mpeg4_background2d.c +++ b/src/compositor/mpeg4_background2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -173,13 +174,13 @@ static void DrawBackground2D_3D(M_Background2D *bck, Background2DStack *st, GF_T visual_3d_set_background_state(tr_state->visual, 1); + visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW); visual_3d_matrix_push(tr_state->visual); /* visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE); gf_sc_texture_get_transform(&st->txh, NULL, &mx, 0); visual_3d_matrix_load(tr_state->visual, mx.m); */ - visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW); /*little opt: if we clear the main visual clear it entirely */ if (! tr_state->is_layer) { diff --git a/src/compositor/mpeg4_bitmap.c b/src/compositor/mpeg4_bitmap.c index c2eee07..f39fce1 100644 --- a/src/compositor/mpeg4_bitmap.c +++ b/src/compositor/mpeg4_bitmap.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_composite.c b/src/compositor/mpeg4_composite.c index 0f8b92a..e7c5b19 100644 --- a/src/compositor/mpeg4_composite.c +++ b/src/compositor/mpeg4_composite.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_form.c b/src/compositor/mpeg4_form.c index 4c2b8cf..8877736 100644 --- a/src/compositor/mpeg4_form.c +++ b/src/compositor/mpeg4_form.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_geometry_2d.c b/src/compositor/mpeg4_geometry_2d.c index 501d21f..6e993a5 100644 --- a/src/compositor/mpeg4_geometry_2d.c +++ b/src/compositor/mpeg4_geometry_2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_geometry_3d.c b/src/compositor/mpeg4_geometry_3d.c index a2689ac..90ee5ac 100644 --- a/src/compositor/mpeg4_geometry_3d.c +++ b/src/compositor/mpeg4_geometry_3d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_geometry_ifs2d.c b/src/compositor/mpeg4_geometry_ifs2d.c index b79e8e8..7970308 100644 --- a/src/compositor/mpeg4_geometry_ifs2d.c +++ b/src/compositor/mpeg4_geometry_ifs2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_geometry_ils2d.c b/src/compositor/mpeg4_geometry_ils2d.c index 26ba0a3..df4014a 100644 --- a/src/compositor/mpeg4_geometry_ils2d.c +++ b/src/compositor/mpeg4_geometry_ils2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_gradients.c b/src/compositor/mpeg4_gradients.c index 27374de..ba2b2ba 100644 --- a/src/compositor/mpeg4_gradients.c +++ b/src/compositor/mpeg4_gradients.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_grouping.c b/src/compositor/mpeg4_grouping.c index 88119bd..4286683 100644 --- a/src/compositor/mpeg4_grouping.c +++ b/src/compositor/mpeg4_grouping.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_grouping.h b/src/compositor/mpeg4_grouping.h index 0032e00..dc42405 100644 --- a/src/compositor/mpeg4_grouping.h +++ b/src/compositor/mpeg4_grouping.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_grouping_2d.c b/src/compositor/mpeg4_grouping_2d.c index 6baf398..f1a70e0 100644 --- a/src/compositor/mpeg4_grouping_2d.c +++ b/src/compositor/mpeg4_grouping_2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_grouping_3d.c b/src/compositor/mpeg4_grouping_3d.c index 68a5b14..9088433 100644 --- a/src/compositor/mpeg4_grouping_3d.c +++ b/src/compositor/mpeg4_grouping_3d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_layer_2d.c b/src/compositor/mpeg4_layer_2d.c index d140cd5..b610edf 100644 --- a/src/compositor/mpeg4_layer_2d.c +++ b/src/compositor/mpeg4_layer_2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -97,6 +98,8 @@ static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy) GF_Node *back; Bool prev_layer; GF_Matrix2D backup; + GF_IRect prev_clip; + GF_Rect rc; SFVec2f prev_vp; #ifndef GPAC_DISABLE_3D @@ -176,9 +179,6 @@ static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy) gf_node_traverse(back, tr_state); } - /*sort all children without transform, and use current transform when flushing contexts*/ - gf_mx_init(tr_state->model_matrix); - /*apply viewport*/ if (viewport) { tr_state->traversing_mode = TRAVERSE_BINDABLE; @@ -216,9 +216,6 @@ static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy) } else #endif { - GF_IRect prev_clip; - GF_Rect rc; - gf_mx2d_copy(backup, tr_state->transform); prev_clip = tr_state->visual->top_clipper; diff --git a/src/compositor/mpeg4_layer_3d.c b/src/compositor/mpeg4_layer_3d.c index 23e0041..89323df 100644 --- a/src/compositor/mpeg4_layer_3d.c +++ b/src/compositor/mpeg4_layer_3d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_layout.c b/src/compositor/mpeg4_layout.c index 7cb9f22..78dba7e 100644 --- a/src/compositor/mpeg4_layout.c +++ b/src/compositor/mpeg4_layout.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_lighting.c b/src/compositor/mpeg4_lighting.c index 14f907c..c86a1ab 100644 --- a/src/compositor/mpeg4_lighting.c +++ b/src/compositor/mpeg4_lighting.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_path_layout.c b/src/compositor/mpeg4_path_layout.c index dd1b856..a8f5420 100644 --- a/src/compositor/mpeg4_path_layout.c +++ b/src/compositor/mpeg4_path_layout.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_sensors.c b/src/compositor/mpeg4_sensors.c index 59e6264..dbda11a 100644 --- a/src/compositor/mpeg4_sensors.c +++ b/src/compositor/mpeg4_sensors.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_sound.c b/src/compositor/mpeg4_sound.c index 576b8c2..19df81f 100644 --- a/src/compositor/mpeg4_sound.c +++ b/src/compositor/mpeg4_sound.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_text.c b/src/compositor/mpeg4_text.c index d211f85..467eb10 100644 --- a/src/compositor/mpeg4_text.c +++ b/src/compositor/mpeg4_text.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_textures.c b/src/compositor/mpeg4_textures.c index 3ae06d0..5b4f95d 100644 --- a/src/compositor/mpeg4_textures.c +++ b/src/compositor/mpeg4_textures.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -279,6 +280,7 @@ static void imagetexture_update(GF_TextureHandler *txh) /*decode cacheTexture data */ if ((ct->data || ct->image.buffer) && !txh->data) { +#ifndef GPAC_DISABLE_AV_PARSERS u32 out_size; GF_Err e; @@ -323,6 +325,7 @@ static void imagetexture_update(GF_TextureHandler *txh) break; } } +#endif // GPAC_DISABLE_AV_PARSERS /*cacheURL is specified, store the image*/ if (ct->cacheURL.buffer) { diff --git a/src/compositor/mpeg4_timesensor.c b/src/compositor/mpeg4_timesensor.c index 683d616..4cc31a4 100644 --- a/src/compositor/mpeg4_timesensor.c +++ b/src/compositor/mpeg4_timesensor.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/mpeg4_viewport.c b/src/compositor/mpeg4_viewport.c index 673087d..18495f8 100644 --- a/src/compositor/mpeg4_viewport.c +++ b/src/compositor/mpeg4_viewport.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/navigate.c b/src/compositor/navigate.c index 7490bc0..6986025 100644 --- a/src/compositor/navigate.c +++ b/src/compositor/navigate.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -209,6 +210,7 @@ Bool gf_sc_fit_world_to_screen(GF_Compositor *compositor) return 0; } memset(&tr_state, 0, sizeof(GF_TraverseState)); + gf_mx_init(tr_state.model_matrix); tr_state.traversing_mode = TRAVERSE_GET_BOUNDS; tr_state.visual = compositor->visual; gf_node_traverse(top, &tr_state); @@ -255,29 +257,37 @@ Bool gf_sc_fit_world_to_screen(GF_Compositor *compositor) return 1; } +//#define SCALE_NAV + static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event *ev) { Fixed x, y, trans_scale; Fixed dx, dy, key_trans, key_pan, key_exam; s32 key_inv; u32 keys; +#ifdef SCALE_NAV Bool is_pixel_metrics; +#endif GF_Camera *cam; Fixed zoom = compositor->zoom; cam = NULL; - if (compositor->active_layer) { #ifndef GPAC_DISABLE_VRML + if (compositor->active_layer) { cam = compositor_layer3d_get_camera(compositor->active_layer); - is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(compositor->active_layer)); +#ifdef SCALE_NAV + is_pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(compositor->active_layer)); #endif } +#endif if (!cam) { cam = &compositor->visual->camera; assert(compositor); assert(compositor->scene); +#ifdef SCALE_NAV is_pixel_metrics = compositor->traverse_state->pixel_metrics; +#endif } keys = compositor->key_states; @@ -292,11 +302,14 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event dx = (x - compositor->grab_x); dy = (compositor->grab_y - y); -/* trans_scale = is_pixel_metrics ? cam->width/2 : INT2FIX(10); +#ifdef SCALE_NAV + trans_scale = is_pixel_metrics ? cam->width/2 : INT2FIX(10); key_trans = is_pixel_metrics ? INT2FIX(10) : cam->avatar_size.x; -*/ +#else trans_scale = cam->width/20; key_trans = cam->avatar_size.x/2; +#endif + if (cam->world_bbox.is_set && (key_trans*5 > cam->world_bbox.radius)) { key_trans = cam->world_bbox.radius / 100; } @@ -450,9 +463,9 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event compositor->visual->camera.start_zoom = compositor->zoom; compositor->zoom = FIX_ONE; compositor->interoccular_offset = 0; - compositor->view_distance_offset = 0; + compositor->focus_distance = 0; compositor->interoccular_offset = 0; - compositor->view_distance_offset = 0; + compositor->focus_distance = 0; compositor_3d_reset_camera(compositor); } break; @@ -467,9 +480,10 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event case GF_KEY_RIGHT: if (keys & GF_KEY_MOD_ALT) { if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) { - compositor->view_distance_offset += key_inv * (is_pixel_metrics ? INT2FIX(1) : FLT2FIX(0.1)); + /*+ or - 10 cm*/ + compositor->focus_distance += INT2FIX(key_inv); cam->flags |= CAM_IS_DIRTY; - fprintf(stdout, "AutoStereo view distance %f\n", FIX2FLT(compositor->view_distance_offset + compositor->video_out->view_distance)/100); + fprintf(stderr, "AutoStereo view distance %f - focus %f\n", FIX2FLT(compositor->video_out->view_distance)/100, FIX2FLT(compositor->focus_distance)/100); gf_sc_invalidate(compositor, NULL); return 1; } @@ -504,7 +518,7 @@ static Bool compositor_handle_navigation_3d(GF_Compositor *compositor, GF_Event if (keys & GF_KEY_MOD_ALT) { if ( (keys & GF_KEY_MOD_SHIFT) && (compositor->visual->nb_views > 1) ) { compositor->interoccular_offset += FLT2FIX(0.5) * key_inv; - fprintf(stdout, "AutoStereo interoccular distance %f\n", FIX2FLT(compositor->interoccular_offset)+6.8); + fprintf(stderr, "AutoStereo interoccular distance %f\n", FIX2FLT(compositor->interoccular_distance + compositor->interoccular_offset)); cam->flags |= CAM_IS_DIRTY; gf_sc_invalidate(compositor, NULL); return 1; diff --git a/src/compositor/nodes_stacks.h b/src/compositor/nodes_stacks.h index 6968d69..94934a4 100644 --- a/src/compositor/nodes_stacks.h +++ b/src/compositor/nodes_stacks.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/offscreen_cache.c b/src/compositor/offscreen_cache.c index 22bf6bb..749abc9 100644 --- a/src/compositor/offscreen_cache.c +++ b/src/compositor/offscreen_cache.c @@ -1,9 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Yi-Zhen Zhang, Jean Le Feuvre - * - * Copyright (c) ENST 2005-200X + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2006-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -335,6 +334,7 @@ Bool group_cache_traverse(GF_Node *node, GroupCache *cache, GF_TraverseState *tr gf_mx2d_copy(backup, tr_state->transform); gf_mx2d_init(tr_state->transform); #else + gf_mx2d_copy(backup, tr_state->transform); if (auto_fit_vp) { if ((tr_state->vp_size.x != cache->orig_vp.x) || (tr_state->vp_size.y != cache->orig_vp.y)) { GF_Matrix2D m; diff --git a/src/compositor/offscreen_cache.h b/src/compositor/offscreen_cache.h index da6d713..85cbc40 100644 --- a/src/compositor/offscreen_cache.h +++ b/src/compositor/offscreen_cache.h @@ -1,9 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Yi-Zhen Zhang, Jean Le Feuvre - * - * Copyright (c) ENST 2005-200X + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2006-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_base.c b/src/compositor/svg_base.c index c45be6d..1517836 100644 --- a/src/compositor/svg_base.c +++ b/src/compositor/svg_base.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_filters.c b/src/compositor/svg_filters.c index b6070d8..1a319e7 100644 --- a/src/compositor/svg_filters.c +++ b/src/compositor/svg_filters.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean le Feuvre - * Copyright (c) 2010-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_font.c b/src/compositor/svg_font.c index 45fff2c..6458058 100644 --- a/src/compositor/svg_font.c +++ b/src/compositor/svg_font.c @@ -2,8 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Jean Le Feuvre - * - * Copyright (c) ENST 2007-200X + * Copyright (c) Telecom ParisTech 2007-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_geometry.c b/src/compositor/svg_geometry.c index 0d309b0..6921f32 100644 --- a/src/compositor/svg_geometry.c +++ b/src/compositor/svg_geometry.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_grouping.c b/src/compositor/svg_grouping.c index bf457d6..0620a81 100644 --- a/src/compositor/svg_grouping.c +++ b/src/compositor/svg_grouping.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -332,7 +332,10 @@ static void svg_traverse_svg(GF_Node *node, void *rs, Bool is_destroy) gf_mx2d_copy(vb_bck, tr_state->vb_transform); #ifndef GPAC_DISABLE_3D - if (tr_state->visual->type_3d) gf_mx_copy(bck_mx, tr_state->model_matrix); + //commented to get rid of GCC warning + //if (tr_state->visual->type_3d) + gf_mx_copy(bck_mx, tr_state->model_matrix); + #endif invalidate_flag = tr_state->invalidate_all; diff --git a/src/compositor/svg_media.c b/src/compositor/svg_media.c index 648c764..90cc6bb 100644 --- a/src/compositor/svg_media.c +++ b/src/compositor/svg_media.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_paint_servers.c b/src/compositor/svg_paint_servers.c index 63a1164..fa71565 100644 --- a/src/compositor/svg_paint_servers.c +++ b/src/compositor/svg_paint_servers.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/svg_text.c b/src/compositor/svg_text.c index 90ac26c..2efb389 100644 --- a/src/compositor/svg_text.c +++ b/src/compositor/svg_text.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004 + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/texturing.c b/src/compositor/texturing.c index 8f5cfc4..9c90f23 100644 --- a/src/compositor/texturing.c +++ b/src/compositor/texturing.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/texturing.h b/src/compositor/texturing.h index 42db1f5..101b30a 100644 --- a/src/compositor/texturing.h +++ b/src/compositor/texturing.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/texturing_gl.c b/src/compositor/texturing_gl.c index 273df27..b205bea 100644 --- a/src/compositor/texturing_gl.c +++ b/src/compositor/texturing_gl.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -940,7 +941,7 @@ static Bool gf_sc_texture_enable_matte_texture(GF_Node *n) #else /*To remove: gcc 4.6 introduces this warning*/ -#if __GNUC__ == 4 && __GNUC_MINOR__ == 6 +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Waddress" #endif @@ -1032,9 +1033,9 @@ static Bool gf_sc_texture_enable_matte_texture(GF_Node *n) GLTEXPARAM( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT ); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1,1,0,GL_RGBA,GL_UNSIGNED_BYTE,texture); - /* fin de la génération de la texture donnée par la fraction ! */ + /* fin de la g\E9n\E9ration de la texture donn\E9e par la fraction ! */ - /* mélange effectif des textures ! } */ + /* m\E9lange effectif des textures ! } */ glActiveTexture(GL_TEXTURE1); tx_bind(b_surf); @@ -1102,7 +1103,7 @@ static Bool gf_sc_texture_enable_matte_texture(GF_Node *n) } /* end INVERT */ - /* opération REPLACE_ALPHA */ + /* op\E9ration REPLACE_ALPHA */ if (!strcmp(action,"REPLACE_ALPHA")) { glActiveTexture(GL_TEXTURE0); tx_bind(b_surf); diff --git a/src/compositor/visual_manager.c b/src/compositor/visual_manager.c index 68509e6..85a7670 100644 --- a/src/compositor/visual_manager.c +++ b/src/compositor/visual_manager.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/visual_manager.h b/src/compositor/visual_manager.h index 5cfd8a3..2b70ce4 100644 --- a/src/compositor/visual_manager.h +++ b/src/compositor/visual_manager.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/visual_manager_2d.c b/src/compositor/visual_manager_2d.c index 156082d..3705a2b 100644 --- a/src/compositor/visual_manager_2d.c +++ b/src/compositor/visual_manager_2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/visual_manager_2d.h b/src/compositor/visual_manager_2d.h index 62d8580..61052ef 100644 --- a/src/compositor/visual_manager_2d.h +++ b/src/compositor/visual_manager_2d.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/visual_manager_2d_draw.c b/src/compositor/visual_manager_2d_draw.c index e5840ea..5516cb5 100644 --- a/src/compositor/visual_manager_2d_draw.c +++ b/src/compositor/visual_manager_2d_draw.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/visual_manager_3d.c b/src/compositor/visual_manager_3d.c index a458758..f362907 100644 --- a/src/compositor/visual_manager_3d.c +++ b/src/compositor/visual_manager_3d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -356,7 +357,7 @@ void visual_3d_setup_projection(GF_TraverseState *tr_state, Bool is_layer) Fixed interocular_dist_pixel; Fixed delta = 0; - interocular_dist_pixel = FLT2FIX(6.8f) + tr_state->visual->compositor->interoccular_offset; + interocular_dist_pixel = tr_state->visual->compositor->interoccular_distance + tr_state->visual->compositor->interoccular_offset; view_idx = tr_state->visual->current_view; view_idx -= tr_state->visual->nb_views/2; @@ -367,9 +368,9 @@ void visual_3d_setup_projection(GF_TraverseState *tr_state, Bool is_layer) if (tr_state->visual->reverse_views) delta = - delta; tr_state->camera->flags |= CAM_IS_DIRTY; - camera_update(tr_state->camera, &tr_state->transform, tr_state->visual->center_coords, delta, tr_state->visual->compositor->video_out->view_distance, tr_state->visual->compositor->view_distance_offset, tr_state->visual->camera_layout); + camera_update_stereo(tr_state->camera, &tr_state->transform, tr_state->visual->center_coords, delta, tr_state->visual->compositor->video_out->view_distance, tr_state->visual->compositor->focus_distance, tr_state->visual->camera_layout); } else { - camera_update(tr_state->camera, &tr_state->transform, tr_state->visual->center_coords, 0, 0, 0, GF_3D_CAMERA_STRAIGHT); + camera_update(tr_state->camera, &tr_state->transform, tr_state->visual->center_coords); } /*setup projection/modelview*/ diff --git a/src/compositor/visual_manager_3d.h b/src/compositor/visual_manager_3d.h index 545a248..6f5787a 100644 --- a/src/compositor/visual_manager_3d.h +++ b/src/compositor/visual_manager_3d.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/compositor/visual_manager_3d_gl.c b/src/compositor/visual_manager_3d_gl.c index e4d50be..4fe850c 100644 --- a/src/compositor/visual_manager_3d_gl.c +++ b/src/compositor/visual_manager_3d_gl.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project @@ -1115,7 +1116,7 @@ void VS3D_DrawMeshIntern(GF_TraverseState *tr_state, GF_Mesh *mesh) #if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_OGL_ES) if (color_array) gf_free(color_array); - if (!mesh->mesh_type && !(mesh->flags & MESH_NO_TEXTURE)) { + if (tr_state->mesh_num_textures && !mesh->mesh_type && !(mesh->flags & MESH_NO_TEXTURE)) { glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); diff --git a/src/compositor/x3d_geometry.c b/src/compositor/x3d_geometry.c index c30a6d7..a31d723 100644 --- a/src/compositor/x3d_geometry.c +++ b/src/compositor/x3d_geometry.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Compositor sub-project diff --git a/src/export.cpp b/src/export.cpp index 04692ab..1027968 100644 --- a/src/export.cpp +++ b/src/export.cpp @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 - * Copyright (c) ENST 2008 - + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC @@ -108,11 +108,13 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_asprintf) ) /* Ring Buffer */ +#ifndef GPAC_DISABLE_PLAYER #pragma comment (linker, EXPORT_SYMBOL(gf_ringbuffer_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_ringbuffer_read) ) #pragma comment (linker, EXPORT_SYMBOL(gf_ringbuffer_write) ) #pragma comment (linker, EXPORT_SYMBOL(gf_ringbuffer_available_for_read ) ) #pragma comment (linker, EXPORT_SYMBOL(gf_ringbuffer_del) ) +#endif /* List */ #pragma comment (linker, EXPORT_SYMBOL(gf_list_new) ) @@ -165,6 +167,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_bs_get_position) ) #pragma comment (linker, EXPORT_SYMBOL(gf_bs_get_size) ) #pragma comment (linker, EXPORT_SYMBOL(gf_bs_get_refreshed_size) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_bs_set_output_buffering) ) /* Thread */ #pragma comment (linker, EXPORT_SYMBOL(gf_th_new) ) @@ -215,6 +218,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_url_is_local) ) #pragma comment (linker, EXPORT_SYMBOL(gf_url_get_absolute_path) ) #pragma comment (linker, EXPORT_SYMBOL(gf_url_concatenate) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_url_get_resource_path) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_url_get_resource_name) ) #pragma comment (linker, EXPORT_SYMBOL(gf_utc_time_since_1970) ) #pragma comment (linker, EXPORT_SYMBOL(gf_net_get_ntp) ) #pragma comment (linker, EXPORT_SYMBOL(gf_net_has_ipv6) ) @@ -232,6 +237,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_cfg_init) ) #pragma comment (linker, EXPORT_SYMBOL(gf_cfg_new) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_cfg_force_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_cfg_del) ) #pragma comment (linker, EXPORT_SYMBOL(gf_cfg_remove) ) #pragma comment (linker, EXPORT_SYMBOL(gf_cfg_save) ) @@ -247,6 +253,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_cfg_get_filename) ) +#ifndef GPAC_DISABLE_PLAYER #pragma comment (linker, EXPORT_SYMBOL(gf_modules_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_modules_del) ) #pragma comment (linker, EXPORT_SYMBOL(gf_modules_refresh) ) @@ -259,18 +266,22 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_modules_get_option) ) #pragma comment (linker, EXPORT_SYMBOL(gf_modules_set_option) ) #pragma comment (linker, EXPORT_SYMBOL(gf_modules_get_config) ) +#endif #pragma comment (linker, EXPORT_SYMBOL(gf_utf8_wcstombs) ) #pragma comment (linker, EXPORT_SYMBOL(gf_utf8_mbstowcs) ) #pragma comment (linker, EXPORT_SYMBOL(gf_utf8_wcslen) ) +#ifndef GPAC_DISABLE_PLAYER #pragma comment (linker, EXPORT_SYMBOL(gf_utf8_is_right_to_left) ) #pragma comment (linker, EXPORT_SYMBOL(gf_utf8_reorder_bidi) ) +#endif #pragma comment (linker, EXPORT_SYMBOL(gf_dm_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_new_simple) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_del) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_process) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_process_headers) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_get_cache_name) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_get_stats) ) #pragma comment (linker, EXPORT_SYMBOL(gf_dm_sess_fetch_data) ) @@ -355,6 +366,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_asin) ) #endif /*GPAC_FIXED_POINT*/ +#ifndef GPAC_DISABLE_PLAYER #pragma comment (linker, EXPORT_SYMBOL(gf_angle_diff) ) #pragma comment (linker, EXPORT_SYMBOL(gf_v2d_len) ) #pragma comment (linker, EXPORT_SYMBOL(gf_v2d_from_polar) ) @@ -478,6 +490,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_path_get_outline) ) #pragma comment (linker, EXPORT_SYMBOL(gf_path_point_over) ) +#endif //GPAC_DISABLE_PLAYER + /*mpeg4_odf.h exports*/ #pragma comment (linker, EXPORT_SYMBOL(gf_odf_desc_new) ) #pragma comment (linker, EXPORT_SYMBOL(gf_odf_desc_del) ) @@ -567,6 +581,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_open_progressive) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_missing_bytes) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_fragmented) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_fragmented_duration) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_fragments_count) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_track_fragmented) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_release_segment) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_open_segment) ) @@ -647,6 +663,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_ismacryp_media) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_ismacryp_delete_sample) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_ismacryp_sample) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_avc_svc_type) ) #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) ) @@ -675,6 +692,7 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_get_meta_primary_item_id) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_is_JPEG2000) ) #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) ) @@ -829,6 +847,9 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_rvc_config) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_sample_rap_group) ) #pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_sample_roll_group) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_composition_offset_mode) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_isom_set_output_buffering) ) + #ifndef GPAC_DISABLE_ISOM_HINTING #pragma comment (linker, EXPORT_SYMBOL(gf_isom_setup_hint_track) ) @@ -892,6 +913,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_media_map_esd) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_get_file_hash) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_reduce_aspect_ratio) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_get_reduced_frame_rate) ) #endif /*GPAC_DISABLE_ISOM*/ @@ -1055,6 +1078,8 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_media_import_chapters) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_change_pl) ) #pragma comment (linker, EXPORT_SYMBOL(gf_media_avc_rewrite_samples) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_split_svc) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_media_merge_svc) ) #endif /*GPAC_DISABLE_MEDIA_IMPORT*/ #ifndef GPAC_DISABLE_ISOM_WRITE @@ -1590,15 +1615,17 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_set_pes_framing) ) #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_get_stream_name) ) #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_crc32_check) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_restamp) ) + /* carousel.h */ -#ifndef GPAC_DISABLE_DSMCC +#ifdef GPAC_ENABLE_DSMCC #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_get_channel_application_info) ) #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_process_dsmcc) ) #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_init_dsmcc_overlord) ) #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_get_dmscc_overlord) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_demux_dmscc_init) ) #endif +#pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_demux_dmscc_init) ) #ifndef GPAC_DISABLE_MPEG2TS_MUX @@ -1652,13 +1679,16 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget_with_cache) ) #ifndef GPAC_DISABLE_ISOM_WRITE -#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_start) ) -#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_end) ) +/*to be removed once TS fragmenter is moved to libgpac */ +#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_format_segment_name) ) #ifndef GPAC_DISABLE_ISOM_FRAGMENTS #pragma comment (linker, EXPORT_SYMBOL(gf_media_fragment_file) ) #endif #endif +#pragma comment (linker, EXPORT_SYMBOL(gf_dasher_segment_files) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dasher_next_update_time) ) + /* dvb_mpe.h */ #ifdef GPAC_ENST_PRIVATE #pragma comment (linker, EXPORT_SYMBOL(gf_dvb_mpe_section_del) ) @@ -1667,3 +1697,40 @@ #pragma comment (linker, EXPORT_SYMBOL(gf_dvb_mpe_shutdown) ) #pragma comment (linker, EXPORT_SYMBOL(gf_m2ts_print_mpe_info) ) #endif + +#ifndef GPAC_DISABLE_DASH_CLIENT +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_new) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_del) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_open) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_close) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_url) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_group_count) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_group_udta) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_set_group_udta) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_is_group_selected) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_info) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_switch_quality) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_duration) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_check_mpd_root_type) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_segment_mime) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_segment_init_url) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_select) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_groups_set_language) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_in_last_period) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_period_switch_status) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_request_period_switch) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_is_running) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_num_segments_ready) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_discard_segment) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_next_segment_location) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_group_get_max_segments_in_cache) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_set_group_done) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_in_period_setup) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_seek) ) +#pragma comment (linker, EXPORT_SYMBOL(gf_dash_get_playback_start_range) ) +#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) ) + +#endif + diff --git a/src/ietf/rtcp.c b/src/ietf/rtcp.c index b0444f0..e3bce07 100644 --- a/src/ietf/rtcp.c +++ b/src/ietf/rtcp.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtp.c b/src/ietf/rtp.c index 20d178e..ed30a39 100644 --- a/src/ietf/rtp.c +++ b/src/ietf/rtp.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtp_depacketizer.c b/src/ietf/rtp_depacketizer.c index 067b698..0ed2abb 100644 --- a/src/ietf/rtp_depacketizer.c +++ b/src/ietf/rtp_depacketizer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / RTP input module @@ -44,7 +45,7 @@ static void gf_rtp_parse_mpeg4(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char hdr_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ); aux_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ); -// printf("parsing packet %d size %d ts %d M %d\n", hdr->SequenceNumber, size, hdr->TimeStamp, hdr->Marker); +// fprintf(stderr, "parsing packet %d size %d ts %d M %d\n", hdr->SequenceNumber, size, hdr->TimeStamp, hdr->Marker); /*global AU header len*/ au_hdr_size = 0; @@ -593,15 +594,19 @@ static void gf_rtp_h264_flush(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, Bool m gf_bs_del(rtp->inter_bs); rtp->inter_bs = NULL; nal_s = data_size-4; - data[0] = nal_s>>24; data[1] = nal_s>>16; data[2] = nal_s>>8; data[3] = nal_s&0xFF; + + if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) { + data[0] = data[1] = data[2] = 0; data[3] = 1; + } else { + data[0] = nal_s>>24; data[1] = nal_s>>16; data[2] = nal_s>>8; data[3] = nal_s&0xFF; + } /*set F-bit since nal is corrupted*/ if (missed_end) data[4] |= 0x80; rtp->sl_hdr.accessUnitEndFlag = (rtp->flags & GF_RTP_UNRELIABLE_M) ? 0 : hdr->Marker; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; - rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; - rtp->sl_hdr.decodingTimeStampFlag = 1; + rtp->sl_hdr.decodingTimeStampFlag = 0; rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.randomAccessPointFlag = 0; @@ -626,8 +631,7 @@ void gf_rtp_parse_h264(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload rtp->sl_hdr.accessUnitStartFlag = 1; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.compositionTimeStampFlag = 1; - rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; - rtp->sl_hdr.decodingTimeStampFlag = 1; + rtp->sl_hdr.decodingTimeStampFlag = 0; rtp->sl_hdr.randomAccessPointFlag = 0; } else if (rtp->sl_hdr.accessUnitEndFlag) { rtp->flags |= GF_RTP_UNRELIABLE_M; @@ -644,9 +648,15 @@ void gf_rtp_parse_h264(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload return; rtp->sl_hdr.accessUnitEndFlag = 0; - /*signal NALU size on 4 bytes*/ - nalhdr[0] = size>>24; nalhdr[1] = size>>16; nalhdr[2] = size>>8; nalhdr[3] = size&0xFF; + + if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) { + nalhdr[0] = 0; nalhdr[1] = 0; nalhdr[2] = 0; nalhdr[3] = 1; + } else { + /*signal NALU size on 4 bytes*/ + nalhdr[0] = size>>24; nalhdr[1] = size>>16; nalhdr[2] = size>>8; nalhdr[3] = size&0xFF; + } rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK); + rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.compositionTimeStampFlag = 0; rtp->sl_hdr.accessUnitEndFlag = (rtp->flags & GF_RTP_UNRELIABLE_M) ? 0 : hdr->Marker; @@ -667,9 +677,13 @@ void gf_rtp_parse_h264(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload } if (rtp->flags & GF_RTP_AVC_WAIT_RAP) send = 0; - /*signal NALU size on 4 bytes*/ - nalhdr[0] = nal_size>>24; nalhdr[1] = nal_size>>16; nalhdr[2] = nal_size>>8; nalhdr[3] = nal_size&0xFF; if (send) { + /*signal NALU size on 4 bytes*/ + if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) { + nalhdr[0] = 0; nalhdr[1] = 0; nalhdr[2] = 0; nalhdr[3] = 1; + } else { + nalhdr[0] = nal_size>>24; nalhdr[1] = nal_size>>16; nalhdr[2] = nal_size>>8; nalhdr[3] = nal_size&0xFF; + } rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.compositionTimeStampFlag = 0; diff --git a/src/ietf/rtp_packetizer.c b/src/ietf/rtp_packetizer.c index f7c4049..071327f 100644 --- a/src/ietf/rtp_packetizer.c +++ b/src/ietf/rtp_packetizer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtp_pck_3gpp.c b/src/ietf/rtp_pck_3gpp.c index ffc7c7c..58d7923 100644 --- a/src/ietf/rtp_pck_3gpp.c +++ b/src/ietf/rtp_pck_3gpp.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtp_pck_mpeg12.c b/src/ietf/rtp_pck_mpeg12.c index 660133c..8ed5dd0 100644 --- a/src/ietf/rtp_pck_mpeg12.c +++ b/src/ietf/rtp_pck_mpeg12.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtp_pck_mpeg4.c b/src/ietf/rtp_pck_mpeg4.c index c9d5931..7dddb71 100644 --- a/src/ietf/rtp_pck_mpeg4.c +++ b/src/ietf/rtp_pck_mpeg4.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtp_streamer.c b/src/ietf/rtp_streamer.c index 335d460..4d638a0 100644 --- a/src/ietf/rtp_streamer.c +++ b/src/ietf/rtp_streamer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtsp_command.c b/src/ietf/rtsp_command.c index ef1c9d7..183349f 100644 --- a/src/ietf/rtsp_command.c +++ b/src/ietf/rtsp_command.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/rtsp_common.c b/src/ietf/rtsp_common.c index 3d3da54..6f1199a 100644 --- a/src/ietf/rtsp_common.c +++ b/src/ietf/rtsp_common.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project @@ -100,8 +101,6 @@ GF_Err gf_rtsp_refill_buffer(GF_RTSPSession *sess) res = sess->CurrentSize - sess->CurrentPos; if (!res) return gf_rtsp_fill_buffer(sess); -// printf("Forcing reading\n"); - ptr = (char *)gf_malloc(sizeof(char) * res); memcpy(ptr, sess->TCPBuffer+sess->CurrentPos, res); memcpy(sess->TCPBuffer, ptr, res); diff --git a/src/ietf/rtsp_response.c b/src/ietf/rtsp_response.c index c4d0136..d1a37de 100644 --- a/src/ietf/rtsp_response.c +++ b/src/ietf/rtsp_response.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project @@ -702,7 +703,7 @@ GF_Err gf_rtsp_send_response(GF_RTSPSession *sess, GF_RTSPResponse *rsp) //send buffer e = gf_rtsp_send_data(sess, buffer, size); if (e) return e; -// printf("RTSP Send Response\n\n%s\n\n", buffer); +// fprintf(stderr, "RTSP Send Response\n\n%s\n\n", buffer); exit: if (buffer) gf_free(buffer); diff --git a/src/ietf/rtsp_session.c b/src/ietf/rtsp_session.c index a509bab..e8e6c64 100644 --- a/src/ietf/rtsp_session.c +++ b/src/ietf/rtsp_session.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/ietf/sdp.c b/src/ietf/sdp.c index c0eb06d..6d3972d 100644 --- a/src/ietf/sdp.c +++ b/src/ietf/sdp.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project diff --git a/src/isomedia/avc_ext.c b/src/isomedia/avc_ext.c index b75f512..e88e74d 100644 --- a/src/isomedia/avc_ext.c +++ b/src/isomedia/avc_ext.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -25,6 +26,10 @@ #include #include +#ifndef GPAC_DISABLE_AV_PARSERS +#include +#endif + #ifndef GPAC_DISABLE_ISOM static GF_AVCConfig *AVC_DuplicateConfig(GF_AVCConfig *cfg) @@ -38,6 +43,9 @@ static GF_AVCConfig *AVC_DuplicateConfig(GF_AVCConfig *cfg) cfg_new->nal_unit_size = cfg->nal_unit_size; cfg_new->profile_compatibility = cfg->profile_compatibility; cfg_new->complete_representation = cfg->complete_representation; + cfg_new->chroma_bit_depth = cfg->chroma_bit_depth; + cfg_new->luma_bit_depth = cfg->luma_bit_depth; + cfg_new->chroma_format = cfg->chroma_format; count = gf_list_count(cfg->sequenceParameterSets); for (i=0; idata, p1->data, sizeof(char)*p1->size); gf_list_add(cfg_new->pictureParameterSets, p2); } + + if (cfg->sequenceParameterSetExtensions) { + cfg_new->sequenceParameterSetExtensions = gf_list_new(); + count = gf_list_count(cfg->sequenceParameterSetExtensions); + for (i=0; isequenceParameterSetExtensions, i); + p2 = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); + p2->size = p1->size; + p2->data = (char*)gf_malloc(sizeof(char)*p1->size); + memcpy(p2->data, p1->data, sizeof(char)*p1->size); + gf_list_add(cfg_new->sequenceParameterSetExtensions, p2); + } + } return cfg_new; } @@ -198,8 +219,8 @@ GF_Err gf_isom_avc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfi entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC); entry->avc_config->config = AVC_DuplicateConfig(cfg); entry->dataReferenceIndex = dataRefIndex; - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, entry); - *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); + *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); AVC_RewriteESDescriptor(entry); return e; } @@ -214,7 +235,7 @@ static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber 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->boxList, DescriptionIndex-1); + 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: @@ -267,6 +288,35 @@ GF_Err gf_isom_svc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 Desc return gf_isom_avc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, is_add ? 1 : 2); } +GF_Err gf_isom_svc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex) +{ + 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 || !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_SVC1: + break; + default: + return GF_BAD_PARAM; + } + + if (entry->svc_config) { + gf_isom_box_del((GF_Box*)entry->svc_config); + entry->svc_config = NULL; + } + AVC_RewriteESDescriptor(entry); + return GF_OK; +} + GF_EXPORT GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber) { @@ -279,7 +329,7 @@ GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber) if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; - entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, 0); + entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, 0); if (!entry) return GF_OK; switch (entry->type) { case GF_ISOM_BOX_TYPE_AVC1: @@ -296,6 +346,40 @@ GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber) return GF_OK; } +GF_Err gf_isom_svc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *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_SVC1); + if (!entry) return GF_OUT_OF_MEM; + entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC); + entry->svc_config->config = AVC_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); + AVC_RewriteESDescriptor(entry); + return e; +} + #endif /*GPAC_DISABLE_ISOM_WRITE*/ GF_EXPORT @@ -305,7 +389,7 @@ 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; - entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); + 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; @@ -319,12 +403,36 @@ 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; - entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); + 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) +{ + GF_TrackBox *trak; + GF_MPEGVisualSampleEntryBox *entry; + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak || !trak->Media || !DescriptionIndex) 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_SVC1: + break; + default: + return GF_ISOM_AVCTYPE_NONE; + } + if (entry->avc_config && !entry->svc_config) return GF_ISOM_AVCTYPE_AVC_ONLY; + if (entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_AVC_SVC; + if (!entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_SVC_ONLY; + return GF_ISOM_AVCTYPE_NONE; +} + + void btrt_del(GF_Box *s) { GF_MPEG4BitRateBox *ptr = (GF_MPEG4BitRateBox *)s; @@ -463,12 +571,15 @@ GF_Err avcc_Read(GF_Box *s, GF_BitStream *bs) gf_bs_read_int(bs, 3); count = gf_bs_read_int(bs, 5); + ptr->size -= 7; //including 2nd count + for (i=0; isize = gf_bs_read_u16(bs); sl->data = (char *)gf_malloc(sizeof(char) * sl->size); gf_bs_read_data(bs, sl->data, sl->size); gf_list_add(ptr->config->sequenceParameterSets, sl); + ptr->size -= 2+sl->size; } count = gf_bs_read_u8(bs); @@ -478,6 +589,57 @@ GF_Err avcc_Read(GF_Box *s, GF_BitStream *bs) sl->data = (char *)gf_malloc(sizeof(char) * sl->size); gf_bs_read_data(bs, sl->data, sl->size); gf_list_add(ptr->config->pictureParameterSets, sl); + ptr->size -= 2+sl->size; + } + + if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) { + + switch (ptr->config->AVCProfileIndication) { + case 100: + case 110: + case 122: + case 144: + if (!ptr->size) { +#ifndef GPAC_DISABLE_AV_PARSERS + 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); + 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; + ptr->config->chroma_bit_depth = 8 + avc.sps[idx].chroma_bit_depth_m8; + } +#else + /*set default values ...*/ + ptr->config->chroma_format = 1; + ptr->config->luma_bit_depth = 8; + ptr->config->chroma_bit_depth = 8; +#endif + return GF_OK; + } + gf_bs_read_int(bs, 6); + ptr->config->chroma_format = gf_bs_read_int(bs, 2); + gf_bs_read_int(bs, 5); + ptr->config->luma_bit_depth = 8 + gf_bs_read_int(bs, 3); + gf_bs_read_int(bs, 5); + ptr->config->chroma_bit_depth = 8 + gf_bs_read_int(bs, 3); + + count = gf_bs_read_int(bs, 8); + ptr->size -= 4; + if (count) { + ptr->config->sequenceParameterSetExtensions = gf_list_new(); + for (i=0; isize = gf_bs_read_u16(bs); + sl->data = (char *)gf_malloc(sizeof(char) * sl->size); + gf_bs_read_data(bs, sl->data, sl->size); + gf_list_add(ptr->config->sequenceParameterSetExtensions, sl); + ptr->size -= sl->size + 2; + } + } + break; + } } return GF_OK; } @@ -528,6 +690,31 @@ GF_Err avcc_Write(GF_Box *s, GF_BitStream *bs) gf_bs_write_u16(bs, sl->size); gf_bs_write_data(bs, sl->data, sl->size); } + + + if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) { + switch (ptr->config->AVCProfileIndication) { + case 100: + case 110: + case 122: + case 144: + gf_bs_write_int(bs, 0xFF, 6); + gf_bs_write_int(bs, ptr->config->chroma_format, 2); + gf_bs_write_int(bs, 0xFF, 5); + gf_bs_write_int(bs, ptr->config->luma_bit_depth - 8, 3); + gf_bs_write_int(bs, 0xFF, 5); + gf_bs_write_int(bs, ptr->config->chroma_bit_depth - 8, 3); + + count = ptr->config->sequenceParameterSetExtensions ? gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0; + gf_bs_write_u8(bs, count); + for (i=0; iconfig->sequenceParameterSetExtensions, i); + gf_bs_write_u16(bs, sl->size); + gf_bs_write_data(bs, sl->data, sl->size); + } + break; + } + } return GF_OK; } GF_Err avcc_Size(GF_Box *s) @@ -543,9 +730,26 @@ GF_Err avcc_Size(GF_Box *s) } ptr->size += 7; count = gf_list_count(ptr->config->sequenceParameterSets); - for (i=0; isize += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSets, i))->size; + for (i=0; isize += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSets, i))->size; + count = gf_list_count(ptr->config->pictureParameterSets); - for (i=0; isize += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->pictureParameterSets, i))->size; + for (i=0; isize += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->pictureParameterSets, i))->size; + + if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) { + switch (ptr->config->AVCProfileIndication) { + case 100: + case 110: + case 122: + case 144: + ptr->size += 4; + count = ptr->config->sequenceParameterSetExtensions ?gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0; + for (i=0; isize += 2 + ((GF_AVCConfigSlot *)gf_list_get(ptr->config->sequenceParameterSetExtensions, i))->size; + break; + } + } return GF_OK; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ diff --git a/src/isomedia/box_code_3gpp.c b/src/isomedia/box_code_3gpp.c index df6b8f5..f6b7c53 100644 --- a/src/isomedia/box_code_3gpp.c +++ b/src/isomedia/box_code_3gpp.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -30,8 +31,9 @@ void gppa_del(GF_Box *s) { GF_3GPPAudioSampleEntryBox *ptr = (GF_3GPPAudioSampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)ptr); + if (ptr->info) gf_isom_box_del((GF_Box *)ptr->info); - if (ptr->protection_info) gf_isom_box_del((GF_Box *)ptr->protection_info); gf_free(ptr); } @@ -50,11 +52,8 @@ GF_Err gppa_Read(GF_Box *s, GF_BitStream *bs) GF_Box *gppa_New(u32 type) { - GF_3GPPAudioSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_3GPPAudioSampleEntryBox); - if (tmp == NULL) return NULL; + ISOM_DECL_BOX_ALLOC(GF_3GPPAudioSampleEntryBox, type); gf_isom_audio_sample_entry_init((GF_AudioSampleEntryBox*)tmp); - tmp->type = type; return (GF_Box *)tmp; } @@ -89,19 +88,16 @@ GF_Err gppa_Size(GF_Box *s) GF_Box *gppv_New(u32 type) { - GF_3GPPVisualSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_3GPPVisualSampleEntryBox); - if (tmp == NULL) return NULL; + ISOM_DECL_BOX_ALLOC(GF_3GPPVisualSampleEntryBox, type); gf_isom_video_sample_entry_init((GF_VisualSampleEntryBox *)tmp); - tmp->type = type; return (GF_Box *)tmp; } void gppv_del(GF_Box *s) { GF_3GPPVisualSampleEntryBox *ptr = (GF_3GPPVisualSampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)ptr); if (ptr->info) gf_isom_box_del((GF_Box *)ptr->info); - if (ptr->protection_info) gf_isom_box_del((GF_Box *)ptr->protection_info); gf_free(ptr); } @@ -148,10 +144,7 @@ GF_Err gppv_Size(GF_Box *s) GF_Box *gppc_New(u32 type) { - GF_3GPPConfigBox *tmp = (GF_3GPPConfigBox *) gf_malloc(sizeof(GF_3GPPConfigBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_3GPPConfigBox)); - tmp->type = type; + ISOM_DECL_BOX_ALLOC(GF_3GPPConfigBox, type); return (GF_Box *)tmp; } @@ -252,10 +245,7 @@ GF_Err gppc_Size(GF_Box *s) GF_Box *ftab_New() { - GF_FontTableBox *tmp; - GF_SAFEALLOC(tmp, GF_FontTableBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_FTAB; + ISOM_DECL_BOX_ALLOC(GF_FontTableBox, GF_ISOM_BOX_TYPE_FTAB); return (GF_Box *) tmp; } void ftab_del(GF_Box *s) @@ -329,17 +319,15 @@ GF_Err ftab_Size(GF_Box *s) GF_Box *text_New() { - GF_TextSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_TextSampleEntryBox); - if (!tmp) - return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TEXT; + ISOM_DECL_BOX_ALLOC(GF_TextSampleEntryBox, GF_ISOM_BOX_TYPE_TEXT); return (GF_Box *) tmp; } void text_del(GF_Box *s) { GF_TextSampleEntryBox *ptr = (GF_TextSampleEntryBox*)s; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->textName) gf_free(ptr->textName); gf_free(ptr); @@ -347,17 +335,16 @@ void text_del(GF_Box *s) GF_Box *tx3g_New() { - GF_Tx3gSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_Tx3gSampleEntryBox); - if (!tmp) - return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TX3G; + ISOM_DECL_BOX_ALLOC(GF_Tx3gSampleEntryBox, GF_ISOM_BOX_TYPE_TX3G); return (GF_Box *) tmp; } void tx3g_del(GF_Box *s) { GF_Tx3gSampleEntryBox *ptr = (GF_Tx3gSampleEntryBox*)s; + + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->font_table) gf_isom_box_del((GF_Box *)ptr->font_table); gf_free(ptr); @@ -580,10 +567,7 @@ GF_Err text_Size(GF_Box *s) GF_Box *styl_New() { - GF_TextStyleBox *tmp; - GF_SAFEALLOC(tmp, GF_TextStyleBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_STYL; + ISOM_DECL_BOX_ALLOC(GF_TextStyleBox, GF_ISOM_BOX_TYPE_STYL); return (GF_Box *) tmp; } @@ -635,10 +619,7 @@ GF_Err styl_Size(GF_Box *s) GF_Box *hlit_New() { - GF_TextHighlightBox *tmp; - GF_SAFEALLOC(tmp, GF_TextHighlightBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_HLIT; + ISOM_DECL_BOX_ALLOC(GF_TextHighlightBox, GF_ISOM_BOX_TYPE_HLIT); return (GF_Box *) tmp; } @@ -679,10 +660,7 @@ GF_Err hlit_Size(GF_Box *s) GF_Box *hclr_New() { - GF_TextHighlightColorBox*tmp; - GF_SAFEALLOC(tmp, GF_TextHighlightColorBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_HCLR; + ISOM_DECL_BOX_ALLOC(GF_TextHighlightColorBox, GF_ISOM_BOX_TYPE_HCLR); return (GF_Box *) tmp; } @@ -721,10 +699,7 @@ GF_Err hclr_Size(GF_Box *s) GF_Box *krok_New() { - GF_TextKaraokeBox*tmp; - GF_SAFEALLOC(tmp, GF_TextKaraokeBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_KROK; + ISOM_DECL_BOX_ALLOC(GF_TextKaraokeBox, GF_ISOM_BOX_TYPE_KROK); return (GF_Box *) tmp; } @@ -785,10 +760,7 @@ GF_Err krok_Size(GF_Box *s) GF_Box *dlay_New() { - GF_TextScrollDelayBox*tmp; - GF_SAFEALLOC(tmp, GF_TextScrollDelayBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_DLAY; + ISOM_DECL_BOX_ALLOC(GF_TextScrollDelayBox, GF_ISOM_BOX_TYPE_DLAY); return (GF_Box *) tmp; } @@ -827,10 +799,7 @@ GF_Err dlay_Size(GF_Box *s) GF_Box *href_New() { - GF_TextHyperTextBox*tmp; - GF_SAFEALLOC(tmp, GF_TextHyperTextBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_HREF; + ISOM_DECL_BOX_ALLOC(GF_TextHyperTextBox, GF_ISOM_BOX_TYPE_HREF); return (GF_Box *) tmp; } @@ -907,10 +876,7 @@ GF_Err href_Size(GF_Box *s) GF_Box *tbox_New() { - GF_TextBoxBox*tmp; - GF_SAFEALLOC(tmp, GF_TextBoxBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TBOX; + ISOM_DECL_BOX_ALLOC(GF_TextBoxBox, GF_ISOM_BOX_TYPE_TBOX); return (GF_Box *) tmp; } @@ -950,10 +916,7 @@ GF_Err tbox_Size(GF_Box *s) GF_Box *blnk_New() { - GF_TextBlinkBox*tmp; - GF_SAFEALLOC(tmp, GF_TextBlinkBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_BLNK; + ISOM_DECL_BOX_ALLOC(GF_TextBlinkBox, GF_ISOM_BOX_TYPE_BLNK); return (GF_Box *) tmp; } @@ -994,10 +957,7 @@ GF_Err blnk_Size(GF_Box *s) GF_Box *twrp_New() { - GF_TextWrapBox*tmp; - GF_SAFEALLOC(tmp, GF_TextWrapBox); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TWRP; + ISOM_DECL_BOX_ALLOC(GF_TextWrapBox, GF_ISOM_BOX_TYPE_TWRP); return (GF_Box *) tmp; } @@ -1064,13 +1024,8 @@ GF_Err tsel_Read(GF_Box *s,GF_BitStream *bs) GF_Box *tsel_New() { - GF_TrackSelectionBox *tmp; - - tmp = (GF_TrackSelectionBox *) gf_malloc(sizeof(GF_TrackSelectionBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackSelectionBox)); + ISOM_DECL_BOX_ALLOC(GF_TrackSelectionBox, GF_ISOM_BOX_TYPE_TSEL); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_TSEL; return (GF_Box *)tmp; } @@ -1109,12 +1064,8 @@ GF_Err tsel_Size(GF_Box *s) GF_Box *dimC_New() { - GF_DIMSSceneConfigBox *tmp; - - GF_SAFEALLOC(tmp, GF_DIMSSceneConfigBox); - if (tmp == NULL) return NULL; + ISOM_DECL_BOX_ALLOC(GF_DIMSSceneConfigBox, GF_ISOM_BOX_TYPE_DIMC); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_DIMC; return (GF_Box *)tmp; } void dimC_del(GF_Box *s) @@ -1195,11 +1146,7 @@ GF_Err dimC_Size(GF_Box *s) GF_Box *diST_New() { - GF_DIMSScriptTypesBox *tmp; - - GF_SAFEALLOC(tmp, GF_DIMSScriptTypesBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_DIST; + ISOM_DECL_BOX_ALLOC(GF_DIMSScriptTypesBox, GF_ISOM_BOX_TYPE_DIST); return (GF_Box *)tmp; } void diST_del(GF_Box *s) @@ -1253,17 +1200,16 @@ GF_Err diST_Size(GF_Box *s) GF_Box *dims_New() { - GF_DIMSSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_DIMSSampleEntryBox); - tmp->type = GF_ISOM_BOX_TYPE_DIMS; + ISOM_DECL_BOX_ALLOC(GF_DIMSSampleEntryBox, GF_ISOM_BOX_TYPE_DIMS); return (GF_Box*)tmp; } void dims_del(GF_Box *s) { GF_DIMSSampleEntryBox *p = (GF_DIMSSampleEntryBox *)s; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (p->config) gf_isom_box_del((GF_Box *)p->config); if (p->bitrate ) gf_isom_box_del((GF_Box *)p->bitrate); - if (p->protection_info) gf_isom_box_del((GF_Box *)p->protection_info); if (p->scripts) gf_isom_box_del((GF_Box *)p->scripts); gf_free(p); } @@ -1285,12 +1231,10 @@ static GF_Err dims_AddBox(GF_Box *s, GF_Box *a) p->bitrate = (GF_MPEG4BitRateBox*)a; break; case GF_ISOM_BOX_TYPE_SINF: - if (p->protection_info) return GF_ISOM_INVALID_FILE; - p->protection_info = (GF_ProtectionInfoBox*)a; + gf_list_add(p->protections, a); break; default: - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -1323,11 +1267,7 @@ GF_Err dims_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write((GF_Box *)p->bitrate, bs); if (e) return e; } - if (p->protection_info) { - e = gf_isom_box_write((GF_Box *)p->protection_info, bs); - if (e) return e; - } - return GF_OK; + return gf_isom_box_array_write(s, p->protections, bs); } GF_Err dims_Size(GF_Box *s) @@ -1342,11 +1282,6 @@ GF_Err dims_Size(GF_Box *s) if (e) return e; p->size += p->config->size; } - if (p->protection_info) { - e = gf_isom_box_size((GF_Box *) p->protection_info); - if (e) return e; - p->size += p->protection_info->size; - } if (p->bitrate) { e = gf_isom_box_size((GF_Box *) p->bitrate); if (e) return e; @@ -1357,7 +1292,7 @@ GF_Err dims_Size(GF_Box *s) if (e) return e; p->size += p->scripts->size; } - return GF_OK; + return gf_isom_box_array_size(s, p->protections); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ diff --git a/src/isomedia/box_code_adobe.c b/src/isomedia/box_code_adobe.c new file mode 100644 index 0000000..32069d8 --- /dev/null +++ b/src/isomedia/box_code_adobe.c @@ -0,0 +1,691 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Author: Romain Bouqueau + * Copyright (c) Romain Bouqueau 2012- + * All rights reserved + * + * Note: this development was kindly sponsorized by Vizion'R (http://vizionr.com) + * + * This file is part of GPAC / ISO Media File Format sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef GPAC_DISABLE_ISOM_ADOBE + +#include + +#ifndef GPAC_DISABLE_ISOM + +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + +void abst_del(GF_Box *s) +{ + GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; + if (ptr == NULL) return; + + if (ptr->movie_identifier) + gf_free(ptr->movie_identifier); + if (ptr->drm_data) + gf_free(ptr->drm_data); + if (ptr->meta_data) + gf_free(ptr->meta_data); + + while (gf_list_count(ptr->server_entry_table)) { + gf_free(gf_list_get(ptr->server_entry_table, 0)); + gf_list_rem(ptr->server_entry_table, 0); + } + gf_list_del(ptr->server_entry_table); + + while (gf_list_count(ptr->quality_entry_table)) { + gf_free(gf_list_get(ptr->quality_entry_table, 0)); + gf_list_rem(ptr->quality_entry_table, 0); + } + gf_list_del(ptr->quality_entry_table); + + while (gf_list_count(ptr->segment_run_table_entries)) { + gf_isom_box_del((GF_Box *)gf_list_get(ptr->segment_run_table_entries, 0)); + gf_list_rem(ptr->segment_run_table_entries, 0); + } + gf_list_del(ptr->segment_run_table_entries); + + while (gf_list_count(ptr->fragment_run_table_entries)) { + gf_isom_box_del((GF_Box *)gf_list_get(ptr->fragment_run_table_entries, 0)); + gf_list_rem(ptr->fragment_run_table_entries, 0); + } + gf_list_del(ptr->fragment_run_table_entries); + + gf_free(ptr); +} + +GF_Err abst_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; + int i; + u32 tmp_strsize = (u32) ptr->size - 8; + char *tmp_str = gf_malloc(sizeof(char)*tmp_strsize); + + GF_Err e = gf_isom_full_box_read(s, bs); + if (e) return e; + + ptr->bootstrapinfo_version = gf_bs_read_u32(bs); + ptr->profile = gf_bs_read_int(bs, 2); + ptr->live = gf_bs_read_int(bs, 1); + ptr->update = gf_bs_read_int(bs, 1); + ptr->reserved = gf_bs_read_int(bs, 4); + ptr->time_scale = gf_bs_read_u32(bs); + ptr->current_media_time = gf_bs_read_u64(bs); + ptr->smpte_time_code_offset = gf_bs_read_u64(bs); + i=0; + tmp_strsize=(u32)ptr->size-8; + while (tmp_strsize) { + tmp_str[i] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[i]) + break; + i++; + } + if (i) + ptr->movie_identifier = gf_strdup(tmp_str); + + ptr->server_entry_count = gf_bs_read_u8(bs); + for (i=0; iserver_entry_count; i++) { + int j=0; + tmp_strsize=(u32)ptr->size-8; + while (tmp_strsize) { + tmp_str[j] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[j]) + break; + j++; + } + gf_list_insert(ptr->server_entry_table, gf_strdup(tmp_str), i); + } + + ptr->quality_entry_count = gf_bs_read_u8(bs); + for (i=0; iquality_entry_count; i++) { + int j=0; + tmp_strsize=(u32)ptr->size-8; + while (tmp_strsize) { + tmp_str[j] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[j]) + break; + j++; + } + gf_list_insert(ptr->quality_entry_table, gf_strdup(tmp_str), i); + } + + i=0; + tmp_strsize=(u32)ptr->size-8; + while (tmp_strsize) { + tmp_str[i] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[i]) + break; + i++; + } + if (i) + ptr->drm_data = gf_strdup(tmp_str); + + i=0; + tmp_strsize=(u32)ptr->size-8; + while (tmp_strsize) { + tmp_str[i] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[i]) + break; + i++; + } + if (i) + ptr->meta_data = gf_strdup(tmp_str); + + ptr->segment_run_table_count = gf_bs_read_u8(bs); + for (i=0; isegment_run_table_count; i++) { + GF_AdobeSegmentRunTableBox *asrt; + e = gf_isom_parse_box((GF_Box **)&asrt, bs); + if (e) return e; + gf_list_insert(ptr->segment_run_table_entries, asrt, i); + } + + ptr->fragment_run_table_count = gf_bs_read_u8(bs); + for (i=0; ifragment_run_table_count; i++) { + GF_AdobeFragmentRunTableBox *afrt; + e = gf_isom_parse_box((GF_Box **)&afrt, bs); + if (e) return e; + gf_list_insert(ptr->fragment_run_table_entries, afrt, i); + } + + gf_free(tmp_str); + + return GF_OK; +} + +GF_Box *abst_New() +{ + ISOM_DECL_BOX_ALLOC(GF_AdobeBootstrapInfoBox, GF_ISOM_BOX_TYPE_ABST); + tmp->server_entry_table = gf_list_new(); + tmp->quality_entry_table = gf_list_new(); + tmp->segment_run_table_entries = gf_list_new(); + tmp->fragment_run_table_entries = gf_list_new(); + return (GF_Box *)tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err abst_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + unsigned int i; + GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; + + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + gf_bs_write_u32(bs, ptr->bootstrapinfo_version); + gf_bs_write_int(bs, ptr->profile, 2); + gf_bs_write_int(bs, ptr->live, 1); + gf_bs_write_int(bs, ptr->update, 1); + gf_bs_write_int(bs, ptr->reserved, 4); + gf_bs_write_u32(bs, ptr->time_scale); + gf_bs_write_u64(bs, ptr->current_media_time); + gf_bs_write_u64(bs, ptr->smpte_time_code_offset); + if (ptr->movie_identifier) + gf_bs_write_data(bs, ptr->movie_identifier, (u32)strlen(ptr->movie_identifier) + 1); + else + gf_bs_write_u8(bs, 0); + + gf_bs_write_u8(bs, ptr->server_entry_count); + for (i=0; iserver_entry_count; i++) { + char *str = (char*)gf_list_get(ptr->server_entry_table, i); + gf_bs_write_data(bs, str, (u32)strlen(str) + 1); + } + + gf_bs_write_u8(bs, ptr->quality_entry_count); + for (i=0; iquality_entry_count; i++) { + char *str = (char*)gf_list_get(ptr->quality_entry_table, i); + gf_bs_write_data(bs, str, (u32)strlen(str) + 1); + } + + if (ptr->drm_data) + gf_bs_write_data(bs, ptr->drm_data, (u32)strlen(ptr->drm_data) + 1); + else + gf_bs_write_u8(bs, 0); + + if (ptr->meta_data) + gf_bs_write_data(bs, ptr->meta_data, (u32)strlen(ptr->meta_data) + 1); + else + gf_bs_write_u8(bs, 0); + + gf_bs_write_u8(bs, ptr->segment_run_table_count); + for (i=0; isegment_run_table_count; i++) { + e = gf_isom_box_write((GF_Box *)gf_list_get(ptr->segment_run_table_entries, i), bs); + if (e) return e; + } + + gf_bs_write_u8(bs, ptr->fragment_run_table_count); + for (i=0; ifragment_run_table_count; i++) { + e = gf_isom_box_write((GF_Box *)gf_list_get(ptr->fragment_run_table_entries, i), bs); + if (e) return e; + } + + return GF_OK; +} + + +GF_Err abst_Size(GF_Box *s) +{ + GF_Err e; + int i; + GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; + + e = gf_isom_full_box_get_size(s); + if (e) return e; + + s->size += 25 + + (ptr->movie_identifier ? (strlen(ptr->movie_identifier) + 1) : 1) + + 1; + + for (i=0; iserver_entry_count; i++) + s->size += strlen(gf_list_get(ptr->server_entry_table, i)) + 1; + + s->size += 1; + + for (i=0; iquality_entry_count; i++) + s->size += strlen(gf_list_get(ptr->quality_entry_table, i)) + 1; + + s->size += (ptr->drm_data ? (strlen(ptr->drm_data) + 1) : 1) + + (ptr->meta_data ? (strlen(ptr->meta_data) + 1) : 1) + + 1; + + for (i=0; isegment_run_table_count; i++) { + GF_Box *box = (GF_Box *)gf_list_get(ptr->segment_run_table_entries, i); + e = gf_isom_box_size(box); + if (e) return e; + s->size += box->size; + } + + s->size += 1; + for (i=0; ifragment_run_table_count; i++) { + GF_Box *box = (GF_Box *)gf_list_get(ptr->fragment_run_table_entries, i); + e = gf_isom_box_size(box); + if (e) return e; + s->size += box->size; + } + + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +void afra_del(GF_Box *s) +{ + GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; + if (ptr == NULL) return; + + while (gf_list_count(ptr->local_access_entries)) { + gf_free(gf_list_get(ptr->local_access_entries, 0)); + gf_list_rem(ptr->local_access_entries, 0); + } + gf_list_del(ptr->local_access_entries); + + while (gf_list_count(ptr->global_access_entries)) { + gf_free(gf_list_get(ptr->global_access_entries, 0)); + gf_list_rem(ptr->global_access_entries, 0); + } + gf_list_del(ptr->global_access_entries); + + gf_free(ptr); +} + +GF_Err afra_Read(GF_Box *s, GF_BitStream *bs) +{ + unsigned int i; + GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; + + GF_Err e = gf_isom_full_box_read(s, bs); + if (e) return e; + + ptr->long_ids = gf_bs_read_int(bs, 1); + ptr->long_offsets = gf_bs_read_int(bs, 1); + ptr->global_entries = gf_bs_read_int(bs, 1); + ptr->reserved = gf_bs_read_int(bs, 5); + ptr->time_scale = gf_bs_read_u32(bs); + + ptr->entry_count = gf_bs_read_u32(bs); + for (i=0; ientry_count; i++) { + GF_AfraEntry *ae = gf_malloc(sizeof(GF_AfraEntry)); + + ae->time = gf_bs_read_u64(bs); + if (ptr->long_offsets) + ae->offset = gf_bs_read_u64(bs); + else + ae->offset = gf_bs_read_u32(bs); + + gf_list_insert(ptr->local_access_entries, ae, i); + } + + if (ptr->global_entries) { + ptr->global_entry_count = gf_bs_read_u32(bs); + for (i=0; iglobal_entry_count; i++) { + GF_GlobalAfraEntry *ae = gf_malloc(sizeof(GF_GlobalAfraEntry)); + + ae->time = gf_bs_read_u64(bs); + if (ptr->long_ids) { + ae->segment = gf_bs_read_u32(bs); + ae->fragment = gf_bs_read_u32(bs); + } else { + ae->segment = gf_bs_read_u16(bs); + ae->fragment = gf_bs_read_u16(bs); + } + if (ptr->long_offsets) { + ae->afra_offset = gf_bs_read_u64(bs); + ae->offset_from_afra = gf_bs_read_u64(bs); + }else { + ae->afra_offset = gf_bs_read_u32(bs); + ae->offset_from_afra = gf_bs_read_u32(bs); + } + + gf_list_insert(ptr->global_access_entries, ae, i); + } + } + + return GF_OK; +} + +GF_Box *afra_New() +{ + ISOM_DECL_BOX_ALLOC(GF_AdobeFragRandomAccessBox, GF_ISOM_BOX_TYPE_AFRA); + tmp->local_access_entries = gf_list_new(); + tmp->global_access_entries = gf_list_new(); + return (GF_Box *)tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err afra_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + unsigned int i; + GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; + + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + gf_bs_write_int(bs, ptr->long_ids, 1); + gf_bs_write_int(bs, ptr->long_offsets, 1); + gf_bs_write_int(bs, ptr->global_entries, 1); + gf_bs_write_int(bs, 0, 5); + gf_bs_write_u32(bs, ptr->time_scale); + + gf_bs_write_u32(bs, ptr->entry_count); + for (i=0; ientry_count; i++) { + GF_AfraEntry *ae = (GF_AfraEntry *)gf_list_get(ptr->local_access_entries, i); + gf_bs_write_u64(bs, ae->time); + if (ptr->long_offsets) + gf_bs_write_u64(bs, ae->offset); + else + gf_bs_write_u32(bs, (u32)ae->offset); + } + + if (ptr->global_entries) { + gf_bs_write_u32(bs, ptr->global_entry_count); + for (i=0; iglobal_entry_count; i++) { + GF_GlobalAfraEntry *gae = (GF_GlobalAfraEntry *)gf_list_get(ptr->global_access_entries, i); + gf_bs_write_u64(bs, gae->time); + if (ptr->long_ids) { + gf_bs_write_u32(bs, gae->segment); + gf_bs_write_u32(bs, gae->fragment); + } else { + gf_bs_write_u16(bs, (u16)gae->segment); + gf_bs_write_u16(bs, (u16)gae->fragment); + } + if (ptr->long_offsets) { + gf_bs_write_u64(bs, gae->afra_offset); + gf_bs_write_u64(bs, gae->offset_from_afra); + } else { + gf_bs_write_u32(bs, (u32)gae->afra_offset); + gf_bs_write_u32(bs, (u32)gae->offset_from_afra); + } + } + } + + return GF_OK; +} + + +GF_Err afra_Size(GF_Box *s) +{ + GF_Err e; + GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; + + e = gf_isom_full_box_get_size(s); + if (e) return e; + + s->size += 9 + + ptr->entry_count * (ptr->long_offsets ? 16 : 12) + + (ptr->global_entries ? 4 + ptr->global_entry_count * (4 + (ptr->long_offsets ? 16 : 8) + (ptr->long_ids ? 8 : 4)) : 0); + + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +void asrt_del(GF_Box *s) +{ + GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; + if (ptr == NULL) return; + + while (gf_list_count(ptr->quality_segment_url_modifiers)) { + gf_free(gf_list_get(ptr->quality_segment_url_modifiers, 0)); + gf_list_rem(ptr->quality_segment_url_modifiers, 0); + } + gf_list_del(ptr->quality_segment_url_modifiers); + + while (gf_list_count(ptr->segment_run_entry_table)) { + gf_free(gf_list_get(ptr->segment_run_entry_table, 0)); + gf_list_rem(ptr->segment_run_entry_table, 0); + } + gf_list_del(ptr->segment_run_entry_table); + + gf_free(ptr); +} + +GF_Err asrt_Read(GF_Box *s, GF_BitStream *bs) +{ + unsigned int i; + GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; + + GF_Err e = gf_isom_full_box_read(s, bs); + if (e) return e; + + ptr->quality_entry_count = gf_bs_read_u8(bs); + for (i=0; iquality_entry_count; i++) { + int j=0; + u32 tmp_strsize=(u32)ptr->size-8; + char *tmp_str = (char*) gf_malloc(tmp_strsize); + while (tmp_strsize) { + tmp_str[j] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[j]) + break; + j++; + } + gf_list_insert(ptr->quality_segment_url_modifiers, tmp_str, i); + } + + ptr->segment_run_entry_count = gf_bs_read_u32(bs); + for (i=0; isegment_run_entry_count; i++) { + GF_AdobeSegmentRunEntry *sre = gf_malloc(sizeof(GF_AdobeSegmentRunEntry)); + sre->first_segment = gf_bs_read_u32(bs); + sre->fragment_per_segment = gf_bs_read_u32(bs); + gf_list_insert(ptr->segment_run_entry_table, sre, i); + } + + return GF_OK; +} + +GF_Box *asrt_New() +{ + ISOM_DECL_BOX_ALLOC(GF_AdobeSegmentRunTableBox, GF_ISOM_BOX_TYPE_ASRT); + tmp->quality_segment_url_modifiers = gf_list_new(); + tmp->segment_run_entry_table = gf_list_new(); + return (GF_Box *)tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err asrt_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + unsigned int i; + GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; + + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + gf_bs_write_u8(bs, ptr->quality_entry_count); + for (i=0; iquality_entry_count; i++) { + char *str = (char*)gf_list_get(ptr->quality_segment_url_modifiers, i); + gf_bs_write_data(bs, str, (u32)strlen(str) + 1); + } + + gf_bs_write_u32(bs, ptr->segment_run_entry_count); + for (i=0; isegment_run_entry_count; i++) { + GF_AdobeSegmentRunEntry *sre = (GF_AdobeSegmentRunEntry *)gf_list_get(ptr->segment_run_entry_table, i); + gf_bs_write_u32(bs, sre->first_segment); + gf_bs_write_u32(bs, sre->fragment_per_segment); + } + + return GF_OK; +} + + +GF_Err asrt_Size(GF_Box *s) +{ + int i; + GF_Err e; + GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; + + e = gf_isom_full_box_get_size(s); + if (e) return e; + + s->size += 5; + + for (i=0; iquality_entry_count; i++) + s->size += strlen(gf_list_get(ptr->quality_segment_url_modifiers, i)) + 1; + + s->size += ptr->segment_run_entry_count * sizeof(GF_AdobeSegmentRunEntry); + + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +void afrt_del(GF_Box *s) +{ + GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; + if (ptr == NULL) return; + + while (gf_list_count(ptr->quality_segment_url_modifiers)) { + gf_free(gf_list_get(ptr->quality_segment_url_modifiers, 0)); + gf_list_rem(ptr->quality_segment_url_modifiers, 0); + } + gf_list_del(ptr->quality_segment_url_modifiers); + + while (gf_list_count(ptr->fragment_run_entry_table)) { + gf_free(gf_list_get(ptr->fragment_run_entry_table, 0)); + gf_list_rem(ptr->fragment_run_entry_table, 0); + } + gf_list_del(ptr->fragment_run_entry_table); + + gf_free(ptr); +} + +GF_Err afrt_Read(GF_Box *s, GF_BitStream *bs) +{ + unsigned int i; + GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; + + GF_Err e = gf_isom_full_box_read(s, bs); + if (e) return e; + + ptr->timescale = gf_bs_read_u32(bs); + + ptr->quality_entry_count = gf_bs_read_u8(bs); + for (i=0; iquality_entry_count; i++) { + int j=0; + u32 tmp_strsize=(u32)ptr->size-8; + char *tmp_str = (char*) gf_malloc(tmp_strsize); + while (tmp_strsize) { + tmp_str[j] = gf_bs_read_u8(bs); + tmp_strsize--; + if (!tmp_str[j]) + break; + j++; + } + gf_list_insert(ptr->quality_segment_url_modifiers, tmp_str, i); + } + + ptr->fragment_run_entry_count = gf_bs_read_u32(bs); + for (i=0; ifragment_run_entry_count; i++) { + GF_AdobeFragmentRunEntry *fre = gf_malloc(sizeof(GF_AdobeFragmentRunEntry)); + fre->first_fragment = gf_bs_read_u32(bs); + fre->first_fragment_timestamp = gf_bs_read_u64(bs); + fre->fragment_duration = gf_bs_read_u32(bs); + if (!fre->fragment_duration) + fre->discontinuity_indicator = gf_bs_read_u8(bs); + gf_list_insert(ptr->fragment_run_entry_table, fre, i); + } + + return GF_OK; +} + +GF_Box *afrt_New() +{ + ISOM_DECL_BOX_ALLOC(GF_AdobeFragmentRunTableBox, GF_ISOM_BOX_TYPE_AFRT); + tmp->quality_segment_url_modifiers = gf_list_new(); + tmp->fragment_run_entry_table = gf_list_new(); + return (GF_Box *)tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err afrt_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + unsigned int i; + GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; + + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + gf_bs_write_u32(bs, ptr->timescale); + gf_bs_write_u8(bs, ptr->quality_entry_count); + for (i=0; iquality_entry_count; i++) { + char *str = (char*)gf_list_get(ptr->quality_segment_url_modifiers, i); + gf_bs_write_data(bs, str, (u32)strlen(str) + 1); + } + + gf_bs_write_u32(bs, ptr->fragment_run_entry_count); + for (i=0; ifragment_run_entry_count; i++) { + GF_AdobeFragmentRunEntry *fre = (GF_AdobeFragmentRunEntry *)gf_list_get(ptr->fragment_run_entry_table, i); + gf_bs_write_u32(bs, fre->first_fragment); + gf_bs_write_u64(bs, fre->first_fragment_timestamp); + gf_bs_write_u32(bs, fre->fragment_duration); + if (!fre->fragment_duration) + gf_bs_write_u8(bs, fre->discontinuity_indicator); + } + + return GF_OK; +} + + +GF_Err afrt_Size(GF_Box *s) +{ + u32 i; + GF_Err e; + GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; + + e = gf_isom_full_box_get_size(s); + if (e) return e; + + s->size += 5; + + for (i=0; iquality_entry_count; i++) + s->size += strlen(gf_list_get(ptr->quality_segment_url_modifiers, i)) + 1; + + s->size += 4; + + for (i=0; ifragment_run_entry_count; i++) { + GF_AdobeFragmentRunEntry *fre = (GF_AdobeFragmentRunEntry *)gf_list_get(ptr->fragment_run_entry_table, i); + if (fre->fragment_duration) + s->size += 16; + else + s->size += 17; + } + + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ + +#endif /*GPAC_DISABLE_ISOM*/ + +#endif /*GPAC_DISABLE_ISOM_ADOBE*/ diff --git a/src/isomedia/box_code_apple.c b/src/isomedia/box_code_apple.c index 7a92d5e..a2b2514 100644 --- a/src/isomedia/box_code_apple.c +++ b/src/isomedia/box_code_apple.c @@ -1,12 +1,27 @@ /* -Author: Andrew Voznytsa - -Project: GPAC - Multimedia Framework C SDK -Module: ISO Media File Format sub-project - -Copyright: (c) 2006, Andrew Voznytsa -License: see License.txt in the top level directory. -*/ + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2006-2012 + * All rights reserved + * + * This file is part of GPAC / ISO Media File Format sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ #include @@ -16,7 +31,6 @@ void ilst_del(GF_Box *s) { GF_ItemListBox *ptr = (GF_ItemListBox *)s; if (ptr == NULL) return; - gf_isom_box_array_del(ptr->tags); gf_free(ptr); } @@ -34,7 +48,7 @@ GF_Err ilst_Read(GF_Box *s, GF_BitStream *bs) if (e) return e; if (ptr->sizesize) return GF_ISOM_INVALID_FILE; ptr->size -= a->size; - gf_list_add(ptr->tags, a); + gf_list_add(ptr->other_boxes, a); } else { gf_bs_read_u32(bs); ptr->size -= 4; @@ -45,11 +59,8 @@ GF_Err ilst_Read(GF_Box *s, GF_BitStream *bs) GF_Box *ilst_New() { - GF_ItemListBox *tmp = (GF_ItemListBox *) gf_malloc(sizeof(GF_ItemListBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ItemListBox)); - tmp->type = GF_ISOM_BOX_TYPE_ILST; - tmp->tags = gf_list_new(); + ISOM_DECL_BOX_ALLOC(GF_ItemListBox, GF_ISOM_BOX_TYPE_ILST); + tmp->other_boxes = gf_list_new(); return (GF_Box *)tmp; } @@ -58,24 +69,24 @@ GF_Box *ilst_New() GF_Err ilst_Write(GF_Box *s, GF_BitStream *bs) { GF_Err e; - GF_ItemListBox *ptr = (GF_ItemListBox *)s; +// GF_ItemListBox *ptr = (GF_ItemListBox *)s; e = gf_isom_box_write_header(s, bs); if (e) return e; - return gf_isom_box_array_write(s, ptr->tags, bs); + return GF_OK; } GF_Err ilst_Size(GF_Box *s) { GF_Err e; - GF_ItemListBox *ptr = (GF_ItemListBox *)s; +// GF_ItemListBox *ptr = (GF_ItemListBox *)s; e = gf_isom_box_get_size(s); if (e) return e; - return gf_isom_box_array_size(s, ptr->tags); + return GF_OK; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -124,13 +135,7 @@ GF_Err ListItem_Read(GF_Box *s,GF_BitStream *bs) GF_Box *ListItem_New(u32 type) { - GF_ListItemBox *tmp; - - tmp = (GF_ListItemBox *) gf_malloc(sizeof(GF_ListItemBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ListItemBox)); - - tmp->type = type; + ISOM_DECL_BOX_ALLOC(GF_ListItemBox, type); tmp->data = (GF_DataBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_DATA); @@ -216,14 +221,9 @@ GF_Err data_Read(GF_Box *s,GF_BitStream *bs) GF_Box *data_New() { - GF_DataBox *tmp; - - tmp = (GF_DataBox *) gf_malloc(sizeof(GF_DataBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_DataBox)); + ISOM_DECL_BOX_ALLOC(GF_DataBox, GF_ISOM_BOX_TYPE_DATA); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_DATA; return (GF_Box *)tmp; } @@ -271,8 +271,8 @@ GF_MetaBox *gf_isom_apple_get_meta_extensions(GF_ISOFile *mov) map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_META, NULL); if (!map) return NULL; - for(i = 0; i < gf_list_count(map->boxList); i++){ - meta = (GF_MetaBox*)gf_list_get(map->boxList, i); + for(i = 0; i < gf_list_count(map->other_boxes); i++){ + meta = (GF_MetaBox*)gf_list_get(map->other_boxes, i); if(meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return meta; } @@ -297,8 +297,8 @@ GF_MetaBox *gf_isom_apple_create_meta_extensions(GF_ISOFile *mov) map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_META, NULL); if (map){ - for(i = 0; i < gf_list_count(map->boxList); i++){ - meta = (GF_MetaBox*)gf_list_get(map->boxList, i); + for(i = 0; i < gf_list_count(map->other_boxes); i++){ + meta = (GF_MetaBox*)gf_list_get(map->other_boxes, i); if(meta != NULL && meta->handler != NULL && meta->handler->handlerType == GF_ISOM_HANDLER_TYPE_MDIR) return meta; } @@ -313,6 +313,7 @@ GF_MetaBox *gf_isom_apple_create_meta_extensions(GF_ISOFile *mov) return NULL; } meta->handler->handlerType = GF_ISOM_HANDLER_TYPE_MDIR; + if (!meta->other_boxes) meta->other_boxes = gf_list_new(); gf_list_add(meta->other_boxes, gf_isom_box_new(GF_ISOM_BOX_TYPE_ILST)); udta_AddBox(mov->moov->udta, (GF_Box *)meta); } diff --git a/src/isomedia/box_code_base.c b/src/isomedia/box_code_base.c index 33420b6..f0eec99 100644 --- a/src/isomedia/box_code_base.c +++ b/src/isomedia/box_code_base.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -54,13 +55,8 @@ GF_Err co64_Read(GF_Box *s,GF_BitStream *bs) GF_Box *co64_New() { - GF_ChunkLargeOffsetBox *tmp; - - tmp = (GF_ChunkLargeOffsetBox *) gf_malloc(sizeof(GF_ChunkLargeOffsetBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ChunkLargeOffsetBox)); + ISOM_DECL_BOX_ALLOC(GF_ChunkLargeOffsetBox, GF_ISOM_BOX_TYPE_CO64); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_CO64; return (GF_Box *)tmp; } @@ -106,14 +102,9 @@ void cprt_del(GF_Box *s) GF_Box *chpl_New() { - GF_ChapterListBox *tmp; - - tmp = (GF_ChapterListBox *) gf_malloc(sizeof(GF_ChapterListBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ChapterListBox)); + ISOM_DECL_BOX_ALLOC(GF_ChapterListBox, GF_ISOM_BOX_TYPE_CHPL); tmp->list = gf_list_new(); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_CHPL; tmp->version = 1; return (GF_Box *)tmp; } @@ -258,14 +249,9 @@ GF_Err cprt_Read(GF_Box *s,GF_BitStream *bs) GF_Box *cprt_New() { - GF_CopyrightBox *tmp; - - tmp = (GF_CopyrightBox *) gf_malloc(sizeof(GF_CopyrightBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_CopyrightBox)); + ISOM_DECL_BOX_ALLOC(GF_CopyrightBox, GF_ISOM_BOX_TYPE_CPRT); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_CPRT; tmp->packedLanguageCode[0] = 'u'; tmp->packedLanguageCode[1] = 'n'; tmp->packedLanguageCode[2] = 'd'; @@ -330,12 +316,15 @@ GF_Err ctts_Read(GF_Box *s, GF_BitStream *bs) if (e) return e; ptr->nb_entries = gf_bs_read_u32(bs); ptr->alloc_size = ptr->nb_entries; - ptr->entries = gf_malloc(sizeof(GF_DttsEntry)*ptr->alloc_size); + ptr->entries = (GF_DttsEntry *)gf_malloc(sizeof(GF_DttsEntry)*ptr->alloc_size); if (!ptr->entries) return GF_OUT_OF_MEM; sampleCount = 0; for (i=0; inb_entries; i++) { ptr->entries[i].sampleCount = gf_bs_read_u32(bs); - ptr->entries[i].decodingOffset = gf_bs_read_u32(bs); + if (ptr->version) + ptr->entries[i].decodingOffset = gf_bs_read_int(bs, 32); + else + ptr->entries[i].decodingOffset = (s32) gf_bs_read_u32(bs); sampleCount += ptr->entries[i].sampleCount; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -346,14 +335,9 @@ GF_Err ctts_Read(GF_Box *s, GF_BitStream *bs) GF_Box *ctts_New() { - GF_CompositionOffsetBox *tmp; - - tmp = (GF_CompositionOffsetBox *) gf_malloc(sizeof(GF_CompositionOffsetBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_CompositionOffsetBox)); + ISOM_DECL_BOX_ALLOC(GF_CompositionOffsetBox, GF_ISOM_BOX_TYPE_CTTS); gf_isom_full_box_init((GF_Box *) tmp); - tmp->type = GF_ISOM_BOX_TYPE_CTTS; return (GF_Box *) tmp; } @@ -372,7 +356,11 @@ GF_Err ctts_Write(GF_Box *s, GF_BitStream *bs) gf_bs_write_u32(bs, ptr->nb_entries); for (i=0; inb_entries; i++ ) { gf_bs_write_u32(bs, ptr->entries[i].sampleCount); - gf_bs_write_u32(bs, ptr->entries[i].decodingOffset); + if (ptr->version) { + gf_bs_write_int(bs, ptr->entries[i].decodingOffset, 32); + } else { + gf_bs_write_u32(bs, (u32) ptr->entries[i].decodingOffset); + } } return GF_OK; } @@ -390,6 +378,67 @@ GF_Err ctts_Size(GF_Box *s) #endif /*GPAC_DISABLE_ISOM_WRITE*/ +void cslg_del(GF_Box *s) +{ + GF_CompositionToDecodeBox *ptr = (GF_CompositionToDecodeBox *)s; + if (ptr == NULL) return; + gf_free(ptr); + return; +} + +GF_Err cslg_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_CompositionToDecodeBox *ptr = (GF_CompositionToDecodeBox *)s; + + e = gf_isom_full_box_read(s, bs); + if (e) return e; + ptr->compositionToDTSShift = gf_bs_read_int(bs, 32); + ptr->leastDecodeToDisplayDelta = gf_bs_read_int(bs, 32); + ptr->greatestDecodeToDisplayDelta = gf_bs_read_int(bs, 32); + ptr->compositionStartTime = gf_bs_read_int(bs, 32); + ptr->compositionEndTime = gf_bs_read_int(bs, 32); + return GF_OK; +} + +GF_Box *cslg_New() +{ + ISOM_DECL_BOX_ALLOC(GF_CompositionToDecodeBox, GF_ISOM_BOX_TYPE_CSLG); + + gf_isom_full_box_init((GF_Box *) tmp); + return (GF_Box *) tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err cslg_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_CompositionToDecodeBox *ptr = (GF_CompositionToDecodeBox *)s; + + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gf_bs_write_int(bs, ptr->compositionToDTSShift, 32); + gf_bs_write_int(bs, ptr->leastDecodeToDisplayDelta, 32); + gf_bs_write_int(bs, ptr->greatestDecodeToDisplayDelta, 32); + gf_bs_write_int(bs, ptr->compositionStartTime, 32); + gf_bs_write_int(bs, ptr->compositionEndTime, 32); + return GF_OK; +} + +GF_Err cslg_Size(GF_Box *s) +{ + GF_Err e; + GF_CompositionToDecodeBox *ptr = (GF_CompositionToDecodeBox *)s; + + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += 20; + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + void url_del(GF_Box *s) { GF_DataEntryURLBox *ptr = (GF_DataEntryURLBox *)s; @@ -417,12 +466,8 @@ GF_Err url_Read(GF_Box *s, GF_BitStream *bs) GF_Box *url_New() { - GF_DataEntryURLBox *tmp = (GF_DataEntryURLBox *) gf_malloc(sizeof(GF_DataEntryURLBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_DataEntryURLBox)); - + ISOM_DECL_BOX_ALLOC(GF_DataEntryURLBox, GF_ISOM_BOX_TYPE_URL); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_URL; return (GF_Box *)tmp; } @@ -523,11 +568,8 @@ GF_Err urn_Read(GF_Box *s, GF_BitStream *bs) GF_Box *urn_New() { - GF_DataEntryURNBox *tmp = (GF_DataEntryURNBox *) gf_malloc(sizeof(GF_DataEntryURNBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_DataEntryURNBox)); + ISOM_DECL_BOX_ALLOC(GF_DataEntryURNBox, GF_ISOM_BOX_TYPE_URN); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_URN; return (GF_Box *)tmp; } @@ -598,8 +640,7 @@ GF_Err defa_Read(GF_Box *s, GF_BitStream *bs) //warning: we don't have any boxType, trick has to be done while creating.. GF_Box *defa_New() { - GF_UnknownBox *tmp = (GF_UnknownBox *) gf_malloc(sizeof(GF_UnknownBox)); - memset(tmp, 0, sizeof(GF_UnknownBox)); + ISOM_DECL_BOX_ALLOC(GF_UnknownBox, 0); return (GF_Box *) tmp; } @@ -657,12 +698,9 @@ GF_Err uuid_Read(GF_Box *s, GF_BitStream *bs) return GF_OK; } -//warning: we don't have any boxType, trick has to be done while creating.. GF_Box *uuid_New() { - GF_UnknownUUIDBox *tmp = (GF_UnknownUUIDBox *) gf_malloc(sizeof(GF_UnknownUUIDBox)); - memset(tmp, 0, sizeof(GF_UnknownUUIDBox)); - tmp->type = GF_ISOM_BOX_TYPE_UUID; + ISOM_DECL_BOX_ALLOC(GF_UnknownUUIDBox, GF_ISOM_BOX_TYPE_UUID); return (GF_Box *) tmp; } @@ -712,9 +750,9 @@ GF_Err dinf_AddBox(GF_Box *s, GF_Box *a) if (ptr->dref) return GF_ISOM_INVALID_FILE; ptr->dref = (GF_DataReferenceBox *)a; return GF_OK; + default: + return gf_isom_box_add_default(s, a); } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); return GF_OK; } @@ -725,10 +763,7 @@ GF_Err dinf_Read(GF_Box *s, GF_BitStream *bs) GF_Box *dinf_New() { - GF_DataInformationBox *tmp = (GF_DataInformationBox *) gf_malloc(sizeof(GF_DataInformationBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_DataInformationBox)); - tmp->type = GF_ISOM_BOX_TYPE_DINF; + ISOM_DECL_BOX_ALLOC(GF_DataInformationBox, GF_ISOM_BOX_TYPE_DINF); return (GF_Box *)tmp; } @@ -767,52 +802,35 @@ void dref_del(GF_Box *s) { GF_DataReferenceBox *ptr = (GF_DataReferenceBox *) s; if (ptr == NULL) return; - gf_isom_box_array_del(ptr->boxList); gf_free(ptr); } GF_Err dref_AddDataEntry(GF_DataReferenceBox *ptr, GF_Box *entry) { - return gf_list_add(ptr->boxList, entry); + return gf_isom_box_add_default((GF_Box *)ptr, entry); } GF_Err dref_Read(GF_Box *s, GF_BitStream *bs) { GF_Err e; - u32 count, i; - GF_Box *a; + //u32 count; GF_DataReferenceBox *ptr = (GF_DataReferenceBox *)s; if (ptr == NULL) return GF_BAD_PARAM; e = gf_isom_full_box_read(s, bs); if (e) return e; - count = gf_bs_read_u32(bs); + //count = + gf_bs_read_u32(bs); + ptr->size -= 4; - for ( i = 0; i < count; i++ ) { - e = gf_isom_parse_box(&a, bs); - if (e) return e; - if (ptr->sizesize) return GF_ISOM_INVALID_FILE; - e = gf_list_add(ptr->boxList, a); - if (e) return e; - ptr->size -= a->size; - } - return GF_OK; + return gf_isom_read_box_list(s, bs, gf_isom_box_add_default); } GF_Box *dref_New() { - GF_DataReferenceBox *tmp = (GF_DataReferenceBox *) gf_malloc(sizeof(GF_DataReferenceBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_DataReferenceBox)); - + ISOM_DECL_BOX_ALLOC(GF_DataReferenceBox, GF_ISOM_BOX_TYPE_DREF); gf_isom_full_box_init((GF_Box *) tmp); - tmp->boxList = gf_list_new(); - if (!tmp->boxList) { - gf_free(tmp); - return NULL; - } - tmp->type = GF_ISOM_BOX_TYPE_DREF; return (GF_Box *)tmp; } @@ -828,9 +846,9 @@ GF_Err dref_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_full_box_write(s, bs); if (e) return e; - count = gf_list_count(ptr->boxList); + count = ptr->other_boxes ? gf_list_count(ptr->other_boxes) : 0; gf_bs_write_u32(bs, count); - return gf_isom_box_array_write(s, ptr->boxList, bs); + return GF_OK; } GF_Err dref_Size(GF_Box *s) @@ -842,8 +860,6 @@ GF_Err dref_Size(GF_Box *s) e = gf_isom_full_box_get_size(s); if (e) return e; ptr->size += 4; - e = gf_isom_box_array_size(s, ptr->boxList); - if (e) return e; return GF_OK; } @@ -864,9 +880,9 @@ GF_Err edts_AddBox(GF_Box *s, GF_Box *a) if (ptr->editList) return GF_BAD_PARAM; ptr->editList = (GF_EditListBox *)a; return GF_OK; + } else { + return gf_isom_box_add_default(s, a); } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); return GF_OK; } @@ -878,10 +894,7 @@ GF_Err edts_Read(GF_Box *s, GF_BitStream *bs) GF_Box *edts_New() { - GF_EditBox *tmp; - GF_SAFEALLOC(tmp, GF_EditBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_EDTS; + ISOM_DECL_BOX_ALLOC(GF_EditBox, GF_ISOM_BOX_TYPE_EDTS); return (GF_Box *) tmp; } @@ -976,11 +989,7 @@ GF_Err elst_Read(GF_Box *s, GF_BitStream *bs) GF_Box *elst_New() { - GF_EditListBox *tmp; - - tmp = (GF_EditListBox *) gf_malloc(sizeof(GF_EditListBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_EditListBox)); + ISOM_DECL_BOX_ALLOC(GF_EditListBox, GF_ISOM_BOX_TYPE_ELST); gf_isom_full_box_init((GF_Box *)tmp); tmp->entryList = gf_list_new(); @@ -988,7 +997,6 @@ GF_Box *elst_New() gf_free(tmp); return NULL; } - tmp->type = GF_ISOM_BOX_TYPE_ELST; return (GF_Box *)tmp; } @@ -1101,13 +1109,9 @@ GF_Err esds_Read(GF_Box *s, GF_BitStream *bs) GF_Box *esds_New() { - GF_ESDBox *tmp = (GF_ESDBox *) gf_malloc(sizeof(GF_ESDBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ESDBox)); + ISOM_DECL_BOX_ALLOC(GF_ESDBox, GF_ISOM_BOX_TYPE_ESDS); gf_isom_full_box_init((GF_Box *) tmp); - tmp->type = GF_ISOM_BOX_TYPE_ESDS; - return (GF_Box *)tmp; } @@ -1172,10 +1176,7 @@ GF_Err free_Read(GF_Box *s, GF_BitStream *bs) GF_Box *free_New() { - GF_FreeSpaceBox *tmp = (GF_FreeSpaceBox *) gf_malloc(sizeof(GF_FreeSpaceBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_FreeSpaceBox)); - tmp->type = GF_ISOM_BOX_TYPE_FREE; + ISOM_DECL_BOX_ALLOC(GF_FreeSpaceBox, GF_ISOM_BOX_TYPE_FREE); return (GF_Box *)tmp; } @@ -1222,13 +1223,7 @@ void ftyp_del(GF_Box *s) GF_Box *ftyp_New() { - GF_FileTypeBox *tmp; - - tmp = (GF_FileTypeBox *) gf_malloc(sizeof(GF_FileTypeBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_FileTypeBox)); - - tmp->type = GF_ISOM_BOX_TYPE_FTYP; + ISOM_DECL_BOX_ALLOC(GF_FileTypeBox, GF_ISOM_BOX_TYPE_FTYP); return (GF_Box *)tmp; } @@ -1290,16 +1285,16 @@ GF_Err ftyp_Size(GF_Box *s) void gnrm_del(GF_Box *s) { GF_GenericSampleEntryBox *ptr = (GF_GenericSampleEntryBox *)s; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)ptr); if (ptr->data) gf_free(ptr->data); gf_free(ptr); } GF_Box *gnrm_New() { - GF_GenericSampleEntryBox *tmp = (GF_GenericSampleEntryBox *) gf_malloc(sizeof(GF_GenericSampleEntryBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_GenericSampleEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_GNRM; + ISOM_DECL_BOX_ALLOC(GF_GenericSampleEntryBox, GF_ISOM_BOX_TYPE_GNRM); + + gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp); return (GF_Box *)tmp; } @@ -1340,16 +1335,14 @@ GF_Err gnrm_Size(GF_Box *s) void gnrv_del(GF_Box *s) { GF_GenericVisualSampleEntryBox *ptr = (GF_GenericVisualSampleEntryBox *)s; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)ptr); if (ptr->data) gf_free(ptr->data); gf_free(ptr); } GF_Box *gnrv_New() { - GF_GenericVisualSampleEntryBox *tmp = (GF_GenericVisualSampleEntryBox *) gf_malloc(sizeof(GF_GenericVisualSampleEntryBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_GenericVisualSampleEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_GNRV; + ISOM_DECL_BOX_ALLOC(GF_GenericVisualSampleEntryBox, GF_ISOM_BOX_TYPE_GNRV); gf_isom_video_sample_entry_init((GF_VisualSampleEntryBox*) tmp); return (GF_Box *)tmp; } @@ -1393,16 +1386,14 @@ GF_Err gnrv_Size(GF_Box *s) void gnra_del(GF_Box *s) { GF_GenericAudioSampleEntryBox *ptr = (GF_GenericAudioSampleEntryBox *)s; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)ptr); if (ptr->data) gf_free(ptr->data); gf_free(ptr); } GF_Box *gnra_New() { - GF_GenericAudioSampleEntryBox *tmp = (GF_GenericAudioSampleEntryBox *) gf_malloc(sizeof(GF_GenericAudioSampleEntryBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_GenericAudioSampleEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_GNRA; + ISOM_DECL_BOX_ALLOC(GF_GenericAudioSampleEntryBox, GF_ISOM_BOX_TYPE_GNRA); gf_isom_audio_sample_entry_init((GF_AudioSampleEntryBox*) tmp); return (GF_Box *)tmp; } @@ -1479,11 +1470,8 @@ GF_Err hdlr_Read(GF_Box *s, GF_BitStream *bs) GF_Box *hdlr_New() { - GF_HandlerBox *tmp = (GF_HandlerBox *) gf_malloc(sizeof(GF_HandlerBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_HandlerBox)); + ISOM_DECL_BOX_ALLOC(GF_HandlerBox, GF_ISOM_BOX_TYPE_HDLR); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_HDLR; return (GF_Box *)tmp; } @@ -1522,29 +1510,14 @@ GF_Err hdlr_Size(GF_Box *s) void hinf_del(GF_Box *s) { GF_HintInfoBox *hinf = (GF_HintInfoBox *)s; - gf_isom_box_array_del(hinf->boxList); - gf_list_del(hinf->dataRates); gf_free(hinf); } GF_Box *hinf_New() { - GF_HintInfoBox *tmp = (GF_HintInfoBox *)gf_malloc(sizeof(GF_HintInfoBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_HintInfoBox)); + ISOM_DECL_BOX_ALLOC(GF_HintInfoBox, GF_ISOM_BOX_TYPE_HINF); - tmp->boxList = gf_list_new(); - if (!tmp->boxList) { - gf_free(tmp); - return NULL; - } - tmp->dataRates = gf_list_new(); - if (!tmp->dataRates) { - gf_list_del(tmp->boxList); - gf_free(tmp); - return NULL; - } - tmp->type = GF_ISOM_BOX_TYPE_HINF; + tmp->other_boxes = gf_list_new(); return (GF_Box *)tmp; } @@ -1556,15 +1529,13 @@ GF_Err hinf_AddBox(GF_Box *s, GF_Box *a) switch (a->type) { case GF_ISOM_BOX_TYPE_MAXR: i=0; - while ((maxR = (GF_MAXRBox *)gf_list_enum(hinf->dataRates, &i))) { - if (maxR->granularity == ((GF_MAXRBox *)a)->granularity) return GF_ISOM_INVALID_FILE; + while ((maxR = (GF_MAXRBox *)gf_list_enum(hinf->other_boxes, &i))) { + if ((maxR->type==GF_ISOM_BOX_TYPE_MAXR) && (maxR->granularity == ((GF_MAXRBox *)a)->granularity)) + return GF_ISOM_INVALID_FILE; } - gf_list_add(hinf->dataRates, a); - break; - default: break; } - return gf_list_add(hinf->boxList, a); + return gf_isom_box_add_default(s, a); } @@ -1577,21 +1548,15 @@ GF_Err hinf_Read(GF_Box *s, GF_BitStream *bs) GF_Err hinf_Write(GF_Box *s, GF_BitStream *bs) { - GF_Err e; - GF_HintInfoBox *ptr = (GF_HintInfoBox *)s; +// GF_HintInfoBox *ptr = (GF_HintInfoBox *)s; if (!s) return GF_BAD_PARAM; - e = gf_isom_box_write_header(s, bs); - if (e) return e; - return gf_isom_box_array_write(s, ptr->boxList, bs); + return gf_isom_box_write_header(s, bs); } GF_Err hinf_Size(GF_Box *s) { - GF_Err e; - GF_HintInfoBox *ptr = (GF_HintInfoBox *)s; - e = gf_isom_box_get_size(s); - if (e) return e; - return gf_isom_box_array_size(s, ptr->boxList); +// GF_HintInfoBox *ptr = (GF_HintInfoBox *)s; + return gf_isom_box_get_size(s); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -1620,13 +1585,9 @@ GF_Err hmhd_Read(GF_Box *s,GF_BitStream *bs) GF_Box *hmhd_New() { - GF_HintMediaHeaderBox *tmp = (GF_HintMediaHeaderBox *) gf_malloc(sizeof(GF_HintMediaHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_HintMediaHeaderBox)); + ISOM_DECL_BOX_ALLOC(GF_HintMediaHeaderBox, GF_ISOM_BOX_TYPE_HMHD); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_HMHD; - return (GF_Box *)tmp; } @@ -1662,15 +1623,13 @@ GF_Err hmhd_Size(GF_Box *s) GF_Box *hnti_New() { - GF_HintTrackInfoBox *tmp = (GF_HintTrackInfoBox *)gf_malloc(sizeof(GF_HintTrackInfoBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_HintTrackInfoBox)); - tmp->boxList = gf_list_new(); - if (!tmp->boxList) { + ISOM_DECL_BOX_ALLOC(GF_HintTrackInfoBox, GF_ISOM_BOX_TYPE_HNTI); + + tmp->hints = gf_list_new(); + if (!tmp->hints) { gf_free(tmp); return NULL; } - tmp->type = GF_ISOM_BOX_TYPE_HNTI; return (GF_Box *)tmp; } @@ -1679,8 +1638,8 @@ void hnti_del(GF_Box *a) GF_Box *t; GF_RTPBox *rtp; GF_HintTrackInfoBox *ptr = (GF_HintTrackInfoBox *)a; - while (gf_list_count(ptr->boxList)) { - t = (GF_Box*)gf_list_get(ptr->boxList, 0); + while (gf_list_count(ptr->hints)) { + t = (GF_Box*)gf_list_get(ptr->hints, 0); if (t->type != GF_ISOM_BOX_TYPE_RTP) { gf_isom_box_del(t); } else { @@ -1688,9 +1647,9 @@ void hnti_del(GF_Box *a) if (rtp->sdpText) gf_free(rtp->sdpText); gf_free(rtp); } - gf_list_rem(ptr->boxList, 0); + gf_list_rem(ptr->hints, 0); } - gf_list_del(ptr->boxList); + gf_list_del(ptr->hints); gf_free(ptr); } @@ -1708,7 +1667,7 @@ GF_Err hnti_AddBox(GF_HintTrackInfoBox *hnti, GF_Box *a) default: break; } - return gf_list_add(hnti->boxList, a); + return gf_list_add(hnti->hints, a); } GF_Err hnti_Read(GF_Box *s, GF_BitStream *bs) @@ -1782,9 +1741,9 @@ GF_Err hnti_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write_header(s, bs); if (e) return e; - count = gf_list_count(ptr->boxList); + count = gf_list_count(ptr->hints); for (i = 0; i < count; i ++) { - a = (GF_Box*)gf_list_get(ptr->boxList, i); + a = (GF_Box*)gf_list_get(ptr->hints, i); if (a->type != GF_ISOM_BOX_TYPE_RTP) { e = gf_isom_box_write(a, bs); if (e) return e; @@ -1815,9 +1774,9 @@ GF_Err hnti_Size(GF_Box *s) e = gf_isom_box_get_size(s); if (e) return e; - count = gf_list_count(ptr->boxList); + count = gf_list_count(ptr->hints); for (i = 0; i < count; i ++) { - a = (GF_Box*)gf_list_get(ptr->boxList, i); + a = (GF_Box*)gf_list_get(ptr->hints, i); if (a->type != GF_ISOM_BOX_TYPE_RTP) { e = gf_isom_box_size(a); if (e) return e; @@ -1863,10 +1822,7 @@ GF_Err sdp_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *sdp_New() { - GF_SDPBox *tmp = (GF_SDPBox *) gf_malloc(sizeof(GF_SDPBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_SDPBox)); - tmp->type = GF_ISOM_BOX_TYPE_SDP; + ISOM_DECL_BOX_ALLOC(GF_SDPBox, GF_ISOM_BOX_TYPE_SDP); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -1911,10 +1867,7 @@ GF_Err trpy_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *trpy_New() { - GF_TRPYBox *tmp = (GF_TRPYBox *) gf_malloc(sizeof(GF_TRPYBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TRPY; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_TRPYBox, GF_ISOM_BOX_TYPE_TRPY); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -1956,10 +1909,7 @@ GF_Err totl_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *totl_New() { - GF_TOTLBox *tmp = (GF_TOTLBox *) gf_malloc(sizeof(GF_TOTLBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TOTL; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_TOTLBox, GF_ISOM_BOX_TYPE_TOTL); return (GF_Box *)tmp; } @@ -2002,10 +1952,7 @@ GF_Err nump_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *nump_New() { - GF_NUMPBox *tmp = (GF_NUMPBox *) gf_malloc(sizeof(GF_NUMPBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_NUMP; - tmp->nbPackets = 0; + ISOM_DECL_BOX_ALLOC(GF_NUMPBox, GF_ISOM_BOX_TYPE_NUMP); return (GF_Box *)tmp; } @@ -2047,10 +1994,7 @@ GF_Err npck_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *npck_New() { - GF_NPCKBox *tmp = (GF_NPCKBox *) gf_malloc(sizeof(GF_NPCKBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_NPCK; - tmp->nbPackets = 0; + ISOM_DECL_BOX_ALLOC(GF_NPCKBox, GF_ISOM_BOX_TYPE_NPCK); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2092,10 +2036,7 @@ GF_Err tpyl_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *tpyl_New() { - GF_NTYLBox *tmp = (GF_NTYLBox *) gf_malloc(sizeof(GF_NTYLBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TPYL; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_NTYLBox, GF_ISOM_BOX_TYPE_TPYL); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2135,10 +2076,7 @@ GF_Err tpay_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *tpay_New() { - GF_TPAYBox *tmp = (GF_TPAYBox *) gf_malloc(sizeof(GF_TPAYBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TPAY; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_TPAYBox, GF_ISOM_BOX_TYPE_TPAY); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2181,10 +2119,7 @@ GF_Err maxr_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *maxr_New() { - GF_MAXRBox *tmp = (GF_MAXRBox *) gf_malloc(sizeof(GF_MAXRBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_MAXR; - tmp->granularity = tmp->maxDataRate = 0; + ISOM_DECL_BOX_ALLOC(GF_MAXRBox, GF_ISOM_BOX_TYPE_MAXR); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2226,10 +2161,7 @@ GF_Err dmed_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *dmed_New() { - GF_DMEDBox *tmp = (GF_DMEDBox *) gf_malloc(sizeof(GF_DMEDBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_DMED; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_DMEDBox, GF_ISOM_BOX_TYPE_DMED); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2269,10 +2201,7 @@ GF_Err dimm_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *dimm_New() { - GF_DIMMBox *tmp = (GF_DIMMBox *) gf_malloc(sizeof(GF_DIMMBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_DIMM; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_DIMMBox, GF_ISOM_BOX_TYPE_DIMM); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2312,10 +2241,7 @@ GF_Err drep_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *drep_New() { - GF_DREPBox *tmp = (GF_DREPBox *) gf_malloc(sizeof(GF_DREPBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_DREP; - tmp->nbBytes = 0; + ISOM_DECL_BOX_ALLOC(GF_DREPBox, GF_ISOM_BOX_TYPE_DREP); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2357,10 +2283,7 @@ GF_Err tmin_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *tmin_New() { - GF_TMINBox *tmp = (GF_TMINBox *) gf_malloc(sizeof(GF_TMINBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TMIN; - tmp->minTime = 0; + ISOM_DECL_BOX_ALLOC(GF_TMINBox, GF_ISOM_BOX_TYPE_TMIN); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2401,10 +2324,7 @@ GF_Err tmax_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *tmax_New() { - GF_TMAXBox *tmp = (GF_TMAXBox *) gf_malloc(sizeof(GF_TMAXBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TMAX; - tmp->maxTime = 0; + ISOM_DECL_BOX_ALLOC(GF_TMAXBox, GF_ISOM_BOX_TYPE_TMAX); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2445,10 +2365,7 @@ GF_Err pmax_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *pmax_New() { - GF_PMAXBox *tmp = (GF_PMAXBox *) gf_malloc(sizeof(GF_PMAXBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_PMAX; - tmp->maxSize = 0; + ISOM_DECL_BOX_ALLOC(GF_PMAXBox, GF_ISOM_BOX_TYPE_PMAX); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2489,10 +2406,7 @@ GF_Err dmax_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *dmax_New() { - GF_DMAXBox *tmp = (GF_DMAXBox *) gf_malloc(sizeof(GF_DMAXBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_DMAX; - tmp->maxDur = 0; + ISOM_DECL_BOX_ALLOC(GF_DMAXBox, GF_ISOM_BOX_TYPE_DMAX); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2543,11 +2457,7 @@ GF_Err payt_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *payt_New() { - GF_PAYTBox *tmp = (GF_PAYTBox *) gf_malloc(sizeof(GF_PAYTBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_PAYT; - tmp->payloadCode = 0; - tmp->payloadString = NULL; + ISOM_DECL_BOX_ALLOC(GF_PAYTBox, GF_ISOM_BOX_TYPE_PAYT); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2602,10 +2512,7 @@ GF_Err name_Read(GF_Box *s, GF_BitStream *bs) } GF_Box *name_New() { - GF_NameBox *tmp = (GF_NameBox *) gf_malloc(sizeof(GF_NameBox)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_NAME; - tmp->string = NULL; + ISOM_DECL_BOX_ALLOC(GF_NameBox, GF_ISOM_BOX_TYPE_NAME); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -2662,11 +2569,8 @@ GF_Err iods_Read(GF_Box *s, GF_BitStream *bs) GF_Box *iods_New() { - GF_ObjectDescriptorBox *tmp = (GF_ObjectDescriptorBox *) gf_malloc(sizeof(GF_ObjectDescriptorBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ObjectDescriptorBox)); + ISOM_DECL_BOX_ALLOC(GF_ObjectDescriptorBox, GF_ISOM_BOX_TYPE_IODS); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_IODS; return (GF_Box *)tmp; } @@ -2726,10 +2630,7 @@ GF_Err mdat_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mdat_New() { - GF_MediaDataBox *tmp = (GF_MediaDataBox *) gf_malloc(sizeof(GF_MediaDataBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MediaDataBox)); - tmp->type = GF_ISOM_BOX_TYPE_MDAT; + ISOM_DECL_BOX_ALLOC(GF_MediaDataBox, GF_ISOM_BOX_TYPE_MDAT); return (GF_Box *)tmp; } @@ -2810,12 +2711,9 @@ GF_Err mdhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mdhd_New() { - GF_MediaHeaderBox *tmp = (GF_MediaHeaderBox *) gf_malloc(sizeof(GF_MediaHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MediaHeaderBox)); + ISOM_DECL_BOX_ALLOC(GF_MediaHeaderBox, GF_ISOM_BOX_TYPE_MDHD); gf_isom_full_box_init((GF_Box *) tmp); - tmp->type = GF_ISOM_BOX_TYPE_MDHD; tmp->packedLanguage[0] = 'u'; tmp->packedLanguage[1] = 'n'; @@ -2896,9 +2794,9 @@ GF_Err mdia_AddBox(GF_Box *s, GF_Box *a) if (ptr->information) return GF_ISOM_INVALID_FILE; ptr->information = (GF_MediaInformationBox *)a; return GF_OK; + default: + return gf_isom_box_add_default(s, a); } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); return GF_OK; } @@ -2910,10 +2808,7 @@ GF_Err mdia_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mdia_New() { - GF_MediaBox *tmp = (GF_MediaBox *) gf_malloc(sizeof(GF_MediaBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MediaBox)); - tmp->type = GF_ISOM_BOX_TYPE_MDIA; + ISOM_DECL_BOX_ALLOC(GF_MediaBox, GF_ISOM_BOX_TYPE_MDIA); return (GF_Box *)tmp; } @@ -2991,10 +2886,7 @@ GF_Err mfhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mfhd_New() { - GF_MovieFragmentHeaderBox *tmp = (GF_MovieFragmentHeaderBox *) gf_malloc(sizeof(GF_MovieFragmentHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MovieFragmentHeaderBox)); - tmp->type = GF_ISOM_BOX_TYPE_MFHD; + ISOM_DECL_BOX_ALLOC(GF_MovieFragmentHeaderBox, GF_ISOM_BOX_TYPE_MFHD); return (GF_Box *)tmp; } @@ -3043,7 +2935,6 @@ void minf_del(GF_Box *s) if (ptr->InfoHeader) gf_isom_box_del((GF_Box *)ptr->InfoHeader); if (ptr->dataInformation) gf_isom_box_del((GF_Box *)ptr->dataInformation); if (ptr->sampleTable) gf_isom_box_del((GF_Box *)ptr->sampleTable); - gf_isom_box_array_del(ptr->boxes); gf_free(ptr); } @@ -3070,7 +2961,7 @@ GF_Err minf_AddBox(GF_Box *s, GF_Box *a) ptr->sampleTable = (GF_SampleTableBox *)a; return GF_OK; default: - return gf_list_add(ptr->boxes, a); + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -3083,11 +2974,7 @@ GF_Err minf_Read(GF_Box *s, GF_BitStream *bs) GF_Box *minf_New() { - GF_MediaInformationBox *tmp = (GF_MediaInformationBox *) gf_malloc(sizeof(GF_MediaInformationBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MediaInformationBox)); - tmp->type = GF_ISOM_BOX_TYPE_MINF; - tmp->boxes = gf_list_new(); + ISOM_DECL_BOX_ALLOC(GF_MediaInformationBox, GF_ISOM_BOX_TYPE_MINF); return (GF_Box *)tmp; } @@ -3118,7 +3005,7 @@ GF_Err minf_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write((GF_Box *) ptr->sampleTable, bs); if (e) return e; } - return gf_isom_box_array_write(s, ptr->boxes, bs); + return GF_OK; } GF_Err minf_Size(GF_Box *s) @@ -3143,7 +3030,7 @@ GF_Err minf_Size(GF_Box *s) if (e) return e; ptr->size += ptr->sampleTable->size; } - return gf_isom_box_array_size(s, ptr->boxes); + return GF_OK; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -3171,10 +3058,9 @@ GF_Err moof_AddBox(GF_Box *s, GF_Box *a) return GF_OK; case GF_ISOM_BOX_TYPE_TRAF: return gf_list_add(ptr->TrackList, a); + case GF_ISOM_BOX_TYPE_PSSH: default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - return GF_OK; + return gf_isom_box_add_default(s, a); } } @@ -3185,10 +3071,7 @@ GF_Err moof_Read(GF_Box *s, GF_BitStream *bs) GF_Box *moof_New() { - GF_MovieFragmentBox *tmp = (GF_MovieFragmentBox *) gf_malloc(sizeof(GF_MovieFragmentBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MovieFragmentBox)); - tmp->type = GF_ISOM_BOX_TYPE_MOOF; + ISOM_DECL_BOX_ALLOC(GF_MovieFragmentBox, GF_ISOM_BOX_TYPE_MOOF); tmp->TrackList = gf_list_new(); return (GF_Box *)tmp; } @@ -3249,7 +3132,6 @@ void moov_del(GF_Box *s) #endif gf_isom_box_array_del(ptr->trackList); - gf_isom_box_array_del(ptr->boxes); gf_free(ptr); } @@ -3295,13 +3177,13 @@ GF_Err moov_AddBox(GF_Box *s, GF_Box *a) //set our pointer to this obj ((GF_TrackBox *)a)->moov = ptr; return gf_list_add(ptr->trackList, a); + case GF_ISOM_BOX_TYPE_PSSH: default: - return gf_list_add(ptr->boxes, a); + return gf_isom_box_add_default(s, a); } } - GF_Err moov_Read(GF_Box *s, GF_BitStream *bs) { return gf_isom_read_box_list(s, bs, moov_AddBox); @@ -3309,21 +3191,12 @@ GF_Err moov_Read(GF_Box *s, GF_BitStream *bs) GF_Box *moov_New() { - GF_MovieBox *tmp = (GF_MovieBox *) gf_malloc(sizeof(GF_MovieBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MovieBox)); + ISOM_DECL_BOX_ALLOC(GF_MovieBox, GF_ISOM_BOX_TYPE_MOOV); tmp->trackList = gf_list_new(); if (!tmp->trackList) { gf_free(tmp); return NULL; } - tmp->boxes = gf_list_new(); - if (!tmp->boxes) { - gf_list_del(tmp->trackList); - gf_free(tmp); - return NULL; - } - tmp->type = GF_ISOM_BOX_TYPE_MOOV; return (GF_Box *)tmp; } @@ -3366,7 +3239,7 @@ GF_Err moov_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write((GF_Box *) ptr->udta, bs); if (e) return e; } - return gf_isom_box_array_write(s, ptr->boxes, bs); + return GF_OK; } GF_Err moov_Size(GF_Box *s) @@ -3404,9 +3277,7 @@ GF_Err moov_Size(GF_Box *s) } #endif - e = gf_isom_box_array_size(s, ptr->trackList); - if (e) return e; - return gf_isom_box_array_size(s, ptr->boxes); + return gf_isom_box_array_size(s, ptr->trackList); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -3415,9 +3286,10 @@ void mp4a_del(GF_Box *s) { GF_MPEGAudioSampleEntryBox *ptr = (GF_MPEGAudioSampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->esd) gf_isom_box_del((GF_Box *)ptr->esd); if (ptr->slc) gf_odf_desc_del((GF_Descriptor *)ptr->slc); - if (ptr->protection_info) gf_isom_box_del((GF_Box *)ptr->protection_info); gf_free(ptr); } @@ -3430,8 +3302,7 @@ GF_Err mp4a_AddBox(GF_Box *s, GF_Box *a) ptr->esd = (GF_ESDBox *)a; break; case GF_ISOM_BOX_TYPE_SINF: - if (ptr->protection_info) return GF_ISOM_INVALID_FILE; - ptr->protection_info = (GF_ProtectionInfoBox*)a; + gf_list_add(ptr->protections, a); break; case GF_4CC('w','a','v','e'): if (ptr->esd) return GF_ISOM_INVALID_FILE; @@ -3456,9 +3327,7 @@ GF_Err mp4a_AddBox(GF_Box *s, GF_Box *a) } break; default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -3497,18 +3366,14 @@ GF_Err mp4a_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mp4a_New() { - GF_MPEGAudioSampleEntryBox *tmp = (GF_MPEGAudioSampleEntryBox *)gf_malloc(sizeof(GF_MPEGAudioSampleEntryBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MPEGAudioSampleEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_MP4A; + ISOM_DECL_BOX_ALLOC(GF_MPEGAudioSampleEntryBox, GF_ISOM_BOX_TYPE_MP4A); gf_isom_audio_sample_entry_init((GF_AudioSampleEntryBox*)tmp); return (GF_Box *)tmp; } GF_Box *enca_New() { - GF_Box *tmp = mp4a_New(); - tmp->type = GF_ISOM_BOX_TYPE_ENCA; + ISOM_DECL_BOX_ALLOC(GF_Box, GF_ISOM_BOX_TYPE_ENCA); return tmp; } @@ -3524,11 +3389,8 @@ GF_Err mp4a_Write(GF_Box *s, GF_BitStream *bs) gf_isom_audio_sample_entry_write((GF_AudioSampleEntryBox*)s, bs); e = gf_isom_box_write((GF_Box *)ptr->esd, bs); if (e) return e; - if (ptr->protection_info && (ptr->type == GF_ISOM_BOX_TYPE_ENCA)) { - e = gf_isom_box_write((GF_Box *)ptr->protection_info, bs); - if (e) return e; - } - return GF_OK; + + return gf_isom_box_array_write(s, ptr->protections, bs); } GF_Err mp4a_Size(GF_Box *s) @@ -3543,12 +3405,7 @@ GF_Err mp4a_Size(GF_Box *s) e = gf_isom_box_size((GF_Box *)ptr->esd); if (e) return e; ptr->size += ptr->esd->size; - if (ptr->protection_info && (ptr->type == GF_ISOM_BOX_TYPE_ENCA)) { - e = gf_isom_box_size((GF_Box *)ptr->protection_info); - if (e) return e; - ptr->size += ptr->protection_info->size; - } - return GF_OK; + return gf_isom_box_array_size(s, ptr->protections); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -3558,9 +3415,10 @@ void mp4s_del(GF_Box *s) { GF_MPEGSampleEntryBox *ptr = (GF_MPEGSampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->esd) gf_isom_box_del((GF_Box *)ptr->esd); if (ptr->slc) gf_odf_desc_del((GF_Descriptor *)ptr->slc); - if (ptr->protection_info) gf_isom_box_del((GF_Box *)ptr->protection_info); gf_free(ptr); } @@ -3573,13 +3431,10 @@ GF_Err mp4s_AddBox(GF_Box *s, GF_Box *a) ptr->esd = (GF_ESDBox *)a; break; case GF_ISOM_BOX_TYPE_SINF: - if (ptr->protection_info) return GF_ISOM_INVALID_FILE; - ptr->protection_info = (GF_ProtectionInfoBox*)a; + gf_list_add(ptr->protections, a); break; default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -3595,18 +3450,14 @@ GF_Err mp4s_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mp4s_New() { - GF_MPEGSampleEntryBox *tmp = (GF_MPEGSampleEntryBox *) gf_malloc(sizeof(GF_MPEGSampleEntryBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MPEGSampleEntryBox)); - - tmp->type = GF_ISOM_BOX_TYPE_MP4S; + ISOM_DECL_BOX_ALLOC(GF_MPEGSampleEntryBox, GF_ISOM_BOX_TYPE_MP4S); + gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp); return (GF_Box *)tmp; } GF_Box *encs_New() { - GF_Box *tmp = mp4s_New(); - tmp->type = GF_ISOM_BOX_TYPE_ENCS; + ISOM_DECL_BOX_ALLOC(GF_Box, GF_ISOM_BOX_TYPE_ENCS); return tmp; } @@ -3624,10 +3475,7 @@ GF_Err mp4s_Write(GF_Box *s, GF_BitStream *bs) gf_bs_write_u16(bs, ptr->dataReferenceIndex); e = gf_isom_box_write((GF_Box *)ptr->esd, bs); if (e) return e; - if (ptr->protection_info && (ptr->type == GF_ISOM_BOX_TYPE_ENCS)) { - e = gf_isom_box_write((GF_Box *)ptr->protection_info, bs); - } - return e; + return gf_isom_box_array_write(s, ptr->protections, bs); } GF_Err mp4s_Size(GF_Box *s) @@ -3641,12 +3489,7 @@ GF_Err mp4s_Size(GF_Box *s) e = gf_isom_box_size((GF_Box *)ptr->esd); if (e) return e; ptr->size += ptr->esd->size; - if (ptr->protection_info && (ptr->type == GF_ISOM_BOX_TYPE_ENCS)) { - e = gf_isom_box_size((GF_Box *)ptr->protection_info); - if (e) return e; - ptr->size += ptr->protection_info->size; - } - return GF_OK; + return gf_isom_box_array_size(s, ptr->protections); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -3655,6 +3498,8 @@ void mp4v_del(GF_Box *s) { GF_MPEGVisualSampleEntryBox *ptr = (GF_MPEGVisualSampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->esd) gf_isom_box_del((GF_Box *)ptr->esd); if (ptr->slc) gf_odf_desc_del((GF_Descriptor *)ptr->slc); if (ptr->avc_config) gf_isom_box_del((GF_Box *) ptr->avc_config); @@ -3668,7 +3513,6 @@ void mp4v_del(GF_Box *s) if (ptr->pasp) gf_isom_box_del((GF_Box *)ptr->pasp); if (ptr->rvcc) gf_isom_box_del((GF_Box *)ptr->rvcc); - if (ptr->protection_info) gf_isom_box_del((GF_Box *)ptr->protection_info); gf_free(ptr); } @@ -3681,8 +3525,7 @@ GF_Err mp4v_AddBox(GF_Box *s, GF_Box *a) ptr->esd = (GF_ESDBox *)a; break; case GF_ISOM_BOX_TYPE_SINF: - if (ptr->protection_info) return GF_ISOM_INVALID_FILE; - ptr->protection_info = (GF_ProtectionInfoBox*)a; + gf_list_add(ptr->protections, a); break; case GF_ISOM_BOX_TYPE_AVCC: if (ptr->avc_config) return GF_ISOM_INVALID_FILE; @@ -3713,9 +3556,7 @@ GF_Err mp4v_AddBox(GF_Box *s, GF_Box *a) ptr->rvcc = (GF_RVCConfigurationBox *)a; break; default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -3812,15 +3653,11 @@ GF_Err mp4v_Write(GF_Box *s, GF_BitStream *bs) if (e) return e; } } - if (ptr->protection_info && (ptr->type == GF_ISOM_BOX_TYPE_ENCV)) { - e = gf_isom_box_write((GF_Box *)ptr->protection_info, bs); - if (e) return e; - } if (ptr->rvcc) { e = gf_isom_box_write((GF_Box *)ptr->rvcc, bs); if (e) return e; } - return e; + return gf_isom_box_array_write(s, ptr->protections, bs); } GF_Err mp4v_Size(GF_Box *s) @@ -3876,12 +3713,7 @@ GF_Err mp4v_Size(GF_Box *s) if (e) return e; ptr->size += ptr->rvcc->size; } - if (ptr->protection_info && (ptr->type == GF_ISOM_BOX_TYPE_ENCV)) { - e = gf_isom_box_size((GF_Box *)ptr->protection_info); - if (e) return e; - ptr->size += ptr->protection_info->size; - } - return GF_OK; + return gf_isom_box_array_size(s, ptr->protections); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -3911,9 +3743,9 @@ GF_Err mvex_AddBox(GF_Box *s, GF_Box *a) if (ptr->mehd) break; ptr->mehd = (GF_MovieExtendsHeaderBox*)a; return GF_OK; + default: + return gf_isom_box_add_default(s, a); } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); return GF_OK; } @@ -3926,15 +3758,12 @@ GF_Err mvex_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mvex_New() { - GF_MovieExtendsBox *tmp = (GF_MovieExtendsBox *) gf_malloc(sizeof(GF_MovieExtendsBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MovieExtendsBox)); + ISOM_DECL_BOX_ALLOC(GF_MovieExtendsBox, GF_ISOM_BOX_TYPE_MVEX); tmp->TrackExList = gf_list_new(); if (!tmp->TrackExList) { gf_free(tmp); return NULL; } - tmp->type = GF_ISOM_BOX_TYPE_MVEX; return (GF_Box *)tmp; } @@ -3950,6 +3779,10 @@ GF_Err mvex_Write(GF_Box *s, GF_BitStream *bs) if (!s) return GF_BAD_PARAM; e = gf_isom_box_write_header(s, bs); if (e) return e; + if (ptr->mehd) { + e = gf_isom_box_write((GF_Box *)ptr->mehd, bs); + if (e) return e; + } return gf_isom_box_array_write(s, ptr->TrackExList, bs); } @@ -3959,6 +3792,11 @@ GF_Err mvex_Size(GF_Box *s) GF_MovieExtendsBox *ptr = (GF_MovieExtendsBox *)s; e = gf_isom_box_get_size(s); if (e) return e; + if (ptr->mehd) { + e = gf_isom_box_size((GF_Box *)ptr->mehd); + if (e) return e; + ptr->size += ptr->mehd->size; + } return gf_isom_box_array_size(s, ptr->TrackExList); } @@ -3968,10 +3806,7 @@ GF_Err mvex_Size(GF_Box *s) GF_Box *mehd_New() { - GF_MovieExtendsHeaderBox *tmp; - GF_SAFEALLOC(tmp, GF_MovieExtendsHeaderBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_MEHD; + ISOM_DECL_BOX_ALLOC(GF_MovieExtendsHeaderBox, GF_ISOM_BOX_TYPE_MEHD); return (GF_Box *)tmp; } void mehd_del(GF_Box *s) @@ -4069,12 +3904,10 @@ GF_Err mvhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *mvhd_New() { - GF_MovieHeaderBox *tmp = (GF_MovieHeaderBox *) gf_malloc(sizeof(GF_MovieHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MovieHeaderBox)); + ISOM_DECL_BOX_ALLOC(GF_MovieHeaderBox, GF_ISOM_BOX_TYPE_MVHD); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_MVHD; + tmp->preferredRate = (1<<16); tmp->preferredVolume = (1<<8); @@ -4133,7 +3966,8 @@ GF_Err mvhd_Size(GF_Box *s) { GF_Err e; GF_MovieHeaderBox *ptr = (GF_MovieHeaderBox *)s; - ptr->version = (ptr->duration>0xFFFFFFFF) ? 1 : 0; + if (ptr->duration==(u64) -1) ptr->version = 0; + else ptr->version = (ptr->duration>0xFFFFFFFF) ? 1 : 0; e = gf_isom_full_box_get_size(s); if (e) return e; ptr->size += (ptr->version == 1) ? 28 : 16; @@ -4162,10 +3996,8 @@ GF_Err nmhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *nmhd_New() { - GF_MPEGMediaHeaderBox *tmp = (GF_MPEGMediaHeaderBox *) gf_malloc(sizeof(GF_MPEGMediaHeaderBox)); - if (tmp == NULL) return NULL; + ISOM_DECL_BOX_ALLOC(GF_MPEGMediaHeaderBox, GF_ISOM_BOX_TYPE_NMHD); gf_isom_full_box_init((GF_Box *) tmp); - tmp->type = GF_ISOM_BOX_TYPE_NMHD; return (GF_Box *)tmp; } @@ -4222,14 +4054,8 @@ GF_Err padb_Read(GF_Box *s,GF_BitStream *bs) GF_Box *padb_New() { - GF_PaddingBitsBox *tmp; - - tmp = (GF_PaddingBitsBox *) gf_malloc(sizeof(GF_PaddingBitsBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_PaddingBitsBox)); - + ISOM_DECL_BOX_ALLOC(GF_PaddingBitsBox, GF_ISOM_BOX_TYPE_PADB); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_FADB; return (GF_Box *)tmp; } @@ -4293,11 +4119,7 @@ GF_Err rely_Read(GF_Box *s, GF_BitStream *bs) GF_Box *rely_New() { - GF_RelyHintBox *tmp = (GF_RelyHintBox *)gf_malloc(sizeof(GF_RelyHintBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_RelyHintBox)); - tmp->type = GF_ISOM_BOX_TYPE_RELY; - + ISOM_DECL_BOX_ALLOC(GF_RelyHintBox, GF_ISOM_BOX_TYPE_RELY); return (GF_Box *)tmp; } @@ -4342,10 +4164,7 @@ GF_Err rtpo_Read(GF_Box *s, GF_BitStream *bs) GF_Box *rtpo_New() { - GF_RTPOBox *tmp = (GF_RTPOBox *) gf_malloc(sizeof(GF_RTPOBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_RTPOBox)); - tmp->type = GF_ISOM_BOX_TYPE_RTPO; + ISOM_DECL_BOX_ALLOC(GF_RTPOBox, GF_ISOM_BOX_TYPE_RTPO); return (GF_Box *)tmp; } #ifndef GPAC_DISABLE_ISOM_WRITE @@ -4393,11 +4212,8 @@ GF_Err smhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *smhd_New() { - GF_SoundMediaHeaderBox *tmp = (GF_SoundMediaHeaderBox *) gf_malloc(sizeof(GF_SoundMediaHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SoundMediaHeaderBox)); + ISOM_DECL_BOX_ALLOC(GF_SoundMediaHeaderBox, GF_ISOM_BOX_TYPE_SMHD); gf_isom_full_box_init((GF_Box *) tmp); - tmp->type = GF_ISOM_BOX_TYPE_SMHD; return (GF_Box *)tmp; } @@ -4444,10 +4260,7 @@ GF_Err snro_Read(GF_Box *s, GF_BitStream *bs) GF_Box *snro_New() { - GF_SeqOffHintEntryBox *tmp = (GF_SeqOffHintEntryBox *) gf_malloc(sizeof(GF_SeqOffHintEntryBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_SeqOffHintEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_SNRO; + ISOM_DECL_BOX_ALLOC(GF_SeqOffHintEntryBox, GF_ISOM_BOX_TYPE_SNRO); return (GF_Box *)tmp; } @@ -4485,6 +4298,7 @@ void stbl_del(GF_Box *s) if (ptr->ChunkOffset) gf_isom_box_del(ptr->ChunkOffset); if (ptr->CompositionOffset) gf_isom_box_del((GF_Box *) ptr->CompositionOffset); + if (ptr->CompositionToDecode) gf_isom_box_del((GF_Box *) ptr->CompositionToDecode); if (ptr->DegradationPriority) gf_isom_box_del((GF_Box *) ptr->DegradationPriority); if (ptr->SampleDescription) gf_isom_box_del((GF_Box *) ptr->SampleDescription); if (ptr->SampleSize) gf_isom_box_del((GF_Box *) ptr->SampleSize); @@ -4499,6 +4313,9 @@ void stbl_del(GF_Box *s) if (ptr->sampleGroups) gf_isom_box_array_del(ptr->sampleGroups); if (ptr->sampleGroupsDescription) gf_isom_box_array_del(ptr->sampleGroupsDescription); + if (ptr->sai_sizes) gf_isom_box_array_del(ptr->sai_sizes); + if (ptr->sai_offsets) gf_isom_box_array_del(ptr->sai_offsets); + gf_free(ptr); } @@ -4514,6 +4331,10 @@ GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a) if (ptr->CompositionOffset) return GF_ISOM_INVALID_FILE; ptr->CompositionOffset = (GF_CompositionOffsetBox *)a; break; + case GF_ISOM_BOX_TYPE_CSLG: + if (ptr->CompositionToDecode) return GF_ISOM_INVALID_FILE; + ptr->CompositionToDecode = (GF_CompositionToDecodeBox *)a; + break; case GF_ISOM_BOX_TYPE_STSS: if (ptr->SyncSample) return GF_ISOM_INVALID_FILE; ptr->SyncSample = (GF_SyncSampleBox *)a; @@ -4531,7 +4352,7 @@ GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a) if (ptr->SampleToChunk) return GF_ISOM_INVALID_FILE; ptr->SampleToChunk = (GF_SampleToChunkBox *)a; break; - case GF_ISOM_BOX_TYPE_FADB: + case GF_ISOM_BOX_TYPE_PADB: if (ptr->PaddingBits) return GF_ISOM_INVALID_FILE; ptr->PaddingBits = (GF_PaddingBitsBox *) a; break; @@ -4576,10 +4397,17 @@ GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a) gf_list_add(ptr->sampleGroupsDescription, a); break; - default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); + case GF_ISOM_BOX_TYPE_SAIZ: + if (!ptr->sai_sizes) ptr->sai_sizes = gf_list_new(); + gf_list_add(ptr->sai_sizes, a); break; + case GF_ISOM_BOX_TYPE_SAIO: + if (!ptr->sai_offsets) ptr->sai_offsets = gf_list_new(); + gf_list_add(ptr->sai_offsets, a); + break; + + default: + return gf_isom_box_add_default((GF_Box *)ptr, a); } return GF_OK; } @@ -4632,11 +4460,7 @@ GF_Err stbl_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stbl_New() { - GF_SampleTableBox *tmp = (GF_SampleTableBox *) gf_malloc(sizeof(GF_SampleTableBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SampleTableBox)); - - tmp->type = GF_ISOM_BOX_TYPE_STBL; + ISOM_DECL_BOX_ALLOC(GF_SampleTableBox, GF_ISOM_BOX_TYPE_STBL); //maxSamplePer chunk is 10 by default tmp->MaxSamplePerChunk = 10; tmp->groupID = 1; @@ -4667,6 +4491,10 @@ GF_Err stbl_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write((GF_Box *) ptr->CompositionOffset, bs); if (e) return e; } + if (ptr->CompositionToDecode) { + e = gf_isom_box_write((GF_Box *) ptr->CompositionToDecode, bs); + if (e) return e; + } if (ptr->SyncSample) { e = gf_isom_box_write((GF_Box *) ptr->SyncSample, bs); if (e) return e; @@ -4711,6 +4539,14 @@ GF_Err stbl_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_array_write(s, ptr->sampleGroups, bs); if (e) return e; } + if (ptr->sai_sizes) { + e = gf_isom_box_array_write(s, ptr->sai_sizes, bs); + if (e) return e; + } + if (ptr->sai_offsets) { + e = gf_isom_box_array_write(s, ptr->sai_offsets, bs); + if (e) return e; + } #if WRITE_SAMPLE_FRAGMENTS //sampleFragments @@ -4762,6 +4598,11 @@ GF_Err stbl_Size(GF_Box *s) if (e) return e; ptr->size += ptr->CompositionOffset->size; } + if (ptr->CompositionToDecode) { + e = gf_isom_box_size((GF_Box *) ptr->CompositionToDecode); + if (e) return e; + ptr->size += ptr->CompositionToDecode->size; + } if (ptr->DegradationPriority) { e = gf_isom_box_size((GF_Box *) ptr->DegradationPriority); if (e) return e; @@ -4810,6 +4651,14 @@ GF_Err stbl_Size(GF_Box *s) e = gf_isom_box_array_size(s, ptr->sampleGroupsDescription); if (e) return e; } + if (ptr->sai_sizes) { + e = gf_isom_box_array_size(s, ptr->sai_sizes); + if (e) return e; + } + if (ptr->sai_offsets) { + e = gf_isom_box_array_size(s, ptr->sai_offsets); + if (e) return e; + } return GF_OK; } @@ -4849,11 +4698,8 @@ GF_Err stco_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stco_New() { - GF_ChunkOffsetBox *tmp = (GF_ChunkOffsetBox *) gf_malloc(sizeof(GF_ChunkOffsetBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ChunkOffsetBox)); + ISOM_DECL_BOX_ALLOC(GF_ChunkOffsetBox, GF_ISOM_BOX_TYPE_STCO); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_STCO; return (GF_Box *)tmp; } @@ -4907,25 +4753,21 @@ GF_Err stdp_Read(GF_Box *s, GF_BitStream *bs) e = gf_isom_full_box_read(s, bs); if (e) return e; - /*out-of-order stdp, assume no padding at the end*/ - if (!ptr->nb_entries) ptr->nb_entries = (u32) (ptr->size-8) / 2; + /*out-of-order stdp, assume no padding at the end and take the entire remaining data for entries*/ + if (!ptr->nb_entries) ptr->nb_entries = (u32) ptr->size / 2; + ptr->priorities = (u16 *) gf_malloc(ptr->nb_entries * sizeof(u16)); if (ptr->priorities == NULL) return GF_OUT_OF_MEM; for (entry = 0; entry < ptr->nb_entries; entry++) { - //we have a bit for padding - gf_bs_read_int(bs, 1); - ptr->priorities[entry] = gf_bs_read_int(bs, 15); + ptr->priorities[entry] = gf_bs_read_u16(bs); } return GF_OK; } GF_Box *stdp_New() { - GF_DegradationPriorityBox *tmp = (GF_DegradationPriorityBox *) gf_malloc(sizeof(GF_DegradationPriorityBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_DegradationPriorityBox)); + ISOM_DECL_BOX_ALLOC(GF_DegradationPriorityBox, GF_ISOM_BOX_TYPE_STDP); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_STDP; return (GF_Box *)tmp; } @@ -4941,8 +4783,7 @@ GF_Err stdp_Write(GF_Box *s, GF_BitStream *bs) if (e) return e; for (i = 0; i < ptr->nb_entries; i++) { - gf_bs_write_int(bs, 0, 1); - gf_bs_write_int(bs, ptr->priorities[i], 15); + gf_bs_write_u16(bs, ptr->priorities[i]); } return GF_OK; } @@ -5001,11 +4842,8 @@ GF_Err stsc_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stsc_New() { - GF_SampleToChunkBox *tmp = (GF_SampleToChunkBox *) gf_malloc(sizeof(GF_SampleToChunkBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SampleToChunkBox)); + ISOM_DECL_BOX_ALLOC(GF_SampleToChunkBox, GF_ISOM_BOX_TYPE_STSC); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_STSC; return (GF_Box *)tmp; } @@ -5045,7 +4883,6 @@ void stsd_del(GF_Box *s) { GF_SampleDescriptionBox *ptr = (GF_SampleDescriptionBox *)s; if (ptr == NULL) return; - gf_isom_box_array_del(ptr->boxList); gf_free(ptr); } @@ -5074,7 +4911,7 @@ GF_Err stsd_AddBox(GF_SampleDescriptionBox *ptr, GF_Box *a) case GF_ISOM_BOX_TYPE_DIMS: case GF_ISOM_BOX_TYPE_AC3: case GF_ISOM_BOX_TYPE_LSR1: - return gf_list_add(ptr->boxList, a); + return gf_isom_box_add_default((GF_Box*)ptr, a); /*for 3GP config, we must set the type*/ case GF_ISOM_SUBTYPE_3GP_AMR: case GF_ISOM_SUBTYPE_3GP_AMR_WB: @@ -5083,12 +4920,12 @@ GF_Err stsd_AddBox(GF_SampleDescriptionBox *ptr, GF_Box *a) case GF_ISOM_SUBTYPE_3GP_SMV: { ((GF_3GPPAudioSampleEntryBox *)a)->info->cfg.type = a->type; - return gf_list_add(ptr->boxList, a); + return gf_isom_box_add_default((GF_Box*)ptr, a); } case GF_ISOM_SUBTYPE_3GP_H263: { ((GF_3GPPVisualSampleEntryBox *)a)->info->cfg.type = a->type; - return gf_list_add(ptr->boxList, a); + return gf_isom_box_add_default((GF_Box*)ptr, a); } //unknown sample description: we need a specific box to handle the data ref index @@ -5100,7 +4937,7 @@ GF_Err stsd_AddBox(GF_SampleDescriptionBox *ptr, GF_Box *a) gf_isom_box_del(a); return GF_OK; } - return gf_list_add(ptr->boxList, a); + return gf_isom_box_add_default((GF_Box*)ptr, a); } } @@ -5127,16 +4964,9 @@ GF_Err stsd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stsd_New() { - GF_SampleDescriptionBox *tmp = (GF_SampleDescriptionBox *) gf_malloc(sizeof(GF_SampleDescriptionBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SampleDescriptionBox)); + ISOM_DECL_BOX_ALLOC(GF_SampleDescriptionBox, GF_ISOM_BOX_TYPE_STSD); gf_isom_full_box_init((GF_Box *)tmp); - tmp->boxList = gf_list_new(); - if (! tmp->boxList) { - gf_free(tmp); - return NULL; - } - tmp->type = GF_ISOM_BOX_TYPE_STSD; + tmp->other_boxes = gf_list_new(); return (GF_Box *)tmp; } @@ -5151,9 +4981,9 @@ GF_Err stsd_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_full_box_write(s, bs); if (e) return e; - nb_entries = gf_list_count(ptr->boxList); + nb_entries = gf_list_count(ptr->other_boxes); gf_bs_write_u32(bs, nb_entries); - return gf_isom_box_array_write(s, ptr->boxList, bs); + return GF_OK; } GF_Err stsd_Size(GF_Box *s) @@ -5163,7 +4993,7 @@ GF_Err stsd_Size(GF_Box *s) e = gf_isom_full_box_get_size(s); if (e) return e; ptr->size += 4; - return gf_isom_box_array_size(s, ptr->boxList); + return GF_OK; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -5225,11 +5055,7 @@ GF_Err stsf_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stsf_New() { - GF_SampleFragmentBox *tmp; - - tmp = (GF_SampleFragmentBox *) gf_malloc(sizeof(GF_SampleFragmentBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SampleFragmentBox)); + ISOM_DECL_BOX_ALLOC(GF_SampleFragmentBox, GF_ISOM_BOX_TYPE_STSF); gf_isom_full_box_init((GF_Box *) tmp); tmp->entryList = gf_list_new(); @@ -5237,7 +5063,6 @@ GF_Box *stsf_New() gf_free(tmp); return NULL; } - tmp->type = GF_ISOM_BOX_TYPE_STSF; return (GF_Box *) tmp; } @@ -5328,16 +5153,13 @@ GF_Err stsh_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stsh_New() { - GF_ShadowSyncBox *tmp = (GF_ShadowSyncBox *) gf_malloc(sizeof(GF_ShadowSyncBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ShadowSyncBox)); + ISOM_DECL_BOX_ALLOC(GF_ShadowSyncBox, GF_ISOM_BOX_TYPE_STSH); gf_isom_full_box_init((GF_Box *)tmp); tmp->entries = gf_list_new(); if (!tmp->entries) { gf_free(tmp); return NULL; } - tmp->type = GF_ISOM_BOX_TYPE_STSH; return (GF_Box *)tmp; } @@ -5405,11 +5227,8 @@ GF_Err stss_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stss_New() { - GF_SyncSampleBox *tmp = (GF_SyncSampleBox *) gf_malloc(sizeof(GF_SyncSampleBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SyncSampleBox)); + ISOM_DECL_BOX_ALLOC(GF_SyncSampleBox, GF_ISOM_BOX_TYPE_STSS); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_STSS; return (GF_Box*)tmp; } @@ -5538,9 +5357,7 @@ GF_Err stsz_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stsz_New() { - GF_SampleSizeBox *tmp = (GF_SampleSizeBox *) gf_malloc(sizeof(GF_SampleSizeBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SampleSizeBox)); + ISOM_DECL_BOX_ALLOC(GF_SampleSizeBox, 0); gf_isom_full_box_init((GF_Box *)tmp); //type is unknown here, can be regular or compact table @@ -5706,11 +5523,8 @@ GF_Err stts_Read(GF_Box *s, GF_BitStream *bs) GF_Box *stts_New() { - GF_TimeToSampleBox *tmp = (GF_TimeToSampleBox *) gf_malloc(sizeof(GF_TimeToSampleBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TimeToSampleBox)); + ISOM_DECL_BOX_ALLOC(GF_TimeToSampleBox, GF_ISOM_BOX_TYPE_STTS); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_STTS; return (GF_Box *)tmp; } @@ -5787,10 +5601,7 @@ GF_Err tfhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *tfhd_New() { - GF_TrackFragmentHeaderBox *tmp = (GF_TrackFragmentHeaderBox *) gf_malloc(sizeof(GF_TrackFragmentHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackFragmentHeaderBox)); - tmp->type = GF_ISOM_BOX_TYPE_TFHD; + ISOM_DECL_BOX_ALLOC(GF_TrackFragmentHeaderBox, GF_ISOM_BOX_TYPE_TFHD); //NO FLAGS SET BY DEFAULT return (GF_Box *)tmp; } @@ -5866,10 +5677,7 @@ GF_Err tims_Read(GF_Box *s, GF_BitStream *bs) GF_Box *tims_New() { - GF_TSHintEntryBox *tmp = (GF_TSHintEntryBox *) gf_malloc(sizeof(GF_TSHintEntryBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_TSHintEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_TIMS; + ISOM_DECL_BOX_ALLOC(GF_TSHintEntryBox, GF_ISOM_BOX_TYPE_TIMS); return (GF_Box *)tmp; } @@ -5948,11 +5756,8 @@ GF_Err tkhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *tkhd_New() { - GF_TrackHeaderBox *tmp = (GF_TrackHeaderBox *) gf_malloc(sizeof(GF_TrackHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackHeaderBox)); + ISOM_DECL_BOX_ALLOC(GF_TrackHeaderBox, GF_ISOM_BOX_TYPE_TKHD); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_TKHD; tmp->matrix[0] = 0x00010000; tmp->matrix[4] = 0x00010000; tmp->matrix[8] = 0x40000000; @@ -6009,7 +5814,8 @@ GF_Err tkhd_Size(GF_Box *s) GF_TrackHeaderBox *ptr = (GF_TrackHeaderBox *)s; e = gf_isom_full_box_get_size(s); if (e) return e; - ptr->version = (ptr->duration>0xFFFFFFFF) ? 1 : 0; + if (ptr->duration==(u64) -1) ptr->version = 0; + else ptr->version = (ptr->duration>0xFFFFFFFF) ? 1 : 0; ptr->size += (ptr->version == 1) ? 32 : 20; ptr->size += 60; return GF_OK; @@ -6029,9 +5835,12 @@ void traf_del(GF_Box *s) if (ptr->sdtp) gf_isom_box_del((GF_Box *) ptr->sdtp); if (ptr->subs) gf_isom_box_del((GF_Box *) ptr->subs); if (ptr->tfdt) gf_isom_box_del((GF_Box *) ptr->tfdt); + if (ptr->piff_sample_encryption) gf_isom_box_del((GF_Box *) ptr->piff_sample_encryption); gf_isom_box_array_del(ptr->TrackRuns); if (ptr->sampleGroups) gf_isom_box_array_del(ptr->sampleGroups); if (ptr->sampleGroupsDescription) gf_isom_box_array_del(ptr->sampleGroupsDescription); + if (ptr->sai_sizes) gf_isom_box_array_del(ptr->sai_sizes); + if (ptr->sai_offsets) gf_isom_box_array_del(ptr->sai_offsets); gf_free(ptr); } @@ -6066,10 +5875,25 @@ GF_Err traf_AddBox(GF_Box *s, GF_Box *a) if (!ptr->sampleGroupsDescription) ptr->sampleGroupsDescription = gf_list_new(); gf_list_add(ptr->sampleGroupsDescription, a); return GF_OK; - default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); + case GF_ISOM_BOX_TYPE_SAIZ: + if (!ptr->sai_sizes) ptr->sai_sizes = gf_list_new(); + gf_list_add(ptr->sai_sizes, a); + return GF_OK; + case GF_ISOM_BOX_TYPE_SAIO: + if (!ptr->sai_offsets) ptr->sai_offsets = gf_list_new(); + gf_list_add(ptr->sai_offsets, a); return GF_OK; + case GF_ISOM_BOX_TYPE_UUID: + if ( ((GF_UUIDBox *)a)->internal_4cc==GF_ISOM_BOX_UUID_PSEC) { + if (ptr->piff_sample_encryption) return GF_ISOM_INVALID_FILE; + ptr->piff_sample_encryption = (GF_PIFFSampleEncryptionBox *)a; + ptr->piff_sample_encryption->traf = ptr; + return GF_OK; + } else { + return gf_isom_box_add_default(s, a); + } + default: + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -6077,16 +5901,50 @@ GF_Err traf_AddBox(GF_Box *s, GF_Box *a) GF_Err traf_Read(GF_Box *s, GF_BitStream *bs) { - GF_Err e = gf_isom_read_box_list(s, bs, traf_AddBox); - return e; + GF_Box *a; + + GF_TrackFragmentBox *ptr = (GF_TrackFragmentBox *)s; + + while (ptr->size) { + GF_Err e = gf_isom_parse_box(&a, bs); + if (e) return e; + + + //we need to read the DegPriority in a different way... + if ((a->type == GF_ISOM_BOX_TYPE_STDP) || (a->type == GF_ISOM_BOX_TYPE_SDTP)) { + u32 nb_samples=0, i=0; + u64 s = a->size; + for (i=0; iTrackRuns); i++) { + GF_TrackFragmentRunBox *trun = gf_list_get(ptr->TrackRuns, i); + nb_samples+=trun->sample_count; + } + if (a->type == GF_ISOM_BOX_TYPE_STDP) { + if (nb_samples) ((GF_DegradationPriorityBox *)a)->nb_entries = nb_samples; + e = stdp_Read(a, bs); + } else { + if (nb_samples) ((GF_SampleDependencyTypeBox *)a)->sampleCount = nb_samples; + e = sdtp_Read(a, bs); + } + if (e) { + gf_isom_box_del(a); + return e; + } + a->size = s; + } + if (ptr->sizesize) { + gf_isom_box_del(a); + return GF_ISOM_INVALID_FILE; + } + ptr->size -= a->size; + e = traf_AddBox((GF_Box*)ptr, a); + if (e) return e; + } + return GF_OK; } GF_Box *traf_New() { - GF_TrackFragmentBox *tmp; - GF_SAFEALLOC(tmp, GF_TrackFragmentBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_TRAF; + ISOM_DECL_BOX_ALLOC(GF_TrackFragmentBox, GF_ISOM_BOX_TYPE_TRAF); tmp->TrackRuns = gf_list_new(); return (GF_Box *)tmp; } @@ -6128,10 +5986,22 @@ GF_Err traf_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_array_write(s, ptr->sampleGroups, bs); if (e) return e; } + if (ptr->sai_sizes) { + e = gf_isom_box_array_write(s, ptr->sai_sizes, bs); + if (e) return e; + } + if (ptr->sai_offsets) { + e = gf_isom_box_array_write(s, ptr->sai_offsets, bs); + if (e) return e; + } e = gf_isom_box_array_write(s, ptr->TrackRuns, bs); if (e) return e; - return e; + if (ptr->piff_sample_encryption) { + e = gf_isom_box_write((GF_Box *) ptr->piff_sample_encryption, bs); + if (e) return e; + } + return GF_OK; } GF_Err traf_Size(GF_Box *s) @@ -6146,6 +6016,11 @@ GF_Err traf_Size(GF_Box *s) if (e) return e; ptr->size += ptr->tfhd->size; } + if (ptr->piff_sample_encryption) { + e = gf_isom_box_size((GF_Box *) ptr->piff_sample_encryption); + if (e) return e; + ptr->size += ptr->piff_sample_encryption->size; + } if (ptr->subs) { e = gf_isom_box_size((GF_Box *) ptr->subs); if (e) return e; @@ -6170,7 +6045,14 @@ GF_Err traf_Size(GF_Box *s) e = gf_isom_box_array_size(s, ptr->sampleGroupsDescription); if (e) return e; } - + if (ptr->sai_sizes) { + e = gf_isom_box_array_size(s, ptr->sai_sizes); + if (e) return e; + } + if (ptr->sai_offsets) { + e = gf_isom_box_array_size(s, ptr->sai_offsets); + if (e) return e; + } return gf_isom_box_array_size(s, ptr->TrackRuns); } @@ -6192,7 +6074,6 @@ void trak_del(GF_Box *s) if (ptr->References) gf_isom_box_del((GF_Box *)ptr->References); if (ptr->editBox) gf_isom_box_del((GF_Box *)ptr->editBox); if (ptr->meta) gf_isom_box_del((GF_Box *)ptr->meta); - gf_isom_box_array_del(ptr->boxes); if (ptr->name) gf_free(ptr->name); gf_free(ptr); } @@ -6207,7 +6088,7 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak) u32 i; i=0; - while ((a = (GF_UnknownBox*)gf_list_enum(trak->Media->information->sampleTable->SampleDescription->boxList, &i))) { + while ((a = (GF_UnknownBox*)gf_list_enum(trak->Media->information->sampleTable->SampleDescription->other_boxes, &i))) { switch (a->type) { case GF_ISOM_BOX_TYPE_MP4S: case GF_ISOM_BOX_TYPE_ENCS: @@ -6242,7 +6123,7 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak) switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_VISUAL: /*remove entry*/ - gf_list_rem(trak->Media->information->sampleTable->SampleDescription->boxList, i-1); + gf_list_rem(trak->Media->information->sampleTable->SampleDescription->other_boxes, i-1); genv = (GF_GenericVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRV); bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ); genv->size = a->size; @@ -6256,11 +6137,11 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak) genv->size = a->size; genv->EntryType = a->type; gf_isom_box_del((GF_Box *)a); - gf_list_insert(trak->Media->information->sampleTable->SampleDescription->boxList, genv, i-1); + gf_list_insert(trak->Media->information->sampleTable->SampleDescription->other_boxes, genv, i-1); break; case GF_ISOM_MEDIA_AUDIO: /*remove entry*/ - gf_list_rem(trak->Media->information->sampleTable->SampleDescription->boxList, i-1); + gf_list_rem(trak->Media->information->sampleTable->SampleDescription->other_boxes, i-1); gena = (GF_GenericAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRA); gena->size = a->size; bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ); @@ -6274,12 +6155,12 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak) gena->size = a->size; gena->EntryType = a->type; gf_isom_box_del((GF_Box *)a); - gf_list_insert(trak->Media->information->sampleTable->SampleDescription->boxList, gena, i-1); + gf_list_insert(trak->Media->information->sampleTable->SampleDescription->other_boxes, gena, i-1); break; default: /*remove entry*/ - gf_list_rem(trak->Media->information->sampleTable->SampleDescription->boxList, i-1); + gf_list_rem(trak->Media->information->sampleTable->SampleDescription->other_boxes, i-1); genm = (GF_GenericSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRM); genm->size = a->size; bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ); @@ -6294,7 +6175,7 @@ static void gf_isom_check_sample_desc(GF_TrackBox *trak) genm->size = a->size; genm->EntryType = a->type; gf_isom_box_del((GF_Box *)a); - gf_list_insert(trak->Media->information->sampleTable->SampleDescription->boxList, genm, i-1); + gf_list_insert(trak->Media->information->sampleTable->SampleDescription->other_boxes, genm, i-1); break; } @@ -6333,9 +6214,7 @@ GF_Err trak_AddBox(GF_Box *s, GF_Box *a) ((GF_MediaBox *)a)->mediaTrack = ptr; return GF_OK; default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - return GF_OK; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -6353,11 +6232,7 @@ GF_Err trak_Read(GF_Box *s, GF_BitStream *bs) GF_Box *trak_New() { - GF_TrackBox *tmp = (GF_TrackBox *) gf_malloc(sizeof(GF_TrackBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackBox)); - tmp->type = GF_ISOM_BOX_TYPE_TRAK; - tmp->boxes = gf_list_new(); + ISOM_DECL_BOX_ALLOC(GF_TrackBox, GF_ISOM_BOX_TYPE_TRAK); return (GF_Box *)tmp; } @@ -6395,7 +6270,7 @@ GF_Err trak_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write((GF_Box *) ptr->udta, bs); if (e) return e; } - return gf_isom_box_array_write(s, ptr->boxes, bs); + return GF_OK; } GF_Err trak_Size(GF_Box *s) @@ -6436,43 +6311,33 @@ GF_Err trak_Size(GF_Box *s) if (e) return e; ptr->size += ptr->meta->size; } - return gf_isom_box_array_size(s, ptr->boxes); + return GF_OK; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ +GF_Err tref_AddBox(GF_Box *ptr, GF_Box *a) +{ + return gf_isom_box_add_default(ptr, a); +} + void tref_del(GF_Box *s) { GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s; if (ptr == NULL) return; - gf_isom_box_array_del(ptr->boxList); gf_free(ptr); } -GF_Err tref_AddBox(GF_Box *s, GF_Box *a) -{ - GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s; - return gf_list_add(ptr->boxList, a); -} - GF_Err tref_Read(GF_Box *s, GF_BitStream *bs) { - return gf_isom_read_box_list_ex(s, bs, tref_AddBox, s->type); + return gf_isom_read_box_list_ex(s, bs, gf_isom_box_add_default, s->type); } GF_Box *tref_New() { - GF_TrackReferenceBox *tmp = (GF_TrackReferenceBox *) gf_malloc(sizeof(GF_TrackReferenceBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackReferenceBox)); - tmp->boxList = gf_list_new(); - if (!tmp->boxList) { - gf_free(tmp); - return NULL; - } - tmp->type = GF_ISOM_BOX_TYPE_TREF; + ISOM_DECL_BOX_ALLOC(GF_TrackReferenceBox, GF_ISOM_BOX_TYPE_TREF); return (GF_Box *)tmp; } @@ -6482,20 +6347,14 @@ GF_Box *tref_New() GF_Err tref_Write(GF_Box *s, GF_BitStream *bs) { - GF_Err e; - GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s; - e = gf_isom_box_write_header(s, bs); - if (e) return e; - return gf_isom_box_array_write(s, ptr->boxList, bs); +// GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s; + return gf_isom_box_write_header(s, bs); } GF_Err tref_Size(GF_Box *s) { - GF_Err e; - GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s; - e = gf_isom_box_get_size(s); - if (e) return e; - return gf_isom_box_array_size(s, ptr->boxList); +// GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s; + return gf_isom_box_get_size(s); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -6530,10 +6389,7 @@ GF_Err reftype_Read(GF_Box *s, GF_BitStream *bs) GF_Box *reftype_New() { - GF_TrackReferenceTypeBox *tmp = (GF_TrackReferenceTypeBox *) gf_malloc(sizeof(GF_TrackReferenceTypeBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackReferenceTypeBox)); - tmp->type = GF_ISOM_BOX_TYPE_REFT; + ISOM_DECL_BOX_ALLOC(GF_TrackReferenceTypeBox, GF_ISOM_BOX_TYPE_REFT); return (GF_Box *)tmp; } @@ -6622,10 +6478,7 @@ GF_Err trex_Read(GF_Box *s, GF_BitStream *bs) GF_Box *trex_New() { - GF_TrackExtendsBox *tmp = (GF_TrackExtendsBox *) gf_malloc(sizeof(GF_TrackExtendsBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackExtendsBox)); - tmp->type = GF_ISOM_BOX_TYPE_TREX; + ISOM_DECL_BOX_ALLOC(GF_TrackExtendsBox, GF_ISOM_BOX_TYPE_TREX); return (GF_Box *)tmp; } @@ -6744,10 +6597,7 @@ GF_Err trun_Read(GF_Box *s, GF_BitStream *bs) GF_Box *trun_New() { - GF_TrackFragmentRunBox *tmp = (GF_TrackFragmentRunBox *) gf_malloc(sizeof(GF_TrackFragmentRunBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_TrackFragmentRunBox)); - tmp->type = GF_ISOM_BOX_TYPE_TRUN; + ISOM_DECL_BOX_ALLOC(GF_TrackFragmentRunBox, GF_ISOM_BOX_TYPE_TRUN); tmp->entries = gf_list_new(); //NO FLAGS SET BY DEFAULT return (GF_Box *)tmp; @@ -6850,10 +6700,7 @@ GF_Err tsro_Read(GF_Box *s, GF_BitStream *bs) GF_Box *tsro_New() { - GF_TimeOffHintEntryBox *tmp = (GF_TimeOffHintEntryBox *) gf_malloc(sizeof(GF_TimeOffHintEntryBox)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_TimeOffHintEntryBox)); - tmp->type = GF_ISOM_BOX_TYPE_TSRO; + ISOM_DECL_BOX_ALLOC(GF_TimeOffHintEntryBox, GF_ISOM_BOX_TYPE_TSRO); return (GF_Box *)tmp; } @@ -6890,7 +6737,7 @@ void udta_del(GF_Box *s) if (ptr == NULL) return; i=0; while ((map = (GF_UserDataMap *)gf_list_enum(ptr->recordList, &i))) { - gf_isom_box_array_del(map->boxList); + gf_isom_box_array_del(map->other_boxes); gf_free(map); } gf_list_del(ptr->recordList); @@ -6928,15 +6775,15 @@ GF_Err udta_AddBox(GF_UserDataBox *ptr, GF_Box *a) map->boxType = a->type; if (a->type == GF_ISOM_BOX_TYPE_UUID) memcpy(map->uuid, ((GF_UUIDBox *)a)->uuid, 16); - map->boxList = gf_list_new(); - if (!map->boxList) { + map->other_boxes = gf_list_new(); + if (!map->other_boxes) { gf_free(map); return GF_OUT_OF_MEM; } e = gf_list_add(ptr->recordList, map); if (e) return e; } - return gf_list_add(map->boxList, a); + return gf_list_add(map->other_boxes, a); } @@ -6966,15 +6813,12 @@ GF_Err udta_Read(GF_Box *s, GF_BitStream *bs) GF_Box *udta_New() { - GF_UserDataBox *tmp = (GF_UserDataBox *) gf_malloc(sizeof(GF_UserDataBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_UserDataBox)); + ISOM_DECL_BOX_ALLOC(GF_UserDataBox, GF_ISOM_BOX_TYPE_UDTA); tmp->recordList = gf_list_new(); if (!tmp->recordList) { gf_free(tmp); return NULL; } - tmp->type = GF_ISOM_BOX_TYPE_UDTA; return (GF_Box *)tmp; } @@ -6994,7 +6838,7 @@ GF_Err udta_Write(GF_Box *s, GF_BitStream *bs) while ((map = (GF_UserDataMap *)gf_list_enum(ptr->recordList, &i))) { //warning: here we are not passing the actual "parent" of the list //but the UDTA box. The parent itself is not an box, we don't care about it - e = gf_isom_box_array_write(s, map->boxList, bs); + e = gf_isom_box_array_write(s, map->other_boxes, bs); if (e) return e; } return GF_OK; @@ -7013,7 +6857,7 @@ GF_Err udta_Size(GF_Box *s) while ((map = (GF_UserDataMap *)gf_list_enum(ptr->recordList, &i))) { //warning: here we are not passing the actual "parent" of the list //but the UDTA box. The parent itself is not an box, we don't care about it - e = gf_isom_box_array_size(s, map->boxList); + e = gf_isom_box_array_size(s, map->other_boxes); if (e) return e; } return GF_OK; @@ -7042,12 +6886,9 @@ GF_Err vmhd_Read(GF_Box *s, GF_BitStream *bs) GF_Box *vmhd_New() { - GF_VideoMediaHeaderBox *tmp = (GF_VideoMediaHeaderBox *) gf_malloc(sizeof(GF_VideoMediaHeaderBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_VideoMediaHeaderBox)); + ISOM_DECL_BOX_ALLOC(GF_VideoMediaHeaderBox, GF_ISOM_BOX_TYPE_VMHD); gf_isom_full_box_init((GF_Box *)tmp); tmp->flags = 1; - tmp->type = GF_ISOM_BOX_TYPE_VMHD; return (GF_Box *)tmp; } @@ -7093,9 +6934,7 @@ GF_Err void_Read(GF_Box *s, GF_BitStream *bs) GF_Box *void_New() { - GF_Box *tmp = (GF_Box *) gf_malloc(sizeof(GF_Box)); - if (!tmp) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_VOID; + ISOM_DECL_BOX_ALLOC(GF_Box, GF_ISOM_BOX_TYPE_VOID); return tmp; } @@ -7120,12 +6959,9 @@ GF_Err void_Size(GF_Box *s) GF_Box *pdin_New() { - GF_ProgressiveDownloadBox *tmp = (GF_ProgressiveDownloadBox*) gf_malloc(sizeof(GF_ProgressiveDownloadBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ProgressiveDownloadBox)); + ISOM_DECL_BOX_ALLOC(GF_ProgressiveDownloadBox, GF_ISOM_BOX_TYPE_PDIN); gf_isom_full_box_init((GF_Box *)tmp); tmp->flags = 1; - tmp->type = GF_ISOM_BOX_TYPE_PDIN; return (GF_Box *)tmp; } @@ -7193,12 +7029,9 @@ GF_Err pdin_Size(GF_Box *s) GF_Box *sdtp_New() { - GF_SampleDependencyTypeBox *tmp = (GF_SampleDependencyTypeBox*) gf_malloc(sizeof(GF_SampleDependencyTypeBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SampleDependencyTypeBox)); + ISOM_DECL_BOX_ALLOC(GF_SampleDependencyTypeBox, GF_ISOM_BOX_TYPE_SDTP); gf_isom_full_box_init((GF_Box *)tmp); tmp->flags = 1; - tmp->type = GF_ISOM_BOX_TYPE_SDTP; return (GF_Box *)tmp; } @@ -7255,10 +7088,7 @@ GF_Err sdtp_Size(GF_Box *s) GF_Box *pasp_New() { - GF_PixelAspectRatioBox *tmp; - GF_SAFEALLOC(tmp, GF_PixelAspectRatioBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_PASP; + ISOM_DECL_BOX_ALLOC(GF_PixelAspectRatioBox, GF_ISOM_BOX_TYPE_PASP); return (GF_Box *)tmp; } @@ -7308,10 +7138,8 @@ GF_Err pasp_Size(GF_Box *s) GF_Box *metx_New(u32 type) { - GF_MetaDataSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_MetaDataSampleEntryBox); - if (tmp == NULL) return NULL; - tmp->type = type; + ISOM_DECL_BOX_ALLOC(GF_MetaDataSampleEntryBox, type); + gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp); return (GF_Box *)tmp; } @@ -7320,6 +7148,8 @@ void metx_del(GF_Box *s) { GF_MetaDataSampleEntryBox *ptr = (GF_MetaDataSampleEntryBox*)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->content_encoding) gf_free(ptr->content_encoding); if (ptr->mime_type_or_namespace) gf_free(ptr->mime_type_or_namespace); if (ptr->xml_schema_loc) gf_free(ptr->xml_schema_loc); @@ -7333,17 +7163,14 @@ GF_Err metx_AddBox(GF_Box *s, GF_Box *a) GF_MPEGVisualSampleEntryBox *ptr = (GF_MPEGVisualSampleEntryBox *)s; switch (a->type) { case GF_ISOM_BOX_TYPE_SINF: - if (ptr->protection_info) return GF_ISOM_INVALID_FILE; - ptr->protection_info = (GF_ProtectionInfoBox*)a; + gf_list_add(ptr->protections, a); break; case GF_ISOM_BOX_TYPE_BTRT: if (ptr->bitrate) return GF_ISOM_INVALID_FILE; ptr->bitrate = (GF_MPEG4BitRateBox *)a; break; default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -7417,19 +7244,17 @@ GF_Err metx_Write(GF_Box *s, GF_BitStream *bs) gf_bs_write_data(bs, ptr->mime_type_or_namespace, strlen(ptr->mime_type_or_namespace)); gf_bs_write_u8(bs, 0); - if (ptr->xml_schema_loc) - gf_bs_write_data(bs, ptr->xml_schema_loc, strlen(ptr->xml_schema_loc)); - gf_bs_write_u8(bs, 0); + if (ptr->type == GF_ISOM_BOX_TYPE_METX) { + if (ptr->xml_schema_loc) + gf_bs_write_data(bs, ptr->xml_schema_loc, strlen(ptr->xml_schema_loc)); + gf_bs_write_u8(bs, 0); + } if (ptr->bitrate) { e = gf_isom_box_write((GF_Box *)ptr->bitrate, bs); if (e) return e; } - if (ptr->protection_info) { - e = gf_isom_box_write((GF_Box *)ptr->protection_info, bs); - if (e) return e; - } - return GF_OK; + return gf_isom_box_array_size(s, ptr->protections); } GF_Err metx_Size(GF_Box *s) @@ -7445,33 +7270,29 @@ GF_Err metx_Size(GF_Box *s) if (ptr->mime_type_or_namespace) ptr->size += strlen(ptr->mime_type_or_namespace); ptr->size++; - if (ptr->xml_schema_loc) - ptr->size += strlen(ptr->xml_schema_loc); - ptr->size++; + if (ptr->type == GF_ISOM_BOX_TYPE_METX) { + if (ptr->xml_schema_loc) + ptr->size += strlen(ptr->xml_schema_loc); + ptr->size++; + } if (ptr->bitrate) { e = gf_isom_box_size((GF_Box *)ptr->bitrate); if (e) return e; ptr->size += ptr->bitrate->size; } - if (ptr->protection_info) { - e = gf_isom_box_size((GF_Box *)ptr->protection_info); - if (e) return e; - ptr->size += ptr->protection_info->size; - } - return GF_OK; + return gf_isom_box_array_size(s, ptr->protections); } #endif /*GPAC_DISABLE_ISOM_WRITE*/ -GF_Box *dac3_New() +GF_Box *dac3_New(u32 boxType) { - GF_AC3ConfigBox *tmp = (GF_AC3ConfigBox *) gf_malloc(sizeof(GF_AC3ConfigBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_AC3ConfigBox)); - tmp->type = GF_ISOM_BOX_TYPE_DAC3; + ISOM_DECL_BOX_ALLOC(GF_AC3ConfigBox, GF_ISOM_BOX_TYPE_DAC3); + if (boxType==GF_ISOM_BOX_TYPE_DEC3) + tmp->cfg.is_ec3 = 1; return (GF_Box *)tmp; } @@ -7487,13 +7308,34 @@ GF_Err dac3_Read(GF_Box *s, GF_BitStream *bs) GF_AC3ConfigBox *ptr = (GF_AC3ConfigBox *)s; if (ptr == NULL) return GF_BAD_PARAM; - ptr->cfg.fscod = gf_bs_read_int(bs, 2); - ptr->cfg.bsid = gf_bs_read_int(bs, 5); - ptr->cfg.bsmod = gf_bs_read_int(bs, 3); - ptr->cfg.acmod = gf_bs_read_int(bs, 3); - ptr->cfg.lfon = gf_bs_read_int(bs, 1); - ptr->cfg.brcode = gf_bs_read_int(bs, 5); - gf_bs_read_int(bs, 5); + if (ptr->cfg.is_ec3) { + u32 i; + ptr->cfg.brcode = gf_bs_read_int(bs, 13); + ptr->cfg.nb_streams = gf_bs_read_int(bs, 3) + 1; + for (i=0; icfg.nb_streams; i++) { + ptr->cfg.streams[i].fscod = gf_bs_read_int(bs, 2); + ptr->cfg.streams[i].bsid = gf_bs_read_int(bs, 5); + ptr->cfg.streams[i].bsmod = gf_bs_read_int(bs, 5); + ptr->cfg.streams[i].acmod = gf_bs_read_int(bs, 3); + ptr->cfg.streams[i].lfon = gf_bs_read_int(bs, 1); + gf_bs_read_int(bs, 3); + ptr->cfg.streams[i].nb_dep_sub = gf_bs_read_int(bs, 4); + if (ptr->cfg.streams[i].nb_dep_sub) { + ptr->cfg.streams[i].chan_loc = gf_bs_read_int(bs, 9); + } else { + gf_bs_read_int(bs, 1); + } + } + } else { + ptr->cfg.nb_streams = 1; + ptr->cfg.streams[0].fscod = gf_bs_read_int(bs, 2); + ptr->cfg.streams[0].bsid = gf_bs_read_int(bs, 5); + ptr->cfg.streams[0].bsmod = gf_bs_read_int(bs, 3); + ptr->cfg.streams[0].acmod = gf_bs_read_int(bs, 3); + ptr->cfg.streams[0].lfon = gf_bs_read_int(bs, 1); + ptr->cfg.brcode = gf_bs_read_int(bs, 5); + gf_bs_read_int(bs, 5); + } return GF_OK; } @@ -7504,25 +7346,60 @@ GF_Err dac3_Write(GF_Box *s, GF_BitStream *bs) { GF_Err e; GF_AC3ConfigBox *ptr = (GF_AC3ConfigBox *)s; - e = gf_isom_box_write_header(s, bs); - if (e) return e; - gf_bs_write_int(bs, ptr->cfg.fscod, 2); - gf_bs_write_int(bs, ptr->cfg.bsid, 5); - gf_bs_write_int(bs, ptr->cfg.bsmod, 3); - gf_bs_write_int(bs, ptr->cfg.acmod, 3); - gf_bs_write_int(bs, ptr->cfg.lfon, 1); - gf_bs_write_int(bs, ptr->cfg.brcode, 5); - gf_bs_write_int(bs, 0, 5); + if (ptr->cfg.is_ec3) s->type = GF_ISOM_BOX_TYPE_DEC3; + e = gf_isom_box_write_header(s, bs); + if (ptr->cfg.is_ec3) s->type = GF_ISOM_BOX_TYPE_DAC3; + if (e) return e; + + if (ptr->cfg.is_ec3) { + u32 i; + gf_bs_write_int(bs, ptr->cfg.brcode, 13); + gf_bs_write_int(bs, ptr->cfg.nb_streams - 1, 3); + for (i=0; icfg.nb_streams; i++) { + gf_bs_write_int(bs, ptr->cfg.streams[i].fscod, 2); + gf_bs_write_int(bs, ptr->cfg.streams[i].bsid, 5); + gf_bs_write_int(bs, ptr->cfg.streams[i].bsmod, 5); + gf_bs_write_int(bs, ptr->cfg.streams[i].acmod, 3); + gf_bs_write_int(bs, ptr->cfg.streams[i].lfon, 1); + gf_bs_write_int(bs, 0, 3); + gf_bs_write_int(bs, ptr->cfg.streams[i].nb_dep_sub, 4); + if (ptr->cfg.streams[i].nb_dep_sub) { + gf_bs_write_int(bs, ptr->cfg.streams[i].chan_loc, 9); + } else { + gf_bs_write_int(bs, 0, 1); + } + } + } else { + gf_bs_write_int(bs, ptr->cfg.streams[0].fscod, 2); + gf_bs_write_int(bs, ptr->cfg.streams[0].bsid, 5); + gf_bs_write_int(bs, ptr->cfg.streams[0].bsmod, 3); + gf_bs_write_int(bs, ptr->cfg.streams[0].acmod, 3); + gf_bs_write_int(bs, ptr->cfg.streams[0].lfon, 1); + gf_bs_write_int(bs, ptr->cfg.brcode, 5); + gf_bs_write_int(bs, 0, 5); + } return GF_OK; } GF_Err dac3_Size(GF_Box *s) { + GF_AC3ConfigBox *ptr = (GF_AC3ConfigBox *)s; GF_Err e; e = gf_isom_box_get_size(s); if (e) return e; - s->size += 3; + + if (ptr->cfg.is_ec3) { + u32 i; + s->size += 2; + for (i=0; icfg.nb_streams; i++) { + s->size += 3; + if (ptr->cfg.streams[i].nb_dep_sub) + s->size += 1; + } + } else { + s->size += 3; + } return GF_OK; } @@ -7534,8 +7411,9 @@ void ac3_del(GF_Box *s) { GF_AC3SampleEntryBox *ptr = (GF_AC3SampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->info) gf_isom_box_del((GF_Box *)ptr->info); - if (ptr->protection_info) gf_isom_box_del((GF_Box *)ptr->protection_info); gf_free(ptr); } @@ -7551,13 +7429,12 @@ GF_Err ac3_Read(GF_Box *s, GF_BitStream *bs) return GF_OK; } -GF_Box *ac3_New() +GF_Box *ac3_New(u32 boxType) { - GF_AC3SampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_AC3SampleEntryBox); - if (tmp == NULL) return NULL; + ISOM_DECL_BOX_ALLOC(GF_AC3SampleEntryBox, GF_ISOM_BOX_TYPE_AC3); gf_isom_audio_sample_entry_init((GF_AudioSampleEntryBox*)tmp); - tmp->type = GF_ISOM_BOX_TYPE_AC3; + if (boxType==GF_ISOM_BOX_TYPE_EC3) + tmp->is_ec3 = 1; return (GF_Box *)tmp; } @@ -7568,7 +7445,9 @@ GF_Err ac3_Write(GF_Box *s, GF_BitStream *bs) { GF_Err e; GF_AC3SampleEntryBox *ptr = (GF_AC3SampleEntryBox *)s; + if (ptr->is_ec3) s->type = GF_ISOM_BOX_TYPE_EC3; e = gf_isom_box_write_header(s, bs); + if (ptr->is_ec3) s->type = GF_ISOM_BOX_TYPE_AC3; if (e) return e; gf_isom_audio_sample_entry_write((GF_AudioSampleEntryBox*)s, bs); return gf_isom_box_write((GF_Box *)ptr->info, bs); @@ -7610,10 +7489,7 @@ GF_Err lsrc_Read(GF_Box *s, GF_BitStream *bs) GF_Box *lsrc_New() { - GF_LASERConfigurationBox *tmp; - GF_SAFEALLOC(tmp, GF_LASERConfigurationBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_LSRC; + ISOM_DECL_BOX_ALLOC(GF_LASERConfigurationBox, GF_ISOM_BOX_TYPE_LSRC); return (GF_Box *)tmp; } @@ -7647,6 +7523,8 @@ void lsr1_del(GF_Box *s) { GF_LASeRSampleEntryBox *ptr = (GF_LASeRSampleEntryBox *)s; if (ptr == NULL) return; + gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s); + if (ptr->slc) gf_odf_desc_del((GF_Descriptor *)ptr->slc); if (ptr->lsr_config) gf_isom_box_del((GF_Box *) ptr->lsr_config); if (ptr->bitrate) gf_isom_box_del((GF_Box *) ptr->bitrate); @@ -7671,9 +7549,7 @@ GF_Err lsr1_AddBox(GF_Box *s, GF_Box *a) ptr->descr = (GF_MPEG4ExtensionDescriptorsBox *)a; break; default: - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Warning box %s unknown type - discarding\n", gf_4cc_to_str(a->type))); - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -7689,10 +7565,8 @@ GF_Err lsr1_Read(GF_Box *s, GF_BitStream *bs) GF_Box *lsr1_New() { - GF_LASeRSampleEntryBox *tmp; - GF_SAFEALLOC(tmp, GF_LASeRSampleEntryBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_LSR1; + ISOM_DECL_BOX_ALLOC(GF_LASeRSampleEntryBox, GF_ISOM_BOX_TYPE_LSR1); + gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp); return (GF_Box *)tmp; } @@ -7797,12 +7671,8 @@ GF_Err sidx_Read(GF_Box *s,GF_BitStream *bs) GF_Box *sidx_New() { - GF_SegmentIndexBox *tmp; - - GF_SAFEALLOC(tmp, GF_SegmentIndexBox); - if (tmp == NULL) return NULL; + ISOM_DECL_BOX_ALLOC(GF_SegmentIndexBox, GF_ISOM_BOX_TYPE_SIDX); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_SIDX; return (GF_Box *)tmp; } @@ -7861,11 +7731,7 @@ GF_Err sidx_Size(GF_Box *s) GF_Box *pcrb_New() { - GF_PcrInfoBox *tmp; - - GF_SAFEALLOC(tmp, GF_PcrInfoBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_PCRB; + ISOM_DECL_BOX_ALLOC(GF_PcrInfoBox, GF_ISOM_BOX_TYPE_PCRB); return (GF_Box *)tmp; } @@ -7937,10 +7803,7 @@ GF_Err pcrb_Size(GF_Box *s) GF_Box *subs_New() { - GF_SubSampleInformationBox *tmp = (GF_SubSampleInformationBox *) gf_malloc(sizeof(GF_SubSampleInformationBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SubSampleInformationBox)); - tmp->type = GF_ISOM_BOX_TYPE_SUBS; + ISOM_DECL_BOX_ALLOC(GF_SubSampleInformationBox, GF_ISOM_BOX_TYPE_SUBS); tmp->Samples = gf_list_new(); return (GF_Box *)tmp; } @@ -7951,8 +7814,8 @@ void subs_del(GF_Box *s) if (ptr == NULL) return; while (gf_list_count(ptr->Samples)) { - GF_SampleEntry *pSamp; - pSamp = (GF_SampleEntry*)gf_list_get(ptr->Samples, 0); + GF_SubSampleInfoEntry *pSamp; + pSamp = (GF_SubSampleInfoEntry*)gf_list_get(ptr->Samples, 0); while (gf_list_count(pSamp->SubSamples)) { GF_SubSampleEntry *pSubSamp; pSubSamp = (GF_SubSampleEntry*) gf_list_get(pSamp->SubSamples, 0); @@ -7975,7 +7838,7 @@ GF_Err subs_Write(GF_Box *s, GF_BitStream *bs) GF_Err e; u32 i, j, entry_count; u16 subsample_count; - GF_SampleEntry *pSamp; + GF_SubSampleInfoEntry *pSamp; GF_SubSampleEntry *pSubSamp; GF_SubSampleInformationBox *ptr = (GF_SubSampleInformationBox *) s; @@ -7986,7 +7849,7 @@ GF_Err subs_Write(GF_Box *s, GF_BitStream *bs) gf_bs_write_u32(bs, entry_count); for (i=0; iSamples, i); + pSamp = (GF_SubSampleInfoEntry*) gf_list_get(ptr->Samples, i); subsample_count = gf_list_count(pSamp->SubSamples); gf_bs_write_u32(bs, pSamp->sample_delta); gf_bs_write_u16(bs, subsample_count); @@ -8010,7 +7873,7 @@ GF_Err subs_Size(GF_Box *s) { GF_Err e; GF_SubSampleInformationBox *ptr = (GF_SubSampleInformationBox *) s; - GF_SampleEntry *pSamp; + GF_SubSampleInfoEntry *pSamp; u32 entry_count, i; u16 subsample_count; @@ -8022,7 +7885,7 @@ GF_Err subs_Size(GF_Box *s) ptr->size += 4; entry_count = gf_list_count(ptr->Samples); for (i=0; iSamples, i); + pSamp = (GF_SubSampleInfoEntry*) gf_list_get(ptr->Samples, i); subsample_count = gf_list_count(pSamp->SubSamples); // 4 byte for sample_delta, 2 byte for subsample_count // and 6 + (4 or 2) bytes for each subsample @@ -8047,10 +7910,10 @@ GF_Err subs_Read(GF_Box *s, GF_BitStream *bs) ptr->size -= 4; for (i=0; iSubSamples = gf_list_new(); pSamp->sample_delta = gf_bs_read_u32(bs); subsample_count = gf_bs_read_u16(bs); @@ -8081,10 +7944,7 @@ GF_Err subs_Read(GF_Box *s, GF_BitStream *bs) GF_Box *tfdt_New() { - GF_TFBaseMediaDecodeTimeBox *tmp; - GF_SAFEALLOC(tmp, GF_TFBaseMediaDecodeTimeBox); - tmp->type = GF_ISOM_BOX_TYPE_TFDT; - tmp->version = 0; + ISOM_DECL_BOX_ALLOC(GF_TFBaseMediaDecodeTimeBox, GF_ISOM_BOX_TYPE_TFDT); return (GF_Box *)tmp; } @@ -8151,9 +8011,7 @@ GF_Err tfdt_Size(GF_Box *s) GF_Box *rvcc_New() { - GF_RVCConfigurationBox *tmp; - GF_SAFEALLOC(tmp, GF_RVCConfigurationBox); - tmp->type = GF_ISOM_BOX_TYPE_RVCC; + ISOM_DECL_BOX_ALLOC(GF_RVCConfigurationBox, GF_ISOM_BOX_TYPE_RVCC); return (GF_Box *)tmp; } @@ -8208,10 +8066,8 @@ GF_Err rvcc_Size(GF_Box *s) GF_Box *sbgp_New() { - GF_SampleGroupBox *p; - GF_SAFEALLOC(p, GF_SampleGroupBox); - p->type = GF_ISOM_BOX_TYPE_SBGP; - return (GF_Box *)p; + ISOM_DECL_BOX_ALLOC(GF_SampleGroupBox, GF_ISOM_BOX_TYPE_SBGP); + return (GF_Box *)tmp; } void sbgp_del(GF_Box *a) { @@ -8365,14 +8221,11 @@ static u32 sgpd_size_entry(u32 grouping_type, void *entry) GF_Box *sgpd_New() { - GF_SampleGroupDescriptionBox *p; - GF_SAFEALLOC(p, GF_SampleGroupDescriptionBox); - p->type = GF_ISOM_BOX_TYPE_SGPD; + ISOM_DECL_BOX_ALLOC(GF_SampleGroupDescriptionBox, GF_ISOM_BOX_TYPE_SGPD); /*version 0 is deprecated, use v1 by default*/ - p->version = 1; - p->group_descriptions = gf_list_new(); - - return (GF_Box *)p; + tmp->version = 1; + tmp->group_descriptions = gf_list_new(); + return (GF_Box *)tmp; } void sgpd_del(GF_Box *a) @@ -8475,5 +8328,195 @@ GF_Err sgpd_Size(GF_Box *s) #endif /*GPAC_DISABLE_ISOM_WRITE*/ +void saiz_del(GF_Box *s) +{ + GF_SampleAuxiliaryInfoSizeBox*ptr = (GF_SampleAuxiliaryInfoSizeBox*)s; + if (ptr == NULL) return; + if (ptr->sample_info_size) gf_free(ptr->sample_info_size); + gf_free(ptr); +} + + +GF_Err saiz_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SampleAuxiliaryInfoSizeBox*ptr = (GF_SampleAuxiliaryInfoSizeBox*)s; + + e = gf_isom_full_box_read(s, bs); + if (e) return e; + if (ptr->flags & 1) { + ptr->aux_info_type = gf_bs_read_u32(bs); + ptr->aux_info_type_parameter = gf_bs_read_u32(bs); + ptr->size -= 8; + } + ptr->default_sample_info_size = gf_bs_read_u8(bs); + ptr->sample_count = gf_bs_read_u32(bs); + ptr->size -= 5; + if (ptr->default_sample_info_size == 0) { + ptr->sample_info_size = gf_malloc(sizeof(u8)*ptr->sample_count); + gf_bs_read_data(bs, ptr->sample_info_size, ptr->sample_count); + ptr->size -= ptr->sample_count; + } + return GF_OK; +} + +GF_Box *saiz_New() +{ + ISOM_DECL_BOX_ALLOC(GF_SampleAuxiliaryInfoSizeBox, GF_ISOM_BOX_TYPE_SAIZ); + return (GF_Box *)tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err saiz_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SampleAuxiliaryInfoSizeBox*ptr = (GF_SampleAuxiliaryInfoSizeBox*) s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + if (ptr->flags & 1) { + gf_bs_write_u32(bs, ptr->aux_info_type); + gf_bs_write_u32(bs, ptr->aux_info_type_parameter); + } + gf_bs_write_u8(bs, ptr->default_sample_info_size); + gf_bs_write_u32(bs, ptr->sample_count); + if (ptr->default_sample_info_size) { + gf_bs_write_data(bs, ptr->sample_info_size, ptr->sample_count); + } + return GF_OK; +} + +GF_Err saiz_Size(GF_Box *s) +{ + GF_Err e; + GF_SampleAuxiliaryInfoSizeBox *ptr = (GF_SampleAuxiliaryInfoSizeBox*)s; + + if (ptr->aux_info_type || ptr->aux_info_type_parameter) { + ptr->flags |= 1; + } + + e = gf_isom_full_box_get_size(s); + if (e) return e; + if (ptr->flags & 1) ptr->size += 8; + ptr->size += 5; + if (ptr->default_sample_info_size==0) ptr->size += ptr->sample_count; + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + +void saio_del(GF_Box *s) +{ + GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox*)s; + if (ptr == NULL) return; + if (ptr->offsets) gf_free(ptr->offsets); + if (ptr->offsets_large) gf_free(ptr->offsets_large); + gf_free(ptr); +} + + +GF_Err saio_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox *)s; + + e = gf_isom_full_box_read(s, bs); + if (e) return e; + if (ptr->flags & 1) { + ptr->aux_info_type = gf_bs_read_u32(bs); + ptr->aux_info_type_parameter = gf_bs_read_u32(bs); + ptr->size -= 8; + } + ptr->entry_count = gf_bs_read_u32(bs); + ptr->size -= 4; + if (ptr->entry_count>1) { + u32 i; + if (ptr->version==0) { + ptr->offsets = gf_malloc(sizeof(u32)*ptr->entry_count); + for (i=0; ientry_count; i++) + ptr->offsets[i] = gf_bs_read_u32(bs); + ptr->size -= 4*ptr->entry_count; + } else { + ptr->offsets_large = gf_malloc(sizeof(u64)*ptr->entry_count); + for (i=0; ientry_count; i++) + ptr->offsets_large[i] = gf_bs_read_u64(bs); + ptr->size -= 8*ptr->entry_count; + } + } else { + if (ptr->version==0) { + ptr->single_offset = gf_bs_read_u32(bs); + ptr->size -= 4; + } else { + ptr->single_offset = gf_bs_read_u64(bs); + ptr->size -= 8; + } + } + return GF_OK; +} + +GF_Box *saio_New() +{ + ISOM_DECL_BOX_ALLOC(GF_SampleAuxiliaryInfoOffsetBox, GF_ISOM_BOX_TYPE_SAIO); + return (GF_Box *)tmp; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err saio_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox *) s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + if (ptr->flags & 1) { + gf_bs_write_u32(bs, ptr->aux_info_type); + gf_bs_write_u32(bs, ptr->aux_info_type_parameter); + } + gf_bs_write_u32(bs, ptr->entry_count); + if (ptr->entry_count>1) { + u32 i; + if (ptr->version==0) { + assert(ptr->offsets); + for (i=0; ientry_count; i++) + gf_bs_write_u32(bs, ptr->offsets[i]); + } else { + assert(ptr->offsets_large); + for (i=0; ientry_count; i++) + gf_bs_write_u64(bs, ptr->offsets_large[i]); + } + } else { + if (ptr->version==0) { + gf_bs_write_u32(bs, (u32) ptr->single_offset); + } else { + gf_bs_write_u64(bs, ptr->single_offset); + } + } + return GF_OK; +} + +GF_Err saio_Size(GF_Box *s) +{ + GF_Err e; + GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox*)s; + + if (ptr->aux_info_type || ptr->aux_info_type_parameter) { + ptr->flags |= 1; + } + if (ptr->offsets_large || (ptr->single_offset >0xFFFFFFFF)) { + ptr->version = 1; + } + + e = gf_isom_full_box_get_size(s); + if (e) return e; + if (ptr->flags & 1) ptr->size += 8; + ptr->size += 4; + ptr->size += ((ptr->version==1) ? 8 : 4) * ptr->entry_count; + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + #endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/box_code_drm.c b/src/isomedia/box_code_drm.c new file mode 100644 index 0000000..200ad10 --- /dev/null +++ b/src/isomedia/box_code_drm.c @@ -0,0 +1,1222 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Cyril Concolato, Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 + * All rights reserved + * + * This file is part of GPAC / ISO Media File Format sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +#ifndef GPAC_DISABLE_ISOM + +/* ProtectionInfo Box */ +GF_Box *sinf_New() +{ + ISOM_DECL_BOX_ALLOC(GF_ProtectionInfoBox, GF_ISOM_BOX_TYPE_SINF); + return (GF_Box *)tmp; +} + +void sinf_del(GF_Box *s) +{ + GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; + if (ptr == NULL) return; + if (ptr->original_format) gf_isom_box_del((GF_Box *)ptr->original_format); + if (ptr->info) gf_isom_box_del((GF_Box *)ptr->info); + if (ptr->scheme_type) gf_isom_box_del((GF_Box *)ptr->scheme_type); + gf_free(ptr); +} + +GF_Err sinf_AddBox(GF_Box *s, GF_Box *a) +{ + GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; + switch (a->type) { + case GF_ISOM_BOX_TYPE_FRMA: + if (ptr->original_format) return GF_ISOM_INVALID_FILE; + ptr->original_format = (GF_OriginalFormatBox*)a; + break; + case GF_ISOM_BOX_TYPE_SCHM: + if (ptr->scheme_type) return GF_ISOM_INVALID_FILE; + ptr->scheme_type = (GF_SchemeTypeBox*)a; + break; + case GF_ISOM_BOX_TYPE_SCHI: + if (ptr->info) return GF_ISOM_INVALID_FILE; + ptr->info = (GF_SchemeInformationBox*)a; + break; + default: + return gf_isom_box_add_default(s, a); + } + return GF_OK; +} + +GF_Err sinf_Read(GF_Box *s, GF_BitStream *bs) +{ + return gf_isom_read_box_list(s, bs, sinf_AddBox); +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err sinf_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_write_header(s, bs); + if (e) return e; + //frma + e = gf_isom_box_write((GF_Box *) ptr->original_format, bs); + if (e) return e; + // schm + e = gf_isom_box_write((GF_Box *) ptr->scheme_type, bs); + if (e) return e; + // schi + e = gf_isom_box_write((GF_Box *) ptr->info, bs); + if (e) return e; + return GF_OK; +} + +GF_Err sinf_Size(GF_Box *s) +{ + GF_Err e; + GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_get_size(s); + if (e) return e; + e = gf_isom_box_size((GF_Box *) ptr->original_format); + if (e) return e; + ptr->size += ptr->original_format->size; + e = gf_isom_box_size((GF_Box *) ptr->scheme_type); + if (e) return e; + ptr->size += ptr->scheme_type->size; + e = gf_isom_box_size((GF_Box *) ptr->info); + if (e) return e; + ptr->size += ptr->info->size; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +/* OriginalFormat Box */ +GF_Box *frma_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OriginalFormatBox, GF_ISOM_BOX_TYPE_FRMA); + return (GF_Box *)tmp; +} + +void frma_del(GF_Box *s) +{ + GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; + if (ptr == NULL) return; + gf_free(ptr); +} + +GF_Err frma_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; + ptr->data_format = gf_bs_read_u32(bs); + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err frma_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_write_header(s, bs); + if (e) return e; + gf_bs_write_u32(bs, ptr->data_format); + return GF_OK; +} + +GF_Err frma_Size(GF_Box *s) +{ + GF_Err e; + GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_get_size(s); + if (e) return e; + ptr->size += 4; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +/* SchemeType Box */ +GF_Box *schm_New() +{ + ISOM_DECL_BOX_ALLOC(GF_SchemeTypeBox, GF_ISOM_BOX_TYPE_SCHM); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void schm_del(GF_Box *s) +{ + GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *)s; + if (ptr == NULL) return; + if (ptr->URI) gf_free(ptr->URI); + gf_free(ptr); +} + +GF_Err schm_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *)s; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + ptr->scheme_type = gf_bs_read_u32(bs); + ptr->scheme_version = gf_bs_read_u32(bs); + ptr->size -= 8; + if (ptr->size && (ptr->flags & 0x000001)) { + u32 len = (u32) (ptr->size); + ptr->URI = (char*)gf_malloc(sizeof(char)*len); + if (!ptr->URI) return GF_OUT_OF_MEM; + gf_bs_read_data(bs, ptr->URI, len); + } + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err schm_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *) s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + assert(e == GF_OK); + gf_bs_write_u32(bs, ptr->scheme_type); + gf_bs_write_u32(bs, ptr->scheme_version); + if (ptr->flags & 0x000001) gf_bs_write_data(bs, ptr->URI, strlen(ptr->URI)+1); + return GF_OK; +} + +GF_Err schm_Size(GF_Box *s) +{ + GF_Err e; + GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *) s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += 8; + if (ptr->flags & 0x000001) ptr->size += strlen(ptr->URI)+1; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +/* SchemeInformation Box */ +GF_Box *schi_New() +{ + ISOM_DECL_BOX_ALLOC(GF_SchemeInformationBox, GF_ISOM_BOX_TYPE_SCHI); + return (GF_Box *)tmp; +} + +void schi_del(GF_Box *s) +{ + GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; + if (ptr == NULL) return; + if (ptr->ikms) gf_isom_box_del((GF_Box *)ptr->ikms); + if (ptr->isfm) gf_isom_box_del((GF_Box *)ptr->isfm); + if (ptr->okms) gf_isom_box_del((GF_Box *)ptr->okms); + if (ptr->tenc) gf_isom_box_del((GF_Box *)ptr->tenc); + if (ptr->piff_tenc) gf_isom_box_del((GF_Box *)ptr->piff_tenc); + gf_free(ptr); +} + +GF_Err schi_AddBox(GF_Box *s, GF_Box *a) +{ + GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; + switch (a->type) { + case GF_ISOM_BOX_TYPE_IKMS: + if (ptr->ikms) return GF_ISOM_INVALID_FILE; + ptr->ikms = (GF_ISMAKMSBox*)a; + return GF_OK; + case GF_ISOM_BOX_TYPE_ISFM: + if (ptr->isfm) return GF_ISOM_INVALID_FILE; + ptr->isfm = (GF_ISMASampleFormatBox*)a; + return GF_OK; + case GF_ISOM_BOX_TYPE_ODKM: + if (ptr->okms) return GF_ISOM_INVALID_FILE; + ptr->okms = (GF_OMADRMKMSBox*)a; + return GF_OK; + case GF_ISOM_BOX_TYPE_TENC: + if (ptr->tenc) return GF_ISOM_INVALID_FILE; + ptr->tenc = (GF_TrackEncryptionBox *)a; + return GF_OK; + case GF_ISOM_BOX_TYPE_UUID: + if (((GF_UUIDBox*)a)->internal_4cc==GF_ISOM_BOX_UUID_TENC) { + if (ptr->piff_tenc) return GF_ISOM_INVALID_FILE; + ptr->piff_tenc = (GF_PIFFTrackEncryptionBox *)a; + return GF_OK; + } else { + return gf_isom_box_add_default(s, a); + } + default: + return gf_isom_box_add_default(s, a); + } +} + +GF_Err schi_Read(GF_Box *s, GF_BitStream *bs) +{ + return gf_isom_read_box_list(s, bs, schi_AddBox); +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err schi_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_write_header(s, bs); + if (e) return e; + + if (ptr->ikms) { + e = gf_isom_box_write((GF_Box *) ptr->ikms, bs); + if (e) return e; + } + if (ptr->isfm) { + e = gf_isom_box_write((GF_Box *) ptr->isfm, bs); + if (e) return e; + } + if (ptr->okms) { + e = gf_isom_box_write((GF_Box *) ptr->okms, bs); + if (e) return e; + } + if (ptr->tenc) { + e = gf_isom_box_write((GF_Box *) ptr->tenc, bs); + if (e) return e; + } + if (ptr->piff_tenc) { + e = gf_isom_box_write((GF_Box *) ptr->piff_tenc, bs); + if (e) return e; + } + return GF_OK; +} + +GF_Err schi_Size(GF_Box *s) +{ + GF_Err e; + GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_get_size(s); + if (e) return e; + + if (ptr->ikms) { + e = gf_isom_box_size((GF_Box *) ptr->ikms); + if (e) return e; + ptr->size += ptr->ikms->size; + } + if (ptr->isfm) { + e = gf_isom_box_size((GF_Box *) ptr->isfm); + if (e) return e; + ptr->size += ptr->isfm->size; + } + if (ptr->okms) { + e = gf_isom_box_size((GF_Box *) ptr->okms); + if (e) return e; + ptr->size += ptr->okms->size; + } + if (ptr->tenc) { + e = gf_isom_box_size((GF_Box *) ptr->tenc); + if (e) return e; + ptr->size += ptr->tenc->size; + } + if (ptr->piff_tenc) { + e = gf_isom_box_size((GF_Box *) ptr->tenc); + if (e) return e; + ptr->size += ptr->tenc->size; + } + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +/* ISMAKMS Box */ +GF_Box *iKMS_New() +{ + ISOM_DECL_BOX_ALLOC(GF_ISMAKMSBox, GF_ISOM_BOX_TYPE_IKMS); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void iKMS_del(GF_Box *s) +{ + GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; + if (ptr == NULL) return; + if (ptr->URI) gf_free(ptr->URI); + gf_free(ptr); +} + +GF_Err iKMS_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + u32 len; + GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; + + e = gf_isom_full_box_read(s, bs); + if (e) return e; + len = (u32) (ptr->size); + ptr->URI = (char*) gf_malloc(sizeof(char)*len); + if (!ptr->URI) return GF_OUT_OF_MEM; + gf_bs_read_data(bs, ptr->URI, len); + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err iKMS_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gf_bs_write_data(bs, ptr->URI, strlen(ptr->URI)+1); + return GF_OK; +} + +GF_Err iKMS_Size(GF_Box *s) +{ + GF_Err e; + GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += strlen(ptr->URI)+1; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +/* ISMASampleFormat Box */ +GF_Box *iSFM_New() +{ + ISOM_DECL_BOX_ALLOC(GF_ISMASampleFormatBox, GF_ISOM_BOX_TYPE_ISFM); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void iSFM_del(GF_Box *s) +{ + GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; + if (ptr == NULL) return; + gf_free(ptr); +} + + +GF_Err iSFM_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; + if (ptr == NULL) return GF_BAD_PARAM; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + ptr->selective_encryption = gf_bs_read_int(bs, 1); + gf_bs_read_int(bs, 7); + ptr->key_indicator_length = gf_bs_read_u8(bs); + ptr->IV_length = gf_bs_read_u8(bs); + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err iSFM_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gf_bs_write_int(bs, ptr->selective_encryption, 1); + gf_bs_write_int(bs, 0, 7); + gf_bs_write_u8(bs, ptr->key_indicator_length); + gf_bs_write_u8(bs, ptr->IV_length); + return GF_OK; +} + +GF_Err iSFM_Size(GF_Box *s) +{ + GF_Err e; + GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += 3; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + + +/* OMADRMCommonHeader Box */ +GF_Box *ohdr_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OMADRMCommonHeaderBox, GF_ISOM_BOX_TYPE_OHDR); + gf_isom_full_box_init((GF_Box *)tmp); + tmp->other_boxes = gf_list_new(); + return (GF_Box *)tmp; +} + +void ohdr_del(GF_Box *s) +{ + GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox*)s; + if (ptr == NULL) return; + if (ptr->ContentID) gf_free(ptr->ContentID); + if (ptr->RightsIssuerURL) gf_free(ptr->RightsIssuerURL); + if (ptr->TextualHeaders) gf_free(ptr->TextualHeaders); + gf_free(ptr); +} + +GF_Err ohdr_AddBox(GF_Box *s, GF_Box *a) +{ + return gf_isom_box_add_default(s, a); +} + +GF_Err ohdr_Read(GF_Box *s, GF_BitStream *bs) +{ + u16 cid_len, ri_len; + GF_Err e; + GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox*)s; + if (ptr == NULL) return GF_BAD_PARAM; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + ptr->EncryptionMethod = gf_bs_read_u8(bs); + ptr->PaddingScheme = gf_bs_read_u8(bs); + ptr->PlaintextLength = gf_bs_read_u64(bs); + cid_len = gf_bs_read_u16(bs); + ri_len = gf_bs_read_u16(bs); + ptr->TextualHeadersLen = gf_bs_read_u16(bs); + ptr->size -= 1+1+8+2+2+2; + if (ptr->sizeTextualHeadersLen) return GF_ISOM_INVALID_FILE; + + if (cid_len) { + ptr->ContentID = (char *)gf_malloc(sizeof(char)*(cid_len+1)); + gf_bs_read_data(bs, ptr->ContentID, cid_len); + ptr->ContentID[cid_len]=0; + } + + if (ri_len) { + ptr->RightsIssuerURL = (char *)gf_malloc(sizeof(char)*(ri_len+1)); + gf_bs_read_data(bs, ptr->RightsIssuerURL, ri_len); + ptr->RightsIssuerURL[ri_len]=0; + } + + if (ptr->TextualHeadersLen) { + ptr->TextualHeaders = (char *)gf_malloc(sizeof(char)*(ptr->TextualHeadersLen+1)); + gf_bs_read_data(bs, ptr->TextualHeaders, ptr->TextualHeadersLen); + ptr->TextualHeaders[ptr->TextualHeadersLen] = 0; + } + + ptr->size -= cid_len+ri_len+ptr->TextualHeadersLen; + + return gf_isom_read_box_list(s, bs, ohdr_AddBox); +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err ohdr_Write(GF_Box *s, GF_BitStream *bs) +{ + u16 cid_len, ri_len; + GF_Err e; + GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gf_bs_write_u8(bs, ptr->EncryptionMethod); + gf_bs_write_u8(bs, ptr->PaddingScheme); + gf_bs_write_u64(bs, ptr->PlaintextLength); + + cid_len = ptr->ContentID ? strlen(ptr->ContentID) : 0; + gf_bs_write_u16(bs, cid_len); + ri_len = ptr->RightsIssuerURL ? strlen(ptr->RightsIssuerURL) : 0; + gf_bs_write_u16(bs, ri_len); + gf_bs_write_u16(bs, ptr->TextualHeadersLen); + + if (cid_len) gf_bs_write_data(bs, ptr->ContentID, strlen(ptr->ContentID)); + if (ri_len) gf_bs_write_data(bs, ptr->RightsIssuerURL, strlen(ptr->RightsIssuerURL)); + if (ptr->TextualHeadersLen) gf_bs_write_data(bs, ptr->TextualHeaders, ptr->TextualHeadersLen); + ptr->size -= cid_len+ri_len+ptr->TextualHeadersLen; + return GF_OK; +} + +GF_Err ohdr_Size(GF_Box *s) +{ + GF_Err e; + GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += 1+1+8+2+2+2; + if (ptr->ContentID) ptr->size += strlen(ptr->ContentID); + if (ptr->RightsIssuerURL) ptr->size += strlen(ptr->RightsIssuerURL); + if (ptr->TextualHeadersLen) ptr->size += ptr->TextualHeadersLen; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + +/* OMADRMGroupID Box */ +GF_Box *grpi_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OMADRMGroupIDBox, GF_ISOM_BOX_TYPE_GRPI); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void grpi_del(GF_Box *s) +{ + GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s; + if (ptr == NULL) return; + if (ptr->GroupID) gf_free(ptr->GroupID); + if (ptr->GroupKey) gf_free(ptr->GroupKey); + gf_free(ptr); +} + +GF_Err grpi_Read(GF_Box *s, GF_BitStream *bs) +{ + u16 gid_len; + GF_Err e; + GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox*)s; + if (ptr == NULL) return GF_BAD_PARAM; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + gid_len = gf_bs_read_u16(bs); + ptr->GKEncryptionMethod = gf_bs_read_u8(bs); + ptr->GKLength = gf_bs_read_u16(bs); + + ptr->size -= 1+2+2; + if (ptr->sizeGKLength) return GF_ISOM_INVALID_FILE; + + ptr->GroupID = gf_malloc(sizeof(char)*(gid_len+1)); + gf_bs_read_data(bs, ptr->GroupID, gid_len); + ptr->GroupID[gid_len]=0; + + ptr->GroupKey = (char *)gf_malloc(sizeof(char)*ptr->GKLength); + gf_bs_read_data(bs, ptr->GroupKey, ptr->GKLength); + ptr->size -= gid_len+ptr->GKLength; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err grpi_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + u16 gid_len; + GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gid_len = ptr->GroupID ? strlen(ptr->GroupID) : 0; + gf_bs_write_u16(bs, gid_len); + gf_bs_write_u8(bs, ptr->GKEncryptionMethod); + gf_bs_write_u16(bs, ptr->GKLength); + gf_bs_write_data(bs, ptr->GroupID, gid_len); + gf_bs_write_data(bs, ptr->GroupKey, ptr->GKLength); + return GF_OK; +} + +GF_Err grpi_Size(GF_Box *s) +{ + GF_Err e; + GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += 2+2+1 + ptr->GKLength; + if (ptr->GroupID) ptr->size += strlen(ptr->GroupID); + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + + + +/* OMADRMMutableInformation Box */ +GF_Box *mdri_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OMADRMMutableInformationBox, GF_ISOM_BOX_TYPE_MDRI); + return (GF_Box *)tmp; +} + +void mdri_del(GF_Box *s) +{ + GF_OMADRMMutableInformationBox*ptr = (GF_OMADRMMutableInformationBox*)s; + if (ptr == NULL) return; + gf_free(ptr); +} + +GF_Err mdri_Read(GF_Box *s, GF_BitStream *bs) +{ + return gf_isom_read_box_list(s, bs, gf_isom_box_add_default); +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err mdri_Write(GF_Box *s, GF_BitStream *bs) +{ +// GF_OMADRMMutableInformationBox*ptr = (GF_OMADRMMutableInformationBox*)s; + GF_Err e = gf_isom_box_write_header(s, bs); + if (e) return e; + return GF_OK; +} + +GF_Err mdri_Size(GF_Box *s) +{ + GF_Err e; +// GF_OMADRMMutableInformationBox *ptr = (GF_OMADRMMutableInformationBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_box_get_size(s); + if (e) return e; + + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + +/* OMADRMTransactionTracking Box */ +GF_Box *odtt_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OMADRMTransactionTrackingBox, GF_ISOM_BOX_TYPE_ODTT); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void odtt_del(GF_Box *s) +{ + GF_OMADRMTransactionTrackingBox *ptr = (GF_OMADRMTransactionTrackingBox*)s; + gf_free(ptr); +} + +GF_Err odtt_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_OMADRMTransactionTrackingBox *ptr = (GF_OMADRMTransactionTrackingBox *)s; + if (ptr == NULL) return GF_BAD_PARAM; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + gf_bs_read_data(bs, ptr->TransactionID, 16); + ptr->size -= 16; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err odtt_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_OMADRMTransactionTrackingBox *ptr = (GF_OMADRMTransactionTrackingBox*)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gf_bs_write_data(bs, ptr->TransactionID, 16); + return GF_OK; +} + +GF_Err odtt_Size(GF_Box *s) +{ + GF_Err e; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + s->size += 16; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + + +/* OMADRMRightsObject Box */ +GF_Box *odrb_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OMADRMRightsObjectBox, GF_ISOM_BOX_TYPE_ODRB); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void odrb_del(GF_Box *s) +{ + GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox*)s; + if (ptr->oma_ro) gf_free(ptr->oma_ro); + gf_free(ptr); +} + +GF_Err odrb_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox *)s; + if (ptr == NULL) return GF_BAD_PARAM; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + ptr->oma_ro_size = (u32) ptr->size; + ptr->oma_ro = (char*) gf_malloc(sizeof(char)*ptr->oma_ro_size); + gf_bs_read_data(bs, ptr->oma_ro, ptr->oma_ro_size); + ptr->size = 0; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err odrb_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + gf_bs_write_data(bs, ptr->oma_ro, ptr->oma_ro_size); + return GF_OK; +} + +GF_Err odrb_Size(GF_Box *s) +{ + GF_Err e; + GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + s->size += ptr->oma_ro_size; + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + + + +/* OMADRMKMS Box */ +GF_Box *odkm_New() +{ + ISOM_DECL_BOX_ALLOC(GF_OMADRMKMSBox, GF_ISOM_BOX_TYPE_ODKM); + gf_isom_full_box_init((GF_Box *)tmp); + return (GF_Box *)tmp; +} + +void odkm_del(GF_Box *s) +{ + GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; + if (ptr->hdr) gf_isom_box_del((GF_Box*)ptr->hdr); + if (ptr->fmt) gf_isom_box_del((GF_Box*)ptr->fmt); + gf_free(ptr); +} + +GF_Err odkm_Add(GF_Box *s, GF_Box *a) +{ + GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; + switch (a->type) { + case GF_ISOM_BOX_TYPE_OHDR: + if (ptr->hdr) gf_isom_box_del((GF_Box*)ptr->hdr); + ptr->hdr = (GF_OMADRMCommonHeaderBox *)a; + return GF_OK; + case GF_ISOM_BOX_TYPE_ODAF: + if (ptr->fmt) gf_isom_box_del((GF_Box*)ptr->fmt); + ptr->fmt = (GF_OMADRMAUFormatBox*)a; + return GF_OK; + default: + gf_isom_box_del(a); + return GF_OK; + } +} + +GF_Err odkm_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + if (s == NULL) return GF_BAD_PARAM; + e = gf_isom_full_box_read(s, bs); + if (e) return e; + return gf_isom_read_box_list(s, bs, odkm_Add); +} + +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err odkm_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + if (ptr->hdr) { + e = gf_isom_box_write((GF_Box*)ptr->hdr, bs); + if (e) return e; + } + if (ptr->fmt) { + e = gf_isom_box_write((GF_Box*)ptr->fmt, bs); + if (e) return e; + } + return GF_OK; +} + +GF_Err odkm_Size(GF_Box *s) +{ + GF_Err e; + GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_get_size(s); + if (e) return e; + if (ptr->hdr) { + e = gf_isom_box_size((GF_Box*)ptr->hdr); + if (e) return e; + ptr->size += ptr->hdr->size; + } + if (ptr->fmt) { + e = gf_isom_box_size((GF_Box*)ptr->fmt); + if (e) return e; + ptr->size += ptr->fmt->size; + } + return GF_OK; +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + + + +GF_Box *pssh_New() +{ + ISOM_DECL_BOX_ALLOC(GF_ProtectionSystemHeaderBox, GF_ISOM_BOX_TYPE_PSSH); + return (GF_Box *)tmp; +} + +void pssh_del(GF_Box *s) +{ + GF_ProtectionSystemHeaderBox *ptr = (GF_ProtectionSystemHeaderBox*)s; + if (ptr == NULL) return; + if (ptr->private_data) gf_free(ptr->private_data); + if (ptr->KIDs) gf_free(ptr->KIDs); + gf_free(ptr); +} + +GF_Err pssh_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_ProtectionSystemHeaderBox *ptr = (GF_ProtectionSystemHeaderBox *)s; + + e = gf_isom_full_box_read(s, bs); + if (e) return e; + + gf_bs_read_data(bs, ptr->SystemID, 16); + ptr->size -= 16; + if (ptr->version > 0) { + ptr->KID_count = gf_bs_read_u32(bs); + ptr->size -= 4; + if (ptr->KID_count) { + u32 i; + ptr->KIDs = gf_malloc(sizeof(bin128)); + for (i=0; iKID_count; i++) { + gf_bs_read_data(bs, ptr->KIDs[i], 16); + ptr->size -= 16; + } + } + } + ptr->private_data_size = gf_bs_read_u32(bs); + ptr->size -= 4; + if (ptr->private_data_size) { + ptr->private_data = gf_malloc(sizeof(char)*ptr->private_data_size); + gf_bs_read_data(bs, ptr->private_data, ptr->private_data_size); + ptr->size -= ptr->private_data_size; + } + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err pssh_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_ProtectionSystemHeaderBox *ptr = (GF_ProtectionSystemHeaderBox *) s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + gf_bs_write_data(bs, ptr->SystemID, 16); + if (ptr->version > 0) { + u32 i; + gf_bs_write_u32(bs, ptr->KID_count); + for (i=0; iKID_count; i++) + gf_bs_write_data(bs, ptr->KIDs[i], 16); + } + if (ptr->private_data) { + gf_bs_write_u32(bs, ptr->private_data_size); + gf_bs_write_data(bs, ptr->private_data, ptr->private_data_size); + } else + gf_bs_write_u32(bs, 0); + return GF_OK; +} + +GF_Err pssh_Size(GF_Box *s) +{ + GF_Err e; + GF_ProtectionSystemHeaderBox *ptr = (GF_ProtectionSystemHeaderBox*)s; + + if (ptr->KID_count && !ptr->version) { + ptr->version = 1; + } + + e = gf_isom_full_box_get_size(s); + if (e) return e; + + ptr->size += 16; + if (ptr->version) ptr->size += 4 + 16*ptr->KID_count; + ptr->size += 4 + ptr->private_data ? ptr->private_data_size : 0; + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + + +GF_Box *tenc_New() +{ + ISOM_DECL_BOX_ALLOC(GF_TrackEncryptionBox, GF_ISOM_BOX_TYPE_TENC); + return (GF_Box *)tmp; +} + +void tenc_del(GF_Box *s) +{ + gf_free(s); +} + +GF_Err tenc_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_TrackEncryptionBox *ptr = (GF_TrackEncryptionBox*)s; + + e = gf_isom_full_box_read(s, bs); + if (e) return e; + + ptr->IsEncrypted = gf_bs_read_int(bs, 24); + ptr->IV_size = gf_bs_read_u8(bs); + gf_bs_read_data(bs, ptr->KID, 16); + ptr->size -= 20; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err tenc_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_TrackEncryptionBox *ptr = (GF_TrackEncryptionBox *) s; + if (!s) return GF_BAD_PARAM; + e = gf_isom_full_box_write(s, bs); + if (e) return e; + + gf_bs_write_int(bs, ptr->IsEncrypted, 24); + gf_bs_write_u8(bs, ptr->IV_size); + gf_bs_write_data(bs, ptr->KID, 16); + return GF_OK; +} + +GF_Err tenc_Size(GF_Box *s) +{ + GF_Err e; + GF_TrackEncryptionBox *ptr = (GF_TrackEncryptionBox*)s; + e = gf_isom_full_box_get_size(s); + if (e) return e; + ptr->size += 20; + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + +GF_Box *piff_tenc_New() +{ + ISOM_DECL_BOX_ALLOC(GF_PIFFTrackEncryptionBox, GF_ISOM_BOX_TYPE_UUID); + tmp->internal_4cc = GF_ISOM_BOX_UUID_TENC; + return (GF_Box *)tmp; +} + +void piff_tenc_del(GF_Box *s) +{ + gf_free(s); +} + +GF_Err piff_tenc_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_PIFFTrackEncryptionBox *ptr = (GF_PIFFTrackEncryptionBox*)s; + + if (ptr->size<4) return GF_ISOM_INVALID_FILE; + ptr->version = gf_bs_read_u8(bs); + ptr->flags = gf_bs_read_u24(bs); + ptr->size -= 4; + + ptr->AlgorithmID = gf_bs_read_int(bs, 24); + ptr->IV_size = gf_bs_read_u8(bs); + gf_bs_read_data(bs, ptr->KID, 16); + ptr->size -= 20; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err piff_tenc_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_PIFFTrackEncryptionBox *ptr = (GF_PIFFTrackEncryptionBox *) s; + if (!s) return GF_BAD_PARAM; + + e = gf_isom_box_write_header(s, bs); + if (e) return e; + gf_bs_write_u8(bs, ptr->version); + gf_bs_write_u24(bs, ptr->flags); + + gf_bs_write_int(bs, ptr->AlgorithmID, 24); + gf_bs_write_u8(bs, ptr->IV_size); + gf_bs_write_data(bs, ptr->KID, 16); + return GF_OK; +} + +GF_Err piff_tenc_Size(GF_Box *s) +{ + GF_Err e; + GF_PIFFTrackEncryptionBox *ptr = (GF_PIFFTrackEncryptionBox*)s; + e = gf_isom_box_get_size(s); + if (e) return e; + ptr->size += 24; + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + + +GF_Box *piff_psec_New() +{ + ISOM_DECL_BOX_ALLOC(GF_PIFFSampleEncryptionBox, GF_ISOM_BOX_TYPE_UUID); + tmp->internal_4cc = GF_ISOM_BOX_UUID_PSEC; + return (GF_Box *)tmp; +} + +void piff_psec_del(GF_Box *s) +{ + GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox *)s; + if (ptr->cenc_data) gf_free(ptr->cenc_data); + gf_free(s); +} + +GF_Err piff_psec_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox *)s; + if (ptr->size<4) return GF_ISOM_INVALID_FILE; + ptr->version = gf_bs_read_u8(bs); + ptr->flags = gf_bs_read_u24(bs); + ptr->size -= 4; + + if (ptr->flags & 1) { + ptr->AlgorithmID = gf_bs_read_int(bs, 24); + ptr->IV_size = gf_bs_read_u8(bs); + gf_bs_read_data(bs, ptr->KID, 16); + ptr->size -= 20; + } + ptr->sample_count = gf_bs_read_u32(bs); + ptr->size -= 4; + ptr->cenc_data_size = (u32) ptr->size; + ptr->cenc_data = gf_malloc(sizeof(char)*ptr->cenc_data_size); + gf_bs_read_data(bs, ptr->cenc_data, ptr->cenc_data_size); + ptr->size = 0; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err piff_psec_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox *) s; + if (!s) return GF_BAD_PARAM; + + e = gf_isom_box_write_header(s, bs); + if (e) return e; + gf_bs_write_u8(bs, ptr->version); + gf_bs_write_u24(bs, ptr->flags); + + if (ptr->flags & 1) { + gf_bs_write_int(bs, ptr->AlgorithmID, 24); + gf_bs_write_u8(bs, ptr->IV_size); + gf_bs_write_data(bs, ptr->KID, 16); + } + gf_bs_write_u32(bs, ptr->sample_count); + if (ptr->cenc_data && ptr->cenc_data_size) { + gf_bs_write_data(bs, ptr->cenc_data, ptr->cenc_data_size); + } + return GF_OK; +} + +GF_Err piff_psec_Size(GF_Box *s) +{ + GF_Err e; + GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox*)s; + e = gf_isom_box_get_size(s); + if (e) return e; + ptr->size += 4; + if (ptr->flags & 1) { + ptr->size += 20; + } + ptr->size += 4; + if (ptr->cenc_data && ptr->cenc_data_size) { + ptr->size += ptr->cenc_data_size; + } + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + + +GF_Box *piff_pssh_New() +{ + ISOM_DECL_BOX_ALLOC(GF_PIFFProtectionSystemHeaderBox, GF_ISOM_BOX_TYPE_UUID); + tmp->internal_4cc = GF_ISOM_BOX_UUID_PSSH; + return (GF_Box *)tmp; +} + +void piff_pssh_del(GF_Box *s) +{ + gf_free(s); +} + +GF_Err piff_pssh_Read(GF_Box *s, GF_BitStream *bs) +{ + GF_PIFFProtectionSystemHeaderBox *ptr = (GF_PIFFProtectionSystemHeaderBox*)s; + + if (ptr->size<4) return GF_ISOM_INVALID_FILE; + ptr->version = gf_bs_read_u8(bs); + ptr->flags = gf_bs_read_u24(bs); + ptr->size -= 4; + + gf_bs_read_data(bs, ptr->SystemID, 16); + ptr->private_data_size = gf_bs_read_u32(bs); + ptr->size -= 20; + ptr->private_data = gf_malloc(sizeof(char)*ptr->private_data_size); + gf_bs_read_data(bs, ptr->private_data, ptr->private_data_size); + ptr->size -= ptr->private_data_size; + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err piff_pssh_Write(GF_Box *s, GF_BitStream *bs) +{ + GF_Err e; + GF_PIFFProtectionSystemHeaderBox *ptr = (GF_PIFFProtectionSystemHeaderBox *) s; + if (!s) return GF_BAD_PARAM; + + e = gf_isom_box_write_header(s, bs); + if (e) return e; + gf_bs_write_u8(bs, ptr->version); + gf_bs_write_u24(bs, ptr->flags); + + gf_bs_write_data(bs, ptr->SystemID, 16); + gf_bs_write_u32(bs, ptr->private_data_size); + gf_bs_write_data(bs, ptr->private_data, ptr->private_data_size); + return GF_OK; +} + +GF_Err piff_pssh_Size(GF_Box *s) +{ + GF_Err e; + GF_PIFFProtectionSystemHeaderBox *ptr = (GF_PIFFProtectionSystemHeaderBox*)s; + e = gf_isom_box_get_size(s); + if (e) return e; + ptr->size += 24 + ptr->private_data_size; + return GF_OK; +} +#endif //GPAC_DISABLE_ISOM_WRITE + +#endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/box_code_isma.c b/src/isomedia/box_code_isma.c deleted file mode 100644 index b059065..0000000 --- a/src/isomedia/box_code_isma.c +++ /dev/null @@ -1,889 +0,0 @@ -/* - * GPAC - Multimedia Framework C SDK - * - * Copyright (c) Cyril Concolato 2005 - * All rights reserved - * - * This file is part of GPAC / ISO Media File Format sub-project - * - * GPAC is free software you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation either version 2, or (at your option) - * any later version. - * - * GPAC is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include - -#ifndef GPAC_DISABLE_ISOM - -/* ProtectionInfo Box */ -GF_Box *sinf_New() -{ - GF_ProtectionInfoBox *tmp = (GF_ProtectionInfoBox *) gf_malloc(sizeof(GF_ProtectionInfoBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ProtectionInfoBox)); - tmp->type = GF_ISOM_BOX_TYPE_SINF; - return (GF_Box *)tmp; -} - -void sinf_del(GF_Box *s) -{ - GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; - if (ptr == NULL) return; - if (ptr->original_format) gf_isom_box_del((GF_Box *)ptr->original_format); - if (ptr->info) gf_isom_box_del((GF_Box *)ptr->info); - if (ptr->scheme_type) gf_isom_box_del((GF_Box *)ptr->scheme_type); - gf_free(ptr); -} - -GF_Err sinf_AddBox(GF_Box *s, GF_Box *a) -{ - GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; - switch (a->type) { - case GF_ISOM_BOX_TYPE_FRMA: - if (ptr->original_format) return GF_ISOM_INVALID_FILE; - ptr->original_format = (GF_OriginalFormatBox*)a; - break; - case GF_ISOM_BOX_TYPE_SCHM: - if (ptr->scheme_type) return GF_ISOM_INVALID_FILE; - ptr->scheme_type = (GF_SchemeTypeBox*)a; - break; - case GF_ISOM_BOX_TYPE_SCHI: - if (ptr->info) return GF_ISOM_INVALID_FILE; - ptr->info = (GF_SchemeInformationBox*)a; - break; - default: - gf_isom_box_del(a); - break; - } - return GF_OK; -} - -GF_Err sinf_Read(GF_Box *s, GF_BitStream *bs) -{ - return gf_isom_read_box_list(s, bs, sinf_AddBox); -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err sinf_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_write_header(s, bs); - if (e) return e; - //frma - e = gf_isom_box_write((GF_Box *) ptr->original_format, bs); - if (e) return e; - // schm - e = gf_isom_box_write((GF_Box *) ptr->scheme_type, bs); - if (e) return e; - // schi - e = gf_isom_box_write((GF_Box *) ptr->info, bs); - if (e) return e; - return GF_OK; -} - -GF_Err sinf_Size(GF_Box *s) -{ - GF_Err e; - GF_ProtectionInfoBox *ptr = (GF_ProtectionInfoBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_get_size(s); - if (e) return e; - e = gf_isom_box_size((GF_Box *) ptr->original_format); - if (e) return e; - ptr->size += ptr->original_format->size; - e = gf_isom_box_size((GF_Box *) ptr->scheme_type); - if (e) return e; - ptr->size += ptr->scheme_type->size; - e = gf_isom_box_size((GF_Box *) ptr->info); - if (e) return e; - ptr->size += ptr->info->size; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - -/* OriginalFormat Box */ -GF_Box *frma_New() -{ - GF_OriginalFormatBox *tmp = (GF_OriginalFormatBox *) gf_malloc(sizeof(GF_OriginalFormatBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_OriginalFormatBox)); - tmp->type = GF_ISOM_BOX_TYPE_FRMA; - return (GF_Box *)tmp; -} - -void frma_del(GF_Box *s) -{ - GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; - if (ptr == NULL) return; - gf_free(ptr); -} - -GF_Err frma_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; - ptr->data_format = gf_bs_read_u32(bs); - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err frma_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_write_header(s, bs); - if (e) return e; - gf_bs_write_u32(bs, ptr->data_format); - return GF_OK; -} - -GF_Err frma_Size(GF_Box *s) -{ - GF_Err e; - GF_OriginalFormatBox *ptr = (GF_OriginalFormatBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_get_size(s); - if (e) return e; - ptr->size += 4; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - -/* SchemeType Box */ -GF_Box *schm_New() -{ - GF_SchemeTypeBox *tmp = (GF_SchemeTypeBox *) gf_malloc(sizeof(GF_SchemeTypeBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SchemeTypeBox)); - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_SCHM; - return (GF_Box *)tmp; -} - -void schm_del(GF_Box *s) -{ - GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *)s; - if (ptr == NULL) return; - if (ptr->URI) gf_free(ptr->URI); - gf_free(ptr); -} - -GF_Err schm_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *)s; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - ptr->scheme_type = gf_bs_read_u32(bs); - ptr->scheme_version = gf_bs_read_u32(bs); - ptr->size -= 8; - if (ptr->size && (ptr->flags & 0x000001)) { - u32 len = (u32) (ptr->size); - ptr->URI = (char*)gf_malloc(sizeof(char)*len); - if (!ptr->URI) return GF_OUT_OF_MEM; - gf_bs_read_data(bs, ptr->URI, len); - } - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err schm_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *) s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - assert(e == GF_OK); - gf_bs_write_u32(bs, ptr->scheme_type); - gf_bs_write_u32(bs, ptr->scheme_version); - if (ptr->flags & 0x000001) gf_bs_write_data(bs, ptr->URI, strlen(ptr->URI)+1); - return GF_OK; -} - -GF_Err schm_Size(GF_Box *s) -{ - GF_Err e; - GF_SchemeTypeBox *ptr = (GF_SchemeTypeBox *) s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - ptr->size += 8; - if (ptr->flags & 0x000001) ptr->size += strlen(ptr->URI)+1; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - -/* SchemeInformation Box */ -GF_Box *schi_New() -{ - GF_SchemeInformationBox *tmp = (GF_SchemeInformationBox *) gf_malloc(sizeof(GF_SchemeInformationBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_SchemeInformationBox)); - tmp->type = GF_ISOM_BOX_TYPE_SCHI; - return (GF_Box *)tmp; -} - -void schi_del(GF_Box *s) -{ - GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; - if (ptr == NULL) return; - if (ptr->ikms) gf_isom_box_del((GF_Box *)ptr->ikms); - if (ptr->isfm) gf_isom_box_del((GF_Box *)ptr->isfm); - gf_free(ptr); -} - -GF_Err schi_AddBox(GF_Box *s, GF_Box *a) -{ - GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; - switch (a->type) { - case GF_ISOM_BOX_TYPE_IKMS: - if (ptr->ikms) return GF_ISOM_INVALID_FILE; - ptr->ikms = (GF_ISMAKMSBox*)a; - return GF_OK; - case GF_ISOM_BOX_TYPE_ISFM: - if (ptr->isfm) return GF_ISOM_INVALID_FILE; - ptr->isfm = (GF_ISMASampleFormatBox*)a; - return GF_OK; - case GF_ISOM_BOX_TYPE_ODKM: - if (ptr->okms) return GF_ISOM_INVALID_FILE; - ptr->okms = (GF_OMADRMKMSBox*)a; - return GF_OK; - default: - gf_isom_box_del(a); - return GF_OK; - } -} - -GF_Err schi_Read(GF_Box *s, GF_BitStream *bs) -{ - return gf_isom_read_box_list(s, bs, schi_AddBox); -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err schi_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_write_header(s, bs); - if (e) return e; - - if (ptr->ikms) { - e = gf_isom_box_write((GF_Box *) ptr->ikms, bs); - if (e) return e; - } - if (ptr->isfm) { - e = gf_isom_box_write((GF_Box *) ptr->isfm, bs); - if (e) return e; - } - if (ptr->okms) { - e = gf_isom_box_write((GF_Box *) ptr->okms, bs); - if (e) return e; - } - return GF_OK; -} - -GF_Err schi_Size(GF_Box *s) -{ - GF_Err e; - GF_SchemeInformationBox *ptr = (GF_SchemeInformationBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_get_size(s); - if (e) return e; - - if (ptr->ikms) { - e = gf_isom_box_size((GF_Box *) ptr->ikms); - if (e) return e; - ptr->size += ptr->ikms->size; - } - if (ptr->isfm) { - e = gf_isom_box_size((GF_Box *) ptr->isfm); - if (e) return e; - ptr->size += ptr->isfm->size; - } - if (ptr->okms) { - e = gf_isom_box_size((GF_Box *) ptr->okms); - if (e) return e; - ptr->size += ptr->okms->size; - } - return GF_OK; -} - -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - -/* ISMAKMS Box */ -GF_Box *iKMS_New() -{ - GF_ISMAKMSBox *tmp = (GF_ISMAKMSBox *) gf_malloc(sizeof(GF_ISMAKMSBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ISMAKMSBox)); - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_IKMS; - return (GF_Box *)tmp; -} - -void iKMS_del(GF_Box *s) -{ - GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; - if (ptr == NULL) return; - if (ptr->URI) gf_free(ptr->URI); - gf_free(ptr); -} - -GF_Err iKMS_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - u32 len; - GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; - - e = gf_isom_full_box_read(s, bs); - if (e) return e; - len = (u32) (ptr->size); - ptr->URI = (char*) gf_malloc(sizeof(char)*len); - if (!ptr->URI) return GF_OUT_OF_MEM; - gf_bs_read_data(bs, ptr->URI, len); - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err iKMS_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - gf_bs_write_data(bs, ptr->URI, strlen(ptr->URI)+1); - return GF_OK; -} - -GF_Err iKMS_Size(GF_Box *s) -{ - GF_Err e; - GF_ISMAKMSBox *ptr = (GF_ISMAKMSBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - ptr->size += strlen(ptr->URI)+1; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - -/* ISMASampleFormat Box */ -GF_Box *iSFM_New() -{ - GF_ISMASampleFormatBox *tmp = (GF_ISMASampleFormatBox *) gf_malloc(sizeof(GF_ISMASampleFormatBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ISMASampleFormatBox)); - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_ISFM; - return (GF_Box *)tmp; -} - -void iSFM_del(GF_Box *s) -{ - GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; - if (ptr == NULL) return; - gf_free(ptr); -} - - -GF_Err iSFM_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; - if (ptr == NULL) return GF_BAD_PARAM; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - ptr->selective_encryption = gf_bs_read_int(bs, 1); - gf_bs_read_int(bs, 7); - ptr->key_indicator_length = gf_bs_read_u8(bs); - ptr->IV_length = gf_bs_read_u8(bs); - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err iSFM_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - gf_bs_write_int(bs, ptr->selective_encryption, 1); - gf_bs_write_int(bs, 0, 7); - gf_bs_write_u8(bs, ptr->key_indicator_length); - gf_bs_write_u8(bs, ptr->IV_length); - return GF_OK; -} - -GF_Err iSFM_Size(GF_Box *s) -{ - GF_Err e; - GF_ISMASampleFormatBox *ptr = (GF_ISMASampleFormatBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - ptr->size += 3; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - - -/* OMADRMCommonHeader Box */ -GF_Box *ohdr_New() -{ - GF_OMADRMCommonHeaderBox *tmp; - GF_SAFEALLOC(tmp, GF_OMADRMCommonHeaderBox); - if (tmp == NULL) return NULL; - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_OHDR; - tmp->ExtendedHeaders = gf_list_new(); - return (GF_Box *)tmp; -} - -void ohdr_del(GF_Box *s) -{ - GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox*)s; - if (ptr == NULL) return; - gf_isom_box_array_del(ptr->ExtendedHeaders); - if (ptr->ContentID) gf_free(ptr->ContentID); - if (ptr->RightsIssuerURL) gf_free(ptr->RightsIssuerURL); - if (ptr->TextualHeaders) gf_free(ptr->TextualHeaders); - gf_free(ptr); -} - -GF_Err ohdr_AddBox(GF_Box *s, GF_Box *a) -{ - GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox*)s; - return gf_list_add(ptr->ExtendedHeaders, a); -} - -GF_Err ohdr_Read(GF_Box *s, GF_BitStream *bs) -{ - u16 cid_len, ri_len; - GF_Err e; - GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox*)s; - if (ptr == NULL) return GF_BAD_PARAM; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - ptr->EncryptionMethod = gf_bs_read_u8(bs); - ptr->PaddingScheme = gf_bs_read_u8(bs); - ptr->PlaintextLength = gf_bs_read_u64(bs); - cid_len = gf_bs_read_u16(bs); - ri_len = gf_bs_read_u16(bs); - ptr->TextualHeadersLen = gf_bs_read_u16(bs); - ptr->size -= 1+1+8+2+2+2; - if (ptr->sizeTextualHeadersLen) return GF_ISOM_INVALID_FILE; - - if (cid_len) { - ptr->ContentID = (char *)gf_malloc(sizeof(char)*(cid_len+1)); - gf_bs_read_data(bs, ptr->ContentID, cid_len); - ptr->ContentID[cid_len]=0; - } - - if (ri_len) { - ptr->RightsIssuerURL = (char *)gf_malloc(sizeof(char)*(ri_len+1)); - gf_bs_read_data(bs, ptr->RightsIssuerURL, ri_len); - ptr->RightsIssuerURL[ri_len]=0; - } - - if (ptr->TextualHeadersLen) { - ptr->TextualHeaders = (char *)gf_malloc(sizeof(char)*(ptr->TextualHeadersLen+1)); - gf_bs_read_data(bs, ptr->TextualHeaders, ptr->TextualHeadersLen); - ptr->TextualHeaders[ptr->TextualHeadersLen] = 0; - } - - ptr->size -= cid_len+ri_len+ptr->TextualHeadersLen; - - return gf_isom_read_box_list(s, bs, ohdr_AddBox); -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err ohdr_Write(GF_Box *s, GF_BitStream *bs) -{ - u16 cid_len, ri_len; - GF_Err e; - GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - gf_bs_write_u8(bs, ptr->EncryptionMethod); - gf_bs_write_u8(bs, ptr->PaddingScheme); - gf_bs_write_u64(bs, ptr->PlaintextLength); - - cid_len = ptr->ContentID ? strlen(ptr->ContentID) : 0; - gf_bs_write_u16(bs, cid_len); - ri_len = ptr->RightsIssuerURL ? strlen(ptr->RightsIssuerURL) : 0; - gf_bs_write_u16(bs, ri_len); - gf_bs_write_u16(bs, ptr->TextualHeadersLen); - - if (cid_len) gf_bs_write_data(bs, ptr->ContentID, strlen(ptr->ContentID)); - if (ri_len) gf_bs_write_data(bs, ptr->RightsIssuerURL, strlen(ptr->RightsIssuerURL)); - if (ptr->TextualHeadersLen) gf_bs_write_data(bs, ptr->TextualHeaders, ptr->TextualHeadersLen); - ptr->size -= cid_len+ri_len+ptr->TextualHeadersLen; - return gf_isom_box_array_write(s, ptr->ExtendedHeaders, bs); -} - -GF_Err ohdr_Size(GF_Box *s) -{ - GF_Err e; - GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - ptr->size += 1+1+8+2+2+2; - if (ptr->ContentID) ptr->size += strlen(ptr->ContentID); - if (ptr->RightsIssuerURL) ptr->size += strlen(ptr->RightsIssuerURL); - if (ptr->TextualHeadersLen) ptr->size += ptr->TextualHeadersLen; - return gf_isom_box_array_size(s, ptr->ExtendedHeaders); -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - -/* OMADRMGroupID Box */ -GF_Box *grpi_New() -{ - GF_OMADRMGroupIDBox *tmp; - GF_SAFEALLOC(tmp, GF_OMADRMGroupIDBox); - if (tmp == NULL) return NULL; - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_GRPI; - return (GF_Box *)tmp; -} - -void grpi_del(GF_Box *s) -{ - GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s; - if (ptr == NULL) return; - if (ptr->GroupID) gf_free(ptr->GroupID); - if (ptr->GroupKey) gf_free(ptr->GroupKey); - gf_free(ptr); -} - -GF_Err grpi_Read(GF_Box *s, GF_BitStream *bs) -{ - u16 gid_len; - GF_Err e; - GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox*)s; - if (ptr == NULL) return GF_BAD_PARAM; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - gid_len = gf_bs_read_u16(bs); - ptr->GKEncryptionMethod = gf_bs_read_u8(bs); - ptr->GKLength = gf_bs_read_u16(bs); - - ptr->size -= 1+2+2; - if (ptr->sizeGKLength) return GF_ISOM_INVALID_FILE; - - ptr->GroupID = gf_malloc(sizeof(char)*(gid_len+1)); - gf_bs_read_data(bs, ptr->GroupID, gid_len); - ptr->GroupID[gid_len]=0; - - ptr->GroupKey = (char *)gf_malloc(sizeof(char)*ptr->GKLength); - gf_bs_read_data(bs, ptr->GroupKey, ptr->GKLength); - ptr->size -= gid_len+ptr->GKLength; - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err grpi_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - u16 gid_len; - GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - gid_len = ptr->GroupID ? strlen(ptr->GroupID) : 0; - gf_bs_write_u16(bs, gid_len); - gf_bs_write_u8(bs, ptr->GKEncryptionMethod); - gf_bs_write_u16(bs, ptr->GKLength); - gf_bs_write_data(bs, ptr->GroupID, gid_len); - gf_bs_write_data(bs, ptr->GroupKey, ptr->GKLength); - return GF_OK; -} - -GF_Err grpi_Size(GF_Box *s) -{ - GF_Err e; - GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - ptr->size += 2+2+1 + ptr->GKLength; - if (ptr->GroupID) ptr->size += strlen(ptr->GroupID); - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - - - -/* OMADRMMutableInformation Box */ -GF_Box *mdri_New() -{ - GF_OMADRMMutableInformationBox *tmp; - GF_SAFEALLOC(tmp, GF_OMADRMMutableInformationBox); - if (tmp == NULL) return NULL; - tmp->type = GF_ISOM_BOX_TYPE_MDRI; - tmp->boxes = gf_list_new(); - return (GF_Box *)tmp; -} - -void mdri_del(GF_Box *s) -{ - GF_OMADRMMutableInformationBox*ptr = (GF_OMADRMMutableInformationBox*)s; - if (ptr == NULL) return; - gf_isom_box_array_del(ptr->boxes); - gf_free(ptr); -} - -GF_Err mdri_AddBox(GF_Box *s, GF_Box *a) -{ - GF_OMADRMMutableInformationBox *ptr = (GF_OMADRMMutableInformationBox *)s; - return gf_list_add(ptr->boxes, a); -} - -GF_Err mdri_Read(GF_Box *s, GF_BitStream *bs) -{ - return gf_isom_read_box_list(s, bs, mdri_AddBox); -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err mdri_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_OMADRMMutableInformationBox*ptr = (GF_OMADRMMutableInformationBox*)s; - GF_Err e = gf_isom_box_write_header(s, bs); - if (e) return e; - return gf_isom_box_array_write(s, ptr->boxes, bs); -} - -GF_Err mdri_Size(GF_Box *s) -{ - GF_Err e; - GF_OMADRMMutableInformationBox *ptr = (GF_OMADRMMutableInformationBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_box_get_size(s); - if (e) return e; - - return gf_isom_box_array_size(s, ptr->boxes); -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - -/* OMADRMTransactionTracking Box */ -GF_Box *odtt_New() -{ - GF_OMADRMTransactionTrackingBox *tmp; - GF_SAFEALLOC(tmp, GF_OMADRMTransactionTrackingBox); - if (tmp == NULL) return NULL; - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_ODTT; - return (GF_Box *)tmp; -} - -void odtt_del(GF_Box *s) -{ - GF_OMADRMTransactionTrackingBox *ptr = (GF_OMADRMTransactionTrackingBox*)s; - gf_free(ptr); -} - -GF_Err odtt_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_OMADRMTransactionTrackingBox *ptr = (GF_OMADRMTransactionTrackingBox *)s; - if (ptr == NULL) return GF_BAD_PARAM; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - gf_bs_read_data(bs, ptr->TransactionID, 16); - ptr->size -= 16; - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err odtt_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_OMADRMTransactionTrackingBox *ptr = (GF_OMADRMTransactionTrackingBox*)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - gf_bs_write_data(bs, ptr->TransactionID, 16); - return GF_OK; -} - -GF_Err odtt_Size(GF_Box *s) -{ - GF_Err e; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - s->size += 16; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - - -/* OMADRMRightsObject Box */ -GF_Box *odrb_New() -{ - GF_OMADRMRightsObjectBox *tmp; - GF_SAFEALLOC(tmp, GF_OMADRMRightsObjectBox); - if (tmp == NULL) return NULL; - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_ODRB; - return (GF_Box *)tmp; -} - -void odrb_del(GF_Box *s) -{ - GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox*)s; - if (ptr->oma_ro) gf_free(ptr->oma_ro); - gf_free(ptr); -} - -GF_Err odrb_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox *)s; - if (ptr == NULL) return GF_BAD_PARAM; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - ptr->oma_ro_size = (u32) ptr->size; - ptr->oma_ro = (char*) gf_malloc(sizeof(char)*ptr->oma_ro_size); - gf_bs_read_data(bs, ptr->oma_ro, ptr->oma_ro_size); - ptr->size = 0; - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err odrb_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - gf_bs_write_data(bs, ptr->oma_ro, ptr->oma_ro_size); - return GF_OK; -} - -GF_Err odrb_Size(GF_Box *s) -{ - GF_Err e; - GF_OMADRMRightsObjectBox *ptr = (GF_OMADRMRightsObjectBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - s->size += ptr->oma_ro_size; - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - - - -/* OMADRMKMS Box */ -GF_Box *odkm_New() -{ - GF_OMADRMKMSBox *tmp; - GF_SAFEALLOC(tmp, GF_OMADRMKMSBox); - if (tmp == NULL) return NULL; - gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_ODKM; - return (GF_Box *)tmp; -} - -void odkm_del(GF_Box *s) -{ - GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; - if (ptr->hdr) gf_isom_box_del((GF_Box*)ptr->hdr); - if (ptr->fmt) gf_isom_box_del((GF_Box*)ptr->fmt); - gf_free(ptr); -} - -GF_Err odkm_Add(GF_Box *s, GF_Box *a) -{ - GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; - switch (a->type) { - case GF_ISOM_BOX_TYPE_OHDR: - if (ptr->hdr) gf_isom_box_del((GF_Box*)ptr->hdr); - ptr->hdr = (GF_OMADRMCommonHeaderBox *)a; - return GF_OK; - case GF_ISOM_BOX_TYPE_ODAF: - if (ptr->fmt) gf_isom_box_del((GF_Box*)ptr->fmt); - ptr->fmt = (GF_OMADRMAUFormatBox*)a; - return GF_OK; - default: - gf_isom_box_del(a); - return GF_OK; - } -} - -GF_Err odkm_Read(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - if (s == NULL) return GF_BAD_PARAM; - e = gf_isom_full_box_read(s, bs); - if (e) return e; - return gf_isom_read_box_list(s, bs, odkm_Add); -} - -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_Err odkm_Write(GF_Box *s, GF_BitStream *bs) -{ - GF_Err e; - GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_write(s, bs); - if (e) return e; - if (ptr->hdr) { - e = gf_isom_box_write((GF_Box*)ptr->hdr, bs); - if (e) return e; - } - if (ptr->fmt) { - e = gf_isom_box_write((GF_Box*)ptr->fmt, bs); - if (e) return e; - } - return GF_OK; -} - -GF_Err odkm_Size(GF_Box *s) -{ - GF_Err e; - GF_OMADRMKMSBox *ptr = (GF_OMADRMKMSBox *)s; - if (!s) return GF_BAD_PARAM; - e = gf_isom_full_box_get_size(s); - if (e) return e; - if (ptr->hdr) { - e = gf_isom_box_size((GF_Box*)ptr->hdr); - if (e) return e; - ptr->size += ptr->hdr->size; - } - if (ptr->fmt) { - e = gf_isom_box_size((GF_Box*)ptr->fmt); - if (e) return e; - ptr->size += ptr->fmt->size; - } - return GF_OK; -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - -#endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/box_code_meta.c b/src/isomedia/box_code_meta.c index 824e9dc..9477452 100644 --- a/src/isomedia/box_code_meta.c +++ b/src/isomedia/box_code_meta.c @@ -1,12 +1,13 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato / Jean Le Feuvre 2005 + * Authors: Cyril Concolato / Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project * - * GPAC is free software you can redistribute it and/or modify + * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation either version 2, or (at your option) * any later version. @@ -28,18 +29,13 @@ GF_Box *meta_New() { - GF_MetaBox *tmp = (GF_MetaBox *) gf_malloc(sizeof(GF_MetaBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_MetaBox)); + ISOM_DECL_BOX_ALLOC(GF_MetaBox, GF_ISOM_BOX_TYPE_META); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_META; - tmp->other_boxes = gf_list_new(); return (GF_Box *)tmp; } void meta_del(GF_Box *s) { - u32 count, i; GF_MetaBox *ptr = (GF_MetaBox *)s; if (ptr == NULL) return; gf_isom_box_del((GF_Box *)ptr->handler); @@ -49,12 +45,6 @@ void meta_del(GF_Box *s) if (ptr->protections) gf_isom_box_del((GF_Box *)ptr->protections); if (ptr->item_infos) gf_isom_box_del((GF_Box *)ptr->item_infos); if (ptr->IPMP_control) gf_isom_box_del((GF_Box *)ptr->IPMP_control); - count = gf_list_count(ptr->other_boxes); - for (i = 0; i < count; i++) { - GF_Box *a = (GF_Box *)gf_list_get(ptr->other_boxes, i); - gf_isom_box_del(a); - } - gf_list_del(ptr->other_boxes); gf_free(ptr); } @@ -90,10 +80,8 @@ GF_Err meta_AddBox(GF_Box *s, GF_Box *a) case GF_ISOM_BOX_TYPE_XML: case GF_ISOM_BOX_TYPE_BXML: case GF_ISOM_BOX_TYPE_ILST: - gf_list_add(ptr->other_boxes, a); break; default: - gf_isom_box_del(a); - break; + return gf_isom_box_add_default(s, a); } return GF_OK; } @@ -113,14 +101,15 @@ GF_Err meta_Read(GF_Box *s, GF_BitStream *bs) #ifndef GPAC_DISABLE_ISOM_WRITE GF_Err meta_Write(GF_Box *s, GF_BitStream *bs) { - u32 count, i; GF_Err e; GF_MetaBox *ptr = (GF_MetaBox *)s; if (!s) return GF_BAD_PARAM; e = gf_isom_full_box_write(s, bs); if (e) return e; - e = gf_isom_box_write((GF_Box *) ptr->handler, bs); - if (e) return e; + if (ptr->handler) { + e = gf_isom_box_write((GF_Box *) ptr->handler, bs); + if (e) return e; + } if (ptr->primary_resource) { e = gf_isom_box_write((GF_Box *) ptr->primary_resource, bs); if (e) return e; @@ -145,27 +134,21 @@ GF_Err meta_Write(GF_Box *s, GF_BitStream *bs) e = gf_isom_box_write((GF_Box *) ptr->IPMP_control, bs); if (e) return e; } - if ((count = gf_list_count(ptr->other_boxes))) { - for (i = 0; i < count; i++) { - GF_Box *a = (GF_Box *)gf_list_get(ptr->other_boxes, i); - e = gf_isom_box_write(a, bs); - if (e) return e; - } - } return GF_OK; } GF_Err meta_Size(GF_Box *s) { - u32 i, count; GF_Err e; GF_MetaBox *ptr = (GF_MetaBox *)s; if (!s) return GF_BAD_PARAM; e = gf_isom_full_box_get_size(s); if (e) return e; - e = gf_isom_box_size((GF_Box *) ptr->handler); - if (e) return e; - ptr->size += ptr->handler->size; + if (ptr->handler) { + e = gf_isom_box_size((GF_Box *) ptr->handler); + if (e) return e; + ptr->size += ptr->handler->size; + } if (ptr->primary_resource) { e = gf_isom_box_size((GF_Box *) ptr->primary_resource); if (e) return e; @@ -196,25 +179,14 @@ GF_Err meta_Size(GF_Box *s) if (e) return e; ptr->size += ptr->IPMP_control->size; } - if ((count = gf_list_count(ptr->other_boxes))) { - for (i = 0; i < count; i++) { - GF_Box *a = (GF_Box *)gf_list_get(ptr->other_boxes, i); - e = gf_isom_box_size(a); - if (e) return e; - ptr->size += a->size; - } - } return GF_OK; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ GF_Box *xml_New() { - GF_XMLBox *tmp = (GF_XMLBox *) gf_malloc(sizeof(GF_XMLBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_XMLBox)); + ISOM_DECL_BOX_ALLOC(GF_XMLBox, GF_ISOM_BOX_TYPE_XML); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_XML; return (GF_Box *)tmp; } @@ -266,11 +238,8 @@ GF_Err xml_Size(GF_Box *s) GF_Box *bxml_New() { - GF_BinaryXMLBox *tmp = (GF_BinaryXMLBox *) gf_malloc(sizeof(GF_BinaryXMLBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_BinaryXMLBox)); + ISOM_DECL_BOX_ALLOC(GF_BinaryXMLBox, GF_ISOM_BOX_TYPE_BXML); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_BXML; return (GF_Box *)tmp; } @@ -321,11 +290,8 @@ GF_Err bxml_Size(GF_Box *s) GF_Box *iloc_New() { - GF_ItemLocationBox *tmp = (GF_ItemLocationBox *) gf_malloc(sizeof(GF_ItemLocationBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ItemLocationBox)); + ISOM_DECL_BOX_ALLOC(GF_ItemLocationBox, GF_ISOM_BOX_TYPE_ILOC); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_ILOC; tmp->location_entries = gf_list_new(); return (GF_Box *)tmp; } @@ -441,11 +407,8 @@ GF_Err iloc_Size(GF_Box *s) GF_Box *pitm_New() { - GF_PrimaryItemBox *tmp = (GF_PrimaryItemBox *) gf_malloc(sizeof(GF_PrimaryItemBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_PrimaryItemBox)); + ISOM_DECL_BOX_ALLOC(GF_PrimaryItemBox, GF_ISOM_BOX_TYPE_PITM); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_PITM; return (GF_Box *)tmp; } @@ -492,11 +455,8 @@ GF_Err pitm_Size(GF_Box *s) GF_Box *ipro_New() { - GF_ItemProtectionBox *tmp = (GF_ItemProtectionBox *) gf_malloc(sizeof(GF_ItemProtectionBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ItemProtectionBox)); + ISOM_DECL_BOX_ALLOC(GF_ItemProtectionBox, GF_ISOM_BOX_TYPE_IPRO); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_IPRO; tmp->protection_information = gf_list_new(); return (GF_Box *)tmp; } @@ -519,10 +479,9 @@ GF_Err ipro_AddBox(GF_Box *s, GF_Box *a) { GF_ItemProtectionBox *ptr = (GF_ItemProtectionBox *)s; if (a->type == GF_ISOM_BOX_TYPE_SINF) - gf_list_add(ptr->protection_information, a); + return gf_list_add(ptr->protection_information, a); else - gf_isom_box_del(a); - return GF_OK; + return gf_isom_box_add_default(s, a); } GF_Err ipro_Read(GF_Box *s, GF_BitStream *bs) { @@ -576,11 +535,8 @@ GF_Err ipro_Size(GF_Box *s) GF_Box *infe_New() { - GF_ItemInfoEntryBox *tmp = (GF_ItemInfoEntryBox *) gf_malloc(sizeof(GF_ItemInfoEntryBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ItemInfoEntryBox)); + ISOM_DECL_BOX_ALLOC(GF_ItemInfoEntryBox, GF_ISOM_BOX_TYPE_INFE); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_INFE; return (GF_Box *)tmp; } @@ -681,11 +637,8 @@ GF_Err infe_Size(GF_Box *s) GF_Box *iinf_New() { - GF_ItemInfoBox *tmp = (GF_ItemInfoBox *) gf_malloc(sizeof(GF_ItemInfoBox)); - if (tmp == NULL) return NULL; - memset(tmp, 0, sizeof(GF_ItemInfoBox)); + ISOM_DECL_BOX_ALLOC(GF_ItemInfoBox, GF_ISOM_BOX_TYPE_IINF); gf_isom_full_box_init((GF_Box *)tmp); - tmp->type = GF_ISOM_BOX_TYPE_IINF; tmp->item_infos = gf_list_new(); return (GF_Box *)tmp; } diff --git a/src/isomedia/box_dump.c b/src/isomedia/box_dump.c index c59c602..9d72e92 100644 --- a/src/isomedia/box_dump.c +++ b/src/isomedia/box_dump.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -49,6 +50,15 @@ static void DumpData(FILE *trace, char *data, u32 dataLength) } } +static void DumpDataHex(FILE *trace, char *data, u32 dataLength) +{ + u32 i; + fprintf(trace, "0x"); + for (i=0; isize > 0xFFFFFFFF) { @@ -70,7 +80,6 @@ GF_Err DumpBox(GF_Box *a, FILE * trace) return GF_OK; } - GF_Err gf_box_dump(void *ptr, FILE * trace) { GF_Box *a = (GF_Box *) ptr; @@ -146,6 +155,8 @@ GF_Err gf_box_dump(void *ptr, FILE * trace) return stts_dump(a, trace); case GF_ISOM_BOX_TYPE_CTTS: return ctts_dump(a, trace); + case GF_ISOM_BOX_TYPE_CSLG: + return cslg_dump(a, trace); case GF_ISOM_BOX_TYPE_STSH: return stsh_dump(a, trace); case GF_ISOM_BOX_TYPE_ELST: @@ -183,7 +194,10 @@ GF_Err gf_box_dump(void *ptr, FILE * trace) return sbgp_dump(a, trace); case GF_ISOM_BOX_TYPE_SGPD: return sgpd_dump(a, trace); - + case GF_ISOM_BOX_TYPE_SAIZ: + return saiz_dump(a, trace); + case GF_ISOM_BOX_TYPE_SAIO: + return saio_dump(a, trace); case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_dump(a, trace); @@ -239,7 +253,7 @@ GF_Err gf_box_dump(void *ptr, FILE * trace) case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_STYP: return ftyp_dump(a, trace); - case GF_ISOM_BOX_TYPE_FADB: + case GF_ISOM_BOX_TYPE_PADB: return padb_dump(a, trace); #ifndef GPAC_DISABLE_ISOM_FRAGMENTS @@ -327,6 +341,11 @@ GF_Err gf_box_dump(void *ptr, FILE * trace) case GF_ISOM_BOX_TYPE_TWRP: return twrp_dump(a, trace); + case GF_ISOM_BOX_TYPE_PSSH: + return pssh_dump(a, trace); + case GF_ISOM_BOX_TYPE_TENC: + return tenc_dump(a, trace); + /* ISMA 1.0 Encryption and Authentication V 1.0 */ case GF_ISOM_BOX_TYPE_IKMS: return iKMS_dump(a, trace); @@ -387,6 +406,17 @@ GF_Err gf_box_dump(void *ptr, FILE * trace) case GF_ISOM_BOX_TYPE_COVR: case GF_ISOM_BOX_TYPE_iTunesSpecificInfo: return apple_tag_dump(a, trace); +#ifndef GPAC_DISABLE_ISOM_ADOBE + /*Adobe extensions*/ + case GF_ISOM_BOX_TYPE_ABST: + return abst_dump(a, trace); + case GF_ISOM_BOX_TYPE_AFRA: + return afra_dump(a, trace); + case GF_ISOM_BOX_TYPE_ASRT: + return asrt_dump(a, trace); + case GF_ISOM_BOX_TYPE_AFRT: + return afrt_dump(a, trace); +#endif /*Apple extensions*/ case GF_ISOM_BOX_TYPE_ILST: return ilst_dump(a, trace); @@ -434,11 +464,22 @@ GF_Err gf_box_dump(void *ptr, FILE * trace) case GF_ISOM_BOX_TYPE_PCRB: return pcrb_dump(a, trace); - default: return defa_dump(a, trace); + case GF_ISOM_BOX_TYPE_UUID: + switch ( ((GF_UnknownUUIDBox *)a)->internal_4cc) { + case GF_ISOM_BOX_UUID_TENC: return piff_tenc_dump(a, trace); + case GF_ISOM_BOX_UUID_PSEC: return piff_psec_dump(a, trace); + case GF_ISOM_BOX_UUID_PSSH: return piff_pssh_dump(a, trace); + case GF_ISOM_BOX_UUID_TFRF: + case GF_ISOM_BOX_UUID_TFXD: + default: + return defa_dump(a, trace); + } + + default: + return defa_dump(a, trace); } } - GF_Err gf_box_array_dump(GF_List *list, FILE * trace) { u32 i; @@ -451,12 +492,19 @@ GF_Err gf_box_array_dump(GF_List *list, FILE * trace) return GF_OK; } +void gf_box_dump_done(char *name, GF_Box *ptr, FILE *trace) +{ + if (ptr && ptr->other_boxes) { + gf_box_array_dump(ptr->other_boxes, trace); + } + if (name) + fprintf(trace, "\n", name); +} GF_EXPORT GF_Err gf_isom_dump(GF_ISOFile *mov, FILE * trace) { - GF_Err gf_box_dump(void *ptr, FILE * trace); u32 i; GF_Box *box; if (!mov || !trace) return GF_BAD_PARAM; @@ -480,7 +528,13 @@ GF_Err gf_isom_dump(GF_ISOFile *mov, FILE * trace) case GF_ISOM_BOX_TYPE_STYP: case GF_ISOM_BOX_TYPE_SIDX: case GF_ISOM_BOX_TYPE_PCRB: +#ifndef GPAC_DISABLE_ISOM_ADOBE + /*Adobe specific*/ + case GF_ISOM_BOX_TYPE_AFRA: + case GF_ISOM_BOX_TYPE_ABST: #endif +#endif + case GF_ISOM_BOX_TYPE_MFRA: break; default: @@ -499,7 +553,7 @@ GF_Err gf_full_box_dump(GF_Box *a, FILE * trace) { GF_FullBox *p; p = (GF_FullBox *)a; - fprintf(trace, "\n", p->version, p->flags); + fprintf(trace, "\n", p->version, p->flags); return GF_OK; } @@ -527,7 +581,10 @@ GF_Err reftype_dump(GF_Box *a, FILE * trace) for (i=0; itrackIDCount; i++) fprintf(trace, " %d", p->trackIDs[i]); fprintf(trace, "\">\n"); DumpBox(a, trace); + + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", s); + p->type = GF_ISOM_BOX_TYPE_REFT; return GF_OK; } @@ -539,7 +596,7 @@ GF_Err free_dump(GF_Box *a, FILE * trace) p = (GF_FreeSpaceBox *)a; fprintf(trace, "\n", p->dataSize); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("FreeSpaceBox", a, trace); return GF_OK; } @@ -550,7 +607,7 @@ GF_Err mdat_dump(GF_Box *a, FILE * trace) p = (GF_MediaDataBox *)a; fprintf(trace, "\n", LLD_CAST p->dataSize); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MediaDataBox", a, trace); return GF_OK; } @@ -571,8 +628,7 @@ GF_Err moov_dump(GF_Box *a, FILE * trace) gf_box_array_dump(p->trackList, trace); if (p->udta) gf_box_dump(p->udta, trace); - gf_box_array_dump(p->boxes, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MovieBox", a, trace); return GF_OK; } @@ -592,7 +648,7 @@ GF_Err mvhd_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, ""); + gf_box_dump_done("MovieHeaderBox", a, trace); return GF_OK; } @@ -611,7 +667,7 @@ GF_Err mdhd_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MediaHeaderBox", a, trace); return GF_OK; } @@ -620,7 +676,7 @@ GF_Err vmhd_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("VideoMediaHeaderBox", a, trace); return GF_OK; } @@ -629,7 +685,7 @@ GF_Err smhd_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("SoundMediaHeaderBox", a, trace); return GF_OK; } @@ -648,7 +704,7 @@ GF_Err hmhd_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("HintMediaHeaderBox", a, trace); return GF_OK; } @@ -657,7 +713,7 @@ GF_Err nmhd_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MPEGMediaHeaderBox", a, trace); return GF_OK; } @@ -671,6 +727,7 @@ GF_Err stbl_dump(GF_Box *a, FILE * trace) gf_box_dump(p->SampleDescription, trace); gf_box_dump(p->TimeToSample, trace); if (p->CompositionOffset) gf_box_dump(p->CompositionOffset, trace); + if (p->CompositionToDecode) gf_box_dump(p->CompositionToDecode, trace); if (p->SyncSample) gf_box_dump(p->SyncSample, trace); if (p->ShadowSync) gf_box_dump(p->ShadowSync, trace); gf_box_dump(p->SampleToChunk, trace); @@ -683,8 +740,8 @@ GF_Err stbl_dump(GF_Box *a, FILE * trace) if (p->Fragments) gf_box_dump(p->Fragments, trace); if (p->sampleGroupsDescription) gf_box_array_dump(p->sampleGroupsDescription, trace); if (p->sampleGroups) gf_box_array_dump(p->sampleGroups, trace); - - fprintf(trace, "\n"); + + gf_box_dump_done("SampleTableBox", a, trace); return GF_OK; } @@ -695,7 +752,7 @@ GF_Err dinf_dump(GF_Box *a, FILE * trace) fprintf(trace, ""); DumpBox(a, trace); gf_box_dump(p->dref, trace); - fprintf(trace, "\n"); + gf_box_dump_done("DataInformationBox", a, trace); return GF_OK; } @@ -717,7 +774,7 @@ GF_Err url_dump(GF_Box *a, FILE * trace) } DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("URLDataEntryBox", a, trace); return GF_OK; } @@ -733,7 +790,7 @@ GF_Err urn_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("URNDataEntryBox", a, trace); return GF_OK; } @@ -745,7 +802,7 @@ GF_Err cprt_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->packedLanguageCode, p->notice); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("CopyrightBox", a, trace); return GF_OK; } @@ -780,7 +837,7 @@ GF_Err chpl_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", ce->name, format_duration(ce->start_time, 1000*10000, szDur)); } - fprintf(trace, "\n"); + gf_box_dump_done("ChapterListBox", a, trace); return GF_OK; } @@ -795,7 +852,7 @@ GF_Err dpin_dump(GF_Box *a, FILE * trace) for (i=0; icount; i++) { fprintf(trace, "\n", p->rates[i], p->times[i]); } - fprintf(trace, "\n"); + gf_box_dump_done("ProgressiveDownloadBox", a, trace); return GF_OK; } @@ -814,7 +871,7 @@ GF_Err hdlr_dump(GF_Box *a, FILE * trace) fprintf(trace, ">\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("HandlerBox", a, trace); return GF_OK; } @@ -836,7 +893,7 @@ GF_Err iods_dump(GF_Box *a, FILE * trace) } else { fprintf(trace, "\n"); } - fprintf(trace, "\n"); + gf_box_dump_done("ObjectDescriptorBox", a, trace); return GF_OK; } @@ -857,8 +914,7 @@ GF_Err trak_dump(GF_Box *a, FILE * trace) if (p->editBox) gf_box_dump(p->editBox, trace); if (p->Media) gf_box_dump(p->Media, trace); if (p->udta) gf_box_dump(p->udta, trace); - gf_box_array_dump(p->boxes, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackBox", a, trace); return GF_OK; } @@ -875,9 +931,9 @@ GF_Err mp4s_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); } if (a->type == GF_ISOM_BOX_TYPE_ENCS) { - gf_box_dump(p->protection_info, trace); + gf_box_array_dump(p->protections, trace); } - fprintf(trace, "\n"); + gf_box_dump_done("MPEGSystemsSampleDescriptionBox", a, trace); return GF_OK; } @@ -901,6 +957,7 @@ GF_Err mp4v_dump(GF_Box *a, FILE * trace) fprintf(trace, "<%s", name); base_visual_entry_dump((GF_VisualSampleEntryBox *)p, trace); fprintf(trace, ">\n"); + DumpBox(a, trace); if (p->esd) { gf_box_dump(p->esd, trace); @@ -912,13 +969,12 @@ GF_Err mp4v_dump(GF_Box *a, FILE * trace) if (p->svc_config) gf_box_dump(p->svc_config, trace); } if (a->type == GF_ISOM_BOX_TYPE_ENCV) { - gf_box_dump(p->protection_info, trace); + gf_box_array_dump(p->protections, trace); } if (p->pasp) gf_box_dump(p->pasp, trace); if (p->rvcc) gf_box_dump(p->rvcc, trace); - DumpBox(a, trace); - + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", name); return GF_OK; } @@ -946,9 +1002,9 @@ GF_Err mp4a_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); } if (a->type == GF_ISOM_BOX_TYPE_ENCA) { - gf_box_dump(p->protection_info, trace); + gf_box_array_dump(p->protections, trace); } - fprintf(trace, "\n"); + gf_box_dump_done("MPEGAudioSampleDescriptionBox", a, trace); return GF_OK; } @@ -959,7 +1015,7 @@ GF_Err gnrm_dump(GF_Box *a, FILE * trace) a->type = p->EntryType; DumpBox(a, trace); a->type = GF_ISOM_BOX_TYPE_GNRM; - fprintf(trace, "\n"); + gf_box_dump_done("SampleDescriptionBox", a, trace); return GF_OK; } @@ -967,11 +1023,11 @@ GF_Err gnrv_dump(GF_Box *a, FILE * trace) { GF_GenericVisualSampleEntryBox *p = (GF_GenericVisualSampleEntryBox *)a; fprintf(trace, "\n", - p->dataReferenceIndex, p->version, p->revision, p->vendor, p->temporal_quality, p->spacial_quality, p->Width, p->Height, p->horiz_res, p->vert_res, p->compressor_name, p->bit_depth); + p->dataReferenceIndex, p->version, p->revision, p->vendor, p->temporal_quality, p->spatial_quality, p->Width, p->Height, p->horiz_res, p->vert_res, p->compressor_name, p->bit_depth); a->type = p->EntryType; DumpBox(a, trace); a->type = GF_ISOM_BOX_TYPE_GNRV; - fprintf(trace, "\n"); + gf_box_dump_done("VisualSampleDescriptionBox", a, trace); return GF_OK; } @@ -983,7 +1039,7 @@ GF_Err gnra_dump(GF_Box *a, FILE * trace) a->type = p->EntryType; DumpBox(a, trace); a->type = GF_ISOM_BOX_TYPE_GNRA; - fprintf(trace, "\n"); + gf_box_dump_done("AudioSampleDescriptionBox", a, trace); return GF_OK; } @@ -995,7 +1051,7 @@ GF_Err edts_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); DumpBox(a, trace); gf_box_dump(p->editList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("EditBox", a, trace); return GF_OK; } @@ -1012,68 +1068,86 @@ GF_Err udta_dump(GF_Box *a, FILE * trace) i=0; while ((map = (GF_UserDataMap *)gf_list_enum(p->recordList, &i))) { fprintf(trace, "\n", gf_4cc_to_str(map->boxType)); - gf_box_array_dump(map->boxList, trace); + gf_box_array_dump(map->other_boxes, trace); fprintf(trace, "\n"); } - fprintf(trace, "\n"); + gf_box_dump_done("UserDataBox", a, trace); return GF_OK; } GF_Err dref_dump(GF_Box *a, FILE * trace) { - GF_DataReferenceBox *p; - - p = (GF_DataReferenceBox *)a; +// GF_DataReferenceBox *p = (GF_DataReferenceBox *)a; fprintf(trace, "\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - gf_box_array_dump(p->boxList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("DataReferenceBox", a, trace); return GF_OK; } GF_Err stsd_dump(GF_Box *a, FILE * trace) { - GF_SampleDescriptionBox *p; - p = (GF_SampleDescriptionBox *)a; +// GF_SampleDescriptionBox *p = (GF_SampleDescriptionBox *)a; fprintf(trace, "\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - gf_box_array_dump(p->boxList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("SampleDescriptionBox", a, trace); return GF_OK; } GF_Err stts_dump(GF_Box *a, FILE * trace) { GF_TimeToSampleBox *p; - u32 i; + u32 i, nb_samples; p = (GF_TimeToSampleBox *)a; fprintf(trace, "\n", p->nb_entries); DumpBox(a, trace); gf_full_box_dump(a, trace); + nb_samples = 0; for (i=0; inb_entries; i++) { fprintf(trace, "\n", p->entries[i].sampleDelta, p->entries[i].sampleCount); + nb_samples += p->entries[i].sampleCount; } - fprintf(trace, "\n"); + fprintf(trace, "\n", nb_samples); + gf_box_dump_done("TimeToSampleBox", a, trace); return GF_OK; } GF_Err ctts_dump(GF_Box *a, FILE * trace) { GF_CompositionOffsetBox *p; - u32 i; + u32 i, nb_samples; p = (GF_CompositionOffsetBox *)a; fprintf(trace, "\n", p->nb_entries); DumpBox(a, trace); gf_full_box_dump(a, trace); + nb_samples = 0; for (i=0; inb_entries;i++) { fprintf(trace, "\n", p->entries[i].decodingOffset, p->entries[i].sampleCount); + nb_samples += p->entries[i].sampleCount; } - fprintf(trace, "\n"); + fprintf(trace, "\n", nb_samples); + gf_box_dump_done("CompositionOffsetBox", a, trace); + return GF_OK; +} + +GF_Err cslg_dump(GF_Box *a, FILE * trace) +{ + GF_CompositionToDecodeBox *p; + + p = (GF_CompositionToDecodeBox *)a; + fprintf(trace, "\n"); + DumpBox(a, trace); + gf_full_box_dump(a, trace); + fprintf(trace, "\n", p->compositionToDTSShift); + fprintf(trace, "\n", p->leastDecodeToDisplayDelta); + fprintf(trace, "\n", p->greatestDecodeToDisplayDelta); + fprintf(trace, "\n", p->compositionStartTime); + fprintf(trace, "\n", p->compositionEndTime); + gf_box_dump_done("CompositionToDecodeBox", a, trace); return GF_OK; } @@ -1091,7 +1165,7 @@ GF_Err stsh_dump(GF_Box *a, FILE * trace) while ((t = (GF_StshEntry *)gf_list_enum(p->entries, &i))) { fprintf(trace, "\n", t->shadowedSampleNumber, t->syncSampleNumber); } - fprintf(trace, "\n"); + gf_box_dump_done("SyncShadowBox", a, trace); return GF_OK; } @@ -1110,24 +1184,31 @@ GF_Err elst_dump(GF_Box *a, FILE * trace) while ((t = (GF_EdtsEntry *)gf_list_enum(p->entryList, &i))) { fprintf(trace, "\n", LLD_CAST t->segmentDuration, LLD_CAST t->mediaTime, t->mediaRate); } - fprintf(trace, "\n"); + gf_box_dump_done("EditListBox", a, trace); return GF_OK; } GF_Err stsc_dump(GF_Box *a, FILE * trace) { GF_SampleToChunkBox *p; - u32 i; + u32 i, nb_samples; p = (GF_SampleToChunkBox *)a; fprintf(trace, "\n", p->nb_entries); DumpBox(a, trace); gf_full_box_dump(a, trace); + nb_samples = 0; for (i=0; inb_entries; i++) { fprintf(trace, "\n", p->entries[i].firstChunk, p->entries[i].samplesPerChunk, p->entries[i].sampleDescriptionIndex); + if (i+1nb_entries) { + nb_samples += (p->entries[i+1].firstChunk - p->entries[i].firstChunk) * p->entries[i].samplesPerChunk; + } else { + nb_samples += p->entries[i].samplesPerChunk; + } } - fprintf(trace, "\n"); + fprintf(trace, "\n", nb_samples); + gf_box_dump_done("SampleToChunkBox", a, trace); return GF_OK; } @@ -1159,6 +1240,7 @@ GF_Err stsz_dump(GF_Box *a, FILE * trace) } } } + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", (a->type == GF_ISOM_BOX_TYPE_STSZ) ? "SampleSize" : "CompactSampleSize"); return GF_OK; } @@ -1180,7 +1262,7 @@ GF_Err stco_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->offsets[i]); } } - fprintf(trace, "\n"); + gf_box_dump_done("ChunkOffsetBox", a, trace); return GF_OK; } @@ -1201,7 +1283,7 @@ GF_Err stss_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->sampleNumbers[i]); } } - fprintf(trace, "\n"); + gf_box_dump_done("SyncSampleBox", a, trace); return GF_OK; } @@ -1222,7 +1304,7 @@ GF_Err stdp_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->priorities[i]); } } - fprintf(trace, "\n"); + gf_box_dump_done("DegradationPriorityBox", a, trace); return GF_OK; } @@ -1263,7 +1345,7 @@ GF_Err sdtp_dump(GF_Box *a, FILE * trace) fprintf(trace, " />\n"); } } - fprintf(trace, "\n"); + gf_box_dump_done("SampleDependencyTypeBox", a, trace); return GF_OK; } @@ -1283,7 +1365,7 @@ GF_Err co64_dump(GF_Box *a, FILE * trace) for (i=0; inb_entries; i++) fprintf(trace, "\n", LLD_CAST p->offsets[i]); } - fprintf(trace, "\n"); + gf_box_dump_done("ChunkLargeOffsetBox", a, trace); return GF_OK; } @@ -1305,7 +1387,7 @@ GF_Err esds_dump(GF_Box *a, FILE * trace) } else { fprintf(trace, "\n"); } - fprintf(trace, "\n"); + gf_box_dump_done("MPEG4ESDescriptorBox", a, trace); return GF_OK; } @@ -1320,7 +1402,7 @@ GF_Err minf_dump(GF_Box *a, FILE * trace) gf_box_dump(p->InfoHeader, trace); gf_box_dump(p->dataInformation, trace); gf_box_dump(p->sampleTable, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MediaInformationBox", a, trace); return GF_OK; } @@ -1352,33 +1434,28 @@ GF_Err tkhd_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackHeaderBox", a, trace); return GF_OK; } GF_Err tref_dump(GF_Box *a, FILE * trace) { - GF_TrackReferenceBox *p; - - p = (GF_TrackReferenceBox *)a; +// GF_TrackReferenceBox *p = (GF_TrackReferenceBox *)a; fprintf(trace, "\n"); DumpBox(a, trace); - gf_box_array_dump(p->boxList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackReferenceBox", a, trace); return GF_OK; } GF_Err mdia_dump(GF_Box *a, FILE * trace) { - GF_MediaBox *p; - - p = (GF_MediaBox *)a; + GF_MediaBox *p = (GF_MediaBox *)a; fprintf(trace, "\n"); DumpBox(a, trace); gf_box_dump(p->mediaHeader, trace); gf_box_dump(p->handler, trace); gf_box_dump(p->information, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MediaBox", a, trace); return GF_OK; } @@ -1408,6 +1485,7 @@ GF_Err ftyp_dump(GF_Box *a, FILE * trace) for (i=0; ialtCount; i++) { fprintf(trace, "\n", gf_4cc_to_str(p->altBrand[i])); } + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n",(a->type == GF_ISOM_BOX_TYPE_FTYP ? "FileTypeBox" : "SegmentTypeBox")); return GF_OK; } @@ -1423,7 +1501,7 @@ GF_Err padb_dump(GF_Box *a, FILE * trace) for (i=0; iSampleCount; i+=1) { fprintf(trace, "\n", p->padbits[i]); } - fprintf(trace, "\n"); + gf_box_dump_done("PaddingBitsBox", a, trace); return GF_OK; } @@ -1446,7 +1524,7 @@ GF_Err stsf_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); } - fprintf(trace, "\n"); + gf_box_dump_done("SampleFragmentBox", a, trace); return GF_OK; } @@ -1473,6 +1551,7 @@ GF_Err gppa_dump(GF_Box *a, FILE * trace) } else { fprintf(trace, "\n"); } + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", szName); return GF_OK; } @@ -1495,6 +1574,7 @@ GF_Err gppv_dump(GF_Box *a, FILE * trace) } else { fprintf(trace, "\n"); } + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", szName); return GF_OK; } @@ -1510,29 +1590,29 @@ GF_Err gppc_dump(GF_Box *a, FILE * trace) fprintf(trace, " FramesPerSample=\"%d\" SupportedModes=\"%x\" ModeRotating=\"%d\"", p->cfg.frames_per_sample, p->cfg.AMR_mode_set, p->cfg.AMR_mode_change_period); fprintf(trace, ">\n"); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("AMRConfigurationBox", a, trace); break; case GF_ISOM_SUBTYPE_3GP_EVRC: fprintf(trace, "\n", name, p->cfg.decoder_version, p->cfg.frames_per_sample); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("EVRCConfigurationBox", a, trace); break; case GF_ISOM_SUBTYPE_3GP_QCELP: fprintf(trace, "\n", name, p->cfg.decoder_version, p->cfg.frames_per_sample); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("QCELPConfigurationBox", a, trace); break; case GF_ISOM_SUBTYPE_3GP_SMV: fprintf(trace, "\n", name, p->cfg.decoder_version, p->cfg.frames_per_sample); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("SMVConfigurationBox", a, trace); break; case GF_ISOM_SUBTYPE_3GP_H263: fprintf(trace, "cfg.decoder_version); fprintf(trace, " Profile=\"%d\" Level=\"%d\"", p->cfg.H263_profile, p->cfg.H263_level); fprintf(trace, ">\n"); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("H263ConfigurationBox", a, trace); break; default: break; @@ -1553,25 +1633,49 @@ GF_Err avcc_dump(GF_Box *a, FILE * trace) if (p->type==GF_ISOM_BOX_TYPE_SVCC) fprintf(trace, " complete_representation=\"%d\"", p->config->complete_representation); + + if (p->type==GF_ISOM_BOX_TYPE_AVCC) { + switch (p->config->AVCProfileIndication) { + case 100: + case 110: + case 122: + case 144: + fprintf(trace, " chroma_format=\"%d\" luma_bit_depth=\"%d\" chroma_bit_depth=\"%d\"", p->config->chroma_format, p->config->luma_bit_depth, p->config->chroma_bit_depth); + break; + } + } + fprintf(trace, ">\n"); count = gf_list_count(p->config->sequenceParameterSets); for (i=0; iconfig->sequenceParameterSets, i); - fprintf(trace, "size); + fprintf(trace, "size); DumpData(trace, c->data, c->size); fprintf(trace, "\"/>\n"); } count = gf_list_count(p->config->pictureParameterSets); for (i=0; iconfig->pictureParameterSets, i); - fprintf(trace, "size); + fprintf(trace, "size); DumpData(trace, c->data, c->size); fprintf(trace, "\"/>\n"); } + + if (p->config->sequenceParameterSetExtensions) { + count = gf_list_count(p->config->sequenceParameterSetExtensions); + for (i=0; iconfig->sequenceParameterSetExtensions, i); + fprintf(trace, "size); + DumpData(trace, c->data, c->size); + fprintf(trace, "\"/>\n"); + } + } + fprintf(trace, "\n", name); DumpBox(a, trace); + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", name); return GF_OK; } @@ -1592,7 +1696,7 @@ GF_Err m4ds_dump(GF_Box *a, FILE * trace) #endif } DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MPEG4ExtensionDescriptorsBox", a, trace); return GF_OK; } @@ -1601,7 +1705,7 @@ GF_Err btrt_dump(GF_Box *a, FILE * trace) GF_MPEG4BitRateBox *p = (GF_MPEG4BitRateBox*)a; fprintf(trace, "\n", p->bufferSizeDB, p->avgBitrate, p->maxBitrate); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MPEG4BitRateBox", a, trace); return GF_OK; } @@ -1614,7 +1718,7 @@ GF_Err ftab_dump(GF_Box *a, FILE * trace) for (i=0; ientry_count; i++) { fprintf(trace, "\n", p->fonts[i].fontID, p->fonts[i].fontName ? p->fonts[i].fontName : "NULL"); } - fprintf(trace, "\n"); + gf_box_dump_done("FontTableBox", a, trace); return GF_OK; } @@ -1657,12 +1761,12 @@ GF_Err tx3g_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); gpp_dump_box(trace, &p->default_box); - fprintf(trace, "\n"); + gf_box_dump_done("DefaultBox", a, trace); fprintf(trace, "\n"); gpp_dump_style(trace, &p->default_style); fprintf(trace, "\n"); gf_box_dump(p->font_table, trace); - fprintf(trace, "\n"); + gf_box_dump_done("Tx3gSampleEntryBox", a, trace); return GF_OK; } @@ -1680,8 +1784,8 @@ GF_Err text_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); gpp_dump_box(trace, &p->default_box); - fprintf(trace, "\n"); - fprintf(trace, "\n"); + gf_box_dump_done("DefaultBox", a, trace); + gf_box_dump_done("TextSampleEntryBox", a, trace); return GF_OK; } @@ -1692,7 +1796,7 @@ GF_Err styl_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); DumpBox(a, trace); for (i=0; ientry_count; i++) gpp_dump_style(trace, &p->styles[i]); - fprintf(trace, "\n"); + gf_box_dump_done("TextStyleBox", a, trace); return GF_OK; } GF_Err hlit_dump(GF_Box *a, FILE * trace) @@ -1700,17 +1804,17 @@ GF_Err hlit_dump(GF_Box *a, FILE * trace) GF_TextHighlightBox*p = (GF_TextHighlightBox*)a; fprintf(trace, "\n", p->startcharoffset, p->endcharoffset); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextHighlightBox", a, trace); return GF_OK; } GF_Err hclr_dump(GF_Box *a, FILE * trace) { GF_TextHighlightColorBox*p = (GF_TextHighlightColorBox*)a; - fprintf(trace, "hil_color); fprintf(trace, ">\n"); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextHighlightColorBox", a, trace); return GF_OK; } @@ -1723,7 +1827,7 @@ GF_Err krok_dump(GF_Box *a, FILE * trace) for (i=0; inb_entries; i++) { fprintf(trace, "\n", p->records[i].highlight_endtime, p->records[i].start_charoffset, p->records[i].end_charoffset); } - fprintf(trace, "\n"); + gf_box_dump_done("TextKaraokeBox", a, trace); return GF_OK; } GF_Err dlay_dump(GF_Box *a, FILE * trace) @@ -1731,7 +1835,7 @@ GF_Err dlay_dump(GF_Box *a, FILE * trace) GF_TextScrollDelayBox*p = (GF_TextScrollDelayBox*)a; fprintf(trace, "\n", p->scroll_delay); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextScrollDelayBox", a, trace); return GF_OK; } GF_Err href_dump(GF_Box *a, FILE * trace) @@ -1739,7 +1843,7 @@ GF_Err href_dump(GF_Box *a, FILE * trace) GF_TextHyperTextBox*p = (GF_TextHyperTextBox*)a; fprintf(trace, "\n", p->startcharoffset, p->endcharoffset, p->URL ? p->URL : "NULL", p->URL_hint ? p->URL_hint : "NULL"); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextHyperTextBox", a, trace); return GF_OK; } GF_Err tbox_dump(GF_Box *a, FILE * trace) @@ -1748,7 +1852,7 @@ GF_Err tbox_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); gpp_dump_box(trace, &p->box); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextBoxBox", a, trace); return GF_OK; } GF_Err blnk_dump(GF_Box *a, FILE * trace) @@ -1756,7 +1860,7 @@ GF_Err blnk_dump(GF_Box *a, FILE * trace) GF_TextBlinkBox*p = (GF_TextBlinkBox*)a; fprintf(trace, "\n", p->startcharoffset, p->endcharoffset); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextBlinkBox", a, trace); return GF_OK; } GF_Err twrp_dump(GF_Box *a, FILE * trace) @@ -1764,7 +1868,7 @@ GF_Err twrp_dump(GF_Box *a, FILE * trace) GF_TextWrapBox*p = (GF_TextWrapBox*)a; fprintf(trace, "\n", p->wrap_flag ? ( (p->wrap_flag>1) ? "Reserved" : "Automatic" ) : "No Wrap"); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TextWrapBox", a, trace); return GF_OK; } @@ -1784,9 +1888,7 @@ GF_Err meta_dump(GF_Box *a, FILE * trace) if (p->protections) gf_box_dump(p->protections, trace); if (p->item_infos) gf_box_dump(p->item_infos, trace); if (p->IPMP_control) gf_box_dump(p->IPMP_control, trace); - - gf_box_array_dump(p->other_boxes, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MetaBox", a, trace); return GF_OK; } @@ -1800,7 +1902,7 @@ GF_Err xml_dump(GF_Box *a, FILE * trace) fprintf(trace, "xml, p->xml_length, 1, trace); fprintf(trace, "]]>\n"); - fprintf(trace, "\n"); + gf_box_dump_done("XMLBox", a, trace); return GF_OK; } @@ -1811,7 +1913,7 @@ GF_Err bxml_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->data_length); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("BinaryXMLBox", a, trace); return GF_OK; } @@ -1822,7 +1924,7 @@ GF_Err pitm_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->item_ID); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("PrimaryItemBox", a, trace); return GF_OK; } @@ -1833,7 +1935,7 @@ GF_Err ipro_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); gf_box_array_dump(p->protection_information, trace); - fprintf(trace, "\n"); + gf_box_dump_done("ItemProtectionBox", a, trace); return GF_OK; } @@ -1843,7 +1945,7 @@ GF_Err infe_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->item_ID, p->item_protection_index, p->item_name, p->content_type, p->content_encoding); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("ItemInfoEntryBox", a, trace); return GF_OK; } @@ -1854,7 +1956,7 @@ GF_Err iinf_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); gf_box_array_dump(p->item_infos, trace); - fprintf(trace, "\n"); + gf_box_dump_done("ItemInfoBox", a, trace); return GF_OK; } @@ -1875,31 +1977,26 @@ GF_Err iloc_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", LLD_CAST iee->extent_offset, LLD_CAST iee->extent_length); } } - fprintf(trace, "\n"); + gf_box_dump_done("ItemLocationBox", a, trace); return GF_OK; } GF_Err hinf_dump(GF_Box *a, FILE * trace) { - GF_HintInfoBox *p; - - p = (GF_HintInfoBox *)a; +// GF_HintInfoBox *p = (GF_HintInfoBox *)a; fprintf(trace, "\n"); DumpBox(a, trace); - gf_box_array_dump(p->boxList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("HintInfoBox", a, trace); return GF_OK; } GF_Err trpy_dump(GF_Box *a, FILE * trace) { - GF_TRPYBox *p; - - p = (GF_TRPYBox *)a; + GF_TRPYBox *p = (GF_TRPYBox *)a; fprintf(trace, "\n", LLD_CAST p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("LargeTotalRTPBytesBox", a, trace); return GF_OK; } @@ -1910,7 +2007,7 @@ GF_Err totl_dump(GF_Box *a, FILE * trace) p = (GF_TOTLBox *)a; fprintf(trace, "\n", p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TotalRTPBytesBox", a, trace); return GF_OK; } @@ -1921,7 +2018,7 @@ GF_Err nump_dump(GF_Box *a, FILE * trace) p = (GF_NUMPBox *)a; fprintf(trace, "\n", LLD_CAST p->nbPackets); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("LargeTotalPacketBox", a, trace); return GF_OK; } @@ -1932,7 +2029,7 @@ GF_Err npck_dump(GF_Box *a, FILE * trace) p = (GF_NPCKBox *)a; fprintf(trace, "\n", p->nbPackets); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TotalPacketBox", a, trace); return GF_OK; } @@ -1943,7 +2040,7 @@ GF_Err tpyl_dump(GF_Box *a, FILE * trace) p = (GF_NTYLBox *)a; fprintf(trace, "\n", LLD_CAST p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("LargeTotalMediaBytesBox", a, trace); return GF_OK; } @@ -1954,7 +2051,7 @@ GF_Err tpay_dump(GF_Box *a, FILE * trace) p = (GF_TPAYBox *)a; fprintf(trace, "\n", p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TotalMediaBytesBox", a, trace); return GF_OK; } @@ -1964,7 +2061,7 @@ GF_Err maxr_dump(GF_Box *a, FILE * trace) p = (GF_MAXRBox *)a; fprintf(trace, "\n", p->maxDataRate, p->granularity); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MaxDataRateBox", a, trace); return GF_OK; } @@ -1975,7 +2072,7 @@ GF_Err dmed_dump(GF_Box *a, FILE * trace) p = (GF_DMEDBox *)a; fprintf(trace, "\n", LLD_CAST p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("BytesFromMediaTrackBox", a, trace); return GF_OK; } @@ -1986,7 +2083,7 @@ GF_Err dimm_dump(GF_Box *a, FILE * trace) p = (GF_DIMMBox *)a; fprintf(trace, "\n", LLD_CAST p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("ImmediateDataBytesBox", a, trace); return GF_OK; } @@ -1997,7 +2094,7 @@ GF_Err drep_dump(GF_Box *a, FILE * trace) p = (GF_DREPBox *)a; fprintf(trace, "\n", LLD_CAST p->nbBytes); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("RepeatedDataBytesBox", a, trace); return GF_OK; } @@ -2008,7 +2105,7 @@ GF_Err tmin_dump(GF_Box *a, FILE * trace) p = (GF_TMINBox *)a; fprintf(trace, "\n", p->minTime); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MinTransmissionTimeBox", a, trace); return GF_OK; } @@ -2019,7 +2116,7 @@ GF_Err tmax_dump(GF_Box *a, FILE * trace) p = (GF_TMAXBox *)a; fprintf(trace, "\n", p->maxTime); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MaxTransmissionTimeBox", a, trace); return GF_OK; } @@ -2030,7 +2127,7 @@ GF_Err pmax_dump(GF_Box *a, FILE * trace) p = (GF_PMAXBox *)a; fprintf(trace, "\n", p->maxSize); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MaxPacketSizeBox", a, trace); return GF_OK; } @@ -2041,7 +2138,7 @@ GF_Err dmax_dump(GF_Box *a, FILE * trace) p = (GF_DMAXBox *)a; fprintf(trace, "\n", p->maxDur); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MaxPacketDurationBox", a, trace); return GF_OK; } @@ -2052,7 +2149,7 @@ GF_Err payt_dump(GF_Box *a, FILE * trace) p = (GF_PAYTBox *)a; fprintf(trace, "\n", p->payloadCode, p->payloadString); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("PayloadTypeBox", a, trace); return GF_OK; } @@ -2063,7 +2160,7 @@ GF_Err name_dump(GF_Box *a, FILE * trace) p = (GF_NameBox *)a; fprintf(trace, "\n", p->string); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("NameBox", a, trace); return GF_OK; } @@ -2074,7 +2171,7 @@ GF_Err rely_dump(GF_Box *a, FILE * trace) p = (GF_RelyHintBox *)a; fprintf(trace, "\n", p->prefered, p->required); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("RelyTransmissionBox", a, trace); return GF_OK; } @@ -2085,7 +2182,7 @@ GF_Err snro_dump(GF_Box *a, FILE * trace) p = (GF_SeqOffHintEntryBox *)a; fprintf(trace, "\n", p->SeqOffset); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("PacketSequenceOffsetBox", a, trace); return GF_OK; } @@ -2096,7 +2193,7 @@ GF_Err tims_dump(GF_Box *a, FILE * trace) p = (GF_TSHintEntryBox *)a; fprintf(trace, "\n", p->timeScale); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("RTPTimeScaleBox", a, trace); return GF_OK; } @@ -2107,7 +2204,7 @@ GF_Err tsro_dump(GF_Box *a, FILE * trace) p = (GF_TimeOffHintEntryBox *)a; fprintf(trace, "\n", p->TimeOffset); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TimeStampOffsetBox", a, trace); return GF_OK; } @@ -2122,7 +2219,7 @@ GF_Err ghnt_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_box_array_dump(p->HintDataTable, trace); - fprintf(trace, "\n"); + gf_box_dump_done("GenericHintSampleEntryBox", a, trace); return GF_OK; } @@ -2138,17 +2235,17 @@ GF_Err hnti_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); i=0; - while ((ptr = (GF_Box *)gf_list_enum(p->boxList, &i))) { + while ((ptr = (GF_Box *)gf_list_enum(p->other_boxes, &i))) { if (ptr->type !=GF_ISOM_BOX_TYPE_RTP) { gf_box_dump(ptr, trace); } else { rtp = (GF_RTPBox *)ptr; fprintf(trace, "\n", gf_4cc_to_str(rtp->subType)); fprintf(trace, "\n", rtp->sdpText); - fprintf(trace, "\n"); + gf_box_dump_done("RTPInfoBox", a, trace); } } - fprintf(trace, "\n"); + gf_box_dump_done("HintTrackInfoBox", NULL, trace); return GF_OK; } @@ -2160,7 +2257,7 @@ GF_Err sdp_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); DumpBox(a, trace); fprintf(trace, "\n", p->sdpText); - fprintf(trace, "\n"); + gf_box_dump_done("SDPBox", a, trace); return GF_OK; } @@ -2171,7 +2268,7 @@ GF_Err rtpo_dump(GF_Box *a, FILE * trace) p = (GF_RTPOBox *)a; fprintf(trace, "\n", p->timeOffset); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("RTPTimeOffsetBox", a, trace); return GF_OK; } @@ -2188,7 +2285,7 @@ GF_Err mvex_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); if (p->mehd) gf_box_dump(p->mehd, trace); gf_box_array_dump(p->TrackExList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MovieExtendsBox", a, trace); return GF_OK; } @@ -2198,7 +2295,7 @@ GF_Err mehd_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", LLD_CAST p->fragment_duration); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MovieExtendsHeaderBox", a, trace); return GF_OK; } @@ -2216,7 +2313,7 @@ GF_Err trex_dump(GF_Box *a, FILE * trace) fprintf(trace, ">\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackExtendsBox", a, trace); return GF_OK; } @@ -2230,7 +2327,7 @@ GF_Err moof_dump(GF_Box *a, FILE * trace) if (p->mfhd) gf_box_dump(p->mfhd, trace); gf_box_array_dump(p->TrackList, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MovieFragmentBox", a, trace); return GF_OK; } @@ -2242,7 +2339,7 @@ GF_Err mfhd_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->sequence_number); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("MovieFragmentHeaderBox", a, trace); return GF_OK; } @@ -2260,7 +2357,8 @@ GF_Err traf_dump(GF_Box *a, FILE * trace) if (p->sampleGroupsDescription) gf_box_array_dump(p->sampleGroupsDescription, trace); if (p->sampleGroups) gf_box_array_dump(p->sampleGroups, trace); gf_box_array_dump(p->TrackRuns, trace); - fprintf(trace, "\n"); + if (p->piff_sample_encryption) gf_box_dump(p->piff_sample_encryption, trace); + gf_box_dump_done("TrackFragmentBox", a, trace); return GF_OK; } @@ -2271,9 +2369,8 @@ GF_Err tfhd_dump(GF_Box *a, FILE * trace) p = (GF_TrackFragmentHeaderBox *)a; fprintf(trace, "trackID); - if (p->flags & GF_ISOM_TRAF_BASE_OFFSET) { - fprintf(trace, " BaseDataOffset=\""LLD"\"", LLD_CAST p->base_data_offset); - } + fprintf(trace, " BaseDataOffset=\"%s\"", (p->flags & GF_ISOM_MOOF_BASE_OFFSET) ? "moof" : ((p->flags & GF_ISOM_TRAF_BASE_OFFSET) ? "traf" : "file") ); + if (p->flags & GF_ISOM_TRAF_SAMPLE_DESC) fprintf(trace, " SampleDescriptionIndex=\"%d\"", p->sample_desc_index); if (p->flags & GF_ISOM_TRAF_SAMPLE_DUR) @@ -2285,11 +2382,12 @@ GF_Err tfhd_dump(GF_Box *a, FILE * trace) fprintf(trace, " SampleSync=\"%d\"", GF_ISOM_GET_FRAG_SYNC(p->def_sample_flags)); fprintf(trace, " SampleDegradationPriority=\"%d\"", GF_ISOM_GET_FRAG_DEG(p->def_sample_flags)); } + fprintf(trace, ">\n"); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackFragmentHeaderBox", a, trace); return GF_OK; } @@ -2333,7 +2431,7 @@ GF_Err trun_dump(GF_Box *a, FILE * trace) } else { fprintf(trace, "\n"); } - fprintf(trace, "\n"); + gf_box_dump_done("TrackRunBox", a, trace); return GF_OK; } @@ -2537,7 +2635,7 @@ static GF_Err gf_isom_dump_ttxt_track(GF_ISOFile *the_file, u32 track, FILE *dum return GF_BAD_PARAM; } - txt = (GF_Tx3gSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, 0); + txt = (GF_Tx3gSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, 0); switch (txt->type) { case GF_ISOM_BOX_TYPE_TX3G: break; @@ -2556,9 +2654,9 @@ static GF_Err gf_isom_dump_ttxt_track(GF_ISOFile *the_file, u32 track, FILE *dum #endif fprintf(dump, "\n", trak->Header->width >> 16 , trak->Header->height >> 16, trak->Header->layer, trak->Header->matrix[6] >> 16, trak->Header->matrix[7] >> 16); - nb_descs = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + nb_descs = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); for (i=0; iMedia->information->sampleTable->SampleDescription->boxList, i); + GF_Tx3gSampleEntryBox *txt = (GF_Tx3gSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, i); fprintf(dump, "horizontal_justification) { @@ -2818,6 +2916,8 @@ static GF_Err gf_isom_dump_srt_track(GF_ISOFile *the_file, u32 track, FILE *dump end = next->DTS; gf_isom_sample_del(&next); } + } else { + end = gf_isom_get_media_duration(the_file, track) ; } cur_frame++; fprintf(dump, "%d\n", cur_frame); @@ -2830,7 +2930,7 @@ static GF_Err gf_isom_dump_srt_track(GF_ISOFile *the_file, u32 track, FILE *dump txt = gf_isom_parse_texte_sample(bs); gf_bs_del(bs); - txtd = (GF_Tx3gSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, di-1); + txtd = (GF_Tx3gSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, di-1); if (!txt->len) { fprintf(dump, "\n"); @@ -3034,7 +3134,7 @@ GF_Err sinf_dump(GF_Box *a, FILE * trace) gf_box_dump(p->original_format, trace); gf_box_dump(p->scheme_type, trace); gf_box_dump(p->info, trace); - fprintf(trace, "\n"); + gf_box_dump_done("ProtectionInfoBox", a, trace); return GF_OK; } @@ -3044,7 +3144,7 @@ GF_Err frma_dump(GF_Box *a, FILE * trace) p = (GF_OriginalFormatBox *)a; fprintf(trace, "\n", gf_4cc_to_str(p->data_format)); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OriginalFormatBox", a, trace); return GF_OK; } @@ -3058,7 +3158,7 @@ GF_Err schm_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("SchemeTypeBox", a, trace); return GF_OK; } @@ -3071,7 +3171,8 @@ GF_Err schi_dump(GF_Box *a, FILE * trace) if (p->ikms) gf_box_dump(p->ikms, trace); if (p->isfm) gf_box_dump(p->isfm, trace); if (p->okms) gf_box_dump(p->okms, trace); - fprintf(trace, "\n"); + if (p->tenc) gf_box_dump(p->tenc, trace); + gf_box_dump_done("SchemeInformationBox", a, trace); return GF_OK; } @@ -3083,7 +3184,7 @@ GF_Err iKMS_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("ISMAKMSBox", a, trace); return GF_OK; } @@ -3097,6 +3198,7 @@ GF_Err iSFM_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); gf_full_box_dump(a, trace); + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", name); return GF_OK; } @@ -3238,7 +3340,7 @@ static GF_Err apple_tag_dump(GF_Box *a, FILE * trace) fprintf(trace, " IsGapeless=\"%s\" ", itune->data->data[0] ? "yes" : "no"); break; default: - if (strcmp(name, "Unknown")) { + if (strcmp(name, "Unknown") && itune->data->data) { if (itune->data && itune->data->data[0]) { fprintf(trace, " value=\"%s\" ", itune->data->data); } else { @@ -3254,10 +3356,121 @@ static GF_Err apple_tag_dump(GF_Box *a, FILE * trace) if (itune->data) gf_full_box_dump((GF_Box *)itune->data, trace); DumpBox(a, trace); + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", name); return GF_OK; } +#ifndef GPAC_DISABLE_ISOM_ADOBE + +GF_Err abst_dump(GF_Box *a, FILE * trace) +{ + u32 i; + GF_AdobeBootstrapInfoBox *p = (GF_AdobeBootstrapInfoBox*)a; + fprintf(trace, "bootstrapinfo_version, p->profile, p->live, p->update, p->time_scale, p->current_media_time, p->smpte_time_code_offset); + if (p->movie_identifier) + fprintf(trace, "MovieIdentifier=\"%s\" ", p->movie_identifier); + if (p->drm_data) + fprintf(trace, "DrmData=\"%s\" ", p->drm_data); + if (p->meta_data) + fprintf(trace, "MetaData=\"%s\" ", p->meta_data); + fprintf(trace, ">\n"); + DumpBox(a, trace); + gf_full_box_dump(a, trace); + + for (i=0; iserver_entry_count; i++) { + char *str = (char*)gf_list_get(p->server_entry_table, i); + fprintf(trace, "%s\n", str); + } + + for (i=0; iquality_entry_count; i++) { + char *str = (char*)gf_list_get(p->quality_entry_table, i); + fprintf(trace, "%s\n", str); + } + + for (i=0; isegment_run_table_count; i++) + gf_box_dump(gf_list_get(p->segment_run_table_entries, i), trace); + + for (i=0; ifragment_run_table_count; i++) + gf_box_dump(gf_list_get(p->fragment_run_table_entries, i), trace); + + gf_box_dump_done("AdobeBootstrapBox", a, trace); + return GF_OK; +} + +GF_Err afra_dump(GF_Box *a, FILE * trace) +{ + u32 i; + GF_AdobeFragRandomAccessBox *p = (GF_AdobeFragRandomAccessBox*)a; + fprintf(trace, "\n", p->long_ids, p->long_offsets, p->time_scale); + DumpBox(a, trace); + gf_full_box_dump(a, trace); + + for (i=0; ientry_count; i++) { + GF_AfraEntry *ae = (GF_AfraEntry *)gf_list_get(p->local_access_entries, i); + fprintf(trace, "\n", ae->time, ae->offset); + } + + for (i=0; iglobal_entry_count; i++) { + GF_GlobalAfraEntry *gae = (GF_GlobalAfraEntry *)gf_list_get(p->global_access_entries, i); + fprintf(trace, "\n", + gae->time, gae->segment, gae->fragment, gae->afra_offset, gae->offset_from_afra); + } + + gf_box_dump_done("AdobeFragmentRandomAccessBox", a, trace); + return GF_OK; +} + +GF_Err afrt_dump(GF_Box *a, FILE * trace) +{ + u32 i; + GF_AdobeFragmentRunTableBox *p = (GF_AdobeFragmentRunTableBox*)a; + fprintf(trace, "\n", p->timescale); + DumpBox(a, trace); + gf_full_box_dump(a, trace); + + for (i=0; iquality_entry_count; i++) { + char *str = (char*)gf_list_get(p->quality_segment_url_modifiers, i); + fprintf(trace, "%s\n", str); + } + + for (i=0; ifragment_run_entry_count; i++) { + GF_AdobeFragmentRunEntry *fre = (GF_AdobeFragmentRunEntry *)gf_list_get(p->fragment_run_entry_table, i); + fprintf(trace, "first_fragment, fre->first_fragment_timestamp, fre->fragment_duration); + if (!fre->fragment_duration) + fprintf(trace, " DiscontinuityIndicator=\"%u\"", fre->discontinuity_indicator); + fprintf(trace, "/>\n"); + } + + gf_box_dump_done("AdobeFragmentRunTableBox", a, trace); + return GF_OK; +} + +GF_Err asrt_dump(GF_Box *a, FILE * trace) +{ + u32 i; + GF_AdobeSegmentRunTableBox *p = (GF_AdobeSegmentRunTableBox*)a; + fprintf(trace, "\n"); + DumpBox(a, trace); + gf_full_box_dump(a, trace); + + for (i=0; iquality_entry_count; i++) { + char *str = (char*)gf_list_get(p->quality_segment_url_modifiers, i); + fprintf(trace, "%s\n", str); + } + + for (i=0; isegment_run_entry_count; i++) { + GF_AdobeSegmentRunEntry *sre = (GF_AdobeSegmentRunEntry *)gf_list_get(p->segment_run_entry_table, i); + fprintf(trace, "\n", sre->first_segment, sre->fragment_per_segment); + } + + gf_box_dump_done("AdobeSegmentRunTableBox", a, trace); + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_ADOBE*/ + GF_Err ilst_dump(GF_Box *a, FILE * trace) { u32 i; @@ -3269,11 +3482,11 @@ GF_Err ilst_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); i=0; - while ( (tag = gf_list_enum(ptr->tags, &i))) { + while ( (tag = gf_list_enum(ptr->other_boxes, &i))) { e = apple_tag_dump(tag, trace); if(e) return e; } - fprintf(trace, "\n"); + gf_box_dump_done("ItemListBox", NULL, trace); return GF_OK; } @@ -3319,8 +3532,7 @@ GF_Err ohdr_dump(GF_Box *a, FILE * trace) fprintf(trace, ">\n"); gf_full_box_dump((GF_Box *)a, trace); - gf_box_array_dump(ptr->ExtendedHeaders, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OMADRMCommonHeaderBox", a, trace); return GF_OK; } GF_Err grpi_dump(GF_Box *a, FILE * trace) @@ -3330,16 +3542,15 @@ GF_Err grpi_dump(GF_Box *a, FILE * trace) DumpData(trace, ptr->GroupKey, ptr->GKLength); fprintf(trace, ">\n"); gf_full_box_dump((GF_Box *)a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OMADRMGroupIDBox", a, trace); return GF_OK; } GF_Err mdri_dump(GF_Box *a, FILE * trace) { - GF_OMADRMMutableInformationBox *ptr = (GF_OMADRMMutableInformationBox*)a; + //GF_OMADRMMutableInformationBox *ptr = (GF_OMADRMMutableInformationBox*)a; fprintf(trace, "\n"); gf_box_dump((GF_Box *)a, trace); - gf_box_array_dump(ptr->boxes, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OMADRMMutableInformationBox", a, trace); return GF_OK; } GF_Err odtt_dump(GF_Box *a, FILE * trace) @@ -3349,7 +3560,7 @@ GF_Err odtt_dump(GF_Box *a, FILE * trace) DumpData(trace, ptr->TransactionID, 16); fprintf(trace, "\">\n"); gf_full_box_dump((GF_Box *)a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OMADRMTransactionTrackingBox", a, trace); return GF_OK; } GF_Err odrb_dump(GF_Box *a, FILE * trace) @@ -3359,7 +3570,7 @@ GF_Err odrb_dump(GF_Box *a, FILE * trace) DumpData(trace, ptr->oma_ro, ptr->oma_ro_size); fprintf(trace, "\">\n"); gf_full_box_dump((GF_Box *)a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OMADRMRightsObjectBox", a, trace); return GF_OK; } GF_Err odkm_dump(GF_Box *a, FILE * trace) @@ -3369,7 +3580,7 @@ GF_Err odkm_dump(GF_Box *a, FILE * trace) gf_full_box_dump((GF_Box *)a, trace); if (ptr->hdr) gf_box_dump((GF_Box *)ptr->hdr, trace); if (ptr->fmt) gf_box_dump((GF_Box *)ptr->fmt, trace); - fprintf(trace, "\n"); + gf_box_dump_done("OMADRMKMSBox", a, trace); return GF_OK; } @@ -3379,7 +3590,7 @@ GF_Err pasp_dump(GF_Box *a, FILE * trace) GF_PixelAspectRatioBox *ptr = (GF_PixelAspectRatioBox*)a; fprintf(trace, "\n", ptr->hSpacing, ptr->vSpacing); DumpBox((GF_Box *)a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("PixelAspectRatioBox", a, trace); return GF_OK; } @@ -3395,7 +3606,7 @@ GF_Err tsel_dump(GF_Box *a, FILE * trace) } fprintf(trace, "\">\n"); gf_full_box_dump((GF_Box *)a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackSelectionBox", a, trace); return GF_OK; } @@ -3416,8 +3627,9 @@ GF_Err metx_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); if (ptr->bitrate) gf_box_dump(ptr->bitrate, trace); - if (ptr->protection_info) gf_box_dump(ptr->protection_info, trace); + gf_box_array_dump(ptr->protections, trace); + gf_box_dump_done(NULL, a, trace); fprintf(trace, "\n", name); return GF_OK; } @@ -3432,8 +3644,8 @@ GF_Err dims_dump(GF_Box *a, FILE * trace) if (p->config) gf_box_dump(p->config, trace); if (p->scripts) gf_box_dump(p->scripts, trace); if (p->bitrate) gf_box_dump(p->bitrate, trace); - if (p->protection_info) gf_box_dump(p->protection_info, trace); - fprintf(trace, "\n"); + gf_box_array_dump(p->protections, trace); + gf_box_dump_done("DIMSSampleEntryBox", a, trace); return GF_OK; } @@ -3443,7 +3655,7 @@ GF_Err diST_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->content_script_types); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("DIMSScriptTypesBox", a, trace); return GF_OK; } GF_Err dimC_dump(GF_Box *a, FILE * trace) @@ -3453,7 +3665,7 @@ GF_Err dimC_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", p->profile, p->level, p->pathComponents, p->fullRequestHost, p->streamType, p->containsRedundant, p->textEncoding, p->contentEncoding); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("DIMSSceneConfigBox", a, trace); return GF_OK; } @@ -3462,22 +3674,43 @@ GF_Err dac3_dump(GF_Box *a, FILE * trace) { GF_AC3ConfigBox *p = (GF_AC3ConfigBox *)a; - fprintf(trace, "\n", - p->cfg.fscod, p->cfg.bsid, p->cfg.bsmod, p->cfg.acmod, p->cfg.lfon, p->cfg.brcode); - DumpBox(a, trace); - fprintf(trace, "\n"); + if (p->cfg.is_ec3) { + u32 i; + fprintf(trace, "\n", p->cfg.nb_streams, p->cfg.brcode); + for (i=0; icfg.nb_streams; i++) { + fprintf(trace, "\n", + p->cfg.streams[i].fscod, p->cfg.streams[i].bsid, p->cfg.streams[i].bsmod, p->cfg.streams[i].acmod, p->cfg.streams[i].lfon, p->cfg.streams[i].nb_dep_sub, p->cfg.streams[i].chan_loc); + } + a->type = GF_ISOM_BOX_TYPE_DEC3; + DumpBox(a, trace); + a->type = GF_ISOM_BOX_TYPE_DAC3; + gf_box_dump_done("EC3SpecificBox", a, trace); + } else { + fprintf(trace, "\n", + p->cfg.streams[0].fscod, p->cfg.streams[0].bsid, p->cfg.streams[0].bsmod, p->cfg.streams[0].acmod, p->cfg.streams[0].lfon, p->cfg.brcode); + DumpBox(a, trace); + gf_box_dump_done("AC3SpecificBox", a, trace); + } return GF_OK; } GF_Err ac3_dump(GF_Box *a, FILE * trace) { GF_AC3SampleEntryBox *p = (GF_AC3SampleEntryBox *)a; - fprintf(trace, "is_ec3) + fprintf(trace, "\n"); + + if (p->is_ec3) + a->type = GF_ISOM_BOX_TYPE_EC3; DumpBox(a, trace); + if (p->is_ec3) + a->type = GF_ISOM_BOX_TYPE_AC3; gf_box_dump(p->info, trace); - fprintf(trace, "\n"); + gf_box_dump_done(p->is_ec3 ? "EC3SampleEntryBox" : "AC3SampleEntryBox", a, trace); return GF_OK; } @@ -3489,19 +3722,19 @@ GF_Err lsrc_dump(GF_Box *a, FILE * trace) dump_data(trace, "LASeRHeader", p->hdr, p->hdr_size); fprintf(trace, ">"); DumpBox(a, trace); - fprintf(trace, ""); + gf_box_dump_done("LASeRConfigurationBox", a, trace); return GF_OK; } GF_Err lsr1_dump(GF_Box *a, FILE * trace) { GF_LASeRSampleEntryBox *p = (GF_LASeRSampleEntryBox*)a; - fprintf(trace, "\n", p->dataReferenceIndex); + fprintf(trace, "\n", p->dataReferenceIndex); DumpBox(a, trace); if (p->lsr_config) gf_box_dump(p->lsr_config, trace); if (p->bitrate) gf_box_dump(p->bitrate, trace); if (p->descr) gf_box_dump(p->descr, trace); - fprintf(trace, "\n"); + gf_box_dump_done("LASeRSampleEntryBox", a, trace); return GF_OK; } @@ -3517,7 +3750,7 @@ GF_Err sidx_dump(GF_Box *a, FILE * trace) for (i=0; inb_refs; i++) { fprintf(trace, "\n", p->refs[i].reference_type, p->refs[i].reference_size, p->refs[i].subsegment_duration, p->refs[i].starts_with_SAP, p->refs[i].SAP_type, p->refs[i].SAP_delta_time); } - fprintf(trace, "\n"); + gf_box_dump_done("SegmentIndexBox", a, trace); return GF_OK; } @@ -3531,7 +3764,7 @@ GF_Err pcrb_dump(GF_Box *a, FILE * trace) for (i=0; isubsegment_count; i++) { fprintf(trace, "\n", p->pcr_values[i]); } - fprintf(trace, "\n"); + gf_box_dump_done("MPEG2TSPCRInfoBox", a, trace); return GF_OK; } @@ -3539,7 +3772,7 @@ GF_Err subs_dump(GF_Box *a, FILE * trace) { u32 entry_count, i, j; u16 subsample_count; - GF_SampleEntry *pSamp; + GF_SubSampleInfoEntry *pSamp; GF_SubSampleEntry *pSubSamp; GF_SubSampleInformationBox *ptr = (GF_SubSampleInformationBox *) a; @@ -3550,7 +3783,7 @@ GF_Err subs_dump(GF_Box *a, FILE * trace) DumpBox(a, trace); for (i=0; iSamples, i); + pSamp = (GF_SubSampleInfoEntry*) gf_list_get(ptr->Samples, i); subsample_count = gf_list_count(pSamp->SubSamples); @@ -3563,7 +3796,7 @@ GF_Err subs_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n"); } - fprintf(trace, "\n"); + gf_box_dump_done("SubSampleInformationBox", a, trace); return GF_OK; } @@ -3576,7 +3809,7 @@ GF_Err tfdt_dump(GF_Box *a, FILE * trace) fprintf(trace, "\n", ptr->baseMediaDecodeTime); DumpBox(a, trace); gf_full_box_dump(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("TrackFragmentBaseMediaDecodeTimeBox", a, trace); return GF_OK; } #endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ @@ -3590,7 +3823,7 @@ GF_Err rvcc_dump(GF_Box *a, FILE * trace) if (! ptr->predefined_rvc_config) fprintf(trace, " rvc_meta_idx=\"%d\"", ptr->rvc_meta_idx); fprintf(trace, ">\n"); DumpBox(a, trace); - fprintf(trace, "\n"); + gf_box_dump_done("RVCConfigurationBox", a, trace); return GF_OK; } @@ -3608,7 +3841,7 @@ GF_Err sbgp_dump(GF_Box *a, FILE * trace) for (i=0; ientry_count; i++) { fprintf(trace, "\n", ptr->sample_entries[i].sample_count, ptr->sample_entries[i].group_description_index ); } - fprintf(trace, "\n"); + gf_box_dump_done("SampleGroupBox", a, trace); return GF_OK; } @@ -3640,7 +3873,172 @@ GF_Err sgpd_dump(GF_Box *a, FILE * trace) fprintf(trace, "\"/>\n"); } } - fprintf(trace, "\n"); + gf_box_dump_done("SampleGroupDescriptionBox", a, trace); + return GF_OK; +} + +GF_Err saiz_dump(GF_Box *a, FILE * trace) +{ + u32 i; + GF_SampleAuxiliaryInfoSizeBox *ptr = (GF_SampleAuxiliaryInfoSizeBox*) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "default_sample_info_size, ptr->sample_count); + if (ptr->flags & 1) fprintf(trace, " aux_info_type=\"%d\" aux_info_type_parameter=\"%d\"", ptr->aux_info_type, ptr->aux_info_type_parameter); + fprintf(trace, ">\n"); + DumpBox(a, trace); + gf_full_box_dump((GF_Box *)a, trace); + if (ptr->default_sample_info_size==0) { + for (i=0; isample_count; i++) { + fprintf(trace, "\n", ptr->sample_info_size[i]); + } + } + gf_box_dump_done("SampleAuxiliaryInfoSizeBox", a, trace); + return GF_OK; +} + +GF_Err saio_dump(GF_Box *a, FILE * trace) +{ + u32 i; + GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox*) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "entry_count); + if (ptr->flags & 1) fprintf(trace, " aux_info_type=\"%d\" aux_info_type_parameter=\"%d\"", ptr->aux_info_type, ptr->aux_info_type_parameter); + fprintf(trace, ">\n"); + DumpBox(a, trace); + gf_full_box_dump((GF_Box *)a, trace); + + if (ptr->single_offset) { + fprintf(trace, "\n", ptr->single_offset); + } else if (ptr->version==0) { + for (i=0; ientry_count; i++) { + fprintf(trace, "\n", ptr->offsets[i]); + } + } else { + for (i=0; ientry_count; i++) { + fprintf(trace, "\n", ptr->offsets_large[i]); + } + } + gf_box_dump_done("SampleAuxiliaryInfoOffsetBox", a, trace); + return GF_OK; +} + +GF_Err pssh_dump(GF_Box *a, FILE * trace) +{ + GF_ProtectionSystemHeaderBox *ptr = (GF_ProtectionSystemHeaderBox*) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "SystemID, 16); + fprintf(trace, "\">\n"); + DumpBox(a, trace); + gf_full_box_dump((GF_Box *)a, trace); + + if (ptr->KID_count) { + u32 i; + for (i=0; iKID_count; i++) { + fprintf(trace, " KIDs[i], 16); + fprintf(trace, "\"/>\n"); + } + } + if (ptr->private_data_size) { + fprintf(trace, " private_data_size); + DumpData(trace, ptr->private_data, ptr->private_data_size); + fprintf(trace, "\"/>\n"); + } + gf_box_dump_done("ProtectionSystemHeaderBox", a, trace); + return GF_OK; +} + +GF_Err tenc_dump(GF_Box *a, FILE * trace) +{ + GF_TrackEncryptionBox *ptr = (GF_TrackEncryptionBox*) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "IsEncrypted, ptr->IV_size); + DumpData(trace, ptr->KID, 16); + fprintf(trace, "\">\n"); + DumpBox(a, trace); + gf_full_box_dump((GF_Box *)a, trace); + gf_box_dump_done("TrackEncryptionBox", a, trace); + return GF_OK; +} + +GF_Err piff_pssh_dump(GF_Box *a, FILE * trace) +{ + GF_PIFFProtectionSystemHeaderBox *ptr = (GF_PIFFProtectionSystemHeaderBox*) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "SystemID, 16); + fprintf(trace, "\" PrivateData=\""); + DumpDataHex(trace, ptr->private_data, ptr->private_data_size); + fprintf(trace, "\">\n"); + DumpBox(a, trace); + fprintf(trace, "\n", ptr->version, ptr->flags); + gf_box_dump_done("PIFFProtectionSystemHeaderBox", a, trace); + return GF_OK; +} + +GF_Err piff_tenc_dump(GF_Box *a, FILE * trace) +{ + GF_PIFFTrackEncryptionBox *ptr = (GF_PIFFTrackEncryptionBox*) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "AlgorithmID, ptr->IV_size); + DumpData(trace, ptr->KID, 16); + fprintf(trace, "\">\n"); + DumpBox(a, trace); + fprintf(trace, "\n", ptr->version, ptr->flags); + gf_box_dump_done("PIFFTrackEncryptionBox", a, trace); + return GF_OK; +} + +GF_Err piff_psec_dump(GF_Box *a, FILE * trace) +{ + u32 IV_size = 0; + GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox *) a; + if (!a) return GF_BAD_PARAM; + + fprintf(trace, "sample_count); + if (ptr->flags & 1) { + fprintf(trace, " default_AlgorithmID=\"%d\" IV_size=\"%d\" KID=\"", ptr->AlgorithmID, ptr->IV_size); + DumpData(trace, ptr->KID, 16); + fprintf(trace, "\""); + IV_size = 0; + } + fprintf(trace, ">\n"); + DumpBox(a, trace); + if (ptr->cenc_data) { + u32 i, j; +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + for (i=0; isample_count; i++) { + GF_CENCSampleInfo *cenc_sample = gf_isom_cenc_get_sample(ptr->traf->trex->track, ptr->traf, i+1); + + if (cenc_sample) { + fprintf(trace, "IV, IV_size); + fprintf(trace, "\" SubsampleCount=\"%d\"", cenc_sample->subsample_count); + if (cenc_sample->is_alt_info) { + fprintf(trace, " AlgorithmID=\"%d\" IV_size=\"%d\" KID=\"", cenc_sample->algo_id, cenc_sample->IV_size); + DumpDataHex(trace, cenc_sample->keyID, 16); + fprintf(trace, "\""); + } + fprintf(trace, ">\n"); + + for (j=0; jsubsample_count; j++) { + fprintf(trace, "\n", cenc_sample->subsamples[j].bytes_clear_data, cenc_sample->subsamples[j].bytes_encrypted_data); + } + fprintf(trace, "\n"); + + gf_isom_cenc_sample_del(cenc_sample); + } + } +#endif // GPAC_DISABLE_ISOM_FRAGMENTS + } + gf_box_dump_done("PIFFSampleEncryptionBox", a, trace); return GF_OK; } diff --git a/src/isomedia/box_funcs.c b/src/isomedia/box_funcs.c index 5af31e2..ac7c774 100644 --- a/src/isomedia/box_funcs.c +++ b/src/isomedia/box_funcs.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -51,10 +52,32 @@ GF_Err gf_isom_parse_root_box(GF_Box **outBox, GF_BitStream *bs, u64 *bytesExpec return ret; } +u32 gf_isom_solve_uuid_box(char *UUID) +{ + u32 i; + char strUUID[33], strChar[3]; + strUUID[0] = 0; + for (i=0; i<16; i++) { + sprintf(strChar, "%02X", (unsigned char) UUID[i]); + strcat(strUUID, strChar); + } + if (!strnicmp(strUUID, "8974dbce7be74c5184f97148f9882554", 32)) + return GF_ISOM_BOX_UUID_TENC; + if (!strnicmp(strUUID, "D4807EF2CA3946958E5426CB9E46A79F", 32)) + return GF_ISOM_BOX_UUID_TFRF; + if (!strnicmp(strUUID, "6D1D9B0542D544E680E2141DAFF757B2", 32)) + return GF_ISOM_BOX_UUID_TFXD; + if (!strnicmp(strUUID, "A2394F525A9B4F14A2446C427C648DF4", 32)) + return GF_ISOM_BOX_UUID_PSEC; + if (!strnicmp(strUUID, "D08A4F1810F34A82B6C832D8ABA183D3", 32)) + return GF_ISOM_BOX_UUID_PSSH; + return 0; +} + GF_Err gf_isom_parse_box_ex(GF_Box **outBox, GF_BitStream *bs, u32 parent_type) { - u32 type, hdr_size; + u32 type, uuid_type, hdr_size; u64 size, start, end; char uuid[16]; GF_Err e; @@ -65,6 +88,7 @@ GF_Err gf_isom_parse_box_ex(GF_Box **outBox, GF_BitStream *bs, u32 parent_type) start = gf_bs_get_position(bs); + uuid_type = 0; size = (u64) gf_bs_read_u32(bs); hdr_size = 4; /*fix for some boxes found in some old hinted files*/ @@ -99,6 +123,7 @@ proceed_box: if (type == GF_ISOM_BOX_TYPE_UUID ) { gf_bs_read_data(bs, uuid, 16); hdr_size += 16; + uuid_type = gf_isom_solve_uuid_box(uuid); } //handle large box @@ -119,12 +144,15 @@ proceed_box: ((GF_TrackReferenceTypeBox*)newBox)->reference_type = type; } else { //OK, create the box based on the type - newBox = gf_isom_box_new(type); + newBox = gf_isom_box_new(uuid_type ? uuid_type : type); if (!newBox) return GF_OUT_OF_MEM; } //OK, init and read this box - if (type==GF_ISOM_BOX_TYPE_UUID) memcpy(((GF_UUIDBox *)newBox)->uuid, uuid, 16); + if (type==GF_ISOM_BOX_TYPE_UUID) { + memcpy(((GF_UUIDBox *)newBox)->uuid, uuid, 16); + ((GF_UnknownUUIDBox *)newBox)->internal_4cc = uuid_type; + } if (!newBox->type) newBox->type = type; @@ -181,6 +209,7 @@ GF_Err gf_isom_full_box_read(GF_Box *ptr, GF_BitStream *bs) return GF_OK; } +/* void gf_isom_full_box_init(GF_Box *a) { GF_FullBox *ptr = (GF_FullBox *)a; @@ -188,19 +217,19 @@ void gf_isom_full_box_init(GF_Box *a) ptr->flags = 0; ptr->version = 0; } +*/ - -void gf_isom_box_array_del(GF_List *boxList) +void gf_isom_box_array_del(GF_List *other_boxes) { u32 count, i; GF_Box *a; - if (!boxList) return; - count = gf_list_count(boxList); + if (!other_boxes) return; + count = gf_list_count(other_boxes); for (i = 0; i < count; i++) { - a = (GF_Box *)gf_list_get(boxList, i); + a = (GF_Box *)gf_list_get(other_boxes, i); if (a) gf_isom_box_del(a); } - gf_list_del(boxList); + gf_list_del(other_boxes); } GF_Err gf_isom_read_box_list_ex(GF_Box *parent, GF_BitStream *bs, GF_Err (*add_box)(GF_Box *par, GF_Box *b), u32 parent_type) @@ -372,6 +401,7 @@ GF_Box *gf_isom_box_new(u32 boxType) case GF_ISOM_BOX_TYPE_STSD: return stsd_New(); case GF_ISOM_BOX_TYPE_STTS: return stts_New(); case GF_ISOM_BOX_TYPE_CTTS: return ctts_New(); + case GF_ISOM_BOX_TYPE_CSLG: return cslg_New(); case GF_ISOM_BOX_TYPE_STSH: return stsh_New(); case GF_ISOM_BOX_TYPE_ELST: return elst_New(); case GF_ISOM_BOX_TYPE_STSC: return stsc_New(); @@ -396,12 +426,16 @@ GF_Box *gf_isom_box_new(u32 boxType) a = ftyp_New(); if (a) a->type = boxType; return a; - case GF_ISOM_BOX_TYPE_FADB: return padb_New(); + case GF_ISOM_BOX_TYPE_PADB: return padb_New(); case GF_ISOM_BOX_TYPE_VOID: return void_New(); case GF_ISOM_BOX_TYPE_STSF: return stsf_New(); case GF_ISOM_BOX_TYPE_PDIN: return pdin_New(); case GF_ISOM_BOX_TYPE_SBGP: return sbgp_New(); case GF_ISOM_BOX_TYPE_SGPD: return sgpd_New(); + case GF_ISOM_BOX_TYPE_SAIZ: return saiz_New(); + case GF_ISOM_BOX_TYPE_SAIO: return saio_New(); + case GF_ISOM_BOX_TYPE_PSSH: return pssh_New(); + case GF_ISOM_BOX_TYPE_TENC: return tenc_New(); #ifndef GPAC_DISABLE_ISOM_HINTING case GF_ISOM_BOX_TYPE_RTP_STSD: @@ -508,7 +542,22 @@ GF_Box *gf_isom_box_new(u32 boxType) case GF_ISOM_BOX_TYPE_ENCA: return enca_New(); case GF_ISOM_BOX_TYPE_ENCV: return encv_New(); case GF_ISOM_BOX_TYPE_ENCS: return encs_New(); - case GF_ISOM_BOX_TYPE_UUID: return uuid_New(); + + case GF_ISOM_BOX_UUID_TENC: return piff_tenc_New(); + case GF_ISOM_BOX_UUID_PSEC: return piff_psec_New(); + case GF_ISOM_BOX_UUID_PSSH: return piff_pssh_New(); + case GF_ISOM_BOX_UUID_TFRF: + case GF_ISOM_BOX_UUID_TFXD: + case GF_ISOM_BOX_TYPE_UUID: + return uuid_New(); + +#ifndef GPAC_DISABLE_ISOM_ADOBE + /* Adobe extensions */ + case GF_ISOM_BOX_TYPE_ABST: return abst_New(); + case GF_ISOM_BOX_TYPE_AFRA: return afra_New(); + case GF_ISOM_BOX_TYPE_ASRT: return asrt_New(); + case GF_ISOM_BOX_TYPE_AFRT: return afrt_New(); +#endif /* Apple extensions */ case GF_ISOM_BOX_TYPE_ILST: return ilst_New(); @@ -561,8 +610,12 @@ GF_Box *gf_isom_box_new(u32 boxType) case GF_ISOM_BOX_TYPE_METT: return metx_New(boxType); - case GF_ISOM_BOX_TYPE_AC3: return ac3_New(); - case GF_ISOM_BOX_TYPE_DAC3: return dac3_New(); + case GF_ISOM_BOX_TYPE_AC3: + case GF_ISOM_BOX_TYPE_EC3: + return ac3_New(boxType); + case GF_ISOM_BOX_TYPE_DAC3: + case GF_ISOM_BOX_TYPE_DEC3: + return dac3_New(boxType); case GF_ISOM_BOX_TYPE_LSRC: return lsrc_New(); case GF_ISOM_BOX_TYPE_LSR1: return lsr1_New(); @@ -582,11 +635,24 @@ GF_Box *gf_isom_box_new(u32 boxType) } } +GF_EXPORT +GF_Err gf_isom_box_add_default(GF_Box *a, GF_Box *subbox) +{ + if (!a->other_boxes) { + a->other_boxes = gf_list_new(); + if (!a->other_boxes) return GF_OUT_OF_MEM; + } + return gf_list_add(a->other_boxes, subbox); +} GF_EXPORT void gf_isom_box_del(GF_Box *a) { if (!a) return; + if (a->other_boxes) { + gf_isom_box_array_del(a->other_boxes); + a->other_boxes = NULL; + } switch (a->type) { case GF_ISOM_BOX_TYPE_REFT: reftype_del(a); @@ -632,6 +698,7 @@ void gf_isom_box_del(GF_Box *a) case GF_ISOM_BOX_TYPE_STSD: stsd_del(a); return; case GF_ISOM_BOX_TYPE_STTS: stts_del(a); return; case GF_ISOM_BOX_TYPE_CTTS: ctts_del(a); return; + case GF_ISOM_BOX_TYPE_CSLG: cslg_del(a); return; case GF_ISOM_BOX_TYPE_STSH: stsh_del(a); return; case GF_ISOM_BOX_TYPE_ELST: elst_del(a); return; case GF_ISOM_BOX_TYPE_STSC: stsc_del(a); return; @@ -653,12 +720,16 @@ void gf_isom_box_del(GF_Box *a) case GF_ISOM_BOX_TYPE_STYP: ftyp_del(a); return; - case GF_ISOM_BOX_TYPE_FADB: padb_del(a); return; + case GF_ISOM_BOX_TYPE_PADB: padb_del(a); return; case GF_ISOM_BOX_TYPE_VOID: void_del(a); return; case GF_ISOM_BOX_TYPE_STSF: stsf_del(a); return; case GF_ISOM_BOX_TYPE_PDIN: pdin_del(a); return; case GF_ISOM_BOX_TYPE_SBGP: sbgp_del(a); return; case GF_ISOM_BOX_TYPE_SGPD: sgpd_del(a); return; + case GF_ISOM_BOX_TYPE_SAIZ: saiz_del(a); return; + case GF_ISOM_BOX_TYPE_SAIO: saio_del(a); return; + case GF_ISOM_BOX_TYPE_PSSH: pssh_del(a); return; + case GF_ISOM_BOX_TYPE_TENC: tenc_del(a); return; #ifndef GPAC_DISABLE_ISOM_HINTING @@ -762,13 +833,39 @@ void gf_isom_box_del(GF_Box *a) case GF_ISOM_BOX_TYPE_ENCA: case GF_ISOM_BOX_TYPE_ENCV: case GF_ISOM_BOX_TYPE_ENCS: - a->type = ((GF_SampleEntryBox *)a)->protection_info->original_format->data_format; - gf_isom_box_del(a); + { + GF_ProtectionInfoBox *sinf = gf_list_get(((GF_SampleEntryBox *)a)->protections, 0); + a->type = sinf->original_format->data_format; + gf_isom_box_del(a); + } return; case GF_ISOM_BOX_TYPE_UUID: - uuid_del(a); + switch (((GF_UnknownUUIDBox *)a)->internal_4cc) { + case GF_ISOM_BOX_UUID_TENC: + piff_tenc_del(a); + return; + case GF_ISOM_BOX_UUID_PSEC: + piff_psec_del(a); + return; + case GF_ISOM_BOX_UUID_PSSH: + piff_pssh_del(a); + return; + case GF_ISOM_BOX_UUID_TFRF: + case GF_ISOM_BOX_UUID_TFXD: + default: + uuid_del(a); + return; + } return; +#ifndef GPAC_DISABLE_ISOM_ADOBE + /* Adobe extensions */ + case GF_ISOM_BOX_TYPE_ABST: abst_del(a); return; + case GF_ISOM_BOX_TYPE_AFRA: afra_del(a); return; + case GF_ISOM_BOX_TYPE_ASRT: asrt_del(a); return; + case GF_ISOM_BOX_TYPE_AFRT: afrt_del(a); return; +#endif + /* Apple extensions */ case GF_ISOM_BOX_TYPE_ILST: ilst_del(a); return; @@ -874,6 +971,7 @@ GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_STSD: return stsd_Read(a, bs); case GF_ISOM_BOX_TYPE_STTS: return stts_Read(a, bs); case GF_ISOM_BOX_TYPE_CTTS: return ctts_Read(a, bs); + case GF_ISOM_BOX_TYPE_CSLG: return cslg_Read(a, bs); case GF_ISOM_BOX_TYPE_STSH: return stsh_Read(a, bs); case GF_ISOM_BOX_TYPE_ELST: return elst_Read(a, bs); case GF_ISOM_BOX_TYPE_STSC: return stsc_Read(a, bs); @@ -894,12 +992,16 @@ GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_STYP: return ftyp_Read(a, bs); - case GF_ISOM_BOX_TYPE_FADB: return padb_Read(a, bs); + case GF_ISOM_BOX_TYPE_PADB: return padb_Read(a, bs); case GF_ISOM_BOX_TYPE_VOID: return void_Read(a, bs); case GF_ISOM_BOX_TYPE_STSF: return stsf_Read(a, bs); case GF_ISOM_BOX_TYPE_PDIN: return pdin_Read(a, bs); case GF_ISOM_BOX_TYPE_SBGP: return sbgp_Read(a, bs); case GF_ISOM_BOX_TYPE_SGPD: return sgpd_Read(a, bs); + case GF_ISOM_BOX_TYPE_SAIZ: return saiz_Read(a, bs); + case GF_ISOM_BOX_TYPE_SAIO: return saio_Read(a, bs); + case GF_ISOM_BOX_TYPE_PSSH: return pssh_Read(a, bs); + case GF_ISOM_BOX_TYPE_TENC: return tenc_Read(a, bs); #ifndef GPAC_DISABLE_ISOM_HINTING case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_Read(a, bs); @@ -1001,8 +1103,25 @@ GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_ENCA: return mp4a_Read(a, bs); case GF_ISOM_BOX_TYPE_ENCV: return mp4v_Read(a, bs); case GF_ISOM_BOX_TYPE_ENCS: return mp4s_Read(a, bs); - case GF_ISOM_BOX_TYPE_UUID: return uuid_Read(a, bs); - + case GF_ISOM_BOX_TYPE_UUID: + switch (((GF_UnknownUUIDBox *)a)->internal_4cc) { + case GF_ISOM_BOX_UUID_TENC: return piff_tenc_Read(a, bs); + case GF_ISOM_BOX_UUID_PSEC: return piff_psec_Read(a, bs); + case GF_ISOM_BOX_UUID_PSSH: return piff_pssh_Read(a, bs); + case GF_ISOM_BOX_UUID_TFRF: + case GF_ISOM_BOX_UUID_TFXD: + default: + return uuid_Read(a, bs); + } + +#ifndef GPAC_DISABLE_ISOM_ADOBE + /* Adobe extensions */ + case GF_ISOM_BOX_TYPE_ABST: return abst_Read(a, bs); + case GF_ISOM_BOX_TYPE_AFRA: return afra_Read(a, bs); + case GF_ISOM_BOX_TYPE_ASRT: return asrt_Read(a, bs); + case GF_ISOM_BOX_TYPE_AFRT: return afrt_Read(a, bs); +#endif + /* Apple extensions */ case GF_ISOM_BOX_TYPE_ILST: return ilst_Read(a, bs); @@ -1069,8 +1188,7 @@ GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs) #ifndef GPAC_DISABLE_ISOM_WRITE -GF_EXPORT -GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs) +GF_Err gf_isom_box_write_listing(GF_Box *a, GF_BitStream *bs) { switch (a->type) { case GF_ISOM_BOX_TYPE_REFT: @@ -1111,6 +1229,7 @@ GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_STSD: return stsd_Write(a, bs); case GF_ISOM_BOX_TYPE_STTS: return stts_Write(a, bs); case GF_ISOM_BOX_TYPE_CTTS: return ctts_Write(a, bs); + case GF_ISOM_BOX_TYPE_CSLG: return cslg_Write(a, bs); case GF_ISOM_BOX_TYPE_STSH: return stsh_Write(a, bs); case GF_ISOM_BOX_TYPE_ELST: return elst_Write(a, bs); case GF_ISOM_BOX_TYPE_STSC: return stsc_Write(a, bs); @@ -1130,12 +1249,16 @@ GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_STYP: return ftyp_Write(a, bs); - case GF_ISOM_BOX_TYPE_FADB: return padb_Write(a, bs); + case GF_ISOM_BOX_TYPE_PADB: return padb_Write(a, bs); case GF_ISOM_BOX_TYPE_VOID: return void_Write(a, bs); case GF_ISOM_BOX_TYPE_STSF: return stsf_Write(a, bs); case GF_ISOM_BOX_TYPE_PDIN: return pdin_Write(a, bs); case GF_ISOM_BOX_TYPE_SBGP: return sbgp_Write(a, bs); case GF_ISOM_BOX_TYPE_SGPD: return sgpd_Write(a, bs); + case GF_ISOM_BOX_TYPE_SAIZ: return saiz_Write(a, bs); + case GF_ISOM_BOX_TYPE_SAIO: return saio_Write(a, bs); + case GF_ISOM_BOX_TYPE_PSSH: return pssh_Write(a, bs); + case GF_ISOM_BOX_TYPE_TENC: return tenc_Write(a, bs); #ifndef GPAC_DISABLE_ISOM_HINTING case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_Write(a, bs); @@ -1237,7 +1360,24 @@ GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_ENCA: return mp4a_Write(a, bs); case GF_ISOM_BOX_TYPE_ENCV: return mp4v_Write(a, bs); case GF_ISOM_BOX_TYPE_ENCS: return mp4s_Write(a, bs); - case GF_ISOM_BOX_TYPE_UUID: return uuid_Write(a, bs); + case GF_ISOM_BOX_TYPE_UUID: + switch ( ((GF_UnknownUUIDBox *)a)->internal_4cc) { + case GF_ISOM_BOX_UUID_TENC: return piff_tenc_Write(a, bs); + case GF_ISOM_BOX_UUID_PSEC: return piff_psec_Write(a, bs); + case GF_ISOM_BOX_UUID_PSSH: return piff_pssh_Write(a, bs); + case GF_ISOM_BOX_UUID_TFRF: + case GF_ISOM_BOX_UUID_TFXD: + default: + return uuid_Write(a, bs); + } + +#ifndef GPAC_DISABLE_ISOM_ADOBE + /* Adobe extensions */ + case GF_ISOM_BOX_TYPE_ABST: return abst_Write(a, bs); + case GF_ISOM_BOX_TYPE_AFRA: return afra_Write(a, bs); + case GF_ISOM_BOX_TYPE_ASRT: return asrt_Write(a, bs); + case GF_ISOM_BOX_TYPE_AFRT: return afrt_Write(a, bs); +#endif /* Apple extensions */ case GF_ISOM_BOX_TYPE_ILST: return ilst_Write(a, bs); @@ -1303,9 +1443,18 @@ GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs) } } - GF_EXPORT -GF_Err gf_isom_box_size(GF_Box *a) +GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs) +{ + GF_Err e = gf_isom_box_write_listing(a, bs); + if (e) return e; + if (a->other_boxes) { + return gf_isom_box_array_write(a, a->other_boxes, bs); + } + return GF_OK; +} + +static GF_Err gf_isom_box_size_listing(GF_Box *a) { switch (a->type) { case GF_ISOM_BOX_TYPE_REFT: @@ -1346,6 +1495,7 @@ GF_Err gf_isom_box_size(GF_Box *a) case GF_ISOM_BOX_TYPE_STSD: return stsd_Size(a); case GF_ISOM_BOX_TYPE_STTS: return stts_Size(a); case GF_ISOM_BOX_TYPE_CTTS: return ctts_Size(a); + case GF_ISOM_BOX_TYPE_CSLG: return cslg_Size(a); case GF_ISOM_BOX_TYPE_STSH: return stsh_Size(a); case GF_ISOM_BOX_TYPE_ELST: return elst_Size(a); case GF_ISOM_BOX_TYPE_STSC: return stsc_Size(a); @@ -1364,12 +1514,16 @@ GF_Err gf_isom_box_size(GF_Box *a) case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_STYP: return ftyp_Size(a); - case GF_ISOM_BOX_TYPE_FADB: return padb_Size(a); + case GF_ISOM_BOX_TYPE_PADB: return padb_Size(a); case GF_ISOM_BOX_TYPE_VOID: return void_Size(a); case GF_ISOM_BOX_TYPE_STSF: return stsf_Size(a); case GF_ISOM_BOX_TYPE_PDIN: return pdin_Size(a); case GF_ISOM_BOX_TYPE_SBGP: return sbgp_Size(a); case GF_ISOM_BOX_TYPE_SGPD: return sgpd_Size(a); + case GF_ISOM_BOX_TYPE_SAIZ: return saiz_Size(a); + case GF_ISOM_BOX_TYPE_SAIO: return saio_Size(a); + case GF_ISOM_BOX_TYPE_PSSH: return pssh_Size(a); + case GF_ISOM_BOX_TYPE_TENC: return tenc_Size(a); #ifndef GPAC_DISABLE_ISOM_HINTING case GF_ISOM_BOX_TYPE_RTP_STSD: return ghnt_Size(a); @@ -1471,7 +1625,24 @@ GF_Err gf_isom_box_size(GF_Box *a) case GF_ISOM_BOX_TYPE_ENCA: return mp4a_Size(a); case GF_ISOM_BOX_TYPE_ENCV: return mp4v_Size(a); case GF_ISOM_BOX_TYPE_ENCS: return mp4s_Size(a); - case GF_ISOM_BOX_TYPE_UUID: return uuid_Size(a); + case GF_ISOM_BOX_TYPE_UUID: + switch ( ((GF_UnknownUUIDBox *)a)->internal_4cc) { + case GF_ISOM_BOX_UUID_TENC: return piff_tenc_Size(a); + case GF_ISOM_BOX_UUID_PSEC: return piff_psec_Size(a); + case GF_ISOM_BOX_UUID_PSSH: return piff_pssh_Size(a); + case GF_ISOM_BOX_UUID_TFRF: + case GF_ISOM_BOX_UUID_TFXD: + default: + return uuid_Size(a); + } + +#ifndef GPAC_DISABLE_ISOM_ADOBE + /* Adobe extensions */ + case GF_ISOM_BOX_TYPE_ABST: return abst_Size(a); + case GF_ISOM_BOX_TYPE_AFRA: return afra_Size(a); + case GF_ISOM_BOX_TYPE_ASRT: return asrt_Size(a); + case GF_ISOM_BOX_TYPE_AFRT: return afrt_Size(a); +#endif /* Apple extensions */ case GF_ISOM_BOX_TYPE_ILST: return ilst_Size(a); @@ -1536,6 +1707,18 @@ GF_Err gf_isom_box_size(GF_Box *a) } } +GF_EXPORT +GF_Err gf_isom_box_size(GF_Box *a) +{ + GF_Err e = gf_isom_box_size_listing(a); + if (e) return e; + if (a->other_boxes) { + e = gf_isom_box_array_size(a, a->other_boxes); + if (e) return e; + } + return GF_OK; +} + #endif /*GPAC_DISABLE_ISOM_WRITE*/ #endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/data_map.c b/src/isomedia/data_map.c index ed3e29b..68bc03c 100644 --- a/src/isomedia/data_map.c +++ b/src/isomedia/data_map.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -27,6 +28,21 @@ #ifndef GPAC_DISABLE_ISOM + +static u32 default_write_buffering_size = 0; + +GF_EXPORT +GF_Err gf_isom_set_output_buffering(GF_ISOFile *movie, u32 size) +{ + if (!movie) { + default_write_buffering_size = size; + return GF_OK; + } + if (!movie->editFileMap) return GF_BAD_PARAM; + return gf_bs_set_output_buffering(movie->editFileMap->bs, size); +} + + void gf_isom_datamap_del(GF_DataMap *ptr) { if (!ptr) return; @@ -52,7 +68,7 @@ void gf_isom_datamap_close(GF_MediaInformationBox *minf) GF_DataEntryBox *ent; if (!minf || !minf->dataHandler) return; - ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->boxList, minf->dataEntryIndex - 1); + ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->other_boxes, minf->dataEntryIndex - 1); //if ent NULL, the data entry was not used (should never happen) if (ent == NULL) return; @@ -166,10 +182,10 @@ GF_Err gf_isom_datamap_open(GF_MediaBox *mdia, u32 dataRefIndex, u8 Edit) minf = mdia->information; - if (dataRefIndex > gf_list_count(minf->dataInformation->dref->boxList)) + if (dataRefIndex > gf_list_count(minf->dataInformation->dref->other_boxes)) return GF_BAD_PARAM; - ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->boxList, dataRefIndex - 1); + ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->other_boxes, dataRefIndex - 1); if (ent == NULL) return GF_ISOM_INVALID_MEDIA; //if the current dataEntry is the desired one, and not self contained, return @@ -296,6 +312,11 @@ GF_DataMap *gf_isom_fdm_new_temp(const char *sPath) gf_free(tmp); return NULL; } + + if (default_write_buffering_size) { + gf_bs_set_output_buffering(tmp->bs, default_write_buffering_size); + } + return (GF_DataMap *)tmp; } @@ -327,12 +348,22 @@ GF_DataMap *gf_isom_fdm_new(const char *sPath, u8 mode) break; ///we open the file in READ/WRITE mode, in case case GF_ISOM_DATA_MAP_WRITE: + if (!strcmp(sPath, "std")) { + tmp->stream = stdout; + tmp->is_stdout = 1; + } + if (!tmp->stream) tmp->stream = gf_f64_open(sPath, "w+b"); if (!tmp->stream) tmp->stream = gf_f64_open(sPath, "wb"); bs_mode = GF_BITSTREAM_WRITE; break; ///we open the file in CAT mode, in case case GF_ISOM_DATA_MAP_CAT: + if (!strcmp(sPath, "std")) { + tmp->stream = stdout; + tmp->is_stdout = 1; + } + if (!tmp->stream) tmp->stream = gf_f64_open(sPath, "a+b"); if (tmp->stream) gf_f64_seek(tmp->stream, 0, SEEK_END); bs_mode = GF_BITSTREAM_WRITE; @@ -351,6 +382,9 @@ GF_DataMap *gf_isom_fdm_new(const char *sPath, u8 mode) gf_free(tmp); return NULL; } + if (default_write_buffering_size) { + gf_bs_set_output_buffering(tmp->bs, default_write_buffering_size); + } return (GF_DataMap *)tmp; } @@ -358,7 +392,7 @@ void gf_isom_fdm_del(GF_FileDataMap *ptr) { if (!ptr || (ptr->type != GF_ISOM_DATA_FILE)) return; if (ptr->bs) gf_bs_del(ptr->bs); - if (ptr->stream) fclose(ptr->stream); + if (ptr->stream && !ptr->is_stdout) fclose(ptr->stream); #ifndef GPAC_DISABLE_ISOM_WRITE if (ptr->temp_file) { diff --git a/src/isomedia/drm_sample.c b/src/isomedia/drm_sample.c new file mode 100644 index 0000000..f94ed33 --- /dev/null +++ b/src/isomedia/drm_sample.c @@ -0,0 +1,609 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Cyril Concolato / Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 + * All rights reserved + * + * This file is part of GPAC / ISO Media File Format sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +#ifndef GPAC_DISABLE_ISOM + +GF_ISMASample *gf_isom_ismacryp_new_sample() +{ + GF_ISMASample *tmp = (GF_ISMASample *) gf_malloc(sizeof(GF_ISMASample)); + if (!tmp) return NULL; + memset(tmp, 0, sizeof(GF_ISMASample)); + return tmp; +} +GF_EXPORT +void gf_isom_ismacryp_delete_sample(GF_ISMASample *samp) +{ + if (!samp) return; + if (samp->data && samp->dataLength) gf_free(samp->data); + if (samp->key_indicator) gf_free(samp->key_indicator); + gf_free(samp); +} + + +GF_ISMASample *gf_isom_ismacryp_sample_from_data(char *data, u32 dataLength, Bool use_selective_encryption, u8 KI_length, u8 IV_length) +{ + GF_ISMASample *s; + GF_BitStream *bs; + /*empty text sample*/ + if (!data || !dataLength) { + return gf_isom_ismacryp_new_sample(); + } + + s = gf_isom_ismacryp_new_sample(); + + /*empty sample*/ + if (!data || !dataLength) return s; + + bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); + + s->dataLength = dataLength; + s->IV_length = IV_length; + s->KI_length = KI_length; + + if (use_selective_encryption) { + s->flags = GF_ISOM_ISMA_USE_SEL_ENC; + if (s->dataLength < 1) goto exit; + if (gf_bs_read_int(bs, 1)) s->flags |= GF_ISOM_ISMA_IS_ENCRYPTED; + gf_bs_read_int(bs, 7); + s->dataLength -= 1; + } else { + s->flags = GF_ISOM_ISMA_IS_ENCRYPTED; + } + if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) { + if (IV_length != 0) { + if (s->dataLength < IV_length) goto exit; + s->IV = gf_bs_read_long_int(bs, 8*IV_length); + s->dataLength -= IV_length; + } + if (KI_length) { + if (s->dataLength < KI_length) goto exit; + s->key_indicator = (u8 *)gf_malloc(KI_length); + gf_bs_read_data(bs, (char*)s->key_indicator, KI_length); + s->dataLength -= KI_length; + } + } + s->data = (char*)gf_malloc(sizeof(char)*s->dataLength); + gf_bs_read_data(bs, s->data, s->dataLength); + gf_bs_del(bs); + return s; + +exit: + gf_isom_ismacryp_delete_sample(s); + return NULL; +} + +GF_Err gf_isom_ismacryp_sample_to_sample(GF_ISMASample *s, GF_ISOSample *dest) +{ + GF_BitStream *bs; + if (!s || !dest) return GF_BAD_PARAM; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + + if (s->flags & GF_ISOM_ISMA_USE_SEL_ENC) { + gf_bs_write_int(bs, (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) ? 1 : 0, 1); + gf_bs_write_int(bs, 0, 7); + } + if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) { + if (s->IV_length) gf_bs_write_long_int(bs, (s64) s->IV, 8*s->IV_length); + if (s->KI_length) gf_bs_write_data(bs, (char*)s->key_indicator, s->KI_length); + } + gf_bs_write_data(bs, s->data, s->dataLength); + if (dest->data) gf_free(dest->data); + dest->data = NULL; + dest->dataLength = 0; + gf_bs_get_content(bs, &dest->data, &dest->dataLength); + gf_bs_del(bs); + return GF_OK; +} + +static GF_ProtectionInfoBox *gf_isom_get_sinf_entry(GF_TrackBox *trak, u32 sampleDescriptionIndex, u32 scheme_type, GF_SampleEntryBox **out_sea) +{ + u32 i=0; + GF_SampleEntryBox *sea; + GF_ProtectionInfoBox *sinf; + + Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); + if (!sea) return NULL; + + i = 0; + while ((sinf = gf_list_enum(sea->protections, &i))) { + if (sinf->original_format && sinf->scheme_type && sinf->info) { + if (!scheme_type || (sinf->scheme_type->scheme_type == scheme_type)) { + if (out_sea) + *out_sea = sea; + return sinf; + } + } + } + return NULL; +} + +GF_EXPORT +GF_ISMASample *gf_isom_get_ismacryp_sample(GF_ISOFile *the_file, u32 trackNumber, GF_ISOSample *samp, u32 sampleDescriptionIndex) +{ + GF_TrackBox *trak; + GF_ISMASampleFormatBox *fmt; + GF_ProtectionInfoBox *sinf; + + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return NULL; + + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, 0, NULL); + if (!sinf) return NULL; + + /*ISMA*/ + if (sinf->scheme_type->scheme_type == GF_ISOM_ISMACRYP_SCHEME) { + fmt = sinf->info->isfm; + if (!fmt) return NULL; + return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, sinf->info->isfm->selective_encryption, sinf->info->isfm->key_indicator_length, sinf->info->isfm->IV_length); + } + /*OMA*/ + else if (sinf->scheme_type->scheme_type == GF_4CC('o','d','k','m') ) { + if (!sinf->info->okms) return NULL; + fmt = sinf->info->okms->fmt; + + if (fmt) { + return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, fmt->selective_encryption, fmt->key_indicator_length, fmt->IV_length); + } + /*OMA default: no selective encryption, one key, 128 bit IV*/ + return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, 0, 0, 128); + } + return NULL; +} + + +GF_EXPORT +u32 gf_isom_is_media_encrypted(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) +{ + GF_TrackBox *trak; + GF_ProtectionInfoBox *sinf; + + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return 0; + + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, 0, NULL); + if (!sinf) return 0; + + /*non-encrypted or non-ISMA*/ + if (!sinf || !sinf->scheme_type) return 0; + return sinf->scheme_type->scheme_type; +} + +GF_EXPORT +Bool gf_isom_is_ismacryp_media(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) +{ + GF_TrackBox *trak; + GF_ProtectionInfoBox *sinf; + + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return 0; + + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ISMACRYP_SCHEME, NULL); + if (!sinf) return 0; + + /*non-encrypted or non-ISMA*/ + if (!sinf->info || !sinf->info->ikms || !sinf->info->isfm ) + return 0; + + return 1; +} + +GF_EXPORT +Bool gf_isom_is_omadrm_media(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) +{ + GF_TrackBox *trak; + GF_ProtectionInfoBox *sinf; + + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return 0; + + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_OMADRM_SCHEME, NULL); + if (!sinf) return 0; + + /*non-encrypted or non-OMA*/ + if (!sinf->info || !sinf->info->okms || !sinf->info->okms->hdr) + return 0; + + return 1; +} + +/*retrieves ISMACryp info for the given track & SDI*/ +GF_EXPORT +GF_Err gf_isom_get_ismacryp_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 *outOriginalFormat, u32 *outSchemeType, u32 *outSchemeVersion, const char **outSchemeURI, const char **outKMS_URI, Bool *outSelectiveEncryption, u32 *outIVLength, u32 *outKeyIndicationLength) +{ + GF_TrackBox *trak; + GF_ProtectionInfoBox *sinf; + + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return GF_BAD_PARAM; + + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ISMACRYP_SCHEME, NULL); + if (!sinf) return 0; + + if (outOriginalFormat) { + *outOriginalFormat = sinf->original_format->data_format; + if (IsMP4Description(sinf->original_format->data_format)) *outOriginalFormat = GF_ISOM_SUBTYPE_MPEG4; + } + if (outSchemeType) *outSchemeType = sinf->scheme_type->scheme_type; + if (outSchemeVersion) *outSchemeVersion = sinf->scheme_type->scheme_version; + if (outSchemeURI) *outSchemeURI = sinf->scheme_type->URI; + + if (sinf->info && sinf->info->ikms) { + if (outKMS_URI) *outKMS_URI = sinf->info->ikms->URI; + } else { + if (outKMS_URI) *outKMS_URI = NULL; + } + if (sinf->info && sinf->info->isfm) { + if (outSelectiveEncryption) *outSelectiveEncryption = sinf->info->isfm->selective_encryption; + if (outIVLength) *outIVLength = sinf->info->isfm->IV_length; + if (outKeyIndicationLength) *outKeyIndicationLength = sinf->info->isfm->key_indicator_length; + } else { + if (outSelectiveEncryption) *outSelectiveEncryption = 0; + if (outIVLength) *outIVLength = 0; + if (outKeyIndicationLength) *outKeyIndicationLength = 0; + } + return GF_OK; +} + + +/*retrieves ISMACryp info for the given track & SDI*/ +GF_EXPORT +GF_Err gf_isom_get_omadrm_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 *outOriginalFormat, + u32 *outSchemeType, u32 *outSchemeVersion, + const char **outContentID, const char **outRightsIssuerURL, const char **outTextualHeaders, u32 *outTextualHeadersLen, u64 *outPlaintextLength, u32 *outEncryptionType, Bool *outSelectiveEncryption, u32 *outIVLength, u32 *outKeyIndicationLength) +{ + GF_TrackBox *trak; + GF_ProtectionInfoBox *sinf; + + trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return GF_BAD_PARAM; + + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_OMADRM_SCHEME, NULL); + if (!sinf) return 0; + + if (!sinf->info || !sinf->info->okms || !sinf->info->okms->hdr) return GF_NON_COMPLIANT_BITSTREAM; + + if (outOriginalFormat) { + *outOriginalFormat = sinf->original_format->data_format; + if (IsMP4Description(sinf->original_format->data_format)) *outOriginalFormat = GF_ISOM_SUBTYPE_MPEG4; + } + if (outSchemeType) *outSchemeType = sinf->scheme_type->scheme_type; + if (outSchemeVersion) *outSchemeVersion = sinf->scheme_type->scheme_version; + if (outContentID) *outContentID = sinf->info->okms->hdr->ContentID; + if (outRightsIssuerURL) *outRightsIssuerURL = sinf->info->okms->hdr->RightsIssuerURL; + if (outTextualHeaders) { + *outTextualHeaders = sinf->info->okms->hdr->TextualHeaders; + if (outTextualHeadersLen) *outTextualHeadersLen = sinf->info->okms->hdr->TextualHeadersLen; + } + if (outPlaintextLength) *outPlaintextLength = sinf->info->okms->hdr->PlaintextLength; + if (outEncryptionType) *outEncryptionType = sinf->info->okms->hdr->EncryptionMethod; + + if (sinf->info && sinf->info->okms && sinf->info->okms->fmt) { + if (outSelectiveEncryption) *outSelectiveEncryption = sinf->info->okms->fmt->selective_encryption; + if (outIVLength) *outIVLength = sinf->info->okms->fmt->IV_length; + if (outKeyIndicationLength) *outKeyIndicationLength = sinf->info->okms->fmt->key_indicator_length; + } else { + if (outSelectiveEncryption) *outSelectiveEncryption = 0; + if (outIVLength) *outIVLength = 0; + if (outKeyIndicationLength) *outKeyIndicationLength = 0; + } + return GF_OK; +} + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err gf_isom_remove_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) +{ + GF_TrackBox *trak; + GF_Err e; + GF_SampleEntryBox *sea; + GF_ProtectionInfoBox *sinf; + + 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 || !sampleDescriptionIndex) return GF_BAD_PARAM; + + sea = NULL; + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ISMACRYP_SCHEME, &sea); + if (!sinf) return 0; + + sea->type = sinf->original_format->data_format; + 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; + return GF_OK; +} + +GF_EXPORT +GF_Err gf_isom_change_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, char *scheme_uri, char *kms_uri) +{ + GF_TrackBox *trak; + GF_Err e; + GF_SampleEntryBox *sea; + GF_ProtectionInfoBox *sinf; + + 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 || !sampleDescriptionIndex) return GF_BAD_PARAM; + + sea = NULL; + sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ISMACRYP_SCHEME, &sea); + if (!sinf) return 0; + + if (scheme_uri) { + gf_free(sinf->scheme_type->URI); + sinf->scheme_type->URI = gf_strdup(scheme_uri); + } + if (kms_uri) { + gf_free(sinf->info->ikms->URI); + sinf->info->ikms->URI = gf_strdup(kms_uri); + } + return GF_OK; +} + + +GF_Err gf_isom_set_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 desc_index, u32 scheme_type, + u32 scheme_version, char *scheme_uri, char *kms_URI, + Bool selective_encryption, u32 KI_length, u32 IV_length) +{ + u32 original_format; + GF_Err e; + GF_SampleEntryBox *sea; + GF_ProtectionInfoBox *sinf; + GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return GF_BAD_PARAM; + + e = Media_GetSampleDesc(trak->Media, desc_index, &sea, NULL); + if (e) return e; + + /* Replacing the Media Type */ + switch (sea->type) { + case GF_ISOM_BOX_TYPE_MP4A: + case GF_ISOM_BOX_TYPE_DAMR: + case GF_ISOM_BOX_TYPE_DEVC: + case GF_ISOM_BOX_TYPE_DQCP: + case GF_ISOM_BOX_TYPE_DSMV: + case GF_ISOM_BOX_TYPE_AC3: + original_format = sea->type; + sea->type = GF_ISOM_BOX_TYPE_ENCA; + break; + case GF_ISOM_BOX_TYPE_MP4V: + case GF_ISOM_BOX_TYPE_D263: + original_format = sea->type; + sea->type = GF_ISOM_BOX_TYPE_ENCV; + break; + /*special case for AVC1*/ + case GF_ISOM_BOX_TYPE_AVC1: + case GF_ISOM_BOX_TYPE_AVC2: + 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_MP4S: + case GF_ISOM_BOX_TYPE_LSR1: + original_format = sea->type; + sea->type = GF_ISOM_BOX_TYPE_ENCS; + break; + default: + return GF_BAD_PARAM; + } + + sinf = (GF_ProtectionInfoBox *)sinf_New(); + gf_list_add(sea->protections, sinf); + + sinf->scheme_type = (GF_SchemeTypeBox *)schm_New(); + sinf->scheme_type->scheme_type = scheme_type; + sinf->scheme_type->scheme_version = scheme_version; + if (scheme_uri) { + sinf->scheme_type->flags |= 0x000001; + sinf->scheme_type->URI = gf_strdup(scheme_uri); + } + sinf->original_format = (GF_OriginalFormatBox *)frma_New(); + sinf->original_format->data_format = original_format; + sinf->info = (GF_SchemeInformationBox *)schi_New(); + + sinf->info->ikms = (GF_ISMAKMSBox *)iKMS_New(); + sinf->info->ikms->URI = gf_strdup(kms_URI); + + sinf->info->isfm = (GF_ISMASampleFormatBox *)iSFM_New(); + sinf->info->isfm->selective_encryption = selective_encryption; + sinf->info->isfm->key_indicator_length = KI_length; + sinf->info->isfm->IV_length = IV_length; + return GF_OK; +} + +GF_Err gf_isom_set_oma_protection(GF_ISOFile *the_file, u32 trackNumber, u32 desc_index, + char *contentID, char *kms_URI, u32 encryption_type, u64 plainTextLength, char *textual_headers, u32 textual_headers_len, + Bool selective_encryption, u32 KI_length, u32 IV_length) +{ + u32 original_format; + GF_ProtectionInfoBox *sinf; + GF_Err e; + GF_SampleEntryBox *sea; + GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); + if (!trak) return GF_BAD_PARAM; + + e = Media_GetSampleDesc(trak->Media, desc_index, &sea, NULL); + if (e) return e; + + /* Replacing the Media Type */ + switch (sea->type) { + case GF_ISOM_BOX_TYPE_MP4A: + case GF_ISOM_BOX_TYPE_DAMR: + case GF_ISOM_BOX_TYPE_DEVC: + case GF_ISOM_BOX_TYPE_DQCP: + case GF_ISOM_BOX_TYPE_DSMV: + original_format = sea->type; + sea->type = GF_ISOM_BOX_TYPE_ENCA; + break; + case GF_ISOM_BOX_TYPE_MP4V: + case GF_ISOM_BOX_TYPE_AVC1: + case GF_ISOM_BOX_TYPE_AVC2: + case GF_ISOM_BOX_TYPE_SVC1: + case GF_ISOM_BOX_TYPE_D263: + original_format = sea->type; + sea->type = GF_ISOM_BOX_TYPE_ENCV; + break; + case GF_ISOM_BOX_TYPE_MP4S: + case GF_ISOM_BOX_TYPE_LSR1: + original_format = sea->type; + sea->type = GF_ISOM_BOX_TYPE_ENCS; + break; + default: + return GF_BAD_PARAM; + } + + sinf = (GF_ProtectionInfoBox *)sinf_New(); + gf_list_add(sea->protections, sinf); + sinf->scheme_type = (GF_SchemeTypeBox *)schm_New(); + sinf->scheme_type->scheme_type = GF_4CC('o','d','k','m'); + sinf->scheme_type->scheme_version = 0x00000200; + + sinf->original_format = (GF_OriginalFormatBox *)frma_New(); + sinf->original_format->data_format = original_format; + sinf->info = (GF_SchemeInformationBox *)schi_New(); + + sinf->info->okms = (GF_OMADRMKMSBox *)odkm_New(); + sinf->info->okms->fmt = (GF_OMADRMAUFormatBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_ODAF); + sinf->info->okms->fmt->selective_encryption = selective_encryption; + sinf->info->okms->fmt->key_indicator_length = KI_length; + sinf->info->okms->fmt->IV_length = IV_length; + + sinf->info->okms->hdr = (GF_OMADRMCommonHeaderBox*)ohdr_New(); + sinf->info->okms->hdr->EncryptionMethod = encryption_type; + sinf->info->okms->hdr->PaddingScheme = (encryption_type==0x01) ? 1 : 0; + sinf->info->okms->hdr->PlaintextLength = plainTextLength; + if (contentID) sinf->info->okms->hdr->ContentID = gf_strdup(contentID); + if (kms_URI) sinf->info->okms->hdr->RightsIssuerURL = gf_strdup(kms_URI); + if (textual_headers) { + sinf->info->okms->hdr->TextualHeaders = gf_malloc(sizeof(char)*textual_headers_len); + memcpy(sinf->info->okms->hdr->TextualHeaders, textual_headers, sizeof(char)*textual_headers_len); + sinf->info->okms->hdr->TextualHeadersLen = textual_headers_len; + } + return GF_OK; +} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + + + +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + + +void gf_isom_cenc_sample_del(GF_CENCSampleInfo *samp) +{ + if (samp->subsamples) gf_free(samp->subsamples); + gf_free(samp); +} + +static GF_Err gf_isom_cenc_parse_sample(GF_CENCSampleInfo *cenc_sample, GF_BitStream *bs, u32 sample_number, Bool use_subsample) +{ + u32 i=0, k; + if ((cenc_sample->IV_size!=0) && (cenc_sample->IV_size!=8) && (cenc_sample->IV_size!=16) ) return GF_ISOM_INVALID_FILE; + + while (gf_bs_available(bs)) { + i++; + if (i == sample_number) { + gf_bs_read_data(bs, cenc_sample->IV, cenc_sample->IV_size); + + if (use_subsample) { + cenc_sample->subsample_count = gf_bs_read_u16(bs); + cenc_sample->subsamples = gf_malloc(sizeof(GF_CENCSubSampleEntry)* cenc_sample->subsample_count); + for (k=0; ksubsample_count; k++) { + cenc_sample->subsamples[k].bytes_clear_data = gf_bs_read_u16(bs); + cenc_sample->subsamples[k].bytes_encrypted_data = gf_bs_read_u32(bs); + } + } + return GF_OK; + } else { + gf_bs_skip_bytes(bs, cenc_sample->IV_size); + if (use_subsample) { + u32 subcount = gf_bs_read_u16(bs); + gf_bs_skip_bytes(bs, subcount * 6); + } + } + } + return GF_ISOM_INVALID_FILE; +} + +GF_CENCSampleInfo *gf_isom_cenc_get_sample(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u32 sample_number) +{ + GF_Err e; + Bool use_subsample = 0; + GF_CENCSampleInfo *cenc_sample; + GF_ProtectionInfoBox *sinf; + GF_SampleEntryBox *sentry; + u32 sample_desc_idx; + GF_BitStream *bs; + + if (!sample_number) return NULL; + + sample_desc_idx = traf->tfhd->sample_desc_index; + if (!sample_desc_idx) sample_desc_idx = traf->trex->def_sample_desc_index; + + sentry = gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, sample_desc_idx - 1); + sinf = sentry ? gf_list_get(sentry->protections, 0) : NULL; + + /*PIFF*/ + if (sinf && sinf->scheme_type && sinf->info->piff_tenc) { + /*TODO !!*/ + if (!traf->piff_sample_encryption) return NULL; + + GF_SAFEALLOC(cenc_sample, GF_CENCSampleInfo); + memcpy(cenc_sample->keyID, sinf->info->piff_tenc->KID, 16); + cenc_sample->IV_size = sinf->info->piff_tenc->IV_size; + cenc_sample->algo_id = sinf->info->piff_tenc->AlgorithmID; + + if (traf->piff_sample_encryption->flags & 1) { + memcpy(cenc_sample->keyID, traf->piff_sample_encryption->KID, 16); + cenc_sample->IV_size = traf->piff_sample_encryption->IV_size; + cenc_sample->algo_id = traf->piff_sample_encryption->AlgorithmID; + cenc_sample->is_alt_info = 1; + } + + use_subsample = (traf->piff_sample_encryption->flags & 2) ? 1 : 0; + + bs = gf_bs_new(traf->piff_sample_encryption->cenc_data, traf->piff_sample_encryption->cenc_data_size, GF_BITSTREAM_READ); + e = gf_isom_cenc_parse_sample(cenc_sample, bs, sample_number, use_subsample); + gf_bs_del(bs); + if (e) { + gf_isom_cenc_sample_del(cenc_sample); + return NULL; + } + return cenc_sample; + } + return NULL; +} + +#endif // GPAC_DISABLE_ISOM_FRAGMENTS + + +#endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/generic_subtitle.c b/src/isomedia/generic_subtitle.c new file mode 100644 index 0000000..80b28a8 --- /dev/null +++ b/src/isomedia/generic_subtitle.c @@ -0,0 +1,322 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2012 + * All rights reserved + * + * This file is part of GPAC / ISO Media File Format sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include + +#ifndef GPAC_DISABLE_ISOM + +#ifndef GPAC_DISABLE_ISOM_WRITE + +GF_Err gf_isom_update_generic_subtitle_description( GF_ISOFile *movie, + u32 trackNumber, + u32 descriptionIndex, + GF_GenericSubtitleSampleDescriptor *desc) +{ + GF_TrackBox *trak; + GF_Err e; + + if (!descriptionIndex || !desc) return GF_BAD_PARAM; + e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); + if (e) return e; + + trak = gf_isom_get_track_from_file(movie, trackNumber); + if (!trak || !trak->Media) return GF_BAD_PARAM; + + switch (trak->Media->handler->handlerType) { + case GF_ISOM_MEDIA_SUBM: + break; + default: + return GF_BAD_PARAM; + } + + //GF_GenericSubtitleSampleEntryBox *gsub; + //gsub = (GF_GenericSubtitleSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, descriptionIndex - 1); + //if (!gsub) return GF_BAD_PARAM; + //switch (txt->type) { + //case GF_ISOM_BOX_TYPE_METX: + //case GF_ISOM_BOX_TYPE_METT: + // break; + //default: + // return GF_BAD_PARAM; + //} + + trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); + + return e; +} + +GF_Err gf_isom_new_generic_subtitle_description(GF_ISOFile *movie, + u32 trackNumber, + char *content_encoding, + char *xml_schema_loc, + char *mime_type_or_namespace, + Bool is_xml, + char *URLname, + char *URNname, + u32 *outDescriptionIndex) +{ + GF_TrackBox *trak; + GF_Err e; + u32 dataRefIndex; + GF_MetaDataSampleEntryBox *metasd; + + e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); + if (e) return e; + + trak = gf_isom_get_track_from_file(movie, trackNumber); + if (!trak || !trak->Media) return GF_BAD_PARAM; + + switch (trak->Media->handler->handlerType) { + case GF_ISOM_MEDIA_SUBM: + break; + default: + 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(); + + metasd = (GF_MetaDataSampleEntryBox *) gf_isom_box_new((is_xml ? GF_ISOM_BOX_TYPE_METX : GF_ISOM_BOX_TYPE_METT)); + metasd->dataReferenceIndex = dataRefIndex; + gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, metasd); + if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); + + metasd->content_encoding = gf_strdup(content_encoding); + metasd->xml_schema_loc = gf_strdup(xml_schema_loc); + metasd->mime_type_or_namespace = gf_strdup(mime_type_or_namespace); + return e; +} + + +/* blindly adds text to a sample following 3GPP Timed Text style */ +GF_Err gf_isom_generic_subtitle_sample_add_text(GF_GenericSubtitleSample *samp, char *text_data, u32 text_len) +{ + if (!samp) return GF_BAD_PARAM; + if (!text_len) return GF_OK; + samp->text = (char*)gf_realloc(samp->text, sizeof(char) * (samp->len + text_len) ); + memcpy(samp->text + samp->len, text_data, sizeof(char) * text_len); + samp->len += text_len; + return GF_OK; +} + +/* + * Writing the generic sample structure into a sample buffer + * 2 options: + * - putting the text or XML in the sample directly + * - or using a meta box to structure the sample data +*/ +GF_ISOSample *gf_isom_generic_subtitle_to_sample(GF_GenericSubtitleSample *samp) +{ + GF_ISOSample *res; + GF_BitStream *bs; + if (!samp) return NULL; + + bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + //gf_bs_write_u16(bs, samp->len); + + if (samp->len) gf_bs_write_data(bs, samp->text, samp->len); + else gf_bs_write_data(bs, "", 1); + + res = gf_isom_sample_new(); + if (!res) { + gf_bs_del(bs); + return NULL; + } + gf_bs_get_content(bs, &res->data, &res->dataLength); + gf_bs_del(bs); + res->IsRAP = 1; + return res; +} + +//GF_Err gf_isom_generic_subtitle_has_similar_description(GF_ISOFile *movie, +// u32 trackNumber, +// GF_GenericSubtitleSampleDescriptor *desc, +// u32 *outDescIdx, +// Bool *same_box) +//{ +// GF_TrackBox *trak; +// GF_Err e; +// u32 i; +// u32 j; +// u32 count; +// GF_Tx3gSampleEntryBox *txt; +// +// *same_box = 0; +// *outDescIdx = 0; +// +// if (!desc) return GF_BAD_PARAM; +// e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); +// if (e) return GF_BAD_PARAM; +// +// trak = gf_isom_get_track_from_file(movie, trackNumber); +// if (!trak || !trak->Media) return GF_BAD_PARAM; +// +// switch (trak->Media->handler->handlerType) { +// case GF_ISOM_MEDIA_SUBT: +// break; +// default: +// return GF_BAD_PARAM; +// } +// +// return GF_OK; +//} + +#endif /*GPAC_DISABLE_ISOM_WRITE*/ + +GF_GenericSubtitleSample *gf_isom_new_generic_subtitle_sample() +{ + GF_GenericSubtitleSample *res; + GF_SAFEALLOC(res, GF_GenericSubtitleSample); + if (!res) return NULL; + return res; +} + +GF_Err gf_isom_generic_subtitle_reset(GF_GenericSubtitleSample *samp) +{ + if (!samp) return GF_BAD_PARAM; + if (samp->text) gf_free(samp->text); + samp->text = NULL; + samp->len = 0; + return GF_OK; +} + +GF_EXPORT +void gf_isom_delete_generic_subtitle_sample(GF_GenericSubtitleSample * samp) +{ + gf_isom_generic_subtitle_reset(samp); + gf_free(samp); +} + +GF_EXPORT +GF_GenericSubtitleSample *gf_isom_parse_generic_subtitle_sample(GF_BitStream *bs) +{ + GF_GenericSubtitleSample *s = gf_isom_new_generic_subtitle_sample(); + + /*empty sample*/ + if (!bs || !gf_bs_available(bs)) return s; + + s->len = gf_bs_read_u16(bs); + if (s->len) { + /*2 extra bytes for UTF-16 term char just in case (we don't know if a BOM marker is present or + not since this may be a sample carried over RTP*/ + s->text = (char *) gf_malloc(sizeof(char)*(s->len+2) ); + s->text[s->len] = 0; + s->text[s->len+1] = 0; + gf_bs_read_data(bs, s->text, s->len); + } + return s; +} + +GF_GenericSubtitleSample *gf_isom_parse_generic_subtitle_sample_from_data(char *data, u32 dataLength) +{ + GF_GenericSubtitleSample *s; + GF_BitStream *bs; + /*empty text sample*/ + if (!data || !dataLength) { + return gf_isom_new_generic_subtitle_sample(); + } + + bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); + s = gf_isom_parse_generic_subtitle_sample(bs); + gf_bs_del(bs); + return s; +} + + +/*out-of-band sample desc (128 and 255 reserved in RFC)*/ +#define SAMPLE_INDEX_OFFSET 129 + +GF_Err gf_isom_rewrite_generic_subtitle_sample(GF_ISOSample *samp, u32 sampleDescriptionIndex, u32 sample_dur) +{ + //GF_BitStream *bs; + //u32 pay_start, txt_size; + //Bool is_utf_16 = 0; + //if (!samp || !samp->data || !samp->dataLength) return GF_OK; + + //bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ); + //txt_size = gf_bs_read_u16(bs); + //gf_bs_del(bs); + + ///*remove BOM*/ + //pay_start = 2; + //if (txt_size>2) { + // /*seems 3GP only accepts BE UTF-16 (no LE, no UTF32)*/ + // if (((u8) samp->data[2]==(u8) 0xFE) && ((u8)samp->data[3]==(u8) 0xFF)) { + // is_utf_16 = 1; + // pay_start = 4; + // txt_size -= 2; + // } + //} + + ///*rewrite as TTU(1)*/ + //bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + //gf_bs_write_int(bs, is_utf_16, 1); + //gf_bs_write_int(bs, 0, 4); + //gf_bs_write_int(bs, 1, 3); + //gf_bs_write_u16(bs, 8 + samp->dataLength - pay_start); + //gf_bs_write_u8(bs, sampleDescriptionIndex + SAMPLE_INDEX_OFFSET); + //gf_bs_write_u24(bs, sample_dur); + ///*write text size*/ + //gf_bs_write_u16(bs, txt_size); + //if (txt_size) gf_bs_write_data(bs, samp->data + pay_start, samp->dataLength - pay_start); + + //gf_free(samp->data); + //samp->data = NULL; + //gf_bs_get_content(bs, &samp->data, &samp->dataLength); + //gf_bs_del(bs); + return GF_OK; +} + + +//GF_Err gf_isom_text_get_encoded_tx3g(GF_ISOFile *file, u32 track, u32 sidx, u32 sidx_offset, char **tx3g, u32 *tx3g_size) +//{ +// GF_BitStream *bs; +// GF_TrackBox *trak; +// GF_Tx3gSampleEntryBox *a; +// +// trak = gf_isom_get_track_from_file(file, track); +// if (!trak) return GF_BAD_PARAM; +// +// a = (GF_Tx3gSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sidx-1); +// if (!a) return GF_BAD_PARAM; +// if ((a->type != GF_ISOM_BOX_TYPE_TX3G) && (a->type != GF_ISOM_BOX_TYPE_TEXT)) return GF_BAD_PARAM; +// +// bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); +// gf_isom_write_tx3g(a, bs, sidx, sidx_offset); +// *tx3g = NULL; +// *tx3g_size = 0; +// gf_bs_get_content(bs, tx3g, tx3g_size); +// gf_bs_del(bs); +// return GF_OK; +//} + +#endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/hint_track.c b/src/isomedia/hint_track.c index 3eeba72..f70366c 100644 --- a/src/isomedia/hint_track.c +++ b/src/isomedia/hint_track.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -41,7 +42,7 @@ u32 GetHintFormat(GF_TrackBox *trak) { GF_HintMediaHeaderBox *hmhd = (GF_HintMediaHeaderBox *)trak->Media->information->InfoHeader; if (!hmhd->subType) { - GF_Box *a = (GF_Box *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, 0); + GF_Box *a = (GF_Box *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, 0); if (a) hmhd->subType = a->type; } return hmhd->subType; @@ -192,7 +193,7 @@ GF_Err gf_isom_new_hint_description(GF_ISOFile *the_file, u32 trackNumber, s32 H //add the entry to our table... e = stsd_AddBox(trak->Media->information->sampleTable->SampleDescription, (GF_Box *) hdesc); if (e) return e; - *HintDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + *HintDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); //RTP needs a default timeScale... use the media one. if (CheckHintFormat(trak, GF_ISOM_HINT_RTP)) { @@ -228,7 +229,7 @@ GF_Err gf_isom_rtp_set_timescale(GF_ISOFile *the_file, u32 trackNumber, u32 Hint if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc - hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); + hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { @@ -257,7 +258,7 @@ GF_Err gf_isom_rtp_set_time_offset(GF_ISOFile *the_file, u32 trackNumber, u32 Hi if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc - hdesc = (GF_HintSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); + hdesc = (GF_HintSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { @@ -286,7 +287,7 @@ GF_Err gf_isom_rtp_set_time_sequence_offset(GF_ISOFile *the_file, u32 trackNumbe if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc - hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); + hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { @@ -730,9 +731,9 @@ GF_Err gf_isom_sdp_add_track_line(GF_ISOFile *the_file, u32 trackNumber, const c if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA - if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; + if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; - hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); + hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) { e = hnti_AddBox(hnti, gf_isom_box_new(GF_ISOM_BOX_TYPE_SDP)); if (e) return e; @@ -772,9 +773,9 @@ GF_Err gf_isom_sdp_clean_track(GF_ISOFile *the_file, u32 trackNumber) if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA - if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; + if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; - hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); + hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) return GF_OK; //and free the SDP gf_free(((GF_SDPBox *)hnti->SDP)->sdpText); @@ -810,13 +811,13 @@ GF_Err gf_isom_sdp_add_line(GF_ISOFile *movie, const char *text) } //there should be one and only one hnti - if (!gf_list_count(map->boxList) ) { + if (!gf_list_count(map->other_boxes) ) { e = udta_AddBox(movie->moov->udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HNTI)); if (e) return e; } - else if (gf_list_count(map->boxList) < 1) return GF_ISOM_INVALID_FILE; + else if (gf_list_count(map->other_boxes) < 1) return GF_ISOM_INVALID_FILE; - hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); + hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) { //we have to create it by hand, as we have a duplication of box type @@ -861,11 +862,11 @@ GF_Err gf_isom_sdp_clean(GF_ISOFile *movie) if (!map) return GF_OK; //there should be one and only one hnti - if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; - hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); + if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; + hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); //remove and destroy the entry - gf_list_rem(map->boxList, 0); + gf_list_rem(map->other_boxes, 0); gf_isom_box_del((GF_Box *)hnti); return GF_OK; } @@ -889,8 +890,8 @@ GF_Err gf_isom_sdp_get(GF_ISOFile *movie, const char **sdp, u32 *length) if (!map) return GF_OK; //there should be one and only one hnti - if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; - hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); + if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; + hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) return GF_OK; rtp = (GF_RTPBox *) hnti->SDP; @@ -919,9 +920,9 @@ GF_Err gf_isom_sdp_track_get(GF_ISOFile *the_file, u32 trackNumber, const char * if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA - if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; + if (gf_list_count(map->other_boxes) != 1) return GF_ISOM_INVALID_FILE; - hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); + hnti = (GF_HintTrackInfoBox *)gf_list_get(map->other_boxes, 0); if (!hnti->SDP) return GF_OK; sdpa = (GF_SDPBox *) hnti->SDP; @@ -946,12 +947,12 @@ u32 gf_isom_get_payt_count(GF_ISOFile *the_file, u32 trackNumber) if (!CheckHintFormat(trak, GF_4CC('r', 't', 'p', ' '))) return 0; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HINF, NULL); if (!map) return 0; - if (gf_list_count(map->boxList) != 1) return 0; + if (gf_list_count(map->other_boxes) != 1) return 0; - hinf = (GF_HintInfoBox *)gf_list_get(map->boxList, 0); + hinf = (GF_HintInfoBox *)gf_list_get(map->other_boxes, 0); count = 0; i = 0; - while ((payt = gf_list_enum(hinf->boxList, &i))) { + while ((payt = gf_list_enum(hinf->other_boxes, &i))) { if (payt->type == GF_ISOM_BOX_TYPE_PAYT) count++; } return count; @@ -972,12 +973,12 @@ const char *gf_isom_get_payt_info(GF_ISOFile *the_file, u32 trackNumber, u32 ind if (!CheckHintFormat(trak, GF_4CC('r', 't', 'p', ' '))) return NULL; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HINF, NULL); if (!map) return NULL; - if (gf_list_count(map->boxList) != 1) return NULL; + if (gf_list_count(map->other_boxes) != 1) return NULL; - hinf = (GF_HintInfoBox *)gf_list_get(map->boxList, 0); + hinf = (GF_HintInfoBox *)gf_list_get(map->other_boxes, 0); count = 0; i = 0; - while ((payt = gf_list_enum(hinf->boxList, &i))) { + while ((payt = gf_list_enum(hinf->other_boxes, &i))) { if (payt->type == GF_ISOM_BOX_TYPE_PAYT) { count++; if (count == index) { diff --git a/src/isomedia/hinting.c b/src/isomedia/hinting.c index 942f3af..947fd74 100644 --- a/src/isomedia/hinting.c +++ b/src/isomedia/hinting.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project diff --git a/src/isomedia/isma_sample.c b/src/isomedia/isma_sample.c deleted file mode 100644 index 485f1ba..0000000 --- a/src/isomedia/isma_sample.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * GPAC - Multimedia Framework C SDK - * - * Copyright (c) Cyril Concolato / Jean Le Feuvre 2005 - * All rights reserved - * - * This file is part of GPAC / ISO Media File Format sub-project - * - * GPAC is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * GPAC is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include - -#ifndef GPAC_DISABLE_ISOM - -GF_ISMASample *gf_isom_ismacryp_new_sample() -{ - GF_ISMASample *tmp = (GF_ISMASample *) gf_malloc(sizeof(GF_ISMASample)); - if (!tmp) return NULL; - memset(tmp, 0, sizeof(GF_ISMASample)); - return tmp; -} -GF_EXPORT -void gf_isom_ismacryp_delete_sample(GF_ISMASample *samp) -{ - if (!samp) return; - if (samp->data && samp->dataLength) gf_free(samp->data); - if (samp->key_indicator) gf_free(samp->key_indicator); - gf_free(samp); -} - - -GF_ISMASample *gf_isom_ismacryp_sample_from_data(char *data, u32 dataLength, Bool use_selective_encryption, u8 KI_length, u8 IV_length) -{ - GF_ISMASample *s; - GF_BitStream *bs; - /*empty text sample*/ - if (!data || !dataLength) { - return gf_isom_ismacryp_new_sample(); - } - - s = gf_isom_ismacryp_new_sample(); - - /*empty sample*/ - if (!data || !dataLength) return s; - - bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); - - s->dataLength = dataLength; - s->IV_length = IV_length; - s->KI_length = KI_length; - - if (use_selective_encryption) { - s->flags = GF_ISOM_ISMA_USE_SEL_ENC; - if (s->dataLength < 1) goto exit; - if (gf_bs_read_int(bs, 1)) s->flags |= GF_ISOM_ISMA_IS_ENCRYPTED; - gf_bs_read_int(bs, 7); - s->dataLength -= 1; - } else { - s->flags = GF_ISOM_ISMA_IS_ENCRYPTED; - } - if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) { - if (IV_length != 0) { - if (s->dataLength < IV_length) goto exit; - s->IV = gf_bs_read_long_int(bs, 8*IV_length); - s->dataLength -= IV_length; - } - if (KI_length) { - if (s->dataLength < KI_length) goto exit; - s->key_indicator = (u8 *)gf_malloc(KI_length); - gf_bs_read_data(bs, (char*)s->key_indicator, KI_length); - s->dataLength -= KI_length; - } - } - s->data = (char*)gf_malloc(sizeof(char)*s->dataLength); - gf_bs_read_data(bs, s->data, s->dataLength); - gf_bs_del(bs); - return s; - -exit: - gf_isom_ismacryp_delete_sample(s); - return NULL; -} - -GF_Err gf_isom_ismacryp_sample_to_sample(GF_ISMASample *s, GF_ISOSample *dest) -{ - GF_BitStream *bs; - if (!s || !dest) return GF_BAD_PARAM; - - bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); - - if (s->flags & GF_ISOM_ISMA_USE_SEL_ENC) { - gf_bs_write_int(bs, (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) ? 1 : 0, 1); - gf_bs_write_int(bs, 0, 7); - } - if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) { - if (s->IV_length) gf_bs_write_long_int(bs, (s64) s->IV, 8*s->IV_length); - if (s->KI_length) gf_bs_write_data(bs, (char*)s->key_indicator, s->KI_length); - } - gf_bs_write_data(bs, s->data, s->dataLength); - if (dest->data) gf_free(dest->data); - dest->data = NULL; - dest->dataLength = 0; - gf_bs_get_content(bs, &dest->data, &dest->dataLength); - gf_bs_del(bs); - return GF_OK; -} - -GF_EXPORT -GF_ISMASample *gf_isom_get_ismacryp_sample(GF_ISOFile *the_file, u32 trackNumber, GF_ISOSample *samp, u32 sampleDescriptionIndex) -{ - GF_TrackBox *trak; - GF_ISMASampleFormatBox *fmt; - GF_SampleEntryBox *sea; - - trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return NULL; - - Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea || !sea->protection_info - || !sea->protection_info->scheme_type - || !sea->protection_info->info - ) { - return NULL; - } - /*ISMA*/ - if (sea->protection_info->scheme_type->scheme_type == GF_ISOM_ISMACRYP_SCHEME) { - fmt = sea->protection_info->info->isfm; - if (!fmt) return NULL; - return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, sea->protection_info->info->isfm->selective_encryption, sea->protection_info->info->isfm->key_indicator_length, sea->protection_info->info->isfm->IV_length); - } - /*OMA*/ - else if (sea->protection_info->scheme_type->scheme_type == GF_4CC('o','d','k','m') ) { - if (!sea->protection_info->info->okms) return NULL; - fmt = sea->protection_info->info->okms->fmt; - - if (fmt) { - return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, fmt->selective_encryption, fmt->key_indicator_length, fmt->IV_length); - } - /*OMA default: no selective encryption, one key, 128 bit IV*/ - return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, 0, 0, 128); - } - return NULL; -} - - -GF_EXPORT -u32 gf_isom_is_media_encrypted(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) -{ - GF_TrackBox *trak; - GF_SampleEntryBox *sea; - - trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return 0; - - Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea || !sea->protection_info || !sea->protection_info->scheme_type) return 0; - return sea->protection_info->scheme_type->scheme_type; -} - -GF_EXPORT -Bool gf_isom_is_ismacryp_media(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) -{ - GF_TrackBox *trak; - GF_SampleEntryBox *sea; - - trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return 0; - - Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea - || !sea->protection_info - || !sea->protection_info->scheme_type - || (sea->protection_info->scheme_type->scheme_type != GF_ISOM_ISMACRYP_SCHEME) - || !sea->protection_info->info - || !sea->protection_info->info->ikms - || !sea->protection_info->info->isfm - ) - return 0; - - return 1; -} - -GF_EXPORT -Bool gf_isom_is_omadrm_media(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) -{ - GF_TrackBox *trak; - GF_SampleEntryBox *sea; - - trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return 0; - - Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea - || !sea->protection_info - || !sea->protection_info->scheme_type - || (sea->protection_info->scheme_type->scheme_type != GF_4CC('o','d','k','m') ) - || !sea->protection_info->info - || !sea->protection_info->info->okms - || !sea->protection_info->info->okms->hdr - ) - return 0; - - return 1; -} - -/*retrieves ISMACryp info for the given track & SDI*/ -GF_EXPORT -GF_Err gf_isom_get_ismacryp_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 *outOriginalFormat, u32 *outSchemeType, u32 *outSchemeVersion, const char **outSchemeURI, const char **outKMS_URI, Bool *outSelectiveEncryption, u32 *outIVLength, u32 *outKeyIndicationLength) -{ - GF_TrackBox *trak; - GF_SampleEntryBox *sea; - - trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return GF_BAD_PARAM; - - Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea || !sea->protection_info) return GF_BAD_PARAM; - if (!sea->protection_info->scheme_type || !sea->protection_info->original_format) return GF_NON_COMPLIANT_BITSTREAM; - - if (outOriginalFormat) { - *outOriginalFormat = sea->protection_info->original_format->data_format; - if (IsMP4Description(sea->protection_info->original_format->data_format)) *outOriginalFormat = GF_ISOM_SUBTYPE_MPEG4; - } - if (outSchemeType) *outSchemeType = sea->protection_info->scheme_type->scheme_type; - if (outSchemeVersion) *outSchemeVersion = sea->protection_info->scheme_type->scheme_version; - if (outSchemeURI) *outSchemeURI = sea->protection_info->scheme_type->URI; - - if (sea->protection_info->info && sea->protection_info->info->ikms) { - if (outKMS_URI) *outKMS_URI = sea->protection_info->info->ikms->URI; - } else { - if (outKMS_URI) *outKMS_URI = NULL; - } - if (sea->protection_info->info && sea->protection_info->info->isfm) { - if (outSelectiveEncryption) *outSelectiveEncryption = sea->protection_info->info->isfm->selective_encryption; - if (outIVLength) *outIVLength = sea->protection_info->info->isfm->IV_length; - if (outKeyIndicationLength) *outKeyIndicationLength = sea->protection_info->info->isfm->key_indicator_length; - } else { - if (outSelectiveEncryption) *outSelectiveEncryption = 0; - if (outIVLength) *outIVLength = 0; - if (outKeyIndicationLength) *outKeyIndicationLength = 0; - } - return GF_OK; -} - - -/*retrieves ISMACryp info for the given track & SDI*/ -GF_EXPORT -GF_Err gf_isom_get_omadrm_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 *outOriginalFormat, - u32 *outSchemeType, u32 *outSchemeVersion, - const char **outContentID, const char **outRightsIssuerURL, const char **outTextualHeaders, u32 *outTextualHeadersLen, u64 *outPlaintextLength, u32 *outEncryptionType, Bool *outSelectiveEncryption, u32 *outIVLength, u32 *outKeyIndicationLength) -{ - GF_TrackBox *trak; - GF_SampleEntryBox *sea; - - trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return GF_BAD_PARAM; - - Media_GetSampleDesc(trak->Media, sampleDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea || !sea->protection_info) return GF_BAD_PARAM; - if (!sea->protection_info->scheme_type || !sea->protection_info->original_format) return GF_NON_COMPLIANT_BITSTREAM; - if (!sea->protection_info->info || !sea->protection_info->info->okms || !sea->protection_info->info->okms->hdr) return GF_NON_COMPLIANT_BITSTREAM; - - if (outOriginalFormat) { - *outOriginalFormat = sea->protection_info->original_format->data_format; - if (IsMP4Description(sea->protection_info->original_format->data_format)) *outOriginalFormat = GF_ISOM_SUBTYPE_MPEG4; - } - if (outSchemeType) *outSchemeType = sea->protection_info->scheme_type->scheme_type; - if (outSchemeVersion) *outSchemeVersion = sea->protection_info->scheme_type->scheme_version; - if (outContentID) *outContentID = sea->protection_info->info->okms->hdr->ContentID; - if (outRightsIssuerURL) *outRightsIssuerURL = sea->protection_info->info->okms->hdr->RightsIssuerURL; - if (outTextualHeaders) { - *outTextualHeaders = sea->protection_info->info->okms->hdr->TextualHeaders; - if (outTextualHeadersLen) *outTextualHeadersLen = sea->protection_info->info->okms->hdr->TextualHeadersLen; - } - if (outPlaintextLength) *outPlaintextLength = sea->protection_info->info->okms->hdr->PlaintextLength; - if (outEncryptionType) *outEncryptionType = sea->protection_info->info->okms->hdr->EncryptionMethod; - - if (sea->protection_info->info && sea->protection_info->info->okms && sea->protection_info->info->okms->fmt) { - if (outSelectiveEncryption) *outSelectiveEncryption = sea->protection_info->info->okms->fmt->selective_encryption; - if (outIVLength) *outIVLength = sea->protection_info->info->okms->fmt->IV_length; - if (outKeyIndicationLength) *outKeyIndicationLength = sea->protection_info->info->okms->fmt->key_indicator_length; - } else { - if (outSelectiveEncryption) *outSelectiveEncryption = 0; - if (outIVLength) *outIVLength = 0; - if (outKeyIndicationLength) *outKeyIndicationLength = 0; - } - return GF_OK; -} - -#ifndef GPAC_DISABLE_ISOM_WRITE - -GF_Err gf_isom_remove_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex) -{ - GF_TrackBox *trak; - GF_Err e; - GF_SampleEntryBox *sea; - - 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 || !StreamDescriptionIndex) return GF_BAD_PARAM; - - Media_GetSampleDesc(trak->Media, StreamDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea || !sea->protection_info) return GF_BAD_PARAM; - if (!sea->protection_info->scheme_type || !sea->protection_info->original_format) return GF_NON_COMPLIANT_BITSTREAM; - - sea->type = sea->protection_info->original_format->data_format; - gf_isom_box_del((GF_Box *)sea->protection_info); - sea->protection_info = NULL; - if (sea->type == GF_4CC('2','6','4','b')) sea->type = GF_ISOM_BOX_TYPE_AVC1; - return GF_OK; -} - -GF_EXPORT -GF_Err gf_isom_change_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, char *scheme_uri, char *kms_uri) -{ - GF_TrackBox *trak; - GF_Err e; - GF_SampleEntryBox *sea; - - 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 || !StreamDescriptionIndex) return GF_BAD_PARAM; - - Media_GetSampleDesc(trak->Media, StreamDescriptionIndex, &sea, NULL); - /*non-encrypted or non-ISMA*/ - if (!sea || !sea->protection_info) return GF_BAD_PARAM; - if (!sea->protection_info->scheme_type || !sea->protection_info->original_format) return GF_NON_COMPLIANT_BITSTREAM; - - if (scheme_uri) { - gf_free(sea->protection_info->scheme_type->URI); - sea->protection_info->scheme_type->URI = gf_strdup(scheme_uri); - } - if (kms_uri) { - gf_free(sea->protection_info->info->ikms->URI); - sea->protection_info->info->ikms->URI = gf_strdup(kms_uri); - } - return GF_OK; -} - - -GF_Err gf_isom_set_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 desc_index, u32 scheme_type, - u32 scheme_version, char *scheme_uri, char *kms_URI, - Bool selective_encryption, u32 KI_length, u32 IV_length) -{ - u32 original_format; - GF_Err e; - GF_SampleEntryBox *sea; - GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return GF_BAD_PARAM; - - e = Media_GetSampleDesc(trak->Media, desc_index, &sea, NULL); - if (e) return e; - - /* Replacing the Media Type */ - switch (sea->type) { - case GF_ISOM_BOX_TYPE_MP4A: - case GF_ISOM_BOX_TYPE_DAMR: - case GF_ISOM_BOX_TYPE_DEVC: - case GF_ISOM_BOX_TYPE_DQCP: - case GF_ISOM_BOX_TYPE_DSMV: - case GF_ISOM_BOX_TYPE_AC3: - original_format = sea->type; - sea->type = GF_ISOM_BOX_TYPE_ENCA; - break; - case GF_ISOM_BOX_TYPE_MP4V: - case GF_ISOM_BOX_TYPE_D263: - original_format = sea->type; - sea->type = GF_ISOM_BOX_TYPE_ENCV; - break; - /*special case for AVC1*/ - case GF_ISOM_BOX_TYPE_AVC1: - case GF_ISOM_BOX_TYPE_AVC2: - 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_MP4S: - case GF_ISOM_BOX_TYPE_LSR1: - original_format = sea->type; - sea->type = GF_ISOM_BOX_TYPE_ENCS; - break; - default: - return GF_BAD_PARAM; - } - - sea->protection_info = (GF_ProtectionInfoBox *)sinf_New(); - sea->protection_info->scheme_type = (GF_SchemeTypeBox *)schm_New(); - sea->protection_info->scheme_type->scheme_type = scheme_type; - sea->protection_info->scheme_type->scheme_version = scheme_version; - if (scheme_uri) { - sea->protection_info->scheme_type->flags |= 0x000001; - sea->protection_info->scheme_type->URI = gf_strdup(scheme_uri); - } - sea->protection_info->original_format = (GF_OriginalFormatBox *)frma_New(); - sea->protection_info->original_format->data_format = original_format; - sea->protection_info->info = (GF_SchemeInformationBox *)schi_New(); - - sea->protection_info->info->ikms = (GF_ISMAKMSBox *)iKMS_New(); - sea->protection_info->info->ikms->URI = gf_strdup(kms_URI); - - sea->protection_info->info->isfm = (GF_ISMASampleFormatBox *)iSFM_New(); - sea->protection_info->info->isfm->selective_encryption = selective_encryption; - sea->protection_info->info->isfm->key_indicator_length = KI_length; - sea->protection_info->info->isfm->IV_length = IV_length; - return GF_OK; -} - -GF_Err gf_isom_set_oma_protection(GF_ISOFile *the_file, u32 trackNumber, u32 desc_index, - char *contentID, char *kms_URI, u32 encryption_type, u64 plainTextLength, char *textual_headers, u32 textual_headers_len, - Bool selective_encryption, u32 KI_length, u32 IV_length) -{ - u32 original_format; - GF_Err e; - GF_SampleEntryBox *sea; - GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); - if (!trak) return GF_BAD_PARAM; - - e = Media_GetSampleDesc(trak->Media, desc_index, &sea, NULL); - if (e) return e; - - /* Replacing the Media Type */ - switch (sea->type) { - case GF_ISOM_BOX_TYPE_MP4A: - case GF_ISOM_BOX_TYPE_DAMR: - case GF_ISOM_BOX_TYPE_DEVC: - case GF_ISOM_BOX_TYPE_DQCP: - case GF_ISOM_BOX_TYPE_DSMV: - original_format = sea->type; - sea->type = GF_ISOM_BOX_TYPE_ENCA; - break; - case GF_ISOM_BOX_TYPE_MP4V: - case GF_ISOM_BOX_TYPE_AVC1: - case GF_ISOM_BOX_TYPE_AVC2: - case GF_ISOM_BOX_TYPE_SVC1: - case GF_ISOM_BOX_TYPE_D263: - original_format = sea->type; - sea->type = GF_ISOM_BOX_TYPE_ENCV; - break; - case GF_ISOM_BOX_TYPE_MP4S: - case GF_ISOM_BOX_TYPE_LSR1: - original_format = sea->type; - sea->type = GF_ISOM_BOX_TYPE_ENCS; - break; - default: - return GF_BAD_PARAM; - } - - sea->protection_info = (GF_ProtectionInfoBox *)sinf_New(); - sea->protection_info->scheme_type = (GF_SchemeTypeBox *)schm_New(); - sea->protection_info->scheme_type->scheme_type = GF_4CC('o','d','k','m'); - sea->protection_info->scheme_type->scheme_version = 0x00000200; - - sea->protection_info->original_format = (GF_OriginalFormatBox *)frma_New(); - sea->protection_info->original_format->data_format = original_format; - sea->protection_info->info = (GF_SchemeInformationBox *)schi_New(); - - sea->protection_info->info->okms = (GF_OMADRMKMSBox *)odkm_New(); - sea->protection_info->info->okms->fmt = (GF_OMADRMAUFormatBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_ODAF); - sea->protection_info->info->okms->fmt->selective_encryption = selective_encryption; - sea->protection_info->info->okms->fmt->key_indicator_length = KI_length; - sea->protection_info->info->okms->fmt->IV_length = IV_length; - - sea->protection_info->info->okms->hdr = (GF_OMADRMCommonHeaderBox*)ohdr_New(); - sea->protection_info->info->okms->hdr->EncryptionMethod = encryption_type; - sea->protection_info->info->okms->hdr->PaddingScheme = (encryption_type==0x01) ? 1 : 0; - sea->protection_info->info->okms->hdr->PlaintextLength = plainTextLength; - if (contentID) sea->protection_info->info->okms->hdr->ContentID = gf_strdup(contentID); - if (kms_URI) sea->protection_info->info->okms->hdr->RightsIssuerURL = gf_strdup(kms_URI); - if (textual_headers) { - sea->protection_info->info->okms->hdr->TextualHeaders = gf_malloc(sizeof(char)*textual_headers_len); - memcpy(sea->protection_info->info->okms->hdr->TextualHeaders, textual_headers, sizeof(char)*textual_headers_len); - sea->protection_info->info->okms->hdr->TextualHeadersLen = textual_headers_len; - } - return GF_OK; -} - -#endif /*GPAC_DISABLE_ISOM_WRITE*/ - - -#endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/isom_intern.c b/src/isomedia/isom_intern.c index 2875354..6d54c1f 100644 --- a/src/isomedia/isom_intern.c +++ b/src/isomedia/isom_intern.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -37,6 +38,7 @@ GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u64 moof_offset, GF_Err MergeFragment(GF_MovieFragmentBox *moof, GF_ISOFile *mov) { + GF_Err e; u32 i, j; u64 MaxDur; GF_TrackFragmentBox *traf; @@ -45,9 +47,16 @@ GF_Err MergeFragment(GF_MovieFragmentBox *moof, GF_ISOFile *mov) MaxDur = 0; //we shall have a MOOV and its MVEX BEFORE any MOOF - if (!mov->moov || !mov->moov->mvex) return GF_ISOM_INVALID_FILE; - //and all fragments must be continous - if (mov->NextMoofNumber && (mov->NextMoofNumber >= moof->mfhd->sequence_number)) return GF_ISOM_INVALID_FILE; + if (!mov->moov || !mov->moov->mvex) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Error: %s not received before merging frament\n", mov->moov ? "mvex" : "moov" )); + return GF_ISOM_INVALID_FILE; + } + //and all fragments must be continous - we do not throw an error as we may still want to be able to concatenate depednent representation in DASH and + //we will likely a-have R1(moofSN 1, 3, 5, 7) plus R2(moofSN 2, 4, 6, 8) + if (mov->NextMoofNumber && (mov->NextMoofNumber >= moof->mfhd->sequence_number)) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Warning: wrong sequence number: got %d but last one was %d\n", moof->mfhd->sequence_number, mov->NextMoofNumber)); +// return GF_ISOM_INVALID_FILE; + } i=0; while ((traf = (GF_TrackFragmentBox*)gf_list_enum(moof->TrackList, &i))) { @@ -62,17 +71,23 @@ GF_Err MergeFragment(GF_MovieFragmentBox *moof, GF_ISOFile *mov) traf->trex = NULL; } } - if (!trak || !traf->trex) return GF_ISOM_INVALID_FILE; - MergeTrack(trak, traf, mov->current_top_box_start, !mov->first_moof_merged); + if (!trak || !traf->trex) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Error: Cannot find fragment track with ID %d\n", traf->tfhd->trackID)); + return GF_ISOM_INVALID_FILE; + } + + e = MergeTrack(trak, traf, mov->current_top_box_start, !trak->first_traf_merged); + if (e) return e; //update trak duration SetTrackDuration(trak); if (trak->Header->duration > MaxDur) MaxDur = trak->Header->duration; + + trak->first_traf_merged = 1; } - mov->first_moof_merged = 1; mov->NextMoofNumber = moof->mfhd->sequence_number; //update movie duration if (mov->moov->mvhd->duration < MaxDur) mov->moov->mvhd->duration = MaxDur; @@ -224,7 +239,25 @@ GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progre mov->moof = (GF_MovieFragmentBox *) a; /*read & debug: store at root level*/ if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) { - gf_list_add(mov->TopBoxes, a); + u32 k; + gf_list_add(mov->TopBoxes, a); + /*also update pointers to trex for debug*/ + if (mov->moov) { + for (k=0; kmoof->TrackList); k++) { + GF_TrackFragmentBox *traf = gf_list_get(mov->moof->TrackList, k); + if (traf->tfhd) { + GF_TrackBox *trak = gf_isom_get_track_from_id(mov->moov, traf->tfhd->trackID); + u32 j=0; + while ((traf->trex = (GF_TrackExtendsBox*)gf_list_enum(mov->moov->mvex->TrackExList, &j))) { + if (traf->trex->trackID == traf->tfhd->trackID) { + if (!traf->trex->track) traf->trex->track = trak; + break; + } + traf->trex = NULL; + } + } + } + } } else if (mov->openMode==GF_ISOM_OPEN_CAT_FRAGMENTS) { mov->NextMoofNumber = mov->moof->mfhd->sequence_number+1; mov->moof = NULL; @@ -233,9 +266,6 @@ GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progre /*merge all info*/ e = MergeFragment((GF_MovieFragmentBox *)a, mov); gf_isom_box_del(a); - if (e) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Error merging fragment: %s\n", gf_error_to_string(e) )); - } } break; #endif @@ -294,7 +324,6 @@ GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progre return GF_OK; } - GF_ISOFile *gf_isom_new_movie() { GF_ISOFile *mov = (GF_ISOFile*)gf_malloc(sizeof(GF_ISOFile)); @@ -764,14 +793,14 @@ GF_EdtsEntry *CreateEditEntry(u64 EditDuration, u64 MediaTime, u8 EditMode) GF_Err gf_isom_add_subsample_info(GF_SubSampleInformationBox *sub_samples, u32 sampleNumber, u32 subSampleSize, u8 priority, u32 reserved, Bool discardable) { u32 i, count, last_sample; - GF_SampleEntry *pSamp; + GF_SubSampleInfoEntry *pSamp; GF_SubSampleEntry *pSubSamp; pSamp = NULL; last_sample = 0; count = gf_list_count(sub_samples->Samples); for (i=0; iSamples, i); + pSamp = (GF_SubSampleInfoEntry*) gf_list_get(sub_samples->Samples, i); /*TODO - do we need to support insertion of subsample info ?*/ if (last_sample + pSamp->sample_delta > sampleNumber) return GF_NOT_SUPPORTED; if (last_sample + pSamp->sample_delta == sampleNumber) break; @@ -780,7 +809,7 @@ GF_Err gf_isom_add_subsample_info(GF_SubSampleInformationBox *sub_samples, u32 s } if (!pSamp) { - GF_SAFEALLOC(pSamp, GF_SampleEntry); + GF_SAFEALLOC(pSamp, GF_SubSampleInfoEntry); if (!pSamp) return GF_OUT_OF_MEM; pSamp->SubSamples = gf_list_new(); if (!pSamp->SubSamples ) { @@ -818,7 +847,7 @@ GF_Err gf_isom_add_subsample_info(GF_SubSampleInformationBox *sub_samples, u32 s #endif /*GPAC_DISABLE_ISOM_WRITE*/ -u32 gf_isom_sample_get_subsample_entry(GF_ISOFile *movie, u32 track, u32 sampleNumber, GF_SampleEntry **sub_sample) +u32 gf_isom_sample_get_subsample_entry(GF_ISOFile *movie, u32 track, u32 sampleNumber, GF_SubSampleInfoEntry **sub_sample) { u32 i, count, last_sample; GF_SubSampleInformationBox *sub_samples; @@ -831,7 +860,7 @@ u32 gf_isom_sample_get_subsample_entry(GF_ISOFile *movie, u32 track, u32 sampleN last_sample = 0; count = gf_list_count(sub_samples->Samples); for (i=0; iSamples, i); + GF_SubSampleInfoEntry *pSamp = (GF_SubSampleInfoEntry *) gf_list_get(sub_samples->Samples, i); if (last_sample + pSamp->sample_delta == sampleNumber) { if (sub_sample) *sub_sample = pSamp; return gf_list_count(pSamp->SubSamples); diff --git a/src/isomedia/isom_read.c b/src/isomedia/isom_read.c index 94bc82d..8638353 100644 --- a/src/isomedia/isom_read.c +++ b/src/isomedia/isom_read.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -109,6 +110,11 @@ Bool gf_isom_probe_file(const char *fileName) #ifndef GPAC_DISABLE_ISOM_FRAGMENTS case GF_ISOM_BOX_TYPE_MOOF: case GF_ISOM_BOX_TYPE_STYP: +#ifndef GPAC_DISABLE_ISOM_ADOBE + /*Adobe specific*/ + case GF_ISOM_BOX_TYPE_AFRA: + case GF_ISOM_BOX_TYPE_ABST: +#endif #endif case GF_ISOM_BOX_TYPE_FREE: case GF_ISOM_BOX_TYPE_SKIP: @@ -438,6 +444,7 @@ u32 gf_isom_get_timescale(GF_ISOFile *movie) return movie->moov->mvhd->timeScale; } + //return the duration of the movie, 0 if error GF_EXPORT u64 gf_isom_get_duration(GF_ISOFile *movie) @@ -677,7 +684,7 @@ u32 gf_isom_get_sample_description_count(GF_ISOFile *the_file, u32 trackNumber) trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; - return gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + return gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); } @@ -757,7 +764,7 @@ u32 gf_isom_get_copyright_count(GF_ISOFile *mov) if (!mov || !mov->moov || !mov->moov->udta) return 0; map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_CPRT, NULL); if (!map) return 0; - return gf_list_count(map->boxList); + return gf_list_count(map->other_boxes); } GF_EXPORT @@ -772,9 +779,9 @@ GF_Err gf_isom_get_copyright(GF_ISOFile *mov, u32 Index, const char **threeCharC map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_CPRT, NULL); if (!map) return GF_OK; - if (Index > gf_list_count(map->boxList)) return GF_BAD_PARAM; + if (Index > gf_list_count(map->other_boxes)) return GF_BAD_PARAM; - cprt = (GF_CopyrightBox*)gf_list_get(map->boxList, Index-1); + cprt = (GF_CopyrightBox*)gf_list_get(map->other_boxes, Index-1); (*threeCharCode) = cprt->packedLanguageCode; (*notice) = cprt->notice; return GF_OK; @@ -792,7 +799,7 @@ GF_Err gf_isom_get_watermark(GF_ISOFile *mov, bin128 UUID, u8** data, u32* lengt map = udta_getEntry(mov->moov->udta, GF_ISOM_BOX_TYPE_UUID, (bin128 *) & UUID); if (!map) return GF_NOT_SUPPORTED; - wm = (GF_UnknownUUIDBox*)gf_list_get(map->boxList, 0); + wm = (GF_UnknownUUIDBox*)gf_list_get(map->other_boxes, 0); if (!wm) return GF_NOT_SUPPORTED; *data = (u8 *) gf_malloc(sizeof(char)*wm->dataSize); @@ -821,7 +828,7 @@ u32 gf_isom_get_chapter_count(GF_ISOFile *movie, u32 trackNumber) if (!udta) return 0; map = udta_getEntry(udta, GF_ISOM_BOX_TYPE_CHPL, NULL); if (!map) return 0; - lst = (GF_ChapterListBox *)gf_list_get(map->boxList, 0); + lst = (GF_ChapterListBox *)gf_list_get(map->other_boxes, 0); if (!lst) return 0; return gf_list_count(lst->list); } @@ -847,7 +854,7 @@ GF_Err gf_isom_get_chapter(GF_ISOFile *movie, u32 trackNumber, u32 Index, u64 *c if (!udta) return GF_BAD_PARAM; map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_CHPL, NULL); if (!map) return GF_BAD_PARAM; - lst = (GF_ChapterListBox *)gf_list_get(map->boxList, 0); + lst = (GF_ChapterListBox *)gf_list_get(map->other_boxes, 0); if (!lst) return GF_BAD_PARAM; ce = (GF_ChapterEntry *)gf_list_get(lst->list, Index-1); @@ -904,7 +911,7 @@ u8 gf_isom_is_track_encrypted(GF_ISOFile *the_file, u32 trackNumber) GF_Box *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 2; - entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, 0); + entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, 0); if (!entry) return 2; return IsMP4EncryptedDescription(entry->type); } @@ -916,7 +923,7 @@ u32 gf_isom_get_media_subtype(GF_ISOFile *the_file, u32 trackNumber, u32 Descrip GF_Box *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !DescriptionIndex) return 0; - entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); + entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!entry) return 0; //filter MPEG sub-types @@ -943,7 +950,7 @@ u32 gf_isom_get_mpeg4_subtype(GF_ISOFile *the_file, u32 trackNumber, u32 Descrip GF_Box *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !DescriptionIndex) return 0; - entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); + entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!entry) return 0; //filter MPEG sub-types @@ -1000,7 +1007,7 @@ GF_Err gf_isom_get_data_reference(GF_ISOFile *the_file, u32 trackNumber, u32 Str if (e) return e; if (!drefIndex) return GF_BAD_PARAM; - url = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, drefIndex - 1); + url = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->other_boxes, drefIndex - 1); if (!url) return GF_ISOM_INVALID_FILE; *outURL = *outURN = NULL; @@ -1042,7 +1049,7 @@ u32 gf_isom_get_constant_sample_size(GF_ISOFile *the_file, u32 trackNumber) } GF_EXPORT -Bool gf_isom_has_time_offset(GF_ISOFile *the_file, u32 trackNumber) +u32 gf_isom_has_time_offset(GF_ISOFile *the_file, u32 trackNumber) { u32 i; GF_CompositionOffsetBox *ctts; @@ -1053,7 +1060,7 @@ Bool gf_isom_has_time_offset(GF_ISOFile *the_file, u32 trackNumber) //return true at the first offset found ctts = trak->Media->information->sampleTable->CompositionOffset; for (i=0; inb_entries; i++) { - if (ctts->entries[i].decodingOffset && ctts->entries[i].sampleCount) return 1; + if (ctts->entries[i].decodingOffset && ctts->entries[i].sampleCount) return ctts->version ? 2 : 1; } return 0; } @@ -1666,7 +1673,7 @@ u32 gf_isom_get_user_data_count(GF_ISOFile *movie, u32 trackNumber, u32 UserData i=0; while ((map = (GF_UserDataMap*)gf_list_enum(udta->recordList, &i))) { - count = gf_list_count(map->boxList); + count = gf_list_count(map->other_boxes); if ((map->boxType == GF_ISOM_BOX_TYPE_UUID) && !memcmp(map->uuid, UUID, 16)) return count; else if (map->boxType == UserDataType) return count; @@ -1711,8 +1718,8 @@ GF_Err gf_isom_get_user_data(GF_ISOFile *movie, u32 trackNumber, u32 UserDataTyp found: - if (UserDataIndex > gf_list_count(map->boxList) ) return GF_BAD_PARAM; - ptr = (GF_UnknownBox*)gf_list_get(map->boxList, UserDataIndex-1); + if (UserDataIndex > gf_list_count(map->other_boxes) ) return GF_BAD_PARAM; + ptr = (GF_UnknownBox*)gf_list_get(map->other_boxes, UserDataIndex-1); //ok alloc the data *userData = (char *)gf_malloc(sizeof(char)*ptr->dataSize); @@ -1769,7 +1776,7 @@ GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min davg += chunk_dur; if (smin>chunk_size) smin = chunk_size; if (smaxentries[i].samplesPerChunk; @@ -1778,8 +1785,10 @@ GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min if (stsc->entries[i].firstChunk + nb_chunk == stsc->entries[i+1].firstChunk) break; } } - if (tot_chunks) davg /= tot_chunks; - + if (tot_chunks) { + davg /= tot_chunks; + savg /= tot_chunks; + } if (dur_min) *dur_min = dmin; if (dur_avg) *dur_avg = (u32) davg; if (dur_max) *dur_max = dmax; @@ -1954,6 +1963,7 @@ GF_Err gf_isom_release_segment(GF_ISOFile *movie, Bool reset_tables) for (i=0; imoov->trackList); i++) { GF_TrackBox *trak = gf_list_get(movie->moov->trackList, i); + trak->first_traf_merged = 0; if (trak->Media->information->dataHandler == movie->movieFileMap) { trak->Media->information->dataHandler = NULL; } @@ -1986,7 +1996,6 @@ GF_Err gf_isom_release_segment(GF_ISOFile *movie, Bool reset_tables) } } - movie->first_moof_merged = 0; gf_isom_datamap_del(movie->movieFileMap); movie->movieFileMap = NULL; #endif @@ -2053,7 +2062,7 @@ GF_GenericSampleDescription *gf_isom_get_generic_sample_description(GF_ISOFile * trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !StreamDescriptionIndex) return NULL; - entry = (GF_GenericVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex-1); + entry = (GF_GenericVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); //no entry or MPEG entry: if (!entry || IsMP4Description(entry->type) ) return NULL; //if we handle the description return false @@ -2076,7 +2085,7 @@ GF_GenericSampleDescription *gf_isom_get_generic_sample_description(GF_ISOFile * udesc->revision = entry->revision; udesc->vendor_code = entry->vendor; udesc->temporal_quality = entry->temporal_quality; - udesc->spacial_quality = entry->spacial_quality; + udesc->spatial_quality = entry->spatial_quality; udesc->width = entry->Width; udesc->height = entry->Height; udesc->h_res = entry->horiz_res; @@ -2140,9 +2149,9 @@ GF_Err gf_isom_get_visual_info(GF_ISOFile *movie, u32 trackNumber, u32 StreamDes stsd = trak->Media->information->sampleTable->SampleDescription; if (!stsd) return movie->LastError = GF_ISOM_INVALID_FILE; - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) return movie->LastError = GF_BAD_PARAM; + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) return movie->LastError = GF_BAD_PARAM; - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; @@ -2180,15 +2189,14 @@ GF_Err gf_isom_get_audio_info(GF_ISOFile *movie, u32 trackNumber, u32 StreamDesc stsd = trak->Media->information->sampleTable->SampleDescription; if (!stsd) return movie->LastError = GF_ISOM_INVALID_FILE; - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) return movie->LastError = GF_BAD_PARAM; + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) return movie->LastError = GF_BAD_PARAM; - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; switch (entry->type) { case GF_ISOM_BOX_TYPE_ENCA: - if (entry->protection_info && (entry->protection_info->original_format->data_format!= GF_ISOM_BOX_TYPE_MP4A)) return GF_ISOM_INVALID_MEDIA; case GF_ISOM_BOX_TYPE_MP4A: case GF_ISOM_SUBTYPE_3GP_AMR: case GF_ISOM_SUBTYPE_3GP_AMR_WB: @@ -2217,9 +2225,9 @@ GF_Err gf_isom_get_pixel_aspect_ratio(GF_ISOFile *movie, u32 trackNumber, u32 St stsd = trak->Media->information->sampleTable->SampleDescription; if (!stsd) return movie->LastError = GF_ISOM_INVALID_FILE; - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) return movie->LastError = GF_BAD_PARAM; + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) return movie->LastError = GF_BAD_PARAM; - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; @@ -2533,7 +2541,7 @@ GF_Err gf_isom_apple_get_tag(GF_ISOFile *mov, u32 tag, const char **data, u32 *d if (tag==GF_ISOM_ITUNE_PROBE) return GF_OK; i=0; - while ( (info=gf_list_enum(ilst->tags, &i))) { + while ( (info=gf_list_enum(ilst->other_boxes, &i))) { if (info->type==tag) break; /*special cases*/ if ((tag==GF_ISOM_ITUNE_GENRE) && (info->type==(u32) GF_ISOM_BOX_TYPE_0xA9GEN)) break; @@ -2573,7 +2581,7 @@ GF_Err gf_isom_get_track_switch_group_count(GF_ISOFile *movie, u32 trackNumber, map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_TSEL, NULL); if (!map) return 0; - *nb_groups = gf_list_count(map->boxList); + *nb_groups = gf_list_count(map->other_boxes); return GF_OK; } @@ -2589,7 +2597,7 @@ const u32 *gf_isom_get_track_switch_parameter(GF_ISOFile *movie, u32 trackNumber map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_TSEL, NULL); if (!map) return NULL; - tsel = gf_list_get(map->boxList, group_index-1); + tsel = gf_list_get(map->other_boxes, group_index-1); *switchGroupID = tsel->switchGroup; *criteriaListSize = tsel->attributeListCount; return (const u32 *) tsel->attributeList; @@ -2603,7 +2611,7 @@ GF_Err gf_isom_get_timed_meta_data_info(GF_ISOFile *file, u32 track, u32 sampleD GF_MetaDataSampleEntryBox *ptr; trak = gf_isom_get_track_from_file(file, track); if (!trak || !sampleDescription) return GF_BAD_PARAM; - ptr = (GF_MetaDataSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sampleDescription-1); + ptr = (GF_MetaDataSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, sampleDescription-1); if (!ptr) return GF_BAD_PARAM; if (ptr->type==GF_ISOM_BOX_TYPE_METX) { @@ -2641,7 +2649,7 @@ u32 gf_isom_sample_has_subsamples(GF_ISOFile *movie, u32 track, u32 sampleNumber GF_Err gf_isom_sample_get_subsample(GF_ISOFile *movie, u32 track, u32 sampleNumber, u32 subSampleNumber, u32 *size, u8 *priority, u32 *reserved, Bool *discardable) { GF_SubSampleEntry *entry; - GF_SampleEntry *sub_sample; + GF_SubSampleInfoEntry *sub_sample; u32 count = gf_isom_sample_get_subsample_entry(movie, track, sampleNumber, &sub_sample); if (!size || !priority || !discardable) return GF_BAD_PARAM; @@ -2667,7 +2675,7 @@ GF_Err gf_isom_get_rvc_config(GF_ISOFile *movie, u32 track, u32 sampleDescriptio if (!trak) return GF_BAD_PARAM; - entry = (GF_MPEGVisualSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sampleDescriptionIndex-1); + entry = (GF_MPEGVisualSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, sampleDescriptionIndex-1); if (!entry ) return GF_BAD_PARAM; switch (entry->type) { case GF_ISOM_BOX_TYPE_MP4V: @@ -2719,6 +2727,7 @@ void gf_isom_reset_fragment_info(GF_ISOFile *movie) #endif } +GF_EXPORT GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u32 sample_number, Bool *is_rap, Bool *has_roll, s32 *roll_distance) { GF_TrackBox *trak; @@ -2732,6 +2741,32 @@ GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u if (!trak) return GF_BAD_PARAM; if (!trak->Media->information->sampleTable->sampleGroups) return GF_OK; + if (!sample_number) { + count = gf_list_count(trak->Media->information->sampleTable->sampleGroupsDescription); + for (i=0; iMedia->information->sampleTable->sampleGroupsDescription, i); + switch (sgdesc->grouping_type) { + case GF_4CC('r','a','p',' '): + if (is_rap) *is_rap = 1; + break; + case GF_4CC('r','o','l','l'): + if (has_roll) *has_roll = 1; + if (roll_distance) { + s32 max_roll = 0; + u32 j; + for (j=0; jgroup_descriptions);j++) { + GF_RollRecoveryEntry *roll_entry = gf_list_get(sgdesc->group_descriptions, j); + if (max_roll < roll_entry->roll_distance) + max_roll = roll_entry->roll_distance; + } + if (*roll_distance < max_roll) *roll_distance = max_roll; + } + break; + } + } + return GF_OK; + } + count = gf_list_count(trak->Media->information->sampleTable->sampleGroups); for (i=0; isample_entries[j].group_description_index; + group_desc_index = 1 + sg->sample_entries[j].group_description_index; break; } /*no sampleGroup info associated*/ @@ -2779,4 +2814,35 @@ GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u return GF_OK; } +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS +//return the duration of the movie+fragments if known, 0 if error +GF_EXPORT +u64 gf_isom_get_fragmented_duration(GF_ISOFile *movie) +{ + if (movie->moov->mvex && movie->moov->mvex->mehd) + return movie->moov->mvex->mehd->fragment_duration; + + return 0; +} +//return the duration of the movie+fragments if known, 0 if error +GF_EXPORT +u32 gf_isom_get_fragments_count(GF_ISOFile *movie, Bool segments_only) +{ + u32 i=0; + u32 nb_frags = 0; + GF_Box *b; + while ((b=gf_list_enum(movie->TopBoxes, &i))) { + if (segments_only) { + if (b->type==GF_ISOM_BOX_TYPE_SIDX) + nb_frags++; + } else { + if (b->type==GF_ISOM_BOX_TYPE_MOOF) + nb_frags++; + } + } + return nb_frags; +} + +#endif + #endif /*GPAC_DISABLE_ISOM*/ diff --git a/src/isomedia/isom_store.c b/src/isomedia/isom_store.c index 6a954e6..73c746b 100644 --- a/src/isomedia/isom_store.c +++ b/src/isomedia/isom_store.c @@ -2,7 +2,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -361,10 +362,12 @@ GF_Err WriteSample(MovieWriter *mw, u32 size, u64 offset, u8 isEdited, GF_BitStr } //get the payload... bytes = gf_isom_datamap_get_data(map, mw->buffer, size, offset); - if (bytes != size) return GF_IO_ERR; + if (bytes != size) + return GF_IO_ERR; //write it to our stream... bytes = gf_bs_write_data(bs, mw->buffer, size); - if (bytes != size) return GF_IO_ERR; + if (bytes != size) + return GF_IO_ERR; mw->nb_done++; gf_set_progress("ISO File Writing", mw->nb_done, mw->total_samples); @@ -674,6 +677,10 @@ GF_Err WriteFlat(MovieWriter *mw, u8 moovFirst, GF_BitStream *bs) case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_PDIN: +#ifndef GPAC_DISABLE_ISOM_ADOBE + case GF_ISOM_BOX_TYPE_AFRA: + case GF_ISOM_BOX_TYPE_ABST: +#endif break; case GF_ISOM_BOX_TYPE_MDAT: //in case we're capturing @@ -704,6 +711,21 @@ GF_Err WriteFlat(MovieWriter *mw, u8 moovFirst, GF_BitStream *bs) e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; +#ifndef GPAC_DISABLE_ISOM_ADOBE + i=0; + while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) { + switch (a->type) { + case GF_ISOM_BOX_TYPE_AFRA: + case GF_ISOM_BOX_TYPE_ABST: + e = gf_isom_box_size(a); + if (e) goto exit; + e = gf_isom_box_write(a, bs); + if (e) goto exit; + break; + } + } +#endif + /*if data has been written, update mdat size*/ if (totSize) { offset = gf_bs_get_position(bs); @@ -958,9 +980,9 @@ GF_Err DoInterleave(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emul memset(blank, 0, sizeof(char)*1024*1024); while (iopenMode == GF_ISOM_OPEN_WRITE) { e = WriteFlat(&mw, 0, movie->editFileMap->bs); } else { + u32 buffer_size = movie->editFileMap ? gf_bs_get_output_buffering(movie->editFileMap->bs) : 0; + Bool is_stdout = 0; + if (!strcmp(movie->finalName, "std")) + is_stdout = 1; + //OK, we need a new bitstream - stream = gf_f64_open(movie->finalName, "w+b"); - if (!stream) return GF_IO_ERR; + stream = is_stdout ? stdout : gf_f64_open(movie->finalName, "w+b"); + if (!stream) + return GF_IO_ERR; bs = gf_bs_from_file(stream, GF_BITSTREAM_WRITE); if (!bs) { - fclose(stream); + if (!is_stdout) + fclose(stream); return GF_OUT_OF_MEM; } + if (buffer_size) { + gf_bs_set_output_buffering(bs, buffer_size); + } + switch (movie->storageMode) { case GF_ISOM_STORE_TIGHT: case GF_ISOM_STORE_INTERLEAVED: @@ -1280,7 +1314,8 @@ GF_Err WriteToFile(GF_ISOFile *movie) } gf_bs_del(bs); - fclose(stream); + if (!is_stdout) + fclose(stream); } if (mw.buffer) gf_free(mw.buffer); if (mw.nb_doneMedia->information->dataInformation->dref->boxList, dataRefIndex - 1); + Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->other_boxes, dataRefIndex - 1); if (!Dentry || Dentry->flags != 1) return GF_BAD_PARAM; //Open our data map. We are adding stuff, so use EDIT @@ -690,7 +691,7 @@ GF_Err gf_isom_add_sample_shadow(GF_ISOFile *movie, u32 trackNumber, GF_ISOSampl trak->Media->information->sampleTable->currentEntryIndex = descIndex; //get this dataRef and return false if not self contained - Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); + Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->other_boxes, dataRefIndex - 1); if (!Dentry || Dentry->flags != 1) return GF_BAD_PARAM; //Open our data map. We are adding stuff, so use EDIT @@ -763,7 +764,7 @@ GF_Err gf_isom_append_sample_data(GF_ISOFile *movie, u32 trackNumber, char *data if (!entry || !dataRefIndex) return GF_BAD_PARAM; //get this dataRef and return false if not self contained - Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); + Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->other_boxes, dataRefIndex - 1); if (!Dentry || Dentry->flags != 1) return GF_BAD_PARAM; //Open our data map. We are adding stuff, so use EDIT @@ -820,7 +821,7 @@ GF_Err gf_isom_add_sample_reference(GF_ISOFile *movie, u32 trackNumber, u32 Stre //get this dataRef and return false if self contained - Dentry =(GF_DataEntryURLBox*) gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); + Dentry =(GF_DataEntryURLBox*) gf_list_get(trak->Media->information->dataInformation->dref->other_boxes, dataRefIndex - 1); if (Dentry->flags == 1) return GF_BAD_PARAM; //add the meta data @@ -1126,10 +1127,10 @@ GF_Err gf_isom_change_mpeg4_description(GF_ISOFile *movie, u32 trackNumber, u32 stsd = trak->Media->information->sampleTable->SampleDescription; if (!stsd) return movie->LastError = GF_ISOM_INVALID_FILE; - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) { + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) { return movie->LastError = GF_BAD_PARAM; } - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; @@ -1156,10 +1157,10 @@ GF_Err gf_isom_set_visual_info(GF_ISOFile *movie, u32 trackNumber, u32 StreamDes if (!stsd) { return movie->LastError = GF_ISOM_INVALID_FILE; } - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) { + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) { return movie->LastError = GF_BAD_PARAM; } - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); @@ -1202,10 +1203,10 @@ GF_Err gf_isom_set_pixel_aspect_ratio(GF_ISOFile *movie, u32 trackNumber, u32 St stsd = trak->Media->information->sampleTable->SampleDescription; if (!stsd) return movie->LastError = GF_ISOM_INVALID_FILE; - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) { + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) { return movie->LastError = GF_BAD_PARAM; } - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); @@ -1248,10 +1249,10 @@ GF_Err gf_isom_set_audio_info(GF_ISOFile *movie, u32 trackNumber, u32 StreamDesc if (!stsd) { return movie->LastError = GF_ISOM_INVALID_FILE; } - if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->boxList)) { + if (!StreamDescriptionIndex || StreamDescriptionIndex > gf_list_count(stsd->other_boxes)) { return movie->LastError = GF_BAD_PARAM; } - entry = (GF_SampleEntryBox *)gf_list_get(stsd->boxList, StreamDescriptionIndex - 1); + entry = (GF_SampleEntryBox *)gf_list_get(stsd->other_boxes, StreamDescriptionIndex - 1); //no support for generic sample entries (eg, no MPEG4 descriptor) if (entry == NULL) return GF_BAD_PARAM; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); @@ -1587,10 +1588,10 @@ GF_Err gf_isom_remove_track(GF_ISOFile *movie, u32 trackNumber) i=0; while ((trak = (GF_TrackBox *)gf_list_enum(movie->moov->trackList, &i))) { if (trak == the_trak) continue; - if (! trak->References || ! gf_list_count(trak->References->boxList)) continue; + if (! trak->References || ! gf_list_count(trak->References->other_boxes)) continue; j=0; - while ((tref = (GF_TrackReferenceTypeBox *)gf_list_enum(trak->References->boxList, &j))) { + while ((tref = (GF_TrackReferenceTypeBox *)gf_list_enum(trak->References->other_boxes, &j))) { found = 0; for (k=0; ktrackIDCount; k++) { if (tref->trackIDs[k] == the_trak->Header->trackID) found++; @@ -1600,7 +1601,7 @@ GF_Err gf_isom_remove_track(GF_ISOFile *movie, u32 trackNumber) if (found == tref->trackIDCount) { gf_isom_box_del((GF_Box *)tref); j--; - gf_list_rem(trak->References->boxList, j); + gf_list_rem(trak->References->other_boxes, j); } else { newRefs = (u32*)gf_malloc(sizeof(u32) * (tref->trackIDCount - found)); found = 0; @@ -1617,7 +1618,7 @@ GF_Err gf_isom_remove_track(GF_ISOFile *movie, u32 trackNumber) } } //a little opt: remove the ref box if empty... - if (! gf_list_count(trak->References->boxList)) { + if (! gf_list_count(trak->References->other_boxes)) { gf_isom_box_del((GF_Box *)trak->References); trak->References = NULL; } @@ -1660,9 +1661,9 @@ GF_Err gf_isom_set_copyright(GF_ISOFile *movie, const char *threeCharCode, char if (map) { //try to find one in our language... - count = gf_list_count(map->boxList); + count = gf_list_count(map->other_boxes); for (i=0; iboxList, i); + ptr = (GF_CopyrightBox*)gf_list_get(map->other_boxes, i); if (!strcmp(threeCharCode, (const char *) ptr->packedLanguageCode)) { gf_free(ptr->notice); ptr->notice = (char*)gf_malloc(sizeof(char) * (strlen(notice) + 1)); @@ -1718,12 +1719,12 @@ GF_Err gf_isom_add_chapter(GF_ISOFile *movie, u32 trackNumber, u64 timestamp, ch e = udta_AddBox(udta, (GF_Box *) ptr); if (e) return e; } else { - ptr = (GF_ChapterListBox*)gf_list_get(map->boxList, 0); + ptr = (GF_ChapterListBox*)gf_list_get(map->other_boxes, 0); } /*this may happen if original MP4 is not properly formatted*/ if (!ptr) { ptr = (GF_ChapterListBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_CHPL); - gf_list_add(map->boxList, ptr); + gf_list_add(map->other_boxes, ptr); } GF_SAFEALLOC(ce, GF_ChapterEntry); @@ -1777,7 +1778,7 @@ GF_Err gf_isom_remove_chapter(GF_ISOFile *movie, u32 trackNumber, u32 index) map = udta_getEntry(udta, GF_ISOM_BOX_TYPE_CHPL, NULL); if (!map) return GF_OK; - ptr = (GF_ChapterListBox*)gf_list_get(map->boxList, 0); + ptr = (GF_ChapterListBox*)gf_list_get(map->other_boxes, 0); if (!ptr) return GF_OK; if (index) { @@ -1796,7 +1797,7 @@ GF_Err gf_isom_remove_chapter(GF_ISOFile *movie, u32 trackNumber, u32 index) } if (!gf_list_count(ptr->list)) { gf_list_del_item(udta->recordList, map); - gf_isom_box_array_del(map->boxList); + gf_isom_box_array_del(map->other_boxes); gf_free(map); } return GF_OK; @@ -1819,19 +1820,19 @@ GF_Err gf_isom_remove_copyright(GF_ISOFile *movie, u32 index) map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_CPRT, NULL); if (!map) return GF_OK; - count = gf_list_count(map->boxList); + count = gf_list_count(map->other_boxes); if (index>count) return GF_BAD_PARAM; - ptr = (GF_CopyrightBox*)gf_list_get(map->boxList, index-1); + ptr = (GF_CopyrightBox*)gf_list_get(map->other_boxes, index-1); if (ptr) { - gf_list_rem(map->boxList, index-1); + gf_list_rem(map->other_boxes, index-1); if (ptr->notice) gf_free(ptr->notice); gf_free(ptr); } /*last copyright, remove*/ - if (!gf_list_count(map->boxList)) { + if (!gf_list_count(map->other_boxes)) { gf_list_del_item(movie->moov->udta->recordList, map); - gf_list_del(map->boxList); + gf_list_del(map->other_boxes); gf_free(map); } return GF_OK; @@ -1856,7 +1857,7 @@ GF_Err gf_isom_set_watermark(GF_ISOFile *movie, bin128 UUID, u8* data, u32 lengt map = udta_getEntry(movie->moov->udta, GF_ISOM_BOX_TYPE_UUID, (bin128 *) & UUID); if (map) { - ptr = (GF_UnknownUUIDBox *)gf_list_get(map->boxList, 0); + ptr = (GF_UnknownUUIDBox *)gf_list_get(map->other_boxes, 0); if (ptr) { gf_free(ptr->data); ptr->data = (char*)gf_malloc(length); @@ -2162,17 +2163,17 @@ GF_Err gf_isom_remove_user_data_item(GF_ISOFile *movie, u32 trackNumber, u32 Use found: - if (UserDataIndex > gf_list_count(map->boxList) ) return GF_BAD_PARAM; + if (UserDataIndex > gf_list_count(map->other_boxes) ) return GF_BAD_PARAM; //delete the box - a = (GF_Box*)gf_list_get(map->boxList, UserDataIndex-1); + a = (GF_Box*)gf_list_get(map->other_boxes, UserDataIndex-1); - gf_list_rem(map->boxList, UserDataIndex-1); + gf_list_rem(map->other_boxes, UserDataIndex-1); gf_isom_box_del(a); //remove the map if empty - if (!gf_list_count(map->boxList)) { + if (!gf_list_count(map->other_boxes)) { gf_list_rem(udta->recordList, i-1); - gf_isom_box_array_del(map->boxList); + gf_isom_box_array_del(map->other_boxes); gf_free(map); } //but we keep the UDTA no matter what @@ -2214,7 +2215,7 @@ GF_Err gf_isom_remove_user_data(GF_ISOFile *movie, u32 trackNumber, u32 UserData found: gf_list_rem(udta->recordList, i-1); - gf_isom_box_array_del(map->boxList); + gf_isom_box_array_del(map->other_boxes); gf_free(map); //but we keep the UDTA no matter what @@ -2334,7 +2335,7 @@ GF_Err gf_isom_clone_pl_indications(GF_ISOFile *orig, GF_ISOFile *dest) return GF_OK; } -static GF_Err clone_box(GF_Box *src, GF_Box **dst) +GF_Err gf_isom_clone_box(GF_Box *src, GF_Box **dst) { GF_Err e; char *data; @@ -2362,6 +2363,8 @@ static GF_Err clone_box(GF_Box *src, GF_Box **dst) GF_Err gf_isom_clone_movie(GF_ISOFile *orig_file, GF_ISOFile *dest_file, Bool clone_tracks, Bool keep_hint_tracks) { GF_Err e; + u32 i; + GF_Box *box; e = CanAccessMovie(dest_file, GF_ISOM_OPEN_WRITE); if (e) return e; @@ -2370,7 +2373,7 @@ GF_Err gf_isom_clone_movie(GF_ISOFile *orig_file, GF_ISOFile *dest_file, Bool cl gf_list_del_item(dest_file->TopBoxes, dest_file->brand); gf_isom_box_del((GF_Box *)dest_file->brand); dest_file->brand = NULL; - clone_box((GF_Box *)orig_file->brand, (GF_Box **)&dest_file->brand); + gf_isom_clone_box((GF_Box *)orig_file->brand, (GF_Box **)&dest_file->brand); if (dest_file->brand) gf_list_add(dest_file->TopBoxes, dest_file->brand); } @@ -2379,7 +2382,7 @@ GF_Err gf_isom_clone_movie(GF_ISOFile *orig_file, GF_ISOFile *dest_file, Bool cl gf_isom_box_del((GF_Box *)dest_file->meta); dest_file->meta = NULL; /*fixme - check imports*/ - clone_box((GF_Box *)orig_file->meta, (GF_Box **)dest_file->meta); + gf_isom_clone_box((GF_Box *)orig_file->meta, (GF_Box **)&dest_file->meta); if (dest_file->meta) gf_list_add(dest_file->TopBoxes, dest_file->meta); } if (orig_file->moov) { @@ -2390,7 +2393,7 @@ GF_Err gf_isom_clone_movie(GF_ISOFile *orig_file, GF_ISOFile *dest_file, Bool cl orig_file->moov->trackList = tracks; iods = (GF_Box*)orig_file->moov->iods; orig_file->moov->iods = NULL; - clone_box((GF_Box *)orig_file->moov, (GF_Box **)&dest_file->moov); + gf_isom_clone_box((GF_Box *)orig_file->moov, (GF_Box **)&dest_file->moov); orig_file->moov->trackList = old_tracks; gf_list_del(tracks); orig_file->moov->iods = (GF_ObjectDescriptorBox*)iods; @@ -2404,13 +2407,40 @@ GF_Err gf_isom_clone_movie(GF_ISOFile *orig_file, GF_ISOFile *dest_file, Bool cl } } if (iods) - clone_box((GF_Box *)orig_file->moov->iods, (GF_Box **)dest_file->moov->iods); + gf_isom_clone_box((GF_Box *)orig_file->moov->iods, (GF_Box **)dest_file->moov->iods); } else { dest_file->moov->mvhd->nextTrackID = 1; gf_isom_clone_pl_indications(orig_file, dest_file); } dest_file->moov->mov = dest_file; } + + //duplicate other boxes + i=0; + while ((box = (GF_Box*)gf_list_get(orig_file->TopBoxes, i++))) { + switch(box->type) { + case GF_ISOM_BOX_TYPE_MOOV: + case GF_ISOM_BOX_TYPE_META: + case GF_ISOM_BOX_TYPE_MDAT: + case GF_ISOM_BOX_TYPE_FTYP: + case GF_ISOM_BOX_TYPE_PDIN: +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + case GF_ISOM_BOX_TYPE_STYP: + case GF_ISOM_BOX_TYPE_SIDX: + case GF_ISOM_BOX_TYPE_MOOF: +#endif + case GF_4CC('j','P',' ',' '): + break; + default: + { + GF_Box *box2 = NULL; + gf_isom_clone_box(box, &box2); + gf_list_add(dest_file->TopBoxes, box2); + } + break; + } + } + return GF_OK; } @@ -2494,10 +2524,10 @@ GF_Err gf_isom_clone_track(GF_ISOFile *orig_file, u32 orig_track, GF_ISOFile *de /*reset data ref*/ if (!keep_data_ref) { - gf_isom_box_array_del(new_tk->Media->information->dataInformation->dref->boxList); - new_tk->Media->information->dataInformation->dref->boxList = gf_list_new(); + gf_isom_box_array_del(new_tk->Media->information->dataInformation->dref->other_boxes); + new_tk->Media->information->dataInformation->dref->other_boxes = gf_list_new(); /*update data ref*/ - entry = (GF_SampleEntryBox*)gf_list_get(new_tk->Media->information->sampleTable->SampleDescription->boxList, 0); + entry = (GF_SampleEntryBox*)gf_list_get(new_tk->Media->information->sampleTable->SampleDescription->other_boxes, 0); if (entry) { u32 dref; Media_CreateDataRef(new_tk->Media->information->dataInformation->dref, NULL, NULL, &dref); @@ -2526,11 +2556,11 @@ GF_Err gf_isom_clone_sample_descriptions(GF_ISOFile *the_file, u32 trackNumber, if (!src_trak || !src_trak->Media) return GF_BAD_PARAM; if (reset_existing) { - gf_isom_box_array_del(dst_trak->Media->information->sampleTable->SampleDescription->boxList); - dst_trak->Media->information->sampleTable->SampleDescription->boxList = gf_list_new(); + gf_isom_box_array_del(dst_trak->Media->information->sampleTable->SampleDescription->other_boxes); + dst_trak->Media->information->sampleTable->SampleDescription->other_boxes = gf_list_new(); } - for (i=0; iMedia->information->sampleTable->SampleDescription->boxList); i++) { + for (i=0; iMedia->information->sampleTable->SampleDescription->other_boxes); i++) { u32 outDesc; e = gf_isom_clone_sample_description(the_file, trackNumber, orig_file, orig_track, i+1, NULL, NULL, &outDesc); if (e) break; @@ -2557,7 +2587,7 @@ GF_Err gf_isom_clone_sample_description(GF_ISOFile *the_file, u32 trackNumber, G trak = gf_isom_get_track_from_file(orig_file, orig_track); if (!trak || !trak->Media) return GF_BAD_PARAM; - entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, orig_desc_index-1); + entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, orig_desc_index-1); if (!entry) return GF_BAD_PARAM; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); @@ -2586,8 +2616,8 @@ GF_Err gf_isom_clone_sample_description(GF_ISOFile *the_file, u32 trackNumber, G trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); /*overwrite dref*/ ((GF_SampleEntryBox *)entry)->dataReferenceIndex = dataRefIndex; - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, entry); - *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); + *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); /*also clone track w/h info*/ if (gf_isom_get_media_type(the_file, trackNumber) == GF_ISOM_MEDIA_VISUAL) { @@ -2639,7 +2669,7 @@ GF_Err gf_isom_new_generic_sample_description(GF_ISOFile *movie, u32 trackNumber entry->version = udesc->version; entry->revision = udesc->revision; entry->temporal_quality = udesc->temporal_quality; - entry->spacial_quality = udesc->spacial_quality; + entry->spatial_quality = udesc->spatial_quality; entry->Width = udesc->width; entry->Height = udesc->height; strcpy(entry->compressor_name, udesc->compressor_name); @@ -2657,7 +2687,7 @@ GF_Err gf_isom_new_generic_sample_description(GF_ISOFile *movie, u32 trackNumber memcpy(entry->data, udesc->extension_buf, udesc->extension_buf_size); entry->data_size = udesc->extension_buf_size; } - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, entry); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); } else if (trak->Media->handler->handlerType==GF_ISOM_MEDIA_AUDIO) { GF_GenericAudioSampleEntryBox *gena; @@ -2689,7 +2719,7 @@ GF_Err gf_isom_new_generic_sample_description(GF_ISOFile *movie, u32 trackNumber memcpy(gena->data, udesc->extension_buf, udesc->extension_buf_size); gena->data_size = udesc->extension_buf_size; } - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, gena); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, gena); } else { GF_GenericSampleEntryBox *genm; @@ -2713,9 +2743,9 @@ GF_Err gf_isom_new_generic_sample_description(GF_ISOFile *movie, u32 trackNumber memcpy(genm->data, udesc->extension_buf, udesc->extension_buf_size); genm->data_size = udesc->extension_buf_size; } - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, genm); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, genm); } - *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); return e; } @@ -2733,14 +2763,14 @@ GF_Err gf_isom_change_generic_sample_description(GF_ISOFile *movie, u32 trackNum trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !StreamDescriptionIndex) return GF_BAD_PARAM; - entry = (GF_GenericVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex-1); + entry = (GF_GenericVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); if (!entry) return GF_BAD_PARAM; if (entry->type == GF_ISOM_BOX_TYPE_GNRV) { entry->vendor = udesc->vendor_code; entry->version = udesc->version; entry->revision = udesc->revision; entry->temporal_quality = udesc->temporal_quality; - entry->spacial_quality = udesc->spacial_quality; + entry->spatial_quality = udesc->spatial_quality; entry->Width = udesc->width; entry->Height = udesc->height; strcpy(entry->compressor_name, udesc->compressor_name); @@ -2816,9 +2846,9 @@ GF_Err gf_isom_remove_sample_description(GF_ISOFile *movie, u32 trackNumber, u32 if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !streamDescIndex) return GF_BAD_PARAM; - entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, streamDescIndex-1); + entry = (GF_Box*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, streamDescIndex-1); if (!entry) return GF_BAD_PARAM; - gf_list_rem(trak->Media->information->sampleTable->SampleDescription->boxList, streamDescIndex-1); + gf_list_rem(trak->Media->information->sampleTable->SampleDescription->other_boxes, streamDescIndex-1); gf_isom_box_del(entry); return GF_OK; } @@ -2878,9 +2908,9 @@ GF_Err gf_isom_remove_track_reference(GF_ISOFile *the_file, u32 trackNumber, u32 //last one if (dpnd->trackIDCount==1) { i=0; - while ((tmp = (GF_TrackReferenceTypeBox *)gf_list_enum(tref->boxList, &i))) { + while ((tmp = (GF_TrackReferenceTypeBox *)gf_list_enum(tref->other_boxes, &i))) { if (tmp==dpnd) { - gf_list_rem(tref->boxList, i-1); + gf_list_rem(tref->other_boxes, i-1); gf_isom_box_del((GF_Box *) dpnd); return GF_OK; } @@ -2921,7 +2951,7 @@ GF_Err gf_isom_set_track_id(GF_ISOFile *movie, u32 trackNumber, u32 trackID) while ((a_trak = (GF_TrackBox*)gf_list_enum(movie->moov->trackList, &i))) { if (!a_trak->References) continue; j=0; - while ((ref = (GF_TrackReferenceTypeBox *)gf_list_enum(a_trak->References->boxList, &j))) { + while ((ref = (GF_TrackReferenceTypeBox *)gf_list_enum(a_trak->References->other_boxes, &j))) { for (k=0; ktrackIDCount; k++) { if (ref->trackIDs[k]==trak->Header->trackID) { ref->trackIDs[k] = trackID; @@ -3134,7 +3164,8 @@ GF_Err gf_isom_load_movie_config(GF_ISOFile *movie) return found_cfg ? GF_OK : GF_NOT_SUPPORTED; } -GF_Err gf_isom_set_media_timescale(GF_ISOFile *the_file, u32 trackNumber, u32 newTS) +GF_EXPORT +GF_Err gf_isom_set_media_timescale(GF_ISOFile *the_file, u32 trackNumber, u32 newTS, Bool force_rescale) { Double scale; GF_TrackBox *trak; @@ -3145,11 +3176,27 @@ GF_Err gf_isom_set_media_timescale(GF_ISOFile *the_file, u32 trackNumber, u32 ne scale = newTS; scale /= trak->Media->mediaHeader->timeScale; trak->Media->mediaHeader->timeScale = newTS; - if (trak->editBox) { - GF_EdtsEntry *ent; - u32 i=0; - while ((ent = (GF_EdtsEntry*)gf_list_enum(trak->editBox->editList->entryList, &i))) { - ent->mediaTime = (u32) (scale*ent->mediaTime); + if (!force_rescale) { + if (trak->editBox) { + GF_EdtsEntry *ent; + u32 i=0; + while ((ent = (GF_EdtsEntry*)gf_list_enum(trak->editBox->editList->entryList, &i))) { + ent->mediaTime = (u32) (scale*ent->mediaTime); + } + } + if (trak->Media->information->sampleTable) { + u32 i; + GF_SampleTableBox *stbl = trak->Media->information->sampleTable; + if (stbl->TimeToSample) { + for (i=0; iTimeToSample->nb_entries; i++) { + stbl->TimeToSample->entries[i].sampleDelta = (u32) (scale * stbl->TimeToSample->entries[i].sampleDelta); + } + } + if (stbl->CompositionOffset) { + for (i=0; iCompositionOffset->nb_entries; i++) { + stbl->CompositionOffset->entries[i].decodingOffset = (u32) (scale * stbl->CompositionOffset->entries[i].decodingOffset); + } + } } } return SetTrackDuration(trak); @@ -3175,18 +3222,18 @@ Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, u32 sdesc_index if (!trak2 || !trak2->Media) return 0; if (trak1->Media->handler->handlerType != trak2->Media->handler->handlerType) return 0; - count = gf_list_count(trak1->Media->information->sampleTable->SampleDescription->boxList); - if (count != gf_list_count(trak2->Media->information->sampleTable->SampleDescription->boxList)) { + count = gf_list_count(trak1->Media->information->sampleTable->SampleDescription->other_boxes); + if (count != gf_list_count(trak2->Media->information->sampleTable->SampleDescription->other_boxes)) { if (!sdesc_index1 && !sdesc_index2) return 0; } need_memcmp = 1; for (i=0; iMedia->information->sampleTable->SampleDescription->boxList, i); - GF_Box *ent2 = (GF_Box *)gf_list_get(trak2->Media->information->sampleTable->SampleDescription->boxList, i); + GF_Box *ent1 = (GF_Box *)gf_list_get(trak1->Media->information->sampleTable->SampleDescription->other_boxes, i); + GF_Box *ent2 = (GF_Box *)gf_list_get(trak2->Media->information->sampleTable->SampleDescription->other_boxes, i); - if (sdesc_index1) ent1 = (GF_Box *)gf_list_get(trak1->Media->information->sampleTable->SampleDescription->boxList, sdesc_index1 - 1); - if (sdesc_index2) ent2 = (GF_Box *)gf_list_get(trak2->Media->information->sampleTable->SampleDescription->boxList, sdesc_index2 - 1); + if (sdesc_index1) ent1 = (GF_Box *)gf_list_get(trak1->Media->information->sampleTable->SampleDescription->other_boxes, sdesc_index1 - 1); + if (sdesc_index2) ent2 = (GF_Box *)gf_list_get(trak2->Media->information->sampleTable->SampleDescription->other_boxes, sdesc_index2 - 1); if (!ent1 || !ent2) return 0; if (ent1->type != ent2->type) return 0; @@ -3199,8 +3246,8 @@ Bool gf_isom_is_same_sample_description(GF_ISOFile *f1, u32 tk1, u32 sdesc_index case GF_ISOM_BOX_TYPE_ENCA: case GF_ISOM_BOX_TYPE_ENCV: case GF_ISOM_BOX_TYPE_ENCS: - Media_GetESD(trak1->Media, sdesc_index1 , &esd1, 1); - Media_GetESD(trak2->Media, sdesc_index2 , &esd2, 1); + Media_GetESD(trak1->Media, sdesc_index1 ? sdesc_index1 : i+1, &esd1, 1); + Media_GetESD(trak2->Media, sdesc_index2 ? sdesc_index2 : i+1, &esd2, 1); if (!esd1 || !esd2) continue; need_memcmp = 0; if (esd1->decoderConfig->streamType != esd2->decoderConfig->streamType) return 0; @@ -3641,7 +3688,7 @@ GF_Err gf_isom_set_media_subtype(GF_ISOFile *movie, u32 trackNumber, u32 sampleD GF_TrackBox *trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !sampleDescriptionIndex || !new_type) return GF_BAD_PARAM; - entry = (GF_SampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sampleDescriptionIndex - 1); + entry = (GF_SampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, sampleDescriptionIndex - 1); if (!entry) return GF_BAD_PARAM; entry->type = new_type; return GF_OK; @@ -3667,13 +3714,13 @@ GF_Err gf_isom_remove_uuid(GF_ISOFile *movie, u32 trackNumber, bin128 UUID) } else if (trackNumber) { GF_TrackBox *trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; - list = trak->boxes; + list = trak->other_boxes; } else { if (!movie) return GF_BAD_PARAM; - list = movie->moov->boxes; + list = movie->moov->other_boxes; } - count = gf_list_count(list); + count = list ? gf_list_count(list) : 0; for (i=0; itype != GF_ISOM_BOX_TYPE_UUID) continue; @@ -3700,10 +3747,12 @@ GF_Err gf_isom_add_uuid(GF_ISOFile *movie, u32 trackNumber, bin128 UUID, char *d } else if (trackNumber) { GF_TrackBox *trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; - list = trak->boxes; + if (!trak->other_boxes) trak->other_boxes = gf_list_new(); + list = trak->other_boxes; } else { if (!movie) return GF_BAD_PARAM; - list = movie->moov->boxes; + if (!movie->moov->other_boxes) movie->moov->other_boxes = gf_list_new(); + list = movie->moov->other_boxes; } GF_SAFEALLOC(uuid, GF_UnknownUUIDBox); @@ -3745,9 +3794,9 @@ GF_Err gf_isom_apple_set_tag(GF_ISOFile *mov, u32 tag, const char *data, u32 dat } /*remove tag*/ i = 0; - while ((info = gf_list_enum(ilst->tags, &i))) { + while ((info = gf_list_enum(ilst->other_boxes, &i))) { if (info->type==btype) { - gf_list_rem(ilst->tags, i-1); + gf_list_rem(ilst->other_boxes, i-1); gf_isom_box_del((GF_Box *) info); break; } @@ -3806,7 +3855,7 @@ GF_Err gf_isom_apple_set_tag(GF_ISOFile *mov, u32 tag, const char *data, u32 dat info->data->flags = 0x15; gf_bs_del(bs); } - return gf_list_add(ilst->tags, info); + return gf_list_add(ilst->other_boxes, info); } GF_EXPORT @@ -3858,9 +3907,9 @@ GF_Err gf_isom_set_track_switch_parameter(GF_ISOFile *movie, u32 trackNumber, u3 u32 j, count; map = udta_getEntry(a_trak->udta, GF_ISOM_BOX_TYPE_TSEL, NULL); if (map) { - count = gf_list_count(map->boxList); + count = gf_list_count(map->other_boxes); for (j=0; jboxList, j); + tsel = gf_list_get(map->other_boxes, j); if (*switchGroupID) { if (tsel->switchGroup==next_switch_group_id) { @@ -3893,9 +3942,9 @@ GF_Err gf_isom_set_track_switch_parameter(GF_ISOFile *movie, u32 trackNumber, u3 /*locate tsel box with no switch group*/ if (map) { - u32 j, count = gf_list_count(map->boxList); + u32 j, count = gf_list_count(map->other_boxes); for (j=0; jboxList, j); + tsel = gf_list_get(map->other_boxes, j); if (tsel->switchGroup == *switchGroupID) break; tsel = NULL; } @@ -3922,7 +3971,7 @@ void reset_tsel_box(GF_TrackBox *trak) map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_TSEL, NULL); if (map) { gf_list_del_item(trak->udta->recordList, map); - gf_isom_box_array_del(map->boxList); + gf_isom_box_array_del(map->other_boxes); gf_free(map); } @@ -4001,8 +4050,8 @@ GF_Err gf_isom_timed_meta_data_config_new(GF_ISOFile *movie, u32 trackNumber, Bo if (content_encoding) metad->content_encoding = gf_strdup(content_encoding); if (schema_loc) metad->xml_schema_loc = gf_strdup(schema_loc); - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, metad); - if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, metad); + if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); return e; } @@ -4045,7 +4094,7 @@ GF_Err gf_isom_set_rvc_config(GF_ISOFile *movie, u32 track, u32 sampleDescriptio if (!trak) return GF_BAD_PARAM; - entry = (GF_MPEGVisualSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sampleDescriptionIndex-1); + entry = (GF_MPEGVisualSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, sampleDescriptionIndex-1); if (!entry ) return GF_BAD_PARAM; switch (entry->type) { case GF_ISOM_BOX_TYPE_MP4V: @@ -4259,6 +4308,107 @@ GF_Err gf_isom_set_sample_roll_group(GF_ISOFile *movie, u32 track, u32 sample_nu return gf_isom_set_sample_group_info(movie, track, sample_number, GF_4CC( 'r', 'o', 'l', 'l' ), &roll_distance, sg_roll_create_entry, sg_roll_compare_entry); } +static GF_Err gf_isom_set_ctts_v1(GF_ISOFile *file, u32 track, GF_TrackBox *trak) +{ + u32 i, shift; + u64 duration; + GF_CompositionOffsetBox *ctts; + GF_CompositionToDecodeBox *cslg; + s32 leastCTTS, greatestCTTS; + + ctts = trak->Media->information->sampleTable->CompositionOffset; + shift = ctts->entries[0].decodingOffset; + leastCTTS = 0; + greatestCTTS = 0; + for (i=0; inb_entries; i++) { + ctts->entries[i].decodingOffset -= shift; + if ((s32)ctts->entries[i].decodingOffset < leastCTTS) + leastCTTS = ctts->entries[i].decodingOffset; + if ((s32)ctts->entries[i].decodingOffset > greatestCTTS) + greatestCTTS = ctts->entries[i].decodingOffset; + } + ctts->version = 1; + + + if (!trak->Media->information->sampleTable->CompositionToDecode) + trak->Media->information->sampleTable->CompositionToDecode = (GF_CompositionToDecodeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CSLG); + + cslg = trak->Media->information->sampleTable->CompositionToDecode; + + cslg->compositionToDTSShift = -leastCTTS; + cslg->leastDecodeToDisplayDelta = leastCTTS; + cslg->greatestDecodeToDisplayDelta = greatestCTTS; + cslg->compositionStartTime = 0; + /*for our use case (first CTS set to 0), the composition end time is the media duration if it fits on 32 bits*/ + duration = gf_isom_get_media_duration(file, track); + cslg->compositionEndTime = (duration<0x7FFFFFFF) ? (s32) duration : 0; + + gf_isom_set_brand_info(file, GF_ISOM_BRAND_ISO4, 0); + return GF_OK; +} + +static GF_Err gf_isom_set_ctts_v0(GF_ISOFile *file, GF_TrackBox *trak) +{ + u32 i; + s32 shift; + GF_CompositionOffsetBox *ctts; + GF_CompositionToDecodeBox *cslg; + + ctts = trak->Media->information->sampleTable->CompositionOffset; + + if (!trak->Media->information->sampleTable->CompositionToDecode) + { + shift = 0; + for (i=0; inb_entries; i++) { + if (-ctts->entries[i].decodingOffset > shift) + shift = -ctts->entries[i].decodingOffset; + } + if (shift > 0) + { + for (i=0; inb_entries; i++) { + ctts->entries[i].decodingOffset += shift; + } + } + } + else + { + cslg = trak->Media->information->sampleTable->CompositionToDecode; + shift = cslg->compositionToDTSShift; + for (i=0; inb_entries; i++) { + ctts->entries[i].decodingOffset += shift; + } + gf_isom_box_del((GF_Box *)cslg); + trak->Media->information->sampleTable->CompositionToDecode = NULL; + } + ctts->version = 0; + gf_isom_set_brand_info(file, GF_ISOM_BRAND_ISOM, 1); + return GF_OK; +} + +GF_EXPORT +GF_Err gf_isom_set_composition_offset_mode(GF_ISOFile *file, u32 track, Bool use_negative_offsets) +{ + GF_Err e; + GF_TrackBox *trak; + GF_CompositionOffsetBox *ctts; + + e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); + if (e) return e; + + trak = gf_isom_get_track_from_file(file, track); + if (!trak) return GF_BAD_PARAM; + + ctts = trak->Media->information->sampleTable->CompositionOffset; + if (!ctts) return GF_OK; + + if (use_negative_offsets) { + if (ctts->version==1) return GF_OK; + return gf_isom_set_ctts_v1(file, track, trak); + } else { + if (ctts->version==0) return GF_OK; + return gf_isom_set_ctts_v0(file, trak); + } +} #endif /*!defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_WRITE)*/ diff --git a/src/isomedia/media.c b/src/isomedia/media.c index c84bfa9..24a6d20 100644 --- a/src/isomedia/media.c +++ b/src/isomedia/media.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -36,9 +37,9 @@ GF_Err Media_GetSampleDesc(GF_MediaBox *mdia, u32 SampleDescIndex, GF_SampleEntr stsd = mdia->information->sampleTable->SampleDescription; if (!stsd) return GF_ISOM_INVALID_FILE; - if (!SampleDescIndex || (SampleDescIndex > gf_list_count(stsd->boxList)) ) return GF_BAD_PARAM; + if (!SampleDescIndex || (SampleDescIndex > gf_list_count(stsd->other_boxes)) ) return GF_BAD_PARAM; - entry = (GF_SampleEntryBox*)gf_list_get(stsd->boxList, SampleDescIndex - 1); + entry = (GF_SampleEntryBox*)gf_list_get(stsd->other_boxes, SampleDescIndex - 1); if (!entry) return GF_ISOM_INVALID_FILE; if (out_entry) *out_entry = entry; @@ -60,7 +61,7 @@ GF_Err Media_GetSampleDescIndex(GF_MediaBox *mdia, u64 DTS, u32 *sampleDescIndex if (!sampleNumber && !prevSampleNumber) { //we have to assume the track was created to be used... If we have a sampleDesc, OK - if (gf_list_count(mdia->information->sampleTable->SampleDescription->boxList)) { + if (gf_list_count(mdia->information->sampleTable->SampleDescription->other_boxes)) { (*sampleDescIndex) = 1; return GF_OK; } @@ -153,11 +154,11 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo GF_SampleDescriptionBox *stsd = mdia->information->sampleTable->SampleDescription; *out_esd = NULL; - if (!stsd || !stsd->boxList || !sampleDescIndex || (sampleDescIndex > gf_list_count(stsd->boxList)) ) + if (!stsd || !stsd->other_boxes || !sampleDescIndex || (sampleDescIndex > gf_list_count(stsd->other_boxes)) ) return GF_BAD_PARAM; esd = NULL; - entry = (GF_MPEGSampleEntryBox*)gf_list_get(stsd->boxList, sampleDescIndex - 1); + entry = (GF_MPEGSampleEntryBox*)gf_list_get(stsd->other_boxes, sampleDescIndex - 1); if (! entry) return GF_ISOM_INVALID_MEDIA; *out_esd = NULL; @@ -396,9 +397,9 @@ GF_Err Media_CheckDataEntry(GF_MediaBox *mdia, u32 dataEntryIndex) GF_DataEntryURLBox *entry; GF_DataMap *map; GF_Err e; - if (!mdia || !dataEntryIndex || dataEntryIndex > gf_list_count(mdia->information->dataInformation->dref->boxList)) return GF_BAD_PARAM; + if (!mdia || !dataEntryIndex || dataEntryIndex > gf_list_count(mdia->information->dataInformation->dref->other_boxes)) return GF_BAD_PARAM; - entry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, dataEntryIndex - 1); + entry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->other_boxes, dataEntryIndex - 1); if (!entry) return GF_ISOM_INVALID_FILE; if (entry->flags == 1) return GF_OK; @@ -424,7 +425,7 @@ Bool Media_IsSelfContained(GF_MediaBox *mdia, u32 StreamDescIndex) Media_GetSampleDesc(mdia, StreamDescIndex, &se, &drefIndex); if (!drefIndex) return 0; - a = (GF_FullBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, drefIndex - 1); + a = (GF_FullBox*)gf_list_get(mdia->information->dataInformation->dref->other_boxes, drefIndex - 1); if (!a) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] broken file: Data reference index set to %d but no data reference entry found\n", drefIndex)); return 0; @@ -488,7 +489,7 @@ GF_Err Media_FindDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNname if (!dref) return GF_BAD_PARAM; *dataRefIndex = 0; i=0; - while ((entry = (GF_DataEntryURLBox*)gf_list_enum(dref->boxList, &i))) { + while ((entry = (GF_DataEntryURLBox*)gf_list_enum(dref->other_boxes, &i))) { if (entry->type == GF_ISOM_BOX_TYPE_URL) { //self-contained case if (entry->flags == 1) { @@ -614,7 +615,7 @@ GF_Err Media_CreateDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNna entry->flags |= 1; e = dref_AddDataEntry(dref, (GF_Box *)entry); if (e) return e; - *dataRefIndex = gf_list_count(dref->boxList); + *dataRefIndex = gf_list_count(dref->other_boxes); return GF_OK; } else if (!URNname && URLname) { //THIS IS URL @@ -628,7 +629,7 @@ GF_Err Media_CreateDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNna strcpy(entry->location, URLname); e = dref_AddDataEntry(dref, (GF_Box *)entry); if (e) return e; - *dataRefIndex = gf_list_count(dref->boxList); + *dataRefIndex = gf_list_count(dref->other_boxes); return GF_OK; } else { //THIS IS URN @@ -651,7 +652,7 @@ GF_Err Media_CreateDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNna } e = dref_AddDataEntry(dref, (GF_Box *)entry); if (e) return e; - *dataRefIndex = gf_list_count(dref->boxList); + *dataRefIndex = gf_list_count(dref->other_boxes); return GF_OK; } return GF_OK; @@ -769,8 +770,6 @@ GF_Err Media_UpdateSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample *sam GF_DataEntryURLBox *Dentry; GF_SampleTableBox *stbl; - GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a); - if (!mdia || !sample || !sampleNumber || !mdia->mediaTrack->moov->mov->editFileMap) return GF_BAD_PARAM; @@ -789,7 +788,7 @@ GF_Err Media_UpdateSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample *sam //then check the data ref e = Media_GetSampleDesc(mdia, descIndex, NULL, &drefIndex); if (e) return e; - Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, drefIndex - 1); + Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->other_boxes, drefIndex - 1); if (!Dentry) return GF_ISOM_INVALID_FILE; if (Dentry->flags != 1) return GF_BAD_PARAM; @@ -814,7 +813,6 @@ GF_Err Media_UpdateSampleReference(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSa u8 isEdited; GF_DataEntryURLBox *Dentry; GF_SampleTableBox *stbl; - GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a); if (!mdia) return GF_BAD_PARAM; stbl = mdia->information->sampleTable; @@ -830,7 +828,7 @@ GF_Err Media_UpdateSampleReference(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSa //then check the data ref e = Media_GetSampleDesc(mdia, descIndex, NULL, &drefIndex); if (e) return e; - Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, drefIndex - 1); + Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->other_boxes, drefIndex - 1); if (!Dentry) return GF_ISOM_INVALID_FILE; //we only modify self-contained data diff --git a/src/isomedia/media_odf.c b/src/isomedia/media_odf.c index 2c0f554..cef8684 100644 --- a/src/isomedia/media_odf.c +++ b/src/isomedia/media_odf.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project diff --git a/src/isomedia/meta.c b/src/isomedia/meta.c index 5f17c15..9e788f1 100644 --- a/src/isomedia/meta.c +++ b/src/isomedia/meta.c @@ -2,7 +2,7 @@ * GPAC Multimedia Framework * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -153,7 +153,7 @@ GF_Err gf_isom_get_meta_item_info(GF_ISOFile *file, Bool root_meta, u32 track_nu GF_ItemLocationEntry *iloc = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i); if (iloc->item_ID==iinf->item_ID) { if (iloc->data_reference_index) { - GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->boxList, iloc->data_reference_index-1); + GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->other_boxes, iloc->data_reference_index-1); if (a->type==GF_ISOM_BOX_TYPE_URL) { if (item_url) (*item_url) = ((GF_DataEntryURLBox*)a)->location; } else if (a->type==GF_ISOM_BOX_TYPE_URN) { @@ -226,7 +226,7 @@ GF_Err gf_isom_extract_meta_item_extended(GF_ISOFile *file, Bool root_meta, u32 /*FIXME*/ if (location_entry->data_reference_index) { char *item_url = NULL, *item_urn = NULL; - GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->boxList, location_entry->data_reference_index-1); + GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->other_boxes, location_entry->data_reference_index-1); if (a->type==GF_ISOM_BOX_TYPE_URL) { item_url = ((GF_DataEntryURLBox*)a)->location; } else if (a->type==GF_ISOM_BOX_TYPE_URN) { diff --git a/src/isomedia/movie_fragments.c b/src/isomedia/movie_fragments.c index 964ffef..02c44c0 100644 --- a/src/isomedia/movie_fragments.c +++ b/src/isomedia/movie_fragments.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -55,8 +56,18 @@ GF_TrackFragmentBox *GetTraf(GF_ISOFile *mov, u32 TrackID) #ifndef GPAC_DISABLE_ISOM_WRITE +GF_Err gf_isom_set_movie_duration(GF_ISOFile *movie, u64 duration) +{ + if (!movie->moov->mvex) return GF_BAD_PARAM; + if (!movie->moov->mvex->mehd) { + movie->moov->mvex->mehd = (GF_MovieExtendsHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MEHD); + } + movie->moov->mvex->mehd->fragment_duration = duration; + movie->moov->mvhd->duration = 0; + return GF_OK; +} -GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie, Bool use_segments) +GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie, u32 media_segment_type) { GF_Err e; u32 i; @@ -82,8 +93,19 @@ GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie, Bool use_segments) if (store_file) { /*"dash" brand: this is a DASH Initialization Segment*/ gf_isom_modify_alternate_brand(movie, GF_4CC('d','a','s','h'), 1); - //update durations - gf_isom_get_duration(movie); + + if (!movie->moov->mvex->mehd || !movie->moov->mvex->mehd->fragment_duration) { + //update durations + gf_isom_get_duration(movie); + } + + i=0; + while ((trex = (GF_TrackExtendsBox *)gf_list_enum(movie->moov->mvex->TrackExList, &i))) { + if (movie->moov->mvex->mehd && movie->moov->mvex->mehd->fragment_duration) { + trex->track->Header->duration = 0; + Media_SetDuration(trex->track); + } + } //write movie e = WriteToFile(movie); @@ -108,7 +130,7 @@ GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie, Bool use_segments) //ok we are fine - note the data map is created at the begining if (i) movie->FragmentsFlags |= GF_ISOM_FRAG_WRITE_READY; - if (use_segments) { + if (media_segment_type) { movie->use_segments = 1; movie->moof_list = gf_list_new(); } @@ -192,6 +214,9 @@ GF_Err gf_isom_setup_track_fragment(GF_ISOFile *movie, u32 TrackID, } else { mvex = movie->moov->mvex; } + if (!mvex->mehd) { + mvex->mehd = (GF_MovieExtendsHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MEHD); + } trex = GetTrex(movie->moov, TrackID); if (!trex) { @@ -364,7 +389,7 @@ u32 UpdateRuns(GF_ISOFile *movie, GF_TrackFragmentBox *traf) #ifndef USE_BASE_DATA_OFFSET if (movie->use_segments) { - traf->tfhd->flags = 0; + traf->tfhd->flags = GF_ISOM_MOOF_BASE_OFFSET; } else #endif { @@ -619,7 +644,10 @@ u32 moof_get_duration(GF_MovieFragmentBox *moof, u32 refTrackID) while ((trun = gf_list_enum(traf->TrackRuns, &i))) { j=0; while ((ent = gf_list_enum(trun->entries, &j))) { - duration += ent->Duration; + if (ent->flags & GF_ISOM_TRAF_SAMPLE_DUR) + duration += ent->Duration; + else + duration += traf->trex->def_sample_duration; } } return duration; @@ -836,7 +864,7 @@ GF_Err gf_isom_allocate_sidx(GF_ISOFile *movie, s32 subsegs_per_sidx, Bool daisy /*we don't write anything between sidx and following moov*/ movie->root_sidx->first_offset = 0; - /*for now we only store one ref per subsegment*/ + /*for now we only store one ref per subsegment and don't support daisy-chaining*/ movie->root_sidx->nb_refs = nb_segs; movie->root_sidx->refs = gf_malloc(sizeof(GF_SIDXReference) * movie->root_sidx->nb_refs); @@ -922,7 +950,7 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 subsegments_per_sidx, u32 re } /*write STYP if we write to a different file or if we write the last segment*/ - if ((!movie->append_segment && !movie->segment_start) || last_segment) { + if (!movie->append_segment && !movie->segment_start ) { /*modify brands STYP*/ @@ -974,6 +1002,7 @@ GF_Err gf_isom_close_segment(GF_ISOFile *movie, s32 subsegments_per_sidx, u32 re frags_per_subseg = count; frags_per_subsidx = count; subseg_per_sidx = 1; + daisy_chain_sidx = 0; idx_offset = movie->root_sidx_index; sidx_end = gf_bs_get_position(movie->editFileMap->bs); @@ -1331,7 +1360,7 @@ GF_Err gf_isom_start_segment(GF_ISOFile *movie, char *SegName) } else { assert(gf_list_count(movie->moof_list) == 0); movie->segment_start = gf_bs_get_position(movie->editFileMap->bs); - /*if movieFileMap is not null, we are concatenating segments to the original move, force a copy*/ + /*if movieFileMap is not null, we are concatenating segments to the original movie, force a copy*/ if (movie->movieFileMap) movie->append_segment = 1; } @@ -1407,8 +1436,7 @@ u32 GetRunSize(GF_TrackFragmentRunBox *trun) GF_Err gf_isom_fragment_add_sample(GF_ISOFile *movie, u32 TrackID, GF_ISOSample *sample, u32 DescIndex, - u32 Duration, - u8 PaddingBits, u16 DegradationPriority) + u32 Duration, u8 PaddingBits, u16 DegradationPriority, Bool redundant_coding) { u32 count, buffer_size; char *buffer; @@ -1507,7 +1535,7 @@ GF_Err gf_isom_fragment_add_sample(GF_ISOFile *movie, u32 TrackID, GF_ISOSample ent->size = sample->dataLength; ent->flags = GF_ISOM_FORMAT_FRAG_FLAGS(PaddingBits, sample->IsRAP, DegradationPriority); if (sample->IsRAP) { - ent->flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(0, 2, 0, 0); + ent->flags |= GF_ISOM_GET_FRAG_DEPEND_FLAGS(0, 2, 0, (redundant_coding ? 1 : 0) ); } gf_list_add(trun->entries, ent); @@ -1599,7 +1627,7 @@ GF_Err gf_isom_fragment_add_subsample(GF_ISOFile *movie, u32 TrackID, u32 subSam GF_Err gf_isom_fragment_copy_subsample(GF_ISOFile *dest, u32 TrackID, GF_ISOFile *orig, u32 track, u32 sampleNumber) { u32 i, count, last_sample; - GF_SampleEntry *sub_sample; + GF_SubSampleInfoEntry *sub_sample; GF_Err e; GF_TrackBox *trak; GF_TrackFragmentBox *traf; @@ -1727,7 +1755,7 @@ GF_Err gf_isom_set_traf_base_media_decode_time(GF_ISOFile *movie, u32 TrackID, u #else -GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *the_file) +GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *the_file, u32 media_segment_type) { return GF_NOT_SUPPORTED; } @@ -1754,8 +1782,7 @@ GF_Err gf_isom_start_fragment(GF_ISOFile *the_file, u32 free_data_insert_size) } GF_Err gf_isom_fragment_add_sample(GF_ISOFile *the_file, u32 TrackID, GF_ISOSample *sample, u32 DescIndex, - u32 Duration, - u8 PaddingBits, u16 DegradationPriority) + u32 Duration, u8 PaddingBits, u16 DegradationPriority, Bool redCoded) { return GF_NOT_SUPPORTED; } diff --git a/src/isomedia/sample_descs.c b/src/isomedia/sample_descs.c index 616cb0b..c5ed05d 100644 --- a/src/isomedia/sample_descs.c +++ b/src/isomedia/sample_descs.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -26,8 +27,19 @@ #ifndef GPAC_DISABLE_ISOM +void gf_isom_sample_entry_predestroy(GF_SampleEntryBox *ptr) +{ + if (ptr->protections) gf_isom_box_array_del(ptr->protections); +} + +void gf_isom_sample_entry_init(GF_SampleEntryBox *ent) +{ + ent->protections = gf_list_new(); +} + void gf_isom_video_sample_entry_init(GF_VisualSampleEntryBox *ent) { + gf_isom_sample_entry_init((GF_SampleEntryBox*)ent); ent->horiz_res = ent->vert_res = 0x00480000; ent->frames_per_sample = 1; ent->bit_depth = 0x18; @@ -44,7 +56,7 @@ GF_Err gf_isom_video_sample_entry_read(GF_VisualSampleEntryBox *ptr, GF_BitStrea ptr->revision = gf_bs_read_u16(bs); ptr->vendor = gf_bs_read_u32(bs); ptr->temporal_quality = gf_bs_read_u32(bs); - ptr->spacial_quality = gf_bs_read_u32(bs); + ptr->spatial_quality = gf_bs_read_u32(bs); ptr->Width = gf_bs_read_u16(bs); ptr->Height = gf_bs_read_u16(bs); ptr->horiz_res = gf_bs_read_u32(bs); @@ -69,7 +81,7 @@ void gf_isom_video_sample_entry_write(GF_VisualSampleEntryBox *ptr, GF_BitStream gf_bs_write_u16(bs, ptr->revision); gf_bs_write_u32(bs, ptr->vendor); gf_bs_write_u32(bs, ptr->temporal_quality); - gf_bs_write_u32(bs, ptr->spacial_quality); + gf_bs_write_u32(bs, ptr->spatial_quality); gf_bs_write_u16(bs, ptr->Width); gf_bs_write_u16(bs, ptr->Height); gf_bs_write_u32(bs, ptr->horiz_res); @@ -92,6 +104,8 @@ void gf_isom_video_sample_entry_size(GF_VisualSampleEntryBox *ent) void gf_isom_audio_sample_entry_init(GF_AudioSampleEntryBox *ptr) { + gf_isom_sample_entry_init((GF_SampleEntryBox*)ptr); + ptr->channel_count = 2; ptr->bitspersample = 16; } @@ -163,7 +177,7 @@ GF_3GPConfig *gf_isom_3gp_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 if (!trak || !StreamDescriptionIndex) return NULL; config = NULL; - entry = (GF_SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex-1); + entry = (GF_SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); if (!entry) return NULL; switch (entry->type) { case GF_ISOM_SUBTYPE_3GP_AMR: @@ -197,7 +211,7 @@ GF_AC3Config *gf_isom_ac3_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !StreamDescriptionIndex) return NULL; - entry = (GF_AC3SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex-1); + entry = (GF_AC3SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); if (!entry || !entry->info || (entry->type!=GF_ISOM_BOX_TYPE_AC3) || (entry->info->type!=GF_ISOM_BOX_TYPE_DAC3) ) return NULL; res = (GF_AC3Config*)gf_malloc(sizeof(GF_AC3Config)); @@ -274,8 +288,8 @@ GF_Err gf_isom_3gp_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_3GPConfi memcpy(&entry->info->cfg, cfg, sizeof(GF_3GPConfig)); entry->samplerate_hi = trak->Media->mediaHeader->timeScale; entry->dataReferenceIndex = dataRefIndex; - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, entry); - *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); + *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); } break; case GF_ISOM_SUBTYPE_3GP_H263: @@ -289,8 +303,8 @@ GF_Err gf_isom_3gp_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_3GPConfi } memcpy(&entry->info->cfg, cfg, sizeof(GF_3GPConfig)); entry->dataReferenceIndex = dataRefIndex; - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, entry); - *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); + *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); } break; } @@ -311,7 +325,7 @@ GF_Err gf_isom_3gp_config_update(GF_ISOFile *the_file, u32 trackNumber, GF_3GPCo if (!trak || !trak->Media || !param || !DescriptionIndex) return GF_BAD_PARAM; cfg = NULL; - entry = (GF_3GPPAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); + entry = (GF_3GPPAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!entry) return GF_BAD_PARAM; switch (entry->type) { case GF_ISOM_SUBTYPE_3GP_AMR: @@ -365,8 +379,8 @@ GF_Err gf_isom_ac3_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AC3Confi memcpy(&entry->info->cfg, cfg, sizeof(GF_AC3Config)); entry->samplerate_hi = trak->Media->mediaHeader->timeScale; entry->dataReferenceIndex = dataRefIndex; - e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, entry); - *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); + *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); return e; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -381,7 +395,7 @@ GF_Err gf_isom_get_dims_description(GF_ISOFile *movie, u32 trackNumber, u32 desc trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !descriptionIndex || !desc) return GF_BAD_PARAM; - dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, descriptionIndex-1); + dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, descriptionIndex-1); if (!dims) return GF_BAD_PARAM; if (dims->type != GF_ISOM_BOX_TYPE_DIMS) return GF_BAD_PARAM; @@ -429,8 +443,8 @@ GF_Err gf_isom_new_dims_description(GF_ISOFile *movie, u32 trackNumber, GF_DIMSD dims = (GF_DIMSSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DIMS); dims->dataReferenceIndex = dataRefIndex; - gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, dims); - if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, dims); + if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); dims->config = (GF_DIMSSceneConfigBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_DIMC); dims->config->profile = desc->profile; @@ -463,7 +477,7 @@ GF_Err gf_isom_update_dims_description(GF_ISOFile *movie, u32 trackNumber, GF_DI trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !desc || !DescriptionIndex) return GF_BAD_PARAM; - dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); + dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!dims) return GF_BAD_PARAM; if (dims->type != GF_ISOM_BOX_TYPE_DIMS) return GF_BAD_PARAM; if (!dims->config) diff --git a/src/isomedia/stbl_read.c b/src/isomedia/stbl_read.c index 49a239d..3830c45 100644 --- a/src/isomedia/stbl_read.c +++ b/src/isomedia/stbl_read.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project diff --git a/src/isomedia/stbl_write.c b/src/isomedia/stbl_write.c index 9ed4a76..aee50e5 100644 --- a/src/isomedia/stbl_write.c +++ b/src/isomedia/stbl_write.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -202,6 +203,7 @@ GF_Err stbl_AddCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 CTSoffset) ctts->entries[ctts->nb_entries].decodingOffset = CTSoffset; ctts->entries[ctts->nb_entries].sampleCount = 1; ctts->nb_entries++; + ctts->w_LastSampleNumber++; return GF_OK; } //check if we're working in order... @@ -219,6 +221,11 @@ GF_Err stbl_AddCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 CTSoffset) sampNum = 0; for (i=0; inb_entries; i++) { for (j = 0; jentries[i].sampleCount; j++) { + if (sampNum > stbl->SampleSize->sampleCount) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Too many CTS Offset entries for %d samples\n", stbl->SampleSize->sampleCount )); + gf_free(CTSs); + return GF_ISOM_INVALID_FILE; + } if (sampNum+1==sampleNumber) { CTSs[sampNum] = CTSoffset; sampNum ++; @@ -899,8 +906,8 @@ GF_Err stbl_RemoveCTS(GF_SampleTableBox *stbl, u32 sampleNumber) //first case, we're removing a sample that was not added yet if (sampleNumber > ctts->w_LastSampleNumber) return GF_OK; + memmove(&ctts->entries[sampleNumber-1], &ctts->entries[sampleNumber], sizeof(GF_DttsEntry)* (ctts->nb_entries-sampleNumber) ); ctts->nb_entries--; - memmove(&ctts->entries[sampleNumber-1], &ctts->entries[sampleNumber], sizeof(GF_DttsEntry)*ctts->nb_entries); ctts->w_LastSampleNumber -= 1; return GF_OK; @@ -1075,7 +1082,7 @@ GF_Err stbl_SetPaddingBits(GF_SampleTableBox *stbl, u32 SampleNumber, u8 bits) if (SampleNumber > stbl->SampleSize->sampleCount) return GF_BAD_PARAM; //create the table - if (!stbl->PaddingBits) stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FADB); + if (!stbl->PaddingBits) stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_PADB); //alloc if (!stbl->PaddingBits->padbits || !stbl->PaddingBits->SampleCount) { @@ -1415,7 +1422,7 @@ void stbl_AppendPadding(GF_SampleTableBox *stbl, u8 padding) { u32 i; u8 *pad_bits; - if (!stbl->PaddingBits) stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FADB); + if (!stbl->PaddingBits) stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_PADB); pad_bits = (u8*)gf_malloc(sizeof(u8) * stbl->SampleSize->sampleCount); if (!pad_bits) return; diff --git a/src/isomedia/track.c b/src/isomedia/track.c index 3534b80..b8b02de 100644 --- a/src/isomedia/track.c +++ b/src/isomedia/track.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -196,8 +197,10 @@ 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 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 } else { esd->decoderConfig->rvc_config->data = rvc_cfg_data; esd->decoderConfig->rvc_config->dataLength = rvc_cfg_size; @@ -314,7 +317,7 @@ GF_Err Track_FindRef(GF_TrackBox *trak, u32 ReferenceType, GF_TrackReferenceType } ref = trak->References; i=0; - while ((a = (GF_TrackReferenceTypeBox *)gf_list_enum(ref->boxList, &i))) { + while ((a = (GF_TrackReferenceTypeBox *)gf_list_enum(ref->other_boxes, &i))) { if (a->reference_type == ReferenceType) { *dpnd = a; return GF_OK; @@ -426,7 +429,11 @@ GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u64 moof_offset, if (traf->tfdt && is_first_merge) { #ifndef GPAC_DISABLE_LOG if (trak->sample_count_at_seg_start && (trak->dts_at_seg_start != traf->tfdt->baseMediaDecodeTime)) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Error: TFDT timing "LLD" different from track cumulated timing "LLD" - using tfdt\n", traf->tfdt->baseMediaDecodeTime, trak->dts_at_seg_start )); + s32 drift = (s32) ((s64)trak->dts_at_seg_start - (s64) traf->tfdt->baseMediaDecodeTime); + if (drift<0) drift = -drift; + if (drift > 1) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Error: TFDT timing "LLD" different from track cumulated timing "LLD" - using tfdt\n", traf->tfdt->baseMediaDecodeTime, trak->dts_at_seg_start )); + } } #endif trak->dts_at_seg_start = traf->tfdt->baseMediaDecodeTime; @@ -457,8 +464,9 @@ GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u64 moof_offset, //add chunk on first sample if (!j) { data_offset = base_offset; - //aggregated offset - if (!(traf->tfhd->flags & GF_ISOM_TRAF_BASE_OFFSET)) data_offset += chunk_size; + //aggregated offset if base-data-offset-present is not set AND if default-base-is-moof is not set + if (!(traf->tfhd->flags & GF_ISOM_TRAF_BASE_OFFSET) && !(traf->tfhd->flags & GF_ISOM_MOOF_BASE_OFFSET) ) + data_offset += chunk_size; if (trun->flags & GF_ISOM_TRUN_DATA_OFFSET) { data_offset += trun->data_offset; @@ -598,10 +606,10 @@ GF_Err Track_RemoveRef(GF_TrackBox *trak, u32 ReferenceType) if (! trak->References) return GF_OK; ref = trak->References; i=0; - while ((a = (GF_Box *)gf_list_enum(ref->boxList, &i))) { + while ((a = (GF_Box *)gf_list_enum(ref->other_boxes, &i))) { if (a->type == ReferenceType) { gf_isom_box_del(a); - gf_list_rem(ref->boxList, i-1); + gf_list_rem(ref->other_boxes, i-1); return GF_OK; } } @@ -846,7 +854,7 @@ GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, //we have a streamDescritpionIndex, use it if (StreamDescriptionIndex) { - entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex - 1); + entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex - 1); if (!entry) return GF_ISOM_INVALID_FILE; switch (entry->type) { @@ -884,9 +892,9 @@ GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, } } else { //need to check we're not in URL mode where only ONE description is allowed... - StreamDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + StreamDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); if (StreamDescriptionIndex) { - entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex - 1); + entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex - 1); if (!entry) return GF_ISOM_INVALID_FILE; if (entry->esd && entry->esd->desc->URLString) return GF_BAD_PARAM; } @@ -934,7 +942,7 @@ GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, //and add the entry to our table... e = stsd_AddBox(trak->Media->information->sampleTable->SampleDescription, (GF_Box *) entry); if (e) return e; - if(outStreamIndex) *outStreamIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + if(outStreamIndex) *outStreamIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); } return GF_OK; } diff --git a/src/isomedia/tx3g.c b/src/isomedia/tx3g.c index 0ee6dfe..733e4b2 100644 --- a/src/isomedia/tx3g.c +++ b/src/isomedia/tx3g.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project @@ -51,7 +52,7 @@ GF_Err gf_isom_update_text_description(GF_ISOFile *movie, u32 trackNumber, u32 d return GF_BAD_PARAM; } - txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, descriptionIndex - 1); + txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, descriptionIndex - 1); if (!txt) return GF_BAD_PARAM; switch (txt->type) { case GF_ISOM_BOX_TYPE_TX3G: @@ -113,8 +114,8 @@ GF_Err gf_isom_new_text_description(GF_ISOFile *movie, u32 trackNumber, GF_TextS txt = (GF_Tx3gSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TX3G); txt->dataReferenceIndex = dataRefIndex; - gf_list_add(trak->Media->information->sampleTable->SampleDescription->boxList, txt); - if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, txt); + if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); txt->back_color = desc->back_color; txt->default_box = desc->default_pos; @@ -370,10 +371,10 @@ GF_Err gf_isom_text_has_similar_description(GF_ISOFile *movie, u32 trackNumber, return GF_BAD_PARAM; } - count = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); + count = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); for (i=0; iMedia->information->sampleTable->SampleDescription->boxList, i); + txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, i); if (!txt) continue; if ((txt->type != GF_ISOM_BOX_TYPE_TX3G) && (txt->type != GF_ISOM_BOX_TYPE_TEXT)) continue; if (txt->back_color != desc->back_color) continue; @@ -592,7 +593,7 @@ GF_Err gf_isom_get_ttxt_esd(GF_MediaBox *mdia, GF_ESD **out_esd) GF_TrackBox *tk; *out_esd = NULL; - sampleDesc = mdia->information->sampleTable->SampleDescription->boxList; + sampleDesc = mdia->information->sampleTable->SampleDescription->other_boxes; count = gf_list_count(sampleDesc); if (!count) return GF_ISOM_INVALID_MEDIA; @@ -705,7 +706,7 @@ GF_Err gf_isom_text_get_encoded_tx3g(GF_ISOFile *file, u32 track, u32 sidx, u32 trak = gf_isom_get_track_from_file(file, track); if (!trak) return GF_BAD_PARAM; - a = (GF_Tx3gSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sidx-1); + a = (GF_Tx3gSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, sidx-1); if (!a) return GF_BAD_PARAM; if ((a->type != GF_ISOM_BOX_TYPE_TX3G) && (a->type != GF_ISOM_BOX_TYPE_TEXT)) return GF_BAD_PARAM; diff --git a/src/laser/lsr_dec.c b/src/laser/lsr_dec.c index 7b5dd8d..c17c3d2 100644 --- a/src/laser/lsr_dec.c +++ b/src/laser/lsr_dec.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / LASeR codec sub-project diff --git a/src/laser/lsr_enc.c b/src/laser/lsr_enc.c index 11981da..87a39c4 100644 --- a/src/laser/lsr_enc.c +++ b/src/laser/lsr_enc.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / LASeR codec sub-project diff --git a/src/laser/lsr_tables.c b/src/laser/lsr_tables.c index f0e6cec..8b962a9 100644 --- a/src/laser/lsr_tables.c +++ b/src/laser/lsr_tables.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c)2004-200X ENST - All rights reserved + * Copyright (c)2004-200X Telecom ParisTech - All rights reserved * * This file is part of GPAC / SVG Scene Graph sub-project * diff --git a/src/mcrypt/des.c b/src/mcrypt/des.c index ea65564..df27960 100644 --- a/src/mcrypt/des.c +++ b/src/mcrypt/des.c @@ -432,7 +432,7 @@ static u32 f(DES_KEY * key, register u32 r, register char *subkey) register int er; #ifdef TRACE - printf("f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ", + fprintf(stderr, "f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ", r, subkey[0], subkey[1], subkey[2], subkey[3], subkey[4], subkey[5], subkey[6], subkey[7]); @@ -471,7 +471,7 @@ static u32 f(DES_KEY * key, register u32 r, register char *subkey) rt |= (r & 1) << 5; rval |= spp[((int) rt ^ *subkey) & 0x3f]; #ifdef TRACE - printf(" %08lx\n", rval); + fprintf(stderr, " %08lx\n", rval); #endif return rval; } @@ -555,7 +555,7 @@ static void spinit(DES_KEY * key) key->sp[s][i] = val; #ifdef DEBUG - printf("sp[%d][%2d] = %08lx\n", s, i, + fprintf(stderr, "sp[%d][%2d] = %08lx\n", s, i, key->sp[s][i]); #endif } diff --git a/src/mcrypt/g_crypt.c b/src/mcrypt/g_crypt.c index a7ef71b..7aefb51 100644 --- a/src/mcrypt/g_crypt.c +++ b/src/mcrypt/g_crypt.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / crypto lib sub-project diff --git a/src/mcrypt/tripledes.c b/src/mcrypt/tripledes.c index df1ab6b..1f6d5ca 100644 --- a/src/mcrypt/tripledes.c +++ b/src/mcrypt/tripledes.c @@ -637,7 +637,7 @@ static u32 f(TRIPLEDES_KEY * key, int pos, register u32 r, register int er; #ifdef TRACE - printf("f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ", + fprintf(stderr, "f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ", r, subkey[0], subkey[1], subkey[2], subkey[3], subkey[4], subkey[5], subkey[6], subkey[7]); @@ -676,7 +676,7 @@ static u32 f(TRIPLEDES_KEY * key, int pos, register u32 r, rt |= (r & 1) << 5; rval |= spp[((int) rt ^ *subkey) & 0x3f]; #ifdef TRACE - printf(" %08lx\n", rval); + fprintf(stderr, " %08lx\n", rval); #endif return rval; } diff --git a/src/media_tools/ait.c b/src/media_tools/ait.c index 112ab70..d4f25ac 100644 --- a/src/media_tools/ait.c +++ b/src/media_tools/ait.c @@ -1,10 +1,31 @@ -/* - * Copyright (c) TELECOM ParisTech 2011 +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jonathan Sillan + * Copyright (c) Telecom ParisTech 2011-2012 + * All rights reserved + * + * This file is part of GPAC / media tools sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * */ #include -#ifndef GPAC_DISABLE_MPEG2TS +#ifdef GPAC_ENABLE_DSMCC /* static functions */ static Bool check_ait_already_received(GF_List* ChannelAppList,u32 pid,char* data); @@ -234,7 +255,7 @@ static GF_Err gf_m2ts_decode_ait(GF_M2TS_AIT *ait, char *data, u32 data_size, u GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte; GF_SAFEALLOC(Transport_http_selector_byte, GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE); Transport_http_selector_byte->URL_base_length = gf_bs_read_int(bs,8); - //printf("Transport_http_selector_byte->URL_base_length %d \n",Transport_http_selector_byte->URL_base_length); + //fprintf(stderr, "Transport_http_selector_byte->URL_base_length %d \n",Transport_http_selector_byte->URL_base_length); Transport_http_selector_byte->URL_base_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_base_length+1,sizeof(char)); gf_bs_read_data(bs,Transport_http_selector_byte->URL_base_byte ,(u32)(Transport_http_selector_byte->URL_base_length)); Transport_http_selector_byte->URL_base_byte[Transport_http_selector_byte->URL_base_length] = 0; @@ -765,6 +786,7 @@ void gf_m2ts_delete_channel_application_info(GF_M2TS_CHANNEL_APPLICATION_INFO* gf_list_del(ChannelApp->Application); gf_free(ChannelApp); } -#endif //GPAC_DISABLE_MPEG2TS + +#endif //GPAC_ENABLE_DSMCC diff --git a/src/media_tools/av_parsers.c b/src/media_tools/av_parsers.c index 92c2b4e..d54f1d6 100644 --- a/src/media_tools/av_parsers.c +++ b/src/media_tools/av_parsers.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre, Romain Bouqueau, Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -24,12 +25,46 @@ #include #include -#include #ifndef GPAC_DISABLE_OGG #include +#include #endif +static const struct { u32 w, h; } std_par[ ] = +{ + { 4, 3}, {3, 2}, {16, 9}, {5, 3}, {5, 4}, {8, 5}, + {0, 0}, +}; + +GF_EXPORT +void gf_media_reduce_aspect_ratio(u32 *width, u32 *height) +{ + u32 i=0; + u32 w = *width; + u32 h = *height; + while (std_par[i].w) { + if (std_par[i].w * h == std_par[i].h * w) { + *width = std_par[i].w; + *height = std_par[i].h; + return; + } + i++; + } +} + +GF_EXPORT +void gf_media_get_reduced_frame_rate(u32 *timescale, u32 *sample_dur) +{ + u32 res; + if (! *sample_dur) return; + res = *timescale / *sample_dur; + if (res * *sample_dur == *timescale) { + *timescale = res; + *sample_dur = 1; + } +} + GF_EXPORT const char *gf_m4v_get_profile_name(u8 video_pl) { @@ -1504,23 +1539,29 @@ u32 AVC_NextStartCode(GF_BitStream *bs) return (u32) (end-start); } +Bool AVC_SliceIsIntra(AVCState *avc) +{ + switch (avc->s_info.slice_type) { + case GF_AVC_TYPE_I: + case GF_AVC_TYPE2_I: + case GF_AVC_TYPE_SI: + case GF_AVC_TYPE2_SI: + return 1; + default: + return 0; + } +} + Bool AVC_SliceIsIDR(AVCState *avc) { - if (avc->sei.recovery_point.valid) - { - avc->sei.recovery_point.valid = 0; - return 1; - } - if (avc->s_info.nal_unit_type != GF_AVC_NALU_IDR_SLICE) return 0; - switch (avc->s_info.slice_type) { - case GF_AVC_TYPE_I: - case GF_AVC_TYPE2_I: - case GF_AVC_TYPE_SI: - case GF_AVC_TYPE2_SI: - return 1; - default: - return 0; - } + if (avc->sei.recovery_point.valid) + { + avc->sei.recovery_point.valid = 0; + return 1; + } + if (avc->s_info.nal_unit_type != GF_AVC_NALU_IDR_SLICE) + return 0; + return AVC_SliceIsIntra(avc); } static const struct { u32 w, h; } avc_sar[14] = @@ -1531,6 +1572,7 @@ static const struct { u32 w, h; } avc_sar[14] = { 64, 33 }, { 160,99 }, }; + /*ISO 14496-10 (N11084) E.1.2*/ static void avc_parse_hrd_parameters(GF_BitStream *bs, AVC_HRD *hrd) { @@ -1696,7 +1738,7 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, AVC_SPS *sps; u32 ChromaArrayType = 0; s32 mb_width, mb_height, sps_id = -1; - u32 profile_idc, level_idc, pcomp, i, chroma_format_idc, cl, cr, ct, cb; + u32 profile_idc, level_idc, pcomp, i, chroma_format_idc, cl, cr, ct, cb, luma_bd, chroma_bd; GF_BitStream *bs; char *sps_data_without_emulation_bytes = NULL; u32 sps_data_without_emulation_bytes_size = 0; @@ -1729,6 +1771,7 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, goto exit; } + chroma_format_idc = luma_bd = chroma_bd = 0; sps = &avc->sps[sps_id]; sps->state |= subseq_sps ? AVC_SUBSPS_PARSED : AVC_SPS_PARSED; @@ -1757,8 +1800,8 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, */ if (separate_colour_plane_flag) ChromaArrayType = 0; } - /*bit_depth_luma_minus8 = */ avc_get_ue(bs); - /*bit_depth_chroma_minus8 = */ avc_get_ue(bs); + luma_bd = avc_get_ue(bs); + chroma_bd = avc_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)) { @@ -1785,6 +1828,9 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, sps->prof_compat = pcomp; sps->log2_max_frame_num = avc_get_ue(bs) + 4; sps->poc_type = avc_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; @@ -1914,9 +1960,9 @@ s32 AVC_ReadSeqInfo(char *sps_data, u32 sps_size, AVCState *avc, u32 subseq_sps, 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; - /*u8 vui_ext_dependency_id = */gf_bs_read_int(bs, 3); - /*u8 vui_ext_quality_id = */gf_bs_read_int(bs, 4); - /*u8 vui_ext_temporal_id = */gf_bs_read_int(bs, 3); + /*u8 vui_ext_dependency_id =*/ gf_bs_read_int(bs, 3); + /*u8 vui_ext_quality_id =*/ gf_bs_read_int(bs, 4); + /*u8 vui_ext_temporal_id =*/ gf_bs_read_int(bs, 3); vui_ext_timing_info_present_flag = gf_bs_read_int(bs, 1); if (vui_ext_timing_info_present_flag) { /*u32 vui_ext_num_units_in_tick = */gf_bs_read_int(bs, 32); @@ -2016,6 +2062,27 @@ exit: return pps_id; } +s32 AVC_ReadSeqParamSetExtId(char *spse_data, u32 spse_size) +{ + GF_BitStream *bs; + char *spse_data_without_emulation_bytes = NULL; + u32 spse_data_without_emulation_bytes_size = 0; + s32 sps_id; + + /*PPS still contains emulation bytes*/ + spse_data_without_emulation_bytes = gf_malloc(spse_size*sizeof(char)); + 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); + + gf_bs_del(bs); + gf_free(spse_data_without_emulation_bytes); + return sps_id; +} + static s32 SVC_ReadNal_header_extension(GF_BitStream *bs, SVC_NALUHeader *NalHeader) { gf_bs_read_int(bs, 1); //reserved_one_bits @@ -2532,7 +2599,9 @@ u32 AVC_ReformatSEI_NALU(char *buffer, u32 nal_size, AVCState *avc) case 16: /*progressive refinement segment start*/ case 17: /*progressive refinement segment end*/ case 18: /*motion constrained slice group*/ + break; default: /*reserved*/ + do_copy = 0; break; } @@ -2572,11 +2641,17 @@ u32 AVC_ReformatSEI_NALU(char *buffer, u32 nal_size, AVCState *avc) if (written) { var = avc_emulation_bytes_add_count(new_buffer, written); if (var) { - assert(written+var<=nal_size); - written = avc_add_emulation_bytes(new_buffer, buffer, written); + if (written+var<=nal_size) { + written = avc_add_emulation_bytes(new_buffer, buffer, written); + } else { + written = 0; + } } else { - assert(written<=nal_size); - memcpy(buffer, new_buffer, sizeof(char)*written); + if (written<=nal_size) { + memcpy(buffer, new_buffer, sizeof(char)*written); + } else { + written = 0; + } } } gf_free(new_buffer); diff --git a/src/media_tools/dash_client.c b/src/media_tools/dash_client.c new file mode 100644 index 0000000..3336f9e --- /dev/null +++ b/src/media_tools/dash_client.c @@ -0,0 +1,3153 @@ +/* +* GPAC - Multimedia Framework C SDK +* +* Authors: Jean Le Feuvre, Cyril Concolato +* Copyright (c) Telecom ParisTech 2010- +* All rights reserved +* +* This file is part of GPAC / Adaptive HTTP Streaming +* +* GPAC is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* GPAC is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*/ + +#include +#include +#include +#include +#include +#include + +#ifndef GPAC_DISABLE_DASH_CLIENT + +/*set to 1 if you want MPD to use SegmentTemplate if possible instead of SegmentList*/ +#define M3U8_TO_MPD_USE_TEMPLATE 0 + + +typedef enum { + GF_DASH_STATE_STOPPED = 0, + /*period setup and playback chain creation*/ + GF_DASH_STATE_SETUP, + /*request to start playback chain*/ + GF_DASH_STATE_CONNECTING, + GF_DASH_STATE_RUNNING, +} GF_DASH_STATE; + + +typedef struct __dash_group GF_DASH_Group; + +struct __dash_client +{ + GF_DASHFileIO *dash_io; + + /*interface to mpd parser - get rid of this and use the DASHIO instead ?*/ + GF_FileDownload getter; + + char *base_url; + + u32 max_cache_duration; + u32 auto_switch_count; + Bool keep_files, disable_switching, allow_local_mpd_update; + + GF_DASHInitialSelectionMode first_select_mode; + + /* MPD downloader*/ + GF_DASHFileIOSession mpd_dnload; + /* MPD */ + GF_MPD *mpd; + /* number of time the MPD has been reloaded and last update time*/ + u32 reload_count, last_update_time; + /*signature of last MPD*/ + u8 lastMPDSignature[20]; + /*mime type of media segments (m3u8)*/ + char *mimeTypeForM3U8Segments; + + /* active period in MPD (only one currently supported) */ + u32 active_period_index; + u32 request_period_switch; + + u64 start_time_in_active_period; + + /*list of groups in the active period*/ + GF_List *groups; + + /*Main Thread handling segment downloads and MPD/M3U8 update*/ + GF_Thread *dash_thread; + /*mutex for group->cache file name access and MPD update*/ + GF_Mutex *dl_mutex; + + /* one of the above state*/ + GF_DASH_STATE dash_state; + Bool mpd_stop_request; + Bool in_period_setup; + + + /* TODO - handle playback status for SPEED/SEEK through SIDX */ + Double playback_start_range; + Double start_range_in_segment_at_next_period; +}; + +static void gf_dash_seek_group(GF_DashClient *dash, GF_DASH_Group *group); + + +typedef struct +{ + char *cache; + char *url; + u64 start_range, end_range; + /*representation index in adaptation_set->representations*/ + u32 representation_index; + Bool do_not_delete; +} segment_cache_entry; + +typedef enum +{ + /*set if group cannot be selected (wrong MPD)*/ + GF_DASH_GROUP_NOT_SELECTABLE = 0, + GF_DASH_GROUP_NOT_SELECTED, + GF_DASH_GROUP_SELECTED, +} GF_DASHGroupSelection; + +/*this structure Group is the implementation of the adaptationSet element of the MPD.*/ +struct __dash_group +{ + GF_DashClient *dash; + + /*pointer to adaptation set*/ + GF_MPD_AdaptationSet *adaptation_set; + /*pointer to active period*/ + GF_MPD_Period *period; + + /*active representation index in adaptation_set->representations*/ + u32 active_rep_index; + + u32 prev_active_rep_index; + + GF_DASHGroupSelection selection; + + + Bool bitstream_switching, dont_delete_first_segment; + + Bool done; + Bool force_switch_bandwidth, min_bandwidth_selected; + u32 nb_bw_check; + u32 active_bitrate, max_bitrate, min_bitrate; + + u32 nb_segments_in_rep; + Double segment_duration; + + /*local file playback, do not delete them*/ + Bool local_files; + /*next segment to download for this group*/ + u32 download_segment_index; + /*number of segments pruged since the start of the period*/ + u32 nb_segments_purged; + + /*next file (cached) to delete at next GF_NET_SERVICE_QUERY_NEXT for this group*/ + char * urlToDeleteNext; + volatile u32 max_cached_segments, nb_cached_segments; + segment_cache_entry *cached; + + GF_DASHFileIOSession segment_download; + + const char *segment_local_url; + /*usually 0-0 (no range) but can be non-zero when playing local MPD/DASH sessions*/ + u64 local_url_start_range, local_url_end_range; + + u32 nb_segments_done; + + Bool segment_must_be_streamed; + + u32 force_representation_idx_plus_one; + + Bool force_segment_switch; + + /*set when switching segment, indicates the current downloaded segment duration*/ + u64 current_downloaded_segment_duration; + + char *service_mime; + + void *udta; +}; + +static const char *gf_dash_get_mime_type(GF_MPD_SubRepresentation *subrep, GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set) +{ + if (subrep && subrep->mime_type) return subrep->mime_type; + if (rep && rep->mime_type) return rep->mime_type; + if (set && set->mime_type) return set->mime_type; + return NULL; +} + +GF_EXPORT +Bool gf_dash_check_mpd_root_type(const char *local_url) +{ + if (local_url) { + char *rtype = gf_xml_get_root_type(local_url, NULL); + if (rtype) { + Bool handled = 0; + if (!strcmp(rtype, "MPD")) { + handled = 1; + } + gf_free(rtype); + return handled; + } + } + return 0; +} + +void gf_dash_group_check_switch(GF_DASHFileIO *dash_io, GF_DASH_Group *group, Bool download_active) +{ + u32 download_rate; + + if (group->dash->disable_switching) return; + download_rate = dash_io->get_bytes_per_sec(dash_io, group->segment_download); + if (!download_rate) return; + + download_rate *= 8; + if (download_ratemin_bitrate) group->min_bitrate = download_rate; + if (download_rate>group->max_bitrate) group->max_bitrate = download_rate; + + if (download_rate && (download_rate < group->active_bitrate)) { + u32 set_idx = gf_list_find(group->period->adaptation_sets, group->adaptation_set)+1; + group->nb_bw_check ++; + if (group->min_bandwidth_selected) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Downloading from set #%d at rate %d kbps but media bitrate is %d kbps - no lower bitrate available ...\n", set_idx, download_rate/1024, group->active_bitrate/1024 )); + } else if (group->nb_bw_check>2) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Downloading from set #%d at rate %d kbps but media bitrate is %d kbps - switching\n", set_idx, download_rate/1024, group->active_bitrate/1024 )); + group->force_switch_bandwidth = 1; + if (download_active) + if (group->segment_download) dash_io->abort(dash_io, group->segment_download); + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Downloading from set #%ds at rate %d kbps but media bitrate is %d kbps\n", set_idx, download_rate/1024, group->active_bitrate/1024 )); + } + } else { + group->nb_bw_check = 0; + } +} + + + +/*! +* Returns true if given mime type is a MPD file +* \param mime the mime-type to check +* \return true if mime-type if MPD-OK +*/ +static Bool gf_dash_is_dash_mime(const char * mime) { + u32 i; + if (!mime) + return 0; + for (i = 0 ; GF_DASH_MPD_MIME_TYPES[i] ; i++){ + if ( !stricmp(mime, GF_DASH_MPD_MIME_TYPES[i])) + return 1; + } + return 0; +} + +/*! +* Returns true if mime type is an M3U8 mime-type +* \param mime The mime-type to check +* \return true if mime-type is OK for M3U8 +*/ +static Bool gf_dash_is_m3u8_mime(const char * mime) { + u32 i; + if (!mime) + return 0; + for (i = 0 ; GF_DASH_M3U8_MIME_TYPES[i] ; i++) { + if ( !stricmp(mime, GF_DASH_M3U8_MIME_TYPES[i])) + return 1; + } + return 0; +} + + +/*! +* Download a file with possible retry if GF_IP_CONNECTION_FAILURE|GF_IP_NETWORK_FAILURE +* (I discovered that with my WIFI connection, I had many issues with BFM-TV downloads) +* Similar to gf_term_download_new() and gf_dm_sess_process(). +* Parameters are identical to the ones of gf_term_download_new. +* \see gf_term_download_new() +*/ +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) +{ + Bool had_sess = 0; + Bool retry = 1; + GF_Err e; + + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Downloading %s...\n", url)); + + if (! *sess) { + *sess = dash_io->create(dash_io, persistent, url); + if (!(*sess)){ + assert(0); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot try to download %s... OUT of memory ?\n", url)); + return GF_OUT_OF_MEM; + } + } else { + had_sess = 1; + e = dash_io->setup_from_url(dash_io, *sess, url); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot resetup session for url %s: %s\n", url, gf_error_to_string(e) )); + return e; + } + } + +retry: + + if (end_range) { + e = dash_io->set_range(dash_io, *sess, start_range, end_range); + if (e) { + if (had_sess) { + dash_io->del(dash_io, *sess); + *sess = NULL; + return gf_dash_download_resource(dash_io, sess, url, start_range, end_range, persistent, group); + } + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot setup byte-range download for %s: %s\n", url, gf_error_to_string(e) )); + return e; + } + } + assert(*sess); + + /*issue HTTP GET for headers only*/ + e = dash_io->init(dash_io, *sess); + + if (e>=GF_OK) { + /*check mime type of the adaptation set if not provided*/ + if (group) { + const char *mime = dash_io->get_mime(dash_io, *sess); + if (mime && !group->service_mime) { + group->service_mime = gf_strdup(mime); + } + /*we allow servers to give us broken mim types for the representation served ...*/ +#if 0 + else if (mime && stricmp(group->service_mime, mime)) { + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + if (! gf_dash_get_mime_type(NULL, rep, group->adaptation_set) ) + rep->mime_type = gf_strdup(mime); + rep->disabled = 1; + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Disabling representation since mime does not match: expected %s, but had %s for %s!\n", group->service_mime, mime, url)); + group->force_switch_bandwidth = 1; + if (group->segment_download) dash_io->abort(dash_io, group->segment_download); + return GF_OK; + } +#endif + } + + /*file cannot be cached on disk !*/ + if (group) { + if (dash_io->get_cache_name(dash_io, group->segment_download) == NULL) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Segment %s cannot be cached on disk, will use direct streaming\n", url)); + group->segment_must_be_streamed = 1; + if (group->segment_download) dash_io->abort(dash_io, group->segment_download); + return GF_OK; + } + group->segment_must_be_streamed = 0; + } + + /*we can download the file*/ + e = dash_io->run(dash_io, *sess); + } + switch (e) { +case GF_IP_CONNECTION_FAILURE: +case GF_IP_NETWORK_FAILURE: + { + dash_io->del(dash_io, *sess); + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] failed to download, retrying once with %s...\n", url)); + *sess = dash_io->create(dash_io, 0, url); + if (! (*sess)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot retry to download %s... OUT of memory ?\n", url)); + return GF_OUT_OF_MEM; + } + + if (retry) { + retry = 0; + goto retry; + } + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] two consecutive failures, aborting the download %s.\n", url)); + return e; + } +case GF_OK: + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Download %s complete\n", url)); + break; +default: + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] FAILED to download %s = %s...\n", url, gf_error_to_string(e))); + return e; + } + return GF_OK; +} + +static void gf_dash_get_timeline_duration(GF_MPD_SegmentTimeline *timeline, u32 *nb_segments, Double *max_seg_duration) +{ + u32 i, count; + + *nb_segments = 0; + if (max_seg_duration) *max_seg_duration = 0; + count = gf_list_count(timeline->entries); + for (i=0; ientries, i); + *nb_segments += 1 + ent->repeat_count; + if (max_seg_duration && (*max_seg_duration < ent->duration)) *max_seg_duration = ent->duration; + } +} + +static void gf_dash_get_segment_duration(GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, GF_MPD *mpd, u32 *nb_segments, Double *max_seg_duration) +{ + Double mediaDuration; + Bool single_segment = 0; + u32 timescale; + u64 duration; + GF_MPD_SegmentTimeline *timeline = NULL; + *nb_segments = timescale = 0; + duration = 0; + + /*single segment*/ + if (rep->segment_base || set->segment_base || period->segment_base) { + *max_seg_duration = mpd->media_presentation_duration; + *max_seg_duration /= 1000; + *nb_segments = 1; + return; + } + if (rep->segment_list || set->segment_list || period->segment_list) { + GF_List *segments = NULL; + if (period->segment_list) { + if (period->segment_list->duration) duration = period->segment_list->duration; + if (period->segment_list->timescale) timescale = period->segment_list->timescale; + if (period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs; + if (period->segment_list->segment_timeline) timeline = period->segment_list->segment_timeline; + } + if (set->segment_list) { + if (set->segment_list->duration) duration = set->segment_list->duration; + if (set->segment_list->timescale) timescale = set->segment_list->timescale; + if (set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs; + if (set->segment_list->segment_timeline) timeline = set->segment_list->segment_timeline; + } + if (rep->segment_list) { + if (rep->segment_list->duration) duration = rep->segment_list->duration; + if (rep->segment_list->timescale) timescale = rep->segment_list->timescale; + if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs; + if (rep->segment_list->segment_timeline) timeline = rep->segment_list->segment_timeline; + } + if (! timescale) timescale=1; + + if (timeline) { + gf_dash_get_timeline_duration(timeline, nb_segments, max_seg_duration); + if (max_seg_duration) *max_seg_duration /= timescale; + } else { + if (segments) + *nb_segments = gf_list_count(segments); + if (max_seg_duration) { + *max_seg_duration = (Double) duration; + *max_seg_duration /= timescale; + } + } + return; + } + + single_segment = 1; + if (period->segment_template) { + single_segment = 0; + if (period->segment_template->duration) duration = period->segment_template->duration; + if (period->segment_template->timescale) timescale = period->segment_template->timescale; + if (period->segment_template->segment_timeline) timeline = period->segment_template->segment_timeline; + } + if (set->segment_template) { + single_segment = 0; + if (set->segment_template->duration) duration = set->segment_template->duration; + if (set->segment_template->timescale) timescale = set->segment_template->timescale; + if (set->segment_template->segment_timeline) timeline = set->segment_template->segment_timeline; + } + if (rep->segment_template) { + single_segment = 0; + if (rep->segment_template->duration) duration = rep->segment_template->duration; + if (rep->segment_template->timescale) timescale = rep->segment_template->timescale; + if (rep->segment_template->segment_timeline) timeline = rep->segment_template->segment_timeline; + } + if (!timescale) timescale=1; + + /*if no SegmentXXX is found, this is a single segment representation (onDemand profile)*/ + if (single_segment) { + *max_seg_duration = mpd->media_presentation_duration; + *max_seg_duration /= 1000; + *nb_segments = 1; + return; + } + + if (timeline) { + gf_dash_get_timeline_duration(timeline, nb_segments, max_seg_duration); + if (max_seg_duration) *max_seg_duration /= timescale; + } else { + if (max_seg_duration) { + *max_seg_duration = (Double) duration; + *max_seg_duration /= timescale; + } + mediaDuration = period->duration; + if (!mediaDuration) mediaDuration = mpd->media_presentation_duration; + if (mediaDuration && duration) { + Double nb_seg = (Double) mediaDuration; + /*duration is given in ms*/ + nb_seg /= 1000; + nb_seg *= timescale; + nb_seg /= duration; + *nb_segments = (u32) nb_seg; + if (*nb_segments < nb_seg) (*nb_segments)++; + } + } +} + +static u64 gf_dash_segment_timeline_start(GF_MPD_SegmentTimeline *timeline, u32 segment_index) +{ + u64 start_time = 0; + u32 i, idx, k; + idx = 0; + for (i=0; ientries); i++) { + GF_MPD_SegmentTimelineEntry *ent = gf_list_get(timeline->entries, i); + if (ent->start_time) start_time = ent->start_time; + for (k=0; krepeat_count+1; k++) { + if (idx==segment_index) + return start_time; + idx ++; + start_time += ent->duration; + } + } + return start_time; +} + +static Double gf_dash_get_segment_start_time(GF_DASH_Group *group) +{ + GF_MPD_Representation *rep; + GF_MPD_AdaptationSet *set; + GF_MPD_Period *period; + Double start_time; + u32 timescale, segment_index; + u64 duration; + GF_MPD_SegmentTimeline *timeline = NULL; + timescale = 0; + duration = 0; + start_time = 0; + + rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + set = group->adaptation_set; + period = group->period; + segment_index = group->download_segment_index - group->nb_cached_segments; + + /*single segment: return nothing*/ + if (rep->segment_base || set->segment_base || period->segment_base) { + return start_time; + } + if (rep->segment_list || set->segment_list || period->segment_list) { + if (period->segment_list) { + if (period->segment_list->duration) duration = period->segment_list->duration; + if (period->segment_list->timescale) timescale = period->segment_list->timescale; + if (period->segment_list->segment_timeline) timeline = period->segment_list->segment_timeline; + } + if (set->segment_list) { + if (set->segment_list->duration) duration = set->segment_list->duration; + if (set->segment_list->timescale) timescale = set->segment_list->timescale; + if (set->segment_list->segment_timeline) timeline = set->segment_list->segment_timeline; + } + if (rep->segment_list) { + if (rep->segment_list->duration) duration = rep->segment_list->duration; + if (rep->segment_list->timescale) timescale = rep->segment_list->timescale; + if (rep->segment_list->segment_timeline) timeline = rep->segment_list->segment_timeline; + } + if (! timescale) timescale=1; + + if (timeline) { + start_time = (Double) gf_dash_segment_timeline_start(timeline, segment_index); + } else { + start_time = segment_index * (Double) duration; + } + start_time /= timescale; + return start_time; + } + + if (period->segment_template) { + if (period->segment_template->duration) duration = period->segment_template->duration; + if (period->segment_template->timescale) timescale = period->segment_template->timescale; + if (period->segment_template->segment_timeline) timeline = period->segment_template->segment_timeline; + } + if (set->segment_template) { + if (set->segment_template->duration) duration = set->segment_template->duration; + if (set->segment_template->timescale) timescale = set->segment_template->timescale; + if (set->segment_template->segment_timeline) timeline = set->segment_template->segment_timeline; + } + if (rep->segment_template) { + if (rep->segment_template->duration) duration = rep->segment_template->duration; + if (rep->segment_template->timescale) timescale = rep->segment_template->timescale; + if (rep->segment_template->segment_timeline) timeline = rep->segment_template->segment_timeline; + } + if (!timescale) timescale=1; + + if (timeline) { + start_time = (Double) gf_dash_segment_timeline_start(timeline, segment_index); + } else { + start_time = segment_index * (Double) duration; + } + start_time /= timescale; + return start_time; +} + +static void gf_dash_resolve_duration(GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, u64 *out_duration, u32 *out_timescale, u64 *out_pts_offset, GF_MPD_SegmentTimeline **out_segment_timeline) +{ + u32 timescale = 0; + u64 pts_offset = 0; + GF_MPD_SegmentTimeline *segment_timeline; + GF_MPD_MultipleSegmentBase *mbase_rep, *mbase_set, *mbase_period; + + if (out_segment_timeline) *out_segment_timeline = NULL; + if (out_pts_offset) *out_pts_offset = 0; + + /*single media segment - duration is not known unless indicated in period*/ + if (rep->segment_base || set->segment_base || period->segment_base) { + *out_duration = period ? period->duration : 0; + timescale = 0; + if (rep->segment_base && rep->segment_base->presentation_time_offset) pts_offset = rep->segment_base->presentation_time_offset; + if (rep->segment_base && rep->segment_base->timescale) timescale = rep->segment_base->timescale; + if (!pts_offset && set->segment_base && set->segment_base->presentation_time_offset) pts_offset = set->segment_base->presentation_time_offset; + if (!timescale && set->segment_base && set->segment_base->timescale) timescale = set->segment_base->timescale; + if (!pts_offset && period->segment_base && period->segment_base->presentation_time_offset) pts_offset = period->segment_base->presentation_time_offset; + if (!timescale && period->segment_base && period->segment_base->timescale) timescale = period->segment_base->timescale; + + if (out_pts_offset) *out_pts_offset = pts_offset; + *out_timescale = timescale ? timescale : 1; + return; + } + /*we have a segment template list or template*/ + mbase_rep = rep->segment_list ? (GF_MPD_MultipleSegmentBase *) rep->segment_list : (GF_MPD_MultipleSegmentBase *) rep->segment_template; + mbase_set = set->segment_list ? (GF_MPD_MultipleSegmentBase *)set->segment_list : (GF_MPD_MultipleSegmentBase *)set->segment_template; + mbase_period = period->segment_list ? (GF_MPD_MultipleSegmentBase *)period->segment_list : (GF_MPD_MultipleSegmentBase *)period->segment_template; + + segment_timeline = NULL; + if (mbase_period) segment_timeline = mbase_period->segment_timeline; + if (mbase_set && mbase_set->segment_timeline) segment_timeline = mbase_set->segment_timeline; + if (mbase_rep && mbase_rep->segment_timeline) segment_timeline = mbase_rep->segment_timeline; + + timescale = mbase_rep ? mbase_rep->timescale : 0; + if (!timescale && mbase_set && mbase_set->timescale) timescale = mbase_set->timescale; + if (!timescale && mbase_period && mbase_period->timescale) timescale = mbase_period->timescale; + if (!timescale) timescale = 1; + *out_timescale = timescale; + + if (out_pts_offset) { + pts_offset = mbase_rep ? mbase_rep->presentation_time_offset : 0; + if (!pts_offset && mbase_set && mbase_set->presentation_time_offset) pts_offset = mbase_set->presentation_time_offset; + if (!pts_offset && mbase_period && mbase_period->presentation_time_offset) pts_offset = mbase_period->presentation_time_offset; + *out_pts_offset = pts_offset; + } + + if (mbase_rep && mbase_rep->duration) *out_duration = mbase_rep->duration; + else if (mbase_set && mbase_set->duration) *out_duration = mbase_set->duration; + else if (mbase_period && mbase_period->duration) *out_duration = mbase_period->duration; + + if (out_segment_timeline) *out_segment_timeline = segment_timeline; + + /*for SegmentTimeline, just pick the first one as an indication (exact timeline solving is not done here)*/ + if (segment_timeline) { + GF_MPD_SegmentTimelineEntry *ent = gf_list_get(segment_timeline->entries, 0); + if (ent) *out_duration = ent->duration; + } +} + +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) +{ + GF_MPD_SegmentTimeline *old_timeline, *new_timeline; + u32 idx; + u64 start_time; + GF_MPD_SegmentTimelineEntry *first_new_entry; + + old_timeline = new_timeline = NULL; + if (old_list && old_list->segment_timeline) { + if (!new_list || !new_list->segment_timeline) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: segment timeline not present in new MPD segmentList\n")); + return GF_NON_COMPLIANT_BITSTREAM; + } + old_timeline = old_list->segment_timeline; + new_timeline = new_list->segment_timeline; + } else if (old_template && old_template->segment_timeline) { + if (!new_template || !new_template->segment_timeline) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: segment timeline not present in new MPD segmentTemplate\n")); + return GF_NON_COMPLIANT_BITSTREAM; + } + old_timeline = old_template->segment_timeline; + new_timeline = new_template->segment_timeline; + } + if (!old_timeline && !new_timeline) return GF_OK; + + first_new_entry = gf_list_get(new_timeline->entries, 0); + idx = 0; + start_time=0; + while (1) { + GF_MPD_SegmentTimelineEntry *ent = gf_list_get(old_timeline->entries, 0); + if (!ent) break; + if (ent->start_time) + start_time = ent->start_time; + /*if starttime is equal or greater than first entry in new timeline, we're done*/ + if (start_time >= first_new_entry->start_time) + break; + + /*if entry overlaps first entry in new timeline, remove segments*/ + while (start_time + ent->duration * (1 + ent->repeat_count) > first_new_entry->start_time) { + ent->repeat_count--; + } + /*we will insert the first entry in the new timeline, make sure we have a start*/ + if (!idx && !ent->start_time) + ent->start_time = start_time; + + start_time += ent->duration * (1 + ent->repeat_count); + + gf_list_insert(new_timeline->entries, ent, idx); + idx ++; + gf_list_rem(old_timeline->entries, 0); + + } + return GF_OK; +} + +static u32 gf_dash_purge_segment_timeline(GF_DASH_Group *group, Double min_start_time) +{ + u32 nb_removed, time_scale; + u64 start_time, min_start, duration; + GF_MPD_SegmentTimeline *timeline=NULL; + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + + if (!min_start_time) return 0; + gf_dash_resolve_duration(rep, group->adaptation_set, group->period, &duration, &time_scale, NULL, &timeline); + if (!timeline) return 0; + + min_start = (u64) (min_start_time*time_scale); + start_time = 0; + nb_removed=0; + while (1) { + GF_MPD_SegmentTimelineEntry *ent = gf_list_get(timeline->entries, 0); + if (!ent) break; + if (ent->start_time) start_time = ent->start_time; + + while (start_time + ent->duration < min_start) { + if (! ent->repeat_count) break; + ent->repeat_count--; + nb_removed++; + start_time += ent->duration; + } + /*this entry is in our range, keep it and make sure it has a start time*/ + if (start_time + ent->duration >= min_start) { + if (!ent->start_time) ent->start_time = start_time; + break; + } + start_time += ent->duration; + gf_list_rem(timeline->entries, 0); + gf_free(ent); + nb_removed++; + } + if (nb_removed) { + GF_MPD_SegmentList *segment_list; + /*update next download index*/ + group->download_segment_index -= nb_removed; + /*clean segmentList*/ + segment_list = NULL; + if (group->period && group->period->segment_list) segment_list = group->period->segment_list; + if (group->adaptation_set && group->adaptation_set->segment_list) segment_list = group->adaptation_set->segment_list; + if (rep && rep->segment_list) segment_list = rep->segment_list; + + if (segment_list) { + u32 i = nb_removed; + while (i) { + GF_MPD_SegmentURL *seg_url = gf_list_get(segment_list->segment_URLs, 0); + gf_list_rem(segment_list->segment_URLs, 0); + gf_mpd_segment_url_free(seg_url); + } + } + group->nb_segments_purged += nb_removed; + } + return nb_removed; +} + +static GF_Err gf_dash_update_manifest(GF_DashClient *dash) +{ + GF_Err e; + u32 group_idx, rep_idx, i, j; + GF_DOMParser *mpd_parser; + GF_MPD_Period *period, *new_period; + const char *local_url; + char mime[128]; + char * purl; + + if (!dash->mpd_dnload) { + local_url = purl = NULL; + if (!gf_list_count(dash->mpd->locations)) { + FILE *t = fopen(dash->base_url, "rt"); + if (t) { + local_url = dash->base_url; + fclose(t); + } + if (!local_url) { + /*we will no longer attempt to update the MPD ...*/ + dash->mpd->minimum_update_period = 0; + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: no HTTP source for MPD could be found\n")); + return GF_BAD_PARAM; + } + } + if (!local_url) { + purl = gf_strdup(gf_list_get(dash->mpd->locations, 0)); + + /*if no absolute URL, use to get MPD in case baseURL is relative...*/ + if (!strstr(dash->base_url, "://")) { + gf_free(dash->base_url); + dash->base_url = gf_strdup(purl); + } + } + } else { + local_url = dash->dash_io->get_cache_name(dash->dash_io, dash->mpd_dnload); + if (!local_url) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: wrong cache file %s\n", local_url)); + return GF_IO_ERR; + } + gf_delete_file(local_url); + purl = gf_strdup( dash->dash_io->get_url(dash->dash_io, dash->mpd_dnload) ); + } + + /*if update location is specified, update - spec does not say whether location is a relative or absoute URL*/ + if (gf_list_count(dash->mpd->locations)) { + char *update_loc = gf_list_get(dash->mpd->locations, 0); + char *update_url = gf_url_concatenate(purl, update_loc); + if (update_url) { + gf_free(purl); + purl = update_url; + } + } + + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Updating Playlist %s...\n", purl ? purl : local_url)); + if (purl) { + /*use non-persistent connection for MPD*/ + e = gf_dash_download_resource(dash->dash_io, &(dash->mpd_dnload), purl, 0, 0, 0, NULL); + if (e!=GF_OK) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: download problem %s for MPD file\n", gf_error_to_string(e))); + gf_free(purl); + return e; + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Playlist %s updated with success\n", purl)); + } + strcpy(mime, dash->dash_io->get_mime(dash->dash_io, dash->mpd_dnload) ); + strlwr(mime); + + /*in case the session has been restarted, local_url may have been destroyed - get it back*/ + local_url = dash->dash_io->get_cache_name(dash->dash_io, dash->mpd_dnload); + + /* Some servers, for instance http://tv.freebox.fr, serve m3u8 as text/plain */ + if (gf_dash_is_m3u8_mime(mime) || strstr(purl, ".m3u8")) { + gf_m3u8_to_mpd(local_url, purl, NULL, dash->reload_count, dash->mimeTypeForM3U8Segments, 0, M3U8_TO_MPD_USE_TEMPLATE, &dash->getter); + } else if (!gf_dash_is_dash_mime(mime)) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] mime '%s' should be m3u8 or mpd\n", mime)); + } + + gf_free(purl); + purl = NULL; + } + + if (!gf_dash_check_mpd_root_type(local_url)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: MPD file type is not correct %s\n", local_url)); + return GF_NON_COMPLIANT_BITSTREAM; + } + { + u8 signature[sizeof(dash->lastMPDSignature)]; + if (gf_sha1_file( local_url, signature)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] : cannot SHA1 file %s\n", local_url)); + } else { + if (! memcmp( signature, dash->lastMPDSignature, sizeof(dash->lastMPDSignature))) { + dash->reload_count++; + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] MPD file did not change for %d consecutive reloads\n", dash->reload_count)); + /*if the MPD did not change, we should refresh "soon" but cannot wait a full refresh cycle in case of + low latencies as we could miss a segment*/ + dash->last_update_time += dash->mpd->minimum_update_period/2; + } else { + Double timeline_start_time; + GF_MPD *new_mpd; + dash->reload_count = 0; + memccpy(dash->lastMPDSignature, signature, sizeof(char), sizeof(dash->lastMPDSignature)); + + /* It means we have to reparse the file ... */ + /* parse the MPD */ + mpd_parser = gf_xml_dom_new(); + e = gf_xml_dom_parse(mpd_parser, local_url, NULL, NULL); + if (e != GF_OK) { + gf_xml_dom_del(mpd_parser); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: error in XML parsing %s\n", gf_error_to_string(e))); + return GF_NON_COMPLIANT_BITSTREAM; + } + new_mpd = gf_mpd_new(); + e = gf_mpd_init_from_dom(gf_xml_dom_get_root(mpd_parser), new_mpd, purl); + gf_xml_dom_del(mpd_parser); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: error in MPD creation %s\n", gf_error_to_string(e))); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + + /*TODO - check periods are the same !!*/ + period = gf_list_get(dash->mpd->periods, dash->active_period_index); + new_period = gf_list_get(new_mpd->periods, dash->active_period_index); + if (!new_period) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: missing period\n")); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + + if (gf_list_count(period->adaptation_sets) != gf_list_count(new_period->adaptation_sets)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: missing AdaptationSet\n")); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + + timeline_start_time = 0; + /*if not infinity for timeShift, compute min media time before merge and adjust it*/ + if (dash->mpd->time_shift_buffer_depth != (u32) -1) { + Double timeshift = dash->mpd->time_shift_buffer_depth; + timeshift /= 1000; + + for (group_idx=0; group_idxgroups); group_idx++) { + GF_DASH_Group *group = gf_list_get(dash->groups, group_idx); + Double group_start = gf_dash_get_segment_start_time(group); + if (!group_idx || (timeline_start_time > group_start) ) timeline_start_time = group_start; + } + /*we can rewind our segments from timeshift*/ + if (timeline_start_time > timeshift) timeline_start_time -= timeshift; + /*we can rewind all segments*/ + else timeline_start_time = 0; + } + + /*update segmentTimeline at Period level*/ + e = gf_dash_merge_segment_timeline(period->segment_list, period->segment_template, new_period->segment_list, new_period->segment_template, timeline_start_time); + if (e) { + gf_mpd_del(new_mpd); + return e; + } + + for (group_idx=0; group_idxgroups); group_idx++) { + GF_MPD_AdaptationSet *set, *new_set; + GF_DASH_Group *group = gf_list_get(dash->groups, group_idx); + if (group->selection != GF_DASH_GROUP_SELECTED) continue; + set = group->adaptation_set; + new_set = gf_list_get(new_period->adaptation_sets, group_idx); + + if (gf_list_count(new_set->representations) != gf_list_count(group->adaptation_set->representations)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: missing representation in adaptation set\n")); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + + /*get all representations in both periods*/ + for (rep_idx = 0; rep_idx adaptation_set->representations); rep_idx++) { + GF_List *segments, *new_segments; + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_idx); + GF_MPD_Representation *new_rep = gf_list_get(new_set->representations, rep_idx); + + if (rep->segment_base || group->adaptation_set->segment_base || period->segment_base) { + if (!new_rep->segment_base && !new_set->segment_base && !new_period->segment_base) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: representation does not use segment base as previous version\n")); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + /*what else should we check ??*/ + + /*OK, this rep is fine*/ + } + + else if (rep->segment_template || group->adaptation_set->segment_template || period->segment_template) { + u32 start; + if (!new_rep->segment_template && !new_set->segment_template && !new_period->segment_template) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: representation does not use segment template as previous version\n")); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + start = 0; + /*override new startNum with old one - otherwise we would need to get rid of the entries before the start number in the MPD ...*/ + if (period->segment_template && (period->segment_template->start_number != (u32) -1) ) start = period->segment_template->start_number; + if (set->segment_template && (set->segment_template->start_number != (u32) -1) ) start = set->segment_template->start_number; + if (rep->segment_template && (rep->segment_template->start_number != (u32) -1) ) start = rep->segment_template->start_number; + + if (new_period->segment_template && (new_period->segment_template->start_number != (u32) -1) ) new_period->segment_template->start_number = start; + if (new_set->segment_template && (new_set->segment_template->start_number != (u32) -1) ) new_set->segment_template->start_number = start; + if (new_rep->segment_template && (new_rep->segment_template->start_number != (u32) -1) ) new_rep->segment_template->start_number = start; + + /*OK, this rep is fine*/ + } + else { + /*we're using segment list*/ + assert(rep->segment_list || group->adaptation_set->segment_list || period->segment_list); + + if (!new_rep->segment_list && !new_set->segment_list && !new_period->segment_list) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update playlist: representation does not use segment list as previous version\n")); + gf_mpd_del(new_mpd); + return GF_NON_COMPLIANT_BITSTREAM; + } + /*get the segment list*/ + segments = new_segments = NULL; + if (period->segment_list && period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs; + if (set->segment_list && set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs; + if (rep->segment_list && rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs; + + if (new_period->segment_list && new_period->segment_list->segment_URLs) new_segments = new_period->segment_list->segment_URLs; + if (new_set->segment_list && new_set->segment_list->segment_URLs) new_segments = new_set->segment_list->segment_URLs; + if (new_rep->segment_list && new_rep->segment_list->segment_URLs) new_segments = new_rep->segment_list->segment_URLs; + + + for (i=0; imedia && new_seg->media && !strcmp(seg->media, new_seg->media)) { + found=1; + break; + } + if (seg->media_range && new_seg->media_range && (seg->media_range->start_range==new_seg->media_range->start_range) && (seg->media_range->end_range==new_seg->media_range->end_range) ) { + found=1; + break; + } + } + /*this is a new segment, merge it: we remove from new list and push to old one, before doing a final swap + this ensures that indexing in the segment_list is still correct after merging*/ + if (!found) { + gf_list_rem(new_segments, i); + i--; + gf_list_add(segments, new_seg); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Representation #%d: Adding new segment %s\n", rep_idx+1, new_seg->media)); + } + } + + /*what else should we check ?*/ + + /*swap segment list content*/ + gf_list_swap(new_segments, segments); + + /*current representation is the active one in the group - update the number of segments*/ + if (group->active_rep_index==rep_idx) { + group->nb_segments_in_rep = gf_list_count(new_segments); + } + } + + e = gf_dash_merge_segment_timeline(rep->segment_list, rep->segment_template, new_rep->segment_list, new_rep->segment_template, timeline_start_time); + if (e) { + gf_mpd_del(new_mpd); + return e; + } + + /*what else should we check ??*/ + + + /*switch all intertnal GPAC stuff*/ + memcpy(&new_rep->playback, &rep->playback, sizeof(GF_DASH_RepresentationPlayback)); + if (rep->playback.cached_init_segment_url) rep->playback.cached_init_segment_url = NULL; + + if (!new_rep->mime_type) { + new_rep->mime_type = rep->mime_type; + rep->mime_type = NULL; + } + } + /*update group/period to new period*/ + j = gf_list_find(group->period->adaptation_sets, group->adaptation_set); + group->adaptation_set = gf_list_get(new_period->adaptation_sets, j); + group->period = new_period; + + /*update segmentTimeline at AdaptationSet level*/ + e = gf_dash_merge_segment_timeline(set->segment_list, set->segment_template, new_set->segment_list, new_set->segment_template, timeline_start_time); + if (e) { + gf_mpd_del(new_mpd); + return e; + } + + /*now that all possible SegmentXXX have been updated, purge them if needed: all segments ending before timeline_start_time + will be removed from MPD*/ + if (timeline_start_time) { + u32 nb_segments_removed = gf_dash_purge_segment_timeline(group, timeline_start_time); + if (nb_segments_removed) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] AdaptationSet %d - removed %d segments from timeline (%d since start of the period)\n", group_idx+1, nb_segments_removed, group->nb_segments_purged)); + } + } + + /*update number of segments in active rep*/ + 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); + + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Updated AdaptationSet %d - %d segments\n", group_idx+1, group->nb_segments_in_rep)); + + } + /*swap representations - we don't need to update download_segment_index as it still points to the right entry in the merged list*/ + if (dash->mpd) + gf_mpd_del(dash->mpd); + dash->mpd = new_mpd; + dash->last_update_time = gf_sys_clock(); + } + } + } + return GF_OK; +} + + +static void gf_dash_set_group_representation(GF_DASH_Group *group, GF_MPD_Representation *rep) +{ +#ifndef GPAC_DISABLE_LOG + u32 width=0, height=0, samplerate=0; + GF_MPD_Fractional *framerate=NULL; +#endif + u32 k; + GF_MPD_AdaptationSet *set; + GF_MPD_Period *period; + u32 i = gf_list_find(group->adaptation_set->representations, rep); + assert((s32) i >= 0); + + group->active_rep_index = i; + group->active_bitrate = rep->bandwidth; + group->nb_segments_in_rep = 1; + + group->min_bandwidth_selected = 1; + for (k=0; kadaptation_set->representations); k++) { + GF_MPD_Representation *arep = gf_list_get(group->adaptation_set->representations, k); + if (group->active_bitrate > arep->bandwidth) { + group->min_bandwidth_selected = 0; + break; + } + } + + set = group->adaptation_set; + period = group->period; + +#ifndef GPAC_DISABLE_LOG + +#define GET_REP_ATTR(_a) _a = rep->_a; if (!_a) _a = set->_a; + + GET_REP_ATTR(width); + GET_REP_ATTR(height); + GET_REP_ATTR(samplerate); + GET_REP_ATTR(framerate); + + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Switched to representation bandwidth %d kbps\n", rep->bandwidth/1024)); + if (group->max_bitrate) GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("\tmax download bandwidth: %d kbps\n", group->max_bitrate/1024)); + if (width&&height) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("\tWidth %d Height %d", width, height)); + if (framerate) GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("framerate %d/%d", framerate->num, framerate->den)); + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("\n")); + } else if (samplerate) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("\tsamplerate %d\n", samplerate)); + } +#endif + + + gf_dash_get_segment_duration(rep, set, period, group->dash->mpd, &group->nb_segments_in_rep, &group->segment_duration); +} + +static void gf_dash_switch_group_representation(GF_DashClient *mpd, GF_DASH_Group *group) +{ + u32 i, bandwidth, min_bandwidth; + GF_MPD_Representation *rep_sel = NULL; + GF_MPD_Representation *min_rep_sel = NULL; + Bool min_bandwidth_selected = 0; + bandwidth = 0; + min_bandwidth = (u32) -1; + + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Checking representations between %d and %d kbps\n", group->min_bitrate/1024, group->max_bitrate/1024)); + + if (group->force_representation_idx_plus_one) { + rep_sel = gf_list_get(group->adaptation_set->representations, group->force_representation_idx_plus_one - 1); + group->force_representation_idx_plus_one = 0; + } + + if (!rep_sel) { + for (i=0; iadaptation_set->representations); i++) { + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, i); + if (rep->playback.disabled) continue; + if ((rep->bandwidth > bandwidth) && (rep->bandwidth < group->max_bitrate )) { + rep_sel = rep; + bandwidth = rep->bandwidth; + } + if (rep->bandwidth < min_bandwidth) { + min_rep_sel = rep; + min_bandwidth = rep->bandwidth; + } + } + } + + if (!rep_sel) { + if (!min_rep_sel) { + min_rep_sel = gf_list_get(group->adaptation_set->representations, 0); + } + rep_sel = min_rep_sel; + min_bandwidth_selected = 1; + } + assert(rep_sel); + i = gf_list_find(group->adaptation_set->representations, rep_sel); + + assert((s32) i >= 0); + + group->force_switch_bandwidth = 0; + group->max_bitrate = 0; + group->min_bitrate = (u32) -1; + + if (i != group->active_rep_index) { + if (min_bandwidth_selected) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] No representation found with bandwidth below %d kbps - using representation @ %d kbps\n", group->max_bitrate/1024, rep_sel->bandwidth/1024)); + } + gf_dash_set_group_representation(group, rep_sel); + } +} + + + +typedef enum +{ + GF_DASH_RESOLVE_URL_MEDIA, + GF_DASH_RESOLVE_URL_INIT, + GF_DASH_RESOLVE_URL_INDEX, +} GF_DASHURLResolveType; + + +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) +{ + GF_MPD_BaseURL *url_child; + GF_MPD_SegmentTimeline *timeline = NULL; + u32 start_number = 1; + GF_MPD_AdaptationSet *set = group->adaptation_set; + GF_MPD_Period *period = group->period; + u32 timescale; + char *url; + char *url_to_solve, *solved_template, *first_sep, *media_url; + char *init_template, *index_template; + + *out_range_start = *out_range_end = 0; + *out_url = NULL; + + /*resolve base URLs from document base (download location) to representation (media)*/ + url = gf_strdup(mpd_url); + + url_child = gf_list_get(mpd->base_URLs, 0); + if (url_child) { + char *t_url = gf_url_concatenate(url, url_child->URL); + gf_free(url); + url = t_url; + } + + url_child = gf_list_get(period->base_URLs, 0); + if (url_child) { + char *t_url = gf_url_concatenate(url, url_child->URL); + gf_free(url); + url = t_url; + } + + url_child = gf_list_get(set->base_URLs, 0); + if (url_child) { + char *t_url = gf_url_concatenate(url, url_child->URL); + gf_free(url); + url = t_url; + } + + url_child = gf_list_get(rep->base_URLs, 0); + if (url_child) { + char *t_url = gf_url_concatenate(url, url_child->URL); + gf_free(url); + url = t_url; + } + + gf_dash_resolve_duration(rep, set, period, segment_duration, ×cale, NULL, NULL); + *segment_duration = (u32) ((Double) (*segment_duration) * 1000.0 / timescale); + + /*single URL*/ + if (rep->segment_base || set->segment_base || period->segment_base) { + GF_MPD_URL *res_url; + if (item_index>0) return GF_EOS; + switch (resolve_type) { + case GF_DASH_RESOLVE_URL_MEDIA: + if (!url) return GF_NON_COMPLIANT_BITSTREAM; + *out_url = url; + return GF_OK; + case GF_DASH_RESOLVE_URL_INIT: + case GF_DASH_RESOLVE_URL_INDEX: + res_url = NULL; + if (resolve_type == GF_DASH_RESOLVE_URL_INDEX) { + if (period->segment_base) res_url = period->segment_base->representation_index; + if (set->segment_base) res_url = set->segment_base->representation_index; + if (rep->segment_base) res_url = rep->segment_base->representation_index; + } else { + if (period->segment_base) res_url = period->segment_base->initialization_segment; + if (set->segment_base) res_url = set->segment_base->initialization_segment; + if (rep->segment_base) res_url = rep->segment_base->initialization_segment; + } + /*no initialization segment / index*/ + if (!res_url) { + gf_free(url); + return GF_OK; + } + if (res_url->sourceURL) { + *out_url = gf_url_concatenate(url, res_url->sourceURL); + gf_free(url); + } else { + *out_url = url; + } + if (res_url->byte_range) { + *out_range_start = res_url->byte_range->start_range; + *out_range_end = res_url->byte_range->end_range; + } + return GF_OK; + default: + break; + } + gf_free(url); + return GF_BAD_PARAM; + } + + /*segmentList*/ + if (rep->segment_list || set->segment_list || period->segment_list) { + GF_MPD_URL *init_url, *index_url; + GF_MPD_SegmentURL *segment; + GF_List *segments = NULL; + u32 segment_count; + + init_url = index_url = NULL; + + /*apply inheritance of attributes, lowest level having preceedence*/ + if (period->segment_list) { + if (period->segment_list->initialization_segment) init_url = period->segment_list->initialization_segment; + if (period->segment_list->representation_index) index_url = period->segment_list->representation_index; + if (period->segment_list->segment_URLs) segments = period->segment_list->segment_URLs; + if (period->segment_list->start_number != (u32) -1) start_number = period->segment_list->start_number; + if (period->segment_list->segment_timeline) timeline = period->segment_list->segment_timeline; + } + if (set->segment_list) { + if (set->segment_list->initialization_segment) init_url = set->segment_list->initialization_segment; + if (set->segment_list->representation_index) index_url = set->segment_list->representation_index; + if (set->segment_list->segment_URLs) segments = set->segment_list->segment_URLs; + if (set->segment_list->start_number != (u32) -1) start_number = set->segment_list->start_number; + if (set->segment_list->segment_timeline) timeline = set->segment_list->segment_timeline; + } + if (rep->segment_list) { + if (rep->segment_list->initialization_segment) init_url = rep->segment_list->initialization_segment; + if (rep->segment_list->representation_index) index_url = rep->segment_list->representation_index; + if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs; + if (rep->segment_list->start_number != (u32) -1) start_number = rep->segment_list->start_number; + if (rep->segment_list->segment_timeline) timeline = rep->segment_list->segment_timeline; + } + + + segment_count = gf_list_count(segments); + + switch (resolve_type) { + case GF_DASH_RESOLVE_URL_INIT: + if (init_url) { + if (init_url->sourceURL) { + *out_url = gf_url_concatenate(url, init_url->sourceURL); + gf_free(url); + } else { + *out_url = url; + } + if (init_url->byte_range) { + *out_range_start = init_url->byte_range->start_range; + *out_range_end = init_url->byte_range->end_range; + } + } else { + gf_free(url); + } + return GF_OK; + case GF_DASH_RESOLVE_URL_MEDIA: + if (!url) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Media URL is not set in segment list\n")); + return GF_SERVICE_ERROR; + } + if (item_index >= segment_count) { + gf_free(url); + return GF_EOS; + } + *out_url = url; + segment = gf_list_get(segments, item_index); + if (segment->media) { + *out_url = gf_url_concatenate(url, segment->media); + gf_free(url); + } + if (segment->media_range) { + *out_range_start = segment->media_range->start_range; + *out_range_end = segment->media_range->end_range; + } + return GF_OK; + case GF_DASH_RESOLVE_URL_INDEX: + if (item_index >= segment_count) { + gf_free(url); + return GF_EOS; + } + *out_url = url; + segment = gf_list_get(segments, item_index); + if (segment->index) { + *out_url = gf_url_concatenate(url, segment->index); + gf_free(url); + } + if (segment->index_range) { + *out_range_start = segment->index_range->start_range; + *out_range_end = segment->index_range->end_range; + } + return GF_OK; + default: + break; + } + gf_free(url); + return GF_BAD_PARAM; + } + + /*segmentTemplate*/ + media_url = init_template = index_template = NULL; + + /*apply inheritance of attributes, lowest level having preceedence*/ + if (period->segment_template) { + if (period->segment_template->initialization) init_template = period->segment_template->initialization; + if (period->segment_template->index) index_template = period->segment_template->index; + if (period->segment_template->media) media_url = period->segment_template->media; + if (period->segment_template->start_number != (u32) -1) start_number = period->segment_template->start_number; + if (period->segment_template->segment_timeline) timeline = period->segment_template->segment_timeline; + } + if (set->segment_template) { + if (set->segment_template->initialization) init_template = set->segment_template->initialization; + if (set->segment_template->index) index_template = set->segment_template->index; + if (set->segment_template->media) media_url = set->segment_template->media; + if (set->segment_template->start_number != (u32) -1) start_number = set->segment_template->start_number; + if (set->segment_template->segment_timeline) timeline = set->segment_template->segment_timeline; + } + if (rep->segment_template) { + if (rep->segment_template->initialization) init_template = rep->segment_template->initialization; + if (rep->segment_template->index) index_template = rep->segment_template->index; + if (rep->segment_template->media) media_url = rep->segment_template->media; + if (rep->segment_template->start_number != (u32) -1) start_number = rep->segment_template->start_number; + if (rep->segment_template->segment_timeline) timeline = rep->segment_template->segment_timeline; + } + + /*offset the start_number with the number of discarded segments (no longer in our lists)*/ + start_number += group->nb_segments_purged; + + if (!media_url) { + GF_MPD_BaseURL *base = gf_list_get(rep->base_URLs, 0); + if (!base) return GF_BAD_PARAM; + media_url = base->URL; + } + url_to_solve = NULL; + switch (resolve_type) { + case GF_DASH_RESOLVE_URL_INIT: + url_to_solve = init_template; + break; + case GF_DASH_RESOLVE_URL_MEDIA: + url_to_solve = media_url; + break; + case GF_DASH_RESOLVE_URL_INDEX: + url_to_solve = index_template; + break; + default: + gf_free(url); + return GF_BAD_PARAM; + } + if (!url_to_solve) { + gf_free(url); + return GF_OK; + } + /*let's solve the template*/ + solved_template = gf_malloc(sizeof(char)*strlen(url_to_solve)*2); + solved_template[0] = 0; + strcpy(solved_template, url_to_solve); + first_sep = strchr(solved_template, '$'); + if (first_sep) first_sep[0] = 0; + + first_sep = strchr(url_to_solve, '$'); + while (first_sep) { + char szPrintFormat[50]; + char szFormat[100]; + char *format_tag; + char *second_sep = strchr(first_sep+1, '$'); + if (!second_sep) { + gf_free(url); + gf_free(solved_template); + return GF_NON_COMPLIANT_BITSTREAM; + } + second_sep[0] = 0; + format_tag = strchr(first_sep+1, '%'); + + if (format_tag) { + strcpy(szPrintFormat, format_tag); + format_tag[0] = 0; + } else { + strcpy(szPrintFormat, "%d"); + } + /* identifier is $$ -> replace by $*/ + if (!strlen(first_sep+1)) { + strcat(solved_template, "$"); + } + else if (!strcmp(first_sep+1, "RepresentationID")) { + strcat(solved_template, rep->id); + } + else if (!strcmp(first_sep+1, "Number")) { + sprintf(szFormat, szPrintFormat, start_number + item_index); + strcat(solved_template, szFormat); + } + else if (!strcmp(first_sep+1, "Index")) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Wrong template identifier Index detected - using Number instead\n\n")); + sprintf(szFormat, szPrintFormat, start_number + item_index); + strcat(solved_template, szFormat); + } + else if (!strcmp(first_sep+1, "Bandwidth")) { + sprintf(szFormat, szPrintFormat, rep->bandwidth); + strcat(solved_template, szFormat); + } + else if (!strcmp(first_sep+1, "Time")) { + if (timeline) { + /*uses segment timeline*/ + u32 k, nb_seg, cur_idx, nb_repeat; + u64 time, start_time; + nb_seg = gf_list_count(timeline->entries); + cur_idx = 0; + start_time=0; + for (k=0; kentries, k); + if (item_index>cur_idx+ent->repeat_count) { + cur_idx += 1 + ent->repeat_count; + if (ent->start_time) start_time = ent->start_time; + + start_time += ent->duration * (1 + ent->repeat_count); + continue; + } + *segment_duration = ent->duration; + *segment_duration = (u32) ((Double) (*segment_duration) * 1000.0 / timescale); + nb_repeat = item_index - cur_idx; + time = ent->start_time ? ent->start_time : start_time; + time += nb_repeat * ent->duration; + + /*replace final 'd' with LLD (%lld or I64d)*/ + szPrintFormat[strlen(szPrintFormat)-1] = 0; + strcat(szPrintFormat, &LLD[1]); + sprintf(szFormat, szPrintFormat, time); + strcat(solved_template, szFormat); + break; + } + } + } + else { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Unknown template identifier %s - disabling rep\n\n", first_sep+1)); + *out_url = NULL; + gf_free(url); + gf_free(solved_template); + group->selection = GF_DASH_GROUP_NOT_SELECTABLE; + return GF_NON_COMPLIANT_BITSTREAM; + } + if (format_tag) format_tag[0] = '%'; + second_sep[0] = '$'; + /*look for next keyword - copy over remaining text if any*/ + first_sep = strchr(second_sep+1, '$'); + if (first_sep) first_sep[0] = 0; + if (strlen(second_sep+1)) + strcat(solved_template, second_sep+1); + if (first_sep) first_sep[0] = '$'; + } + *out_url = gf_url_concatenate(url, solved_template); + gf_free(url); + gf_free(solved_template); + return GF_OK; +} + +static GF_Err gf_dash_download_init_segment(GF_DashClient *dash, GF_DASH_Group *group) +{ + GF_Err e; + char *base_init_url; + GF_MPD_Representation *rep; + u64 start_range, end_range; + /* This variable is 0 if there is a initURL, the index of first segment downloaded otherwise */ + u32 nb_segment_read = 0; + if (!dash || !group) + return GF_BAD_PARAM; + gf_mx_p(dash->dl_mutex); + + assert( group->adaptation_set && group->adaptation_set->representations ); + rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + if (!rep) { + gf_mx_v(dash->dl_mutex); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Unable to find any representation, aborting.\n")); + return GF_IO_ERR; + } + start_range = end_range = 0; + + 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); + if (e) { + gf_mx_v(dash->dl_mutex); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Unable to resolve initialization URL: %s\n", gf_error_to_string(e) )); + return e; + } + + /*no error and no init segment, go for media segment*/ + if (!base_init_url) { + 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); + if (e) { + gf_mx_v(dash->dl_mutex); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Unable to resolve media URL: %s\n", gf_error_to_string(e) )); + return e; + } + nb_segment_read = 1; + } else if (!group->bitstream_switching) { + group->dont_delete_first_segment = 1; + } + + if (!strstr(base_init_url, "://") || !strnicmp(base_init_url, "file://", 7) || !strnicmp(base_init_url, "views://", 8)) { + assert(!group->nb_cached_segments); + group->cached[0].cache = gf_strdup(base_init_url); + group->cached[0].url = gf_strdup(base_init_url); + group->cached[0].representation_index = group->active_rep_index; + group->prev_active_rep_index = group->active_rep_index; + + group->nb_cached_segments = 1; + /*do not erase local files*/ + group->local_files = 1; + group->download_segment_index += nb_segment_read; + group->segment_local_url = group->cached[0].cache; + group->local_url_start_range = start_range; + group->local_url_end_range = end_range; + rep->playback.cached_init_segment_url = gf_strdup(group->segment_local_url); + rep->playback.init_start_range = start_range; + rep->playback.init_end_range = end_range; + + + /*finally download all init segments if any*/ + if (!group->bitstream_switching) { + u32 k; + for (k=0; kadaptation_set->representations); k++) { + char *a_base_init_url = NULL; + u64 a_start, a_end, a_dur; + GF_MPD_Representation *a_rep = gf_list_get(group->adaptation_set->representations, k); + if (a_rep==rep) continue; + if (a_rep->playback.disabled) continue; + + 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); + if (!e && a_base_init_url) { + a_rep->playback.cached_init_segment_url = a_base_init_url; + rep->playback.init_start_range = a_start; + rep->playback.init_end_range =a_end ; + } else if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot solve initialization segment for representation: %s - discarding representation\n", gf_error_to_string(e) )); + a_rep->playback.disabled = 1; + } + } + } + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] First segment is %s \n", group->segment_local_url)); + gf_mx_v(dash->dl_mutex); + gf_free(base_init_url); + return GF_OK; + } + + group->max_bitrate = 0; + group->min_bitrate = (u32)-1; + /*use persistent connection for segment downloads*/ + e = gf_dash_download_resource(dash->dash_io, &(group->segment_download), base_init_url, start_range, end_range, 1, group); + + if ((e==GF_OK) && group->force_switch_bandwidth && !dash->auto_switch_count) { + gf_dash_switch_group_representation(dash, group); + gf_mx_v(dash->dl_mutex); + return gf_dash_download_init_segment(dash, group); + } + + + if (e == GF_URL_ERROR && !base_init_url) { /* We have a 404 and started with segments */ + /* It is possible that the first segment has been deleted while we made the first request... + * so we try with the next segment on some M3U8 servers */ + + gf_free(base_init_url); + + 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); + if (!e) { + gf_mx_v(dash->dl_mutex); + return e; + } + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("Download of first segment failed... retrying with second one : %s\n", base_init_url)); + nb_segment_read = 2; + /*use persistent connection for segment downloads*/ + e = gf_dash_download_resource(dash->dash_io, &(group->segment_download), base_init_url, 0, 0, 1, group); + } /* end of 404 */ + + if (e!= GF_OK && !group->segment_must_be_streamed) { + dash->mpd_stop_request = 1; + gf_mx_v(dash->dl_mutex); + gf_free(base_init_url); + return e; + } else { + char mime[128]; + const char *mime_type; + if (!group->nb_segments_in_rep) { + if (dash->mpd->type==GF_MPD_TYPE_STATIC) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] 0 segments in static representation, aborting\n")); + gf_free(base_init_url); + gf_mx_v(dash->dl_mutex); + return GF_BAD_PARAM; + } + } else if (group->nb_segments_in_rep < group->max_cached_segments) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Resizing to %u max_cached_segments elements instead of %u.\n", group->nb_segments_in_rep, group->max_cached_segments)); + /* OK, we have a problem, it may ends download */ + group->max_cached_segments = group->nb_segments_in_rep; + } + + /* Mime-Type check */ + mime_type = dash->dash_io->get_mime(dash->dash_io, group->segment_download) ; + strcpy(mime, mime_type ? mime_type : ""); + strlwr(mime); + + if (dash->mimeTypeForM3U8Segments) + gf_free(dash->mimeTypeForM3U8Segments); + dash->mimeTypeForM3U8Segments = gf_strdup( mime ); + mime_type = gf_dash_get_mime_type(NULL, rep, group->adaptation_set); + + if (!rep->mime_type) { + rep->mime_type = gf_strdup( mime_type ? mime_type : mime ); + mime_type = gf_dash_get_mime_type(NULL, rep, group->adaptation_set); + } + + if (stricmp(mime, mime_type)) { + Bool valid = 0; + char *stype1, *stype2; + stype1 = strchr(mime_type, '/'); + stype2 = strchr(mime, '/'); + if (stype1 && stype2 && !strcmp(stype1, stype2)) valid = 1; + + if (!valid && 0) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Mime '%s' is not correct for '%s', it should be '%s'\n", mime, base_init_url, mime_type)); + dash->mpd_stop_request = 0; + gf_mx_v(dash->dl_mutex); + gf_free(base_init_url); + base_init_url = NULL; + return GF_BAD_PARAM; + } + } + + if (group->segment_must_be_streamed ) { + group->segment_local_url = dash->dash_io->get_url(dash->dash_io, group->segment_download); + e = GF_OK; + } else { + group->segment_local_url = dash->dash_io->get_cache_name(dash->dash_io, group->segment_download); + } + + if ((e!=GF_OK) || !group->segment_local_url) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error with initialization segment: download result:%s, cache file:%s\n", gf_error_to_string(e), group->segment_local_url)); + dash->mpd_stop_request = 1; + gf_mx_v(dash->dl_mutex); + gf_free(base_init_url); + return GF_BAD_PARAM; + } + + assert(!group->nb_cached_segments); + group->cached[0].cache = gf_strdup(group->segment_local_url); + group->cached[0].url = gf_strdup( dash->dash_io->get_url(dash->dash_io, group->segment_download) ); + group->cached[0].representation_index = group->active_rep_index; + rep->playback.cached_init_segment_url = gf_strdup(group->segment_local_url); + rep->playback.init_start_range = 0; + rep->playback.init_end_range = 0; + + group->nb_cached_segments = 1; + group->download_segment_index += nb_segment_read; + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Adding initialization segment %s to cache: %s\n", group->segment_local_url, group->cached[0].url )); + gf_mx_v(dash->dl_mutex); + gf_free(base_init_url); + + /*finally download all init segments if any*/ + if (!group->bitstream_switching) { + u32 k; + for (k=0; kadaptation_set->representations); k++) { + char *a_base_init_url = NULL; + u64 a_start, a_end, a_dur; + GF_MPD_Representation *a_rep = gf_list_get(group->adaptation_set->representations, k); + if (a_rep==rep) continue; + if (a_rep->playback.disabled) continue; + + 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); + if (!e && a_base_init_url) { + e = gf_dash_download_resource(dash->dash_io, &(group->segment_download), a_base_init_url, a_start, a_end, 1, group); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot retrieve initialization segment %s for representation: %s - discarding representation\n", a_base_init_url, gf_error_to_string(e) )); + a_rep->playback.disabled = 1; + } else { + a_rep->playback.cached_init_segment_url = gf_strdup( dash->dash_io->get_cache_name(dash->dash_io, group->segment_download) ); + rep->playback.init_start_range = 0; + rep->playback.init_end_range = 0; + } + gf_free(a_base_init_url); + } else if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Cannot solve initialization segment for representation: %s - discarding representation\n", gf_error_to_string(e) )); + a_rep->playback.disabled = 1; + } + + } + } + + return GF_OK; + } +} + +static void gf_dash_skip_disabled_representation(GF_DASH_Group *group, GF_MPD_Representation *rep) +{ + s32 rep_idx = gf_list_find(group->adaptation_set->representations, rep); + while (1) { + rep_idx++; + if (rep_idx==gf_list_count(group->adaptation_set->representations)) rep_idx = 0; + rep = gf_list_get(group->adaptation_set->representations, rep_idx); + if (!rep->playback.disabled) break; + } + assert(rep && !rep->playback.disabled); + gf_dash_set_group_representation(group, rep); +} + +static void gf_dash_reset_groups(GF_DashClient *dash) +{ + /*send playback destroy event*/ + dash->dash_io->on_dash_event(dash->dash_io, GF_DASH_EVENT_DESTROY_PLAYBACK, GF_OK); + + while (gf_list_count(dash->groups)) { + GF_DASH_Group *group = gf_list_last(dash->groups); + gf_list_rem_last(dash->groups); + + if (group->urlToDeleteNext) { + if (!dash->keep_files && !group->local_files) + dash->dash_io->delete_cache_file(dash->dash_io, group->segment_download, group->urlToDeleteNext); + + gf_free(group->urlToDeleteNext); + group->urlToDeleteNext = NULL; + } + if (group->segment_download) { + dash->dash_io->del(dash->dash_io, group->segment_download); + group->segment_download = NULL; + } + while (group->nb_cached_segments) { + group->nb_cached_segments --; + if (!dash->keep_files && !group->local_files) + gf_delete_file(group->cached[group->nb_cached_segments].cache); + + gf_free(group->cached[group->nb_cached_segments].cache); + gf_free(group->cached[group->nb_cached_segments].url); + } + gf_free(group->cached); + + if (group->service_mime) + gf_free(group->service_mime); + gf_free(group); + } + gf_list_del(dash->groups); + dash->groups = NULL; +} + + +/* create groups (implemntation of adaptations set) */ +GF_Err gf_dash_setup_groups(GF_DashClient *dash) +{ + GF_Err e; + u32 i, j, count; + GF_MPD_Period *period; + + if (!dash->groups) { + dash->groups = gf_list_new(); + if (!dash->groups) return GF_OUT_OF_MEM; + } + + period = gf_list_get(dash->mpd->periods, dash->active_period_index); + if (!period) return GF_BAD_PARAM; + + count = gf_list_count(period->adaptation_sets); + for (i=0; iadaptation_sets, i); + for (j=0; jgroups); j++) { + GF_DASH_Group *group = gf_list_get(dash->groups, j); + if (group->adaptation_set==set) { + found = 1; + break; + } + } + + if (found) continue; + + + GF_SAFEALLOC(group, GF_DASH_Group); + if (!group) return GF_OUT_OF_MEM; + group->dash = dash; + group->adaptation_set = set; + group->period = period; + + group->bitstream_switching = (set->bitstream_switching || period->bitstream_switching) ? 1 : 0; + + seg_dur = 0; + for (j=0; jrepresentations); j++) { + Double dur; + u32 nb_seg; + gf_dash_get_segment_duration(gf_list_get(set->representations, j), set, period, dash->mpd, &nb_seg, &dur); + if (dur>seg_dur) seg_dur = dur; + } + + if (!seg_dur) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Cannot compute default segment duration\n")); + } + + cache_duration = dash->max_cache_duration * 1000; + if (dash->mpd->min_buffer_time) + cache_duration = dash->mpd->min_buffer_time; + group->max_cached_segments = 1; + if (seg_dur) { + while (group->max_cached_segments * seg_dur * 1000 < cache_duration) + group->max_cached_segments ++; + + /*we need one more entry in cache for segment being currently played*/ + group->max_cached_segments ++; + } + + group->cached = gf_malloc(sizeof(segment_cache_entry)*group->max_cached_segments); + memset(group->cached, 0, sizeof(segment_cache_entry)*group->max_cached_segments); + if (!group->cached) { + gf_free(group); + return GF_OUT_OF_MEM; + } + e = gf_list_add(dash->groups, group); + if (e) { + gf_free(group->cached); + gf_free(group); + return e; + } + } + return GF_OK; +} + +static GF_Err gf_dash_setup_period(GF_DashClient *dash) +{ + u32 rep_i, group_i, nb_groups_ok; + + /*setup all groups*/ + gf_dash_setup_groups(dash); + + nb_groups_ok = 0; + for (group_i=0; group_igroups); group_i++) { + GF_MPD_Representation *rep_sel; + u32 active_rep, nb_rep; + const char *mime_type; + GF_DASH_Group *group = gf_list_get(dash->groups, group_i); + + nb_rep = gf_list_count(group->adaptation_set->representations); + + if ((nb_rep>1) && !group->adaptation_set->segment_alignment && !group->adaptation_set->subsegment_alignment) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] AdaptationSet without segmentAlignment flag set - ignoring because not supported\n")); + continue; + } + if (group->adaptation_set->xlink_href) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] AdaptationSet with xlink:href to %s - ignoring because not supported\n", group->adaptation_set->xlink_href)); + continue; + } + + /* Select the appropriate representation in the given period */ + active_rep = 0; + for (rep_i = 0; rep_i < nb_rep; rep_i++) { + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, rep_i); + rep_sel = gf_list_get(group->adaptation_set->representations, active_rep); + + if (rep_i) { + Bool ok; + char *sep; + if ( !rep->codecs || !rep_sel->codecs ) continue; + sep = strchr(rep_sel->codecs, '.'); + if (sep) sep[0] = 0; + ok = !strnicmp(rep->codecs, rep_sel->codecs, strlen(rep_sel->codecs) ); + if (sep) sep[0] = '.'; + if (!ok) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Different codec types (%s vs %s) in same AdaptationSet - disabling %s\n", rep_sel->codecs, rep->codecs, rep->codecs)); + rep->playback.disabled = 1; + continue; + } + if (rep->dependency_id) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Representation dependent on representation %d - not supported\n", rep->dependency_id)); + rep->playback.disabled = 1; + continue; + } + if (rep->segment_list && rep->segment_list->xlink_href) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Representation SegmentList uses xlink:href to %s - disabling because not supported\n", rep->segment_list->xlink_href)); + rep->playback.disabled = 1; + continue; + } + } + + switch (dash->first_select_mode) { + case GF_DASH_SELECT_QUALITY_LOWEST: + if (rep->quality_ranking && (rep->quality_ranking < rep_sel->quality_ranking)) { + active_rep = rep_i; + break; + }/*fallthrough if quality is not indicated*/ + case GF_DASH_SELECT_BANDWIDTH_LOWEST: + if (rep->bandwidth < rep_sel->bandwidth) { + active_rep = rep_i; + } + break; + case GF_DASH_SELECT_QUALITY_HIGHEST: + if (rep->quality_ranking > rep_sel->quality_ranking) { + active_rep = rep_i; + break; + }/*fallthrough if quality is not indicated*/ + case GF_DASH_SELECT_BANDWIDTH_HIGHEST: + if (rep->bandwidth > rep_sel->bandwidth) { + active_rep = rep_i; + } + break; + default: + break; + } + } + + rep_sel = gf_list_get(group->adaptation_set->representations, active_rep); + gf_dash_set_group_representation(group, rep_sel); + + if (dash->playback_start_range>=0) + gf_dash_seek_group(dash, group); + + mime_type = gf_dash_get_mime_type(NULL, rep_sel, group->adaptation_set); + + if (!mime_type) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Missing MIME type for AdaptationSet - skipping\n")); + continue; + } + + /* TODO: Generate segment names if urltemplates are used */ + if (!rep_sel->segment_base && !rep_sel->segment_list && !rep_sel->segment_template + && !group->adaptation_set->segment_base && !group->adaptation_set->segment_list && !group->adaptation_set->segment_template + && !group->period->segment_base && !group->period->segment_list && !group->period->segment_template + && !gf_list_count(rep_sel->base_URLs) + ) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Segment URLs are not present for AdaptationSet - skipping\n")); + continue; + } + + group->selection = GF_DASH_GROUP_NOT_SELECTED; + nb_groups_ok++; + } + if (!nb_groups_ok) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] No AdaptationSet could be selected in the MPD - Cannot play\n")); + return GF_NON_COMPLIANT_BITSTREAM; + } + + /*and seek if needed*/ + return GF_OK; +} + + +static u32 dash_main_thread_proc(void *par) +{ + GF_Err e; + GF_DashClient *dash = (GF_DashClient*) par; + GF_MPD_Representation *rep; + u32 i, group_count, ret = 0; + Bool go_on = 1; + char *new_base_seg_url; + assert(dash); + if (!dash->mpd) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Incorrect state, no dash->mpd for URL=%s, already stopped ?\n", dash->base_url)); + return 1; + } + +restart_period: + + /* Setting the download status in exclusive code */ + gf_mx_p(dash->dl_mutex); + dash->dash_state = GF_DASH_STATE_SETUP; + gf_mx_v(dash->dl_mutex); + + dash->in_period_setup = 1; + + dash->dash_io->on_dash_event(dash->dash_io, GF_DASH_EVENT_SELECT_GROUPS, GF_OK); + + e = GF_OK; + group_count = gf_list_count(dash->groups); + for (i=0; igroups, i); + if (group->selection != GF_DASH_GROUP_SELECTED) continue; + e = gf_dash_download_init_segment(dash, group); + if (e) break; + } + dash->mpd_stop_request=0; + + /*if error signal to the user*/ + if (e != GF_OK) { + dash->dash_io->on_dash_event(dash->dash_io, GF_DASH_EVENT_PERIOD_SETUP_ERROR, e); + ret = 1; + goto exit; + } + + + dash->last_update_time = gf_sys_clock(); + + gf_mx_p(dash->dl_mutex); + dash->dash_state = GF_DASH_STATE_CONNECTING; + gf_mx_v(dash->dl_mutex); + + + /*ask the user to connect to desired groups*/ + e = dash->dash_io->on_dash_event(dash->dash_io, GF_DASH_EVENT_CREATE_PLAYBACK, GF_OK); + if (e) { + ret = 1; + goto exit; + } + if (dash->mpd_stop_request) { + ret = 1; + goto exit; + } + + gf_mx_p(dash->dl_mutex); + dash->in_period_setup = 0; + dash->dash_state = GF_DASH_STATE_RUNNING; + gf_mx_v(dash->dl_mutex); + + while (go_on) { + const char *local_file_name = NULL; + const char *resource_name = NULL; + /*wait until next segment is needed*/ + while (!dash->mpd_stop_request) { + u32 timer = gf_sys_clock() - dash->last_update_time; + Bool shouldParsePlaylist = dash->mpd->minimum_update_period && (timer > dash->mpd->minimum_update_period); + + if (shouldParsePlaylist) { + 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)); + e = gf_dash_update_manifest(dash); + group_count = gf_list_count(dash->groups); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error updating MPD %s\n", gf_error_to_string(e))); + } + } else { + Bool all_groups_done = 1; + Bool cache_full = 1; + gf_mx_p(dash->dl_mutex); + for (i=0; igroups, i); + if ((group->selection != GF_DASH_GROUP_SELECTED) || group->done) continue; + all_groups_done = 0; + if (group->nb_cached_segmentsmax_cached_segments) { + cache_full = 0; + break; + } + } + gf_mx_v(dash->dl_mutex); + if (!cache_full) break; + + if (dash->request_period_switch==2) all_groups_done = 1; + + if (all_groups_done && dash->request_period_switch) { + gf_dash_reset_groups(dash); + if (dash->request_period_switch == 1) + dash->active_period_index++; + + gf_dash_setup_period(dash); + dash->request_period_switch = 0; + + goto restart_period; + } + + gf_sleep(16); + } + } + + /* stop the thread if requested */ + if (dash->mpd_stop_request) { + go_on = 0; + break; + } + + /*for each selected groups*/ + for (i=0; igroups, i); + if (group->selection != GF_DASH_GROUP_SELECTED) continue; + if (group->done) continue; + + + if (group->nb_cached_segments>=group->max_cached_segments) { + continue; + } + + /*remember the active rep index, since group->active_rep_index may change because of bandwidth control algorithm*/ + representation_index = group->active_rep_index; + rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + + /* if the index of the segment to be downloaded is greater or equal to the last segment (as seen in the playlist), + we need to check if a new playlist is ready */ + if (group->nb_segments_in_rep && (group->download_segment_index>=group->nb_segments_in_rep)) { + u32 timer = gf_sys_clock() - dash->last_update_time; + /* update of the playlist, only if indicated */ + if (dash->mpd->minimum_update_period && timer > dash->mpd->minimum_update_period) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Last segment in current playlist downloaded, checking updates after %u ms\n", timer)); + e = gf_dash_update_manifest(dash); + if (e) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error updating MPD %s\n", gf_error_to_string(e))); + } + group_count = gf_list_count(dash->groups); + rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + } else { + gf_sleep(16); + } + /* Now that the playlist is up to date, we can check again */ + if (group->download_segment_index >= group->nb_segments_in_rep) { + if (dash->mpd->minimum_update_period) { + /* if there is a specified update period, we redo the whole process */ + continue; + } else { + /* if not, we are really at the end of the playlist, we can quit */ + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] End of playlist reached... downloading remaining elements...")); + group->done = 1; + break; + } + } + } + gf_mx_p(dash->dl_mutex); + + /*todo for live - check we don't attempt to request segments before their availabilityStartTime !*/ + + /* At this stage, there are some segments left to be downloaded */ + 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); + gf_mx_v(dash->dl_mutex); + if (e) { + /*do something!!*/ + break; + } + use_byterange = (start_range || end_range) ? 1 : 0; + + if (use_byterange) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Downloading new segment: %s (range: "LLD"-"LLD")\n", new_base_seg_url, start_range, end_range)); + } + + /*local file*/ + if (!strstr(new_base_seg_url, "://") || !strnicmp(new_base_seg_url, "file://", 7)) { + resource_name = local_file_name = (char *) new_base_seg_url; + e = GF_OK; + /*do not erase local files*/ + group->local_files = 1; + if (group->force_switch_bandwidth && !dash->auto_switch_count) { + gf_dash_switch_group_representation(dash, group); + /*restart*/ + i--; + continue; + } + + } else { + u32 total_size, bytes_per_sec; + + group->max_bitrate = 0; + group->min_bitrate = (u32)-1; + /*use persistent connection for segment downloads*/ + if (use_byterange) { + e = gf_dash_download_resource(dash->dash_io, &(group->segment_download), new_base_seg_url, start_range, end_range, 1, group); + } else { + e = gf_dash_download_resource(dash->dash_io, &(group->segment_download), new_base_seg_url, 0, 0, 1, group); + } + + /*TODO decide what is the best, fetch from another representation or ignore ...*/ + if (e != GF_OK) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error in downloading new segment: %s %s\n", new_base_seg_url, gf_error_to_string(e))); + group->download_segment_index++; + continue; + } + + if ((e==GF_OK) && group->force_switch_bandwidth) { + if (!dash->auto_switch_count) { + gf_dash_switch_group_representation(dash, group); + /*restart*/ + i--; + continue; + } + if (rep->playback.disabled) { + gf_dash_skip_disabled_representation(group, rep); + /*restart*/ + i--; + continue; + } + } + + if (group->segment_must_be_streamed) local_file_name = dash->dash_io->get_url(dash->dash_io, group->segment_download); + else local_file_name = dash->dash_io->get_cache_name(dash->dash_io, group->segment_download); + + resource_name = dash->dash_io->get_url(dash->dash_io, group->segment_download); + + total_size = dash->dash_io->get_total_size(dash->dash_io, group->segment_download); + bytes_per_sec = dash->dash_io->get_bytes_per_sec(dash->dash_io, group->segment_download); + + if (total_size && bytes_per_sec && group->current_downloaded_segment_duration) { + Double bitrate, time; + bitrate = 8*total_size; + bitrate *= 1000; + bitrate /= group->current_downloaded_segment_duration; + bitrate /= 1024; + time = total_size; + time /= bytes_per_sec; + + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Downloaded segment %d bytes in %g seconds - duration %g sec - Bandwidth (kbps): indicated %d - computed %d - download %d\n", total_size, time, group->current_downloaded_segment_duration/1000.0, rep->bandwidth/1024, (u32) bitrate, 8*bytes_per_sec/1024)); + + if (rep->bandwidth < 8*bytes_per_sec) { + u32 k; + /*find highest bandwidth that fits our bitrate*/ + GF_MPD_Representation *new_rep = NULL; + for (k=0; kadaptation_set->representations); k++) { + GF_MPD_Representation *arep = gf_list_get(group->adaptation_set->representations, k); + if (8*bytes_per_sec > arep->bandwidth) { + if (!new_rep) new_rep = arep; + else if (arep->bandwidth > new_rep->bandwidth) { + new_rep = arep; + } + } + } + if (!dash->disable_switching && new_rep && (new_rep!=rep)) { + gf_dash_set_group_representation(group, new_rep); + } + } + } + } + + if (local_file_name && (e == GF_OK || group->segment_must_be_streamed )) { + gf_mx_p(dash->dl_mutex); + assert(group->nb_cached_segmentsmax_cached_segments); + assert( local_file_name ); + group->cached[group->nb_cached_segments].cache = gf_strdup(local_file_name); + group->cached[group->nb_cached_segments].url = gf_strdup( resource_name ); + group->cached[group->nb_cached_segments].start_range = 0; + group->cached[group->nb_cached_segments].end_range = 0; + group->cached[group->nb_cached_segments].representation_index = representation_index; + if (group->local_files && use_byterange) { + group->cached[group->nb_cached_segments].start_range = start_range; + group->cached[group->nb_cached_segments].end_range = end_range; + } + if (!group->local_files) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH] Added file to cache (%u/%u in cache): %s\n", group->nb_cached_segments+1, group->max_cached_segments, group->cached[group->nb_cached_segments].url)); + } + group->nb_cached_segments++; + group->download_segment_index++; + if (dash->auto_switch_count) { + group->nb_segments_done++; + if (group->nb_segments_done==dash->auto_switch_count) { + group->nb_segments_done=0; + gf_dash_skip_disabled_representation(group, rep); + } + } + gf_mx_v(dash->dl_mutex); + } + gf_free(new_base_seg_url); + new_base_seg_url = NULL; + } + } + +exit: + /* Signal that the download thread has ended */ + gf_mx_p(dash->dl_mutex); + + /*an error occured during playback chain creation and we couldn't release our plyayback chain in time, do it now*/ + if (dash->dash_state == GF_DASH_STATE_CONNECTING) + gf_dash_reset_groups(dash); + + dash->dash_state = GF_DASH_STATE_STOPPED; + gf_mx_v(dash->dl_mutex); + return ret; +} + +static u32 gf_dash_period_index_from_time(GF_DashClient *dash, u32 time) +{ + u32 i, count, cumul_start=0; + GF_MPD_Period *period; + count = gf_list_count(dash->mpd->periods); + for (i = 0; impd->periods, i); + if ((period->start > time) || (cumul_start > time)) { + break; + } + cumul_start+=period->duration; + } + return (i-1 >= 0 ? (i-1) : 0); +} + +static void gf_dash_download_stop(GF_DashClient *dash) +{ + u32 i; + assert( dash ); + if (dash->groups) { + for (i=0; igroups); i++) { + GF_DASH_Group *group = gf_list_get(dash->groups, i); + assert( group ); + if ((group->selection == GF_DASH_GROUP_SELECTED) && group->segment_download) { + if (group->segment_download) + dash->dash_io->abort(dash->dash_io, group->segment_download); + group->done = 1; + } + } + } + /* stop the download thread */ + gf_mx_p(dash->dl_mutex); + if (dash->dash_state != GF_DASH_STATE_STOPPED) { + dash->mpd_stop_request = 1; + gf_mx_v(dash->dl_mutex); + while (1) { + /* waiting for the download thread to stop */ + gf_sleep(16); + gf_mx_p(dash->dl_mutex); + if (dash->dash_state != GF_DASH_STATE_RUNNING) { + /* it's stopped we can continue */ + gf_mx_v(dash->dl_mutex); + break; + } + gf_mx_v(dash->dl_mutex); + } + } else { + gf_mx_v(dash->dl_mutex); + } +} + + + +Bool gf_dash_seek_periods(GF_DashClient *dash) +{ + Double start_time; + u32 i, period_idx; + + gf_mx_p(dash->dl_mutex); + + dash->start_range_in_segment_at_next_period = 0; + start_time = 0; + period_idx = 0; + for (i=0; i<=gf_list_count(dash->mpd->periods); i++) { + GF_MPD_Period *period = gf_list_get(dash->mpd->periods, i); + Double dur = period->duration; + dur /= 1000; + if (dash->playback_start_range >= start_time) { + if ((i+1==gf_list_count(dash->mpd->periods)) || (dash->playback_start_range < start_time + dur) ) { + period_idx = i; + break; + } + } + start_time += dur; + } + if (period_idx != dash->active_period_index) { + dash->playback_start_range -= start_time; + dash->active_period_index = period_idx; + dash->request_period_switch = 2; + + /*figure out default segment duration and substract from our start range request*/ + if (dash->playback_start_range) { + Double duration; + u32 nb_segs; + GF_MPD_Period *period = gf_list_get(dash->mpd->periods, period_idx); + GF_MPD_AdaptationSet *set = gf_list_get(period->adaptation_sets, 0); + GF_MPD_Representation *rep = gf_list_get(set->representations, 0); + + gf_dash_get_segment_duration(rep, set, period, dash->mpd, &nb_segs, &duration); + + if (duration) { + while (dash->playback_start_range - dash->start_range_in_segment_at_next_period >= duration) + dash->start_range_in_segment_at_next_period += duration; + } + + } + } + gf_mx_v(dash->dl_mutex); + + return dash->request_period_switch ? 1 : 0; +} + +static void gf_dash_seek_group(GF_DashClient *dash, GF_DASH_Group *group) +{ + Double seg_start; + u32 first_downloaded, last_downloaded, segment_idx; + + group->force_segment_switch = 0; + if (!group->segment_duration) return; + + /*figure out where to seek*/ + segment_idx = 0; + seg_start = 0.0; + while (1) { + if ((dash->playback_start_range >= seg_start) && (dash->playback_start_range < seg_start + group->segment_duration)) + break; + seg_start += group->segment_duration; + segment_idx++; + } + /*todo - seek to given duration*/ + dash->playback_start_range -= seg_start; + + first_downloaded = last_downloaded = group->download_segment_index; + if (group->download_segment_index +1 >= group->nb_cached_segments) { + first_downloaded = group->download_segment_index + 1 - group->nb_cached_segments; + } + /*we are seeking in our download range, just go on*/ + if ((segment_idx >= first_downloaded) && (segment_idx<=last_downloaded)) return; + + group->force_segment_switch = 1; + group->download_segment_index = segment_idx; + + if (group->segment_download) + dash->dash_io->abort(dash->dash_io, group->segment_download); + + if (group->urlToDeleteNext) { + if (!dash->keep_files && !group->local_files) + dash->dash_io->delete_cache_file(dash->dash_io, group->segment_download, group->urlToDeleteNext); + + gf_free(group->urlToDeleteNext); + group->urlToDeleteNext = NULL; + } + if (group->segment_download) { + dash->dash_io->del(dash->dash_io, group->segment_download); + group->segment_download = NULL; + } + while (group->nb_cached_segments) { + group->nb_cached_segments --; + if (!dash->keep_files && !group->local_files && !group->segment_must_be_streamed) + gf_delete_file(group->cached[group->nb_cached_segments].cache); + + gf_free(group->cached[group->nb_cached_segments].cache); + gf_free(group->cached[group->nb_cached_segments].url); + memset(&group->cached[group->nb_cached_segments], 0, sizeof(segment_cache_entry)); + } +} + +void gf_dash_seek_groups(GF_DashClient *dash) +{ + u32 i; + + gf_mx_p(dash->dl_mutex); + + if (dash->active_period_index) { + Double dur = 0; + u32 i; + for (i=0; iactive_period_index; i++) { + GF_MPD_Period *period = gf_list_get(dash->mpd->periods, dash->active_period_index-1); + dur += period->duration/1000.0; + } + dash->playback_start_range -= dur; + } + for (i=0; igroups); i++) { + GF_DASH_Group *group = gf_list_get(dash->groups, i); + gf_dash_seek_group(dash, group); + } + gf_mx_v(dash->dl_mutex); +} + + +static GF_Err http_ifce_get(GF_FileDownload *getter, char *url) +{ + GF_Err e; + GF_DashClient *dash = (GF_DashClient*) getter->udta; + GF_DASHFileIOSession *sess = dash->dash_io->create(dash->dash_io, 0, url); + if (!sess) return GF_IO_ERR; + getter->session = sess; + e = dash->dash_io->init(dash->dash_io, sess); + if (e) return e; + return dash->dash_io->run(dash->dash_io, sess); +} + +static void http_ifce_clean(GF_FileDownload *getter) +{ + GF_DashClient *dash = (GF_DashClient*) getter->udta; + if (getter->session) dash->dash_io->del(dash->dash_io, getter->session); + getter->session = NULL; +} + +static const char *http_ifce_cache_name(GF_FileDownload *getter) +{ + GF_DashClient *dash = (GF_DashClient*) getter->udta; + if (getter->session) return dash->dash_io->get_cache_name(dash->dash_io, getter->session); + return NULL; +} + +GF_EXPORT +GF_Err gf_dash_open(GF_DashClient *dash, const char *manifest_url) +{ + char local_path[GF_MAX_PATH]; + const char *local_url; + GF_Err e; + GF_MPD_Period *period; + GF_DOMParser *mpd_parser; + Bool is_m3u8 = 0; + Bool is_local = 0; + + if (!dash || !manifest_url) return GF_BAD_PARAM; + + memset( dash->lastMPDSignature, 0, sizeof(dash->last_update_time)); + dash->reload_count = 0; + + if (dash->base_url) gf_free(dash->base_url); + dash->base_url = gf_strdup(manifest_url); + + dash->getter.udta = dash; + dash->getter.new_session = http_ifce_get; + dash->getter.del_session = http_ifce_clean; + dash->getter.get_cache_name = http_ifce_cache_name; + dash->getter.session = NULL; + + + + if (dash->mpd_dnload) dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + local_url = NULL; + + if (!strnicmp(manifest_url, "file://", 7)) { + local_url = manifest_url + 7; + is_local = 1; + if (strstr(manifest_url, ".m3u8")) { + is_m3u8 = 1; + } + } else if (strstr(manifest_url, "://")) { + const char *reloc_url, *mtype; + char mime[128]; + e = gf_dash_download_resource(dash->dash_io, &(dash->mpd_dnload), manifest_url, 0, 0, 1, NULL); + if (e!=GF_OK) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot connect service: MPD downloading problem %s for %s\n", gf_error_to_string(e), manifest_url)); + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + return e; + } + + mtype = dash->dash_io->get_mime(dash->dash_io, dash->mpd_dnload); + strcpy(mime, mtype ? mtype : ""); + strlwr(mime); + + reloc_url = dash->dash_io->get_url(dash->dash_io, dash->mpd_dnload); + /* Some servers, for instance http://tv.freebox.fr, serve m3u8 as text/plain */ + if (gf_dash_is_m3u8_mime(mime) || strstr(reloc_url, ".m3u8") || strstr(reloc_url, ".M3U8")) { + is_m3u8 = 1; + } else if (!gf_dash_is_dash_mime(mime) && !strstr(reloc_url, ".mpd") && !strstr(reloc_url, ".MPD")) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] mime '%s' for '%s' should be m3u8 or mpd\n", mime, reloc_url)); + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + return GF_REMOTE_SERVICE_ERROR; + } + + local_url = dash->dash_io->get_cache_name(dash->dash_io, dash->mpd_dnload); + if (!local_url) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot connect service: cache problem %s\n", local_url)); + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + return GF_IO_ERR; + } + } else { + local_url = manifest_url; + is_local = 1; + if (strstr(manifest_url, ".m3u8")) + is_m3u8 = 1; + } + + if (is_local) { + FILE *f = fopen(local_url, "rt"); + if (!f) return GF_URL_ERROR; + fclose(f); + } + + if (is_m3u8) { + if (is_local) { + char *sep; + strcpy(local_path, local_url); + sep = strrchr(local_path, '.'); + if (sep) sep[0]=0; + strcat(local_path, ".mpd"); + + gf_m3u8_to_mpd(local_url, manifest_url, local_path, dash->reload_count, dash->mimeTypeForM3U8Segments, 0, M3U8_TO_MPD_USE_TEMPLATE, &dash->getter); + local_url = local_path; + } else { + gf_m3u8_to_mpd(local_url, manifest_url, NULL, dash->reload_count, dash->mimeTypeForM3U8Segments, 0, M3U8_TO_MPD_USE_TEMPLATE, &dash->getter); + } + } + + if (!gf_dash_check_mpd_root_type(local_url)) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot connect service: wrong file type %s\n", local_url)); + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + return GF_URL_ERROR; + } + + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] parsing MPD %s\n", local_url)); + + /* parse the MPD */ + mpd_parser = gf_xml_dom_new(); + e = gf_xml_dom_parse(mpd_parser, local_url, NULL, NULL); + if (e != GF_OK) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot connect service: MPD parsing problem %s\n", gf_xml_dom_get_error(mpd_parser) )); + gf_xml_dom_del(mpd_parser); + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + return GF_URL_ERROR; + } + if (dash->mpd) + gf_mpd_del(dash->mpd); + + dash->mpd = gf_mpd_new(); + if (!dash->mpd) { + e = GF_OUT_OF_MEM; + } else { + e = gf_mpd_init_from_dom(gf_xml_dom_get_root(mpd_parser), dash->mpd, manifest_url); + } + gf_xml_dom_del(mpd_parser); + + if (e != GF_OK) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot connect service: MPD creation problem %s\n", gf_error_to_string(e))); + goto exit; + } + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] DASH client initialized from MPD\n")); + if (is_local && dash->mpd->minimum_update_period) { + e = gf_dash_update_manifest(dash); + if (e != GF_OK) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot update MPD: %s\n", gf_error_to_string(e))); + goto exit; + } + } + + /* Get the right period from the given time */ + dash->active_period_index = gf_dash_period_index_from_time(dash, 0); + period = gf_list_get(dash->mpd->periods, dash->active_period_index); + if (!period || !gf_list_count(period->adaptation_sets) ) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Error - cannot start: not enough periods or representations in MPD\n")); + e = GF_URL_ERROR; + goto exit; + } + + e = gf_dash_setup_period(dash); + if (e) goto exit; + + e = gf_th_run(dash->dash_thread, dash_main_thread_proc, dash); + gf_sleep(0); + return e; +exit: + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + + if (dash->mpd) + gf_mpd_del(dash->mpd); + dash->mpd = NULL; + return e; +} + +GF_EXPORT +void gf_dash_close(GF_DashClient *dash) +{ + assert( dash ); + + gf_dash_download_stop(dash); + + gf_mx_p(dash->dl_mutex); + if (dash->mpd_dnload) { + dash->dash_io->del(dash->dash_io, dash->mpd_dnload); + dash->mpd_dnload = NULL; + } + if (dash->mpd) + gf_mpd_del(dash->mpd); + dash->mpd = NULL; + + gf_mx_v(dash->dl_mutex); + + if (dash->dash_state != GF_DASH_STATE_CONNECTING) + gf_dash_reset_groups(dash); +} + +GF_EXPORT +GF_DashClient *gf_dash_new(GF_DASHFileIO *dash_io, u32 max_cache_duration_sec, u32 auto_switch_count, Bool keep_files, Bool disable_switching, GF_DASHInitialSelectionMode first_select_mode) +{ + GF_DashClient *dash; + GF_SAFEALLOC(dash, GF_DashClient); + dash->dash_io = dash_io; + + dash->dash_thread = gf_th_new("MPD Segment Downloader Thread"); + dash->dl_mutex = gf_mx_new("MPD Segment Downloader Mutex"); + dash->mimeTypeForM3U8Segments = gf_strdup( M3U8_UNKOWN_MIME_TYPE ); + + dash->max_cache_duration = max_cache_duration_sec; + + dash->auto_switch_count = auto_switch_count; + dash->keep_files = keep_files; + dash->disable_switching = disable_switching; + dash->first_select_mode = first_select_mode; + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[DASH] Client created\n")); + return dash; +} + +GF_EXPORT +void gf_dash_del(GF_DashClient *dash) +{ + gf_dash_close(dash); + + gf_th_del(dash->dash_thread); + gf_mx_del(dash->dl_mutex); + + if (dash->mimeTypeForM3U8Segments) gf_free(dash->mimeTypeForM3U8Segments); + if (dash->base_url) gf_free(dash->base_url); + + gf_free(dash); +} + +GF_EXPORT +u32 gf_dash_get_group_count(GF_DashClient *dash) +{ + return gf_list_count(dash->groups); +} + + +GF_EXPORT +void *gf_dash_get_group_udta(GF_DashClient *dash, u32 idx) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (!group) return NULL; + return group->udta; +} + +GF_EXPORT +GF_Err gf_dash_set_group_udta(GF_DashClient *dash, u32 idx, void *udta) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (!group) return GF_BAD_PARAM; + group->udta = udta; + return GF_OK; +} + +GF_EXPORT +Bool gf_dash_is_group_selected(GF_DashClient *dash, u32 idx) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (!group) return 0; + return (group->selection == GF_DASH_GROUP_SELECTED) ? 1 : 0; +} + +GF_EXPORT +void gf_dash_get_info(GF_DashClient *dash, const char **title, const char **source) +{ + GF_MPD_ProgramInfo *info = gf_list_get(dash->mpd->program_infos, 0); + if (info) { + *title = info->title; + *source = info->source; + } +} + +GF_EXPORT +void gf_dash_switch_quality(GF_DashClient *dash, Bool switch_up) +{ + u32 i; + for (i=0; igroups); i++) { + Bool do_switch = 0; + GF_DASH_Group *group = gf_list_get(dash->groups, i); + u32 current_idx = group->active_rep_index; + if (group->selection != GF_DASH_GROUP_SELECTED) continue; + + if (group->force_representation_idx_plus_one) current_idx = group->force_representation_idx_plus_one - 1; + if (switch_up) { + if (current_idx + 1 < gf_list_count(group->adaptation_set->representations)) { + group->force_representation_idx_plus_one = 1 + current_idx+1; + do_switch = 1; + } + } else { + if (current_idx) { + group->force_representation_idx_plus_one = 1 + current_idx - 1; + do_switch = 1; + } + } + if (do_switch) { + gf_mx_p(dash->dl_mutex); + group->force_switch_bandwidth = 1; + /*in local playback just switch at the end of the current segment + for remote, we should let the user decide*/ + while (group->nb_cached_segments>1) { + group->nb_cached_segments--; + gf_free(group->cached[group->nb_cached_segments].url); + group->cached[group->nb_cached_segments].url = NULL; + if (!group->local_files && group->cached[group->nb_cached_segments].cache) { + gf_delete_file( group->cached[group->nb_cached_segments].cache ); + gf_free(group->cached[group->nb_cached_segments].cache); + group->cached[group->nb_cached_segments].cache = NULL; + } + group->cached[group->nb_cached_segments].representation_index = 0; + group->cached[group->nb_cached_segments].start_range = 0; + group->cached[group->nb_cached_segments].end_range = 0; + assert(group->download_segment_index>1); + group->download_segment_index--; + } + gf_mx_v(dash->dl_mutex); + } + } +} + +GF_EXPORT +Double gf_dash_get_duration(GF_DashClient *dash) +{ + Double duration; + duration = (Double)dash->mpd->media_presentation_duration; + if (!duration) { + u32 i; + for (i=0; impd->periods); i++) { + GF_MPD_Period *period = gf_list_get(dash->mpd->periods, i); + duration += (Double)period->duration; + } + } + duration /= 1000; + return duration; +} + +GF_EXPORT +const char *gf_dash_get_url(GF_DashClient *dash) +{ + return dash->base_url; +} + +GF_EXPORT +const char *gf_dash_group_get_segment_mime(GF_DashClient *dash, u32 idx) +{ + GF_MPD_Representation *rep; + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (!group) return NULL; + + rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + return gf_dash_get_mime_type(NULL, rep, group->adaptation_set); +} + +GF_EXPORT +const char *gf_dash_group_get_segment_init_url(GF_DashClient *dash, u32 idx, u64 *start_range, u64 *end_range) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (!group) return NULL; + + if (start_range) *start_range = group->local_url_start_range; + if (end_range) *end_range = group->local_url_end_range; + return group->segment_local_url; +} + +GF_EXPORT +void gf_dash_group_select(GF_DashClient *dash, u32 idx, Bool select) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (!group) return; + if (group->selection == GF_DASH_GROUP_NOT_SELECTABLE) + return; + + group->selection = select ? GF_DASH_GROUP_SELECTED : GF_DASH_GROUP_NOT_SELECTED; + /*this set is part of a group, make sure no all other sets from the indicated group are unselected*/ + if (select && (group->adaptation_set->group>=0)) { + u32 i; + for (i=0; igroups, i); + if (agroup==group) continue; + + /*either one Representation from group 0, if present,*/ + if ((group->adaptation_set->group==0) + /*or the combination of at most one Representation from each non-zero group*/ + || (group->adaptation_set->group==agroup->adaptation_set->group) + ) { + agroup->selection = GF_DASH_GROUP_NOT_SELECTED; + } + } + } +} + +GF_EXPORT +void gf_dash_groups_set_language(GF_DashClient *dash, const char *lang_3cc) +{ + u32 i; + if (!lang_3cc) return; + for (i=0; igroups); i++) { + GF_DASH_Group *group = gf_list_get(dash->groups, i); + if (group->selection==GF_DASH_GROUP_NOT_SELECTABLE) continue; + if (group->adaptation_set->lang && !stricmp(group->adaptation_set->lang, lang_3cc)) { + gf_dash_group_select(dash, i, 1); + } + } +} + +GF_EXPORT +Bool gf_dash_is_running(GF_DashClient *dash) +{ + return dash->dash_state; +} + +GF_EXPORT +u32 gf_dash_get_period_switch_status(GF_DashClient *dash) +{ + return dash->request_period_switch; +} +GF_EXPORT +void gf_dash_request_period_switch(GF_DashClient *dash) +{ + dash->request_period_switch = 1; +} +GF_EXPORT +Bool gf_dash_in_last_period(GF_DashClient *dash) +{ + return (dash->active_period_index+1 < gf_list_count(dash->mpd->periods)) ? 0 : 1; +} +GF_EXPORT +Bool gf_dash_in_period_setup(GF_DashClient *dash) +{ + return dash->in_period_setup; +} + +GF_EXPORT +u32 gf_dash_group_get_max_segments_in_cache(GF_DashClient *dash, u32 idx) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + return group->max_cached_segments; +} + + +GF_EXPORT +u32 gf_dash_group_get_num_segments_ready(GF_DashClient *dash, u32 idx, Bool *group_is_done) +{ + u32 res = 0; + GF_DASH_Group *group; + + gf_mx_p(dash->dl_mutex); + group = gf_list_get(dash->groups, idx); + + *group_is_done = 0; + if (!group) { + *group_is_done = 1; + } else { + *group_is_done = group->done; + res = group->nb_cached_segments; + } + gf_mx_v(dash->dl_mutex); + return res; +} + +GF_EXPORT +void gf_dash_group_discard_segment(GF_DashClient *dash, u32 idx) +{ + GF_DASH_Group *group; + + gf_mx_p(dash->dl_mutex); + group = gf_list_get(dash->groups, idx); + + if (!group->nb_cached_segments) { + gf_mx_v(dash->dl_mutex); + return; + } + if (group->cached[0].cache) { + if (group->urlToDeleteNext) { + if (!group->local_files && !dash->keep_files) + dash->dash_io->delete_cache_file(dash->dash_io, group->segment_download, group->urlToDeleteNext); + + gf_free( group->urlToDeleteNext); + group->urlToDeleteNext = NULL; + } + assert( group->cached[0].url ); + + if (group->dont_delete_first_segment) { + group->dont_delete_first_segment = 0; + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] deleting cache file %s : %s\n", group->cached[0].url, group->cached[0].cache)); + group->urlToDeleteNext = gf_strdup( group->cached[0].url ); + } + + gf_free(group->cached[0].cache); + gf_free(group->cached[0].url); + group->cached[0].url = NULL; + group->cached[0].cache = NULL; + group->cached[0].representation_index = 0; + } + memmove(&group->cached[0], &group->cached[1], sizeof(segment_cache_entry)*(group->nb_cached_segments-1)); + memset(&(group->cached[group->nb_cached_segments-1]), 0, sizeof(segment_cache_entry)); + group->nb_cached_segments--; + + gf_mx_v(dash->dl_mutex); +} + +GF_EXPORT +void gf_dash_set_group_done(GF_DashClient *dash, u32 idx, Bool done) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (group) { + group->done = done; + if (done && group->segment_download) dash->dash_io->abort(dash->dash_io, group->segment_download); + } +} + +GF_EXPORT +GF_Err gf_dash_group_get_presentation_time_offset(GF_DashClient *dash, u32 idx, u64 *presentation_time_offset, u32 *timescale) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + if (group) { + u64 duration; + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->active_rep_index); + gf_dash_resolve_duration(rep, group->adaptation_set, group->period, &duration, timescale, presentation_time_offset, NULL); + return GF_OK; + } + return GF_BAD_PARAM; +} + +GF_EXPORT +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) +{ + GF_DASH_Group *group; + + *url = NULL; + if (switching_url) *switching_url = NULL; + if (start_range) *start_range = 0; + if (end_range) *end_range = 0; + if (switching_start_range) *switching_start_range = 0; + if (switching_end_range) *switching_end_range = 0; + if (original_url) *original_url = NULL; + + gf_mx_p(dash->dl_mutex); + group = gf_list_get(dash->groups, idx); + if (!group->nb_cached_segments) { + gf_mx_v(dash->dl_mutex); + return GF_BAD_PARAM; + } + *url = group->cached[0].cache; + if (start_range) + *start_range = group->cached[0].start_range; + if (end_range) + *end_range = group->cached[0].end_range; + if (original_url) *original_url = group->cached[0].url; + + if (group->cached[0].representation_index != group->prev_active_rep_index) { + GF_MPD_Representation *rep = gf_list_get(group->adaptation_set->representations, group->cached[0].representation_index); + if (switching_start_range) + *switching_start_range = rep->playback.init_start_range; + if (switching_end_range) + *switching_end_range = rep->playback.init_end_range; + if (switching_url) + *switching_url = rep->playback.cached_init_segment_url; + } + group->force_segment_switch = 0; + group->prev_active_rep_index = group->cached[0].representation_index; + gf_mx_v(dash->dl_mutex); + return GF_OK; +} + +GF_EXPORT +void gf_dash_seek(GF_DashClient *dash, Double start_range) +{ + gf_mx_p(dash->dl_mutex); + + dash->playback_start_range = start_range; + /*first check if we seek to another period*/ + if (! gf_dash_seek_periods(dash)) { + /*if no, seek in group*/ + gf_dash_seek_groups(dash); + } + gf_mx_v(dash->dl_mutex); +} + +GF_EXPORT +Double gf_dash_get_playback_start_range(GF_DashClient *dash) +{ + return dash->playback_start_range; +} + +GF_EXPORT +Bool gf_dash_group_segment_switch_forced(GF_DashClient *dash, u32 idx) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + return group->force_segment_switch; +} + +GF_EXPORT +Double gf_dash_group_current_segment_start_time(GF_DashClient *dash, u32 idx) +{ + GF_DASH_Group *group = gf_list_get(dash->groups, idx); + return gf_dash_get_segment_start_time(group); +} + +#endif //GPAC_DISABLE_DASH_CLIENT + diff --git a/src/media_tools/dash_segmenter.c b/src/media_tools/dash_segmenter.c new file mode 100644 index 0000000..f82e725 --- /dev/null +++ b/src/media_tools/dash_segmenter.c @@ -0,0 +1,3678 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre , Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved + * + * This file is part of GPAC / Media Tools sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#ifndef _WIN32_WCE +#include +#endif +#include + +#ifdef GPAC_DISABLE_ISOM +/*we should need a better way to work with sidx when no isom is defined*/ +#define GPAC_DISABLE_MPEG2TS +#endif + + +typedef struct _dash_segment_input GF_DashSegInput; + +struct _dash_component +{ + u32 ID;/*audio/video/text/ ...*/ + u32 media_type;/*audio/video/text/ ...*/ + char szCodec[50]; + /*for video */ + u32 width, height, fps_num, fps_denum, sar_num, sar_denum, max_sap; + + /*for audio*/ + u32 sample_rate, channels; + /*for anything*/ + char szLang[4]; +}; + +typedef struct +{ + Double segment_duration; + Bool segments_start_with_rap; + FILE *mpd; + const char *mpd_name, *seg_rad_name, *seg_ext; + s32 subsegs_per_sidx; + Bool daisy_chain_sidx; + Bool use_url_template; + u32 single_file_mode; + s32 time_shift_depth; + Double subduration; + const char *bs_switch_segment_file; + + /*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*/ + Bool variable_seg_rad_name; + + Bool fragments_start_with_rap; + Double fragment_duration; + + GF_Config *dash_ctx; + + const char *tmpdir; +} GF_DASHSegmenterOptions; + +struct _dash_segment_input +{ + char *file_name; + char representationID[100]; + char periodID[100]; + u32 bandwidth; + + /*if 0, input is disabled*/ + u32 adaptation_set; + /*if 0, input is disabled*/ + u32 period; + u32 group_id; + /*only set for the first representation in the AdaptationSet*/ + u32 nb_rep_in_adaptation_set; + Double period_duration; + + /*media-format specific functions*/ + /*assigns the different media to the same adaptation set or group than the input_idx one*/ + GF_Err (* dasher_input_classify) (GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 input_idx, u32 *current_group_id, u32 *max_sap_type); + GF_Err ( *dasher_get_components_info) (GF_DashSegInput *dash_input, GF_DASHSegmenterOptions *opts); + 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); + GF_Err ( *dasher_segment_file) (GF_DashSegInput *dash_input, const char *szOutName, GF_DASHSegmenterOptions *opts, Bool first_in_set); + + /*shall be set after call to dasher_input_classify*/ + char szMime[50]; + + /*all these shall be set after call to dasher_get_components_info*/ + Double duration; + struct _dash_component components[20]; + u32 nb_components; +}; + + + +#define EXTRACT_FORMAT(_nb_chars) \ + strcpy(szFmt, "%d"); \ + char_template+=_nb_chars; \ + if (seg_rad_name[char_template]=='%') { \ + char *sep = strchr(seg_rad_name+char_template, '$'); \ + if (sep) { \ + sep[0] = 0; \ + strcpy(szFmt, seg_rad_name+char_template); \ + char_template += strlen(seg_rad_name+char_template); \ + sep[0] = '$'; \ + } \ + } \ + char_template+=1; \ + +GF_EXPORT +GF_Err gf_media_mpd_format_segment_name(GF_DashTemplateSegmentType seg_type, Bool is_bs_switching, char *segment_name, const char *output_file_name, const char *rep_id, const char *seg_rad_name, const char *seg_ext, u64 start_time, u32 bandwidth, u32 segment_number) +{ + char szFmt[20]; + Bool has_number=0; + Bool is_index = (seg_type==GF_DASH_TEMPLATE_REPINDEX) ? 1 : 0; + Bool is_init = (seg_type==GF_DASH_TEMPLATE_INITIALIZATION) ? 1 : 0; + Bool is_template = (seg_type==GF_DASH_TEMPLATE_TEMPLATE) ? 1 : 0; + Bool is_init_template = (seg_type==GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE) ? 1 : 0; + Bool needs_init=((is_init || is_init_template) && !is_bs_switching) ? 1 : 0; + u32 char_template = 0; + char tmp[100]; + strcpy(segment_name, ""); + + if (seg_rad_name && (strstr(seg_rad_name, "$RepresentationID$") || strstr(seg_rad_name, "$ID$") || strstr(seg_rad_name, "$Bandwidth$"))) + needs_init = 0; + + if (!seg_rad_name) { + char *sep; + strcpy(segment_name, output_file_name); + sep = strrchr(segment_name, '.'); + if (sep) sep[0] = 0; + } else { + + while (1) { + char c = seg_rad_name[char_template]; + if (!c) break; + + if (!is_template && !is_init_template && !strnicmp(& seg_rad_name[char_template], "$RepresentationID$", 18)) { + char_template+=18; + strcat(segment_name, rep_id); + needs_init=0; + } + else if (!is_template && !is_init_template && !strnicmp(& seg_rad_name[char_template], "$Bandwidth", 10)) { + EXTRACT_FORMAT(10); + + sprintf(tmp, szFmt, bandwidth); + strcat(segment_name, tmp); + needs_init=0; + } + else if (!is_template && !strnicmp(& seg_rad_name[char_template], "$Time", 5)) { + EXTRACT_FORMAT(5); + if (is_init || is_init_template) continue; + /*replace %d to LLD*/ + szFmt[strlen(szFmt)-1]=0; + strcat(szFmt, &LLD[1]); + sprintf(tmp, szFmt, start_time); + strcat(segment_name, tmp); + } + else if (!is_template && !strnicmp(& seg_rad_name[char_template], "$Number", 7)) { + EXTRACT_FORMAT(7); + + if (is_init || is_init_template) continue; + sprintf(tmp, szFmt, segment_number); + strcat(segment_name, tmp); + has_number=1; + } + else if (!strnicmp(& seg_rad_name[char_template], "$Init=", 6)) { + char *sep = strchr(seg_rad_name + char_template+6, '$'); + if (sep) sep[0] = 0; + if (is_init || is_init_template) { + strcat(segment_name, seg_rad_name + char_template+6); + needs_init=0; + } + char_template += strlen(seg_rad_name + char_template)+1; + if (sep) sep[0] = '$'; + } + else if (!strnicmp(& seg_rad_name[char_template], "$Index=", 7)) { + char *sep = strchr(seg_rad_name + char_template+7, '$'); + if (sep) sep[0] = 0; + if (is_index) { + strcat(segment_name, seg_rad_name + char_template+6); + needs_init=0; + } + char_template += strlen(seg_rad_name + char_template)+1; + if (sep) sep[0] = '$'; + } + + else { + char_template+=1; + sprintf(tmp, "%c", c); + strcat(segment_name, tmp); + } + } + } + + if (is_template && !strstr(seg_rad_name, "$Number")) + strcat(segment_name, "$Number$"); + + if (needs_init) + strcat(segment_name, "init"); + + if (!is_init && !is_template && !is_init_template && !is_index && !has_number) { + sprintf(tmp, "%d", segment_number); + strcat(segment_name, tmp); + } + if (seg_ext) { + strcat(segment_name, "."); + strcat(segment_name, seg_ext); + } + return GF_OK; +} + +GF_Err gf_dasher_store_segment_info(GF_DASHSegmenterOptions *dash_cfg, const char *SegmentName, Double segStartTime) +{ + char szKey[512]; + if (!dash_cfg->dash_ctx) return GF_OK; + + sprintf(szKey, "%g", segStartTime); + return gf_cfg_set_key(dash_cfg->dash_ctx, "SegmentsStartTimes", SegmentName, szKey); +} + + +#ifndef GPAC_DISABLE_ISOM + +GF_Err gf_media_get_rfc_6381_codec_name(GF_ISOFile *movie, u32 track, char *szCodec) +{ + GF_ESD *esd; + GF_AVCConfig *avcc; + GF_AVCConfigSlot *sps; + u32 subtype = gf_isom_is_media_encrypted(movie, track, 1); + if (!subtype) subtype = gf_isom_get_media_subtype(movie, track, 1); + + switch (subtype) { + case GF_ISOM_SUBTYPE_MPEG4: + esd = gf_isom_get_esd(movie, track, 1); + switch (esd->decoderConfig->streamType) { + case GF_STREAM_AUDIO: + if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) { + /*5 first bits of AAC config*/ + u8 audio_object_type = (esd->decoderConfig->decoderSpecificInfo->data[0] & 0xF8) >> 3; + sprintf(szCodec, "mp4a.%02x.%02x", esd->decoderConfig->objectTypeIndication, audio_object_type); + } else { + sprintf(szCodec, "mp4a.%02x", esd->decoderConfig->objectTypeIndication); + } + break; + case GF_STREAM_VISUAL: +#ifndef GPAC_DISABLE_AV_PARSERS + if (esd->decoderConfig->decoderSpecificInfo) { + GF_M4VDecSpecInfo dsi; + gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); + sprintf(szCodec, "mp4v.%02x.%02x", esd->decoderConfig->objectTypeIndication, dsi.VideoPL); + } else +#endif + { + sprintf(szCodec, "mp4v.%02x", esd->decoderConfig->objectTypeIndication); + } + break; + default: + sprintf(szCodec, "mp4s.%02x", esd->decoderConfig->objectTypeIndication); + break; + } + gf_odf_desc_del((GF_Descriptor *)esd); + return GF_OK; + + case GF_ISOM_SUBTYPE_AVC_H264: + case GF_ISOM_SUBTYPE_AVC2_H264: + case GF_ISOM_SUBTYPE_SVC_H264: + avcc = gf_isom_avc_config_get(movie, track, 1); + sps = gf_list_get(avcc->sequenceParameterSets, 0); + if (sps) + sprintf(szCodec, "%s.%02x%02x%02x", gf_4cc_to_str(subtype), (u8) sps->data[1], (u8) sps->data[2], (u8) sps->data[3]); + else { + GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISOM Tools] AVC/SVC SPS not known - setting codecs string to default value \"%s\"\n", gf_4cc_to_str(subtype) )); + sprintf(szCodec, "%s", gf_4cc_to_str(subtype)); + } + gf_odf_avc_cfg_del(avcc); + return GF_OK; + default: + GF_LOG(GF_LOG_DEBUG, GF_LOG_AUTHOR, ("[ISOM Tools] codec parameters not known - setting codecs string to default value \"%s\"\n", gf_4cc_to_str(subtype) )); + sprintf(szCodec, "%s", gf_4cc_to_str(subtype)); + return GF_OK; + } + return GF_OK; +} + +#endif //GPAC_DISABLE_ISOM + + +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + +typedef struct +{ + Bool is_ref_track; + Bool done; + u32 TrackID; + u32 SampleNum, SampleCount; + u32 FragmentLength; + u32 OriginalTrack; + u32 finalSampleDescriptionIndex; + u32 TimeScale, MediaType, DefaultDuration, InitialTSOffset; + u64 last_sample_cts, next_sample_dts; + Bool all_sample_raps, splitable; + u32 split_sample_dts_shift; +} GF_ISOMTrackFragmenter; + +static u64 isom_get_next_sap_time(GF_ISOFile *input, u32 track, u32 sample_count, u32 sample_num) +{ + GF_ISOSample *samp; + u64 time; + Bool is_rap, has_roll; + u32 i, found_sample = 0; + for (i=sample_num; i<=sample_count; i++) { + if (gf_isom_get_sample_sync(input, track, i)) { + found_sample = i; + break; + } + gf_isom_get_sample_rap_roll_info(input, track, i, &is_rap, &has_roll, NULL); + if (is_rap || has_roll) { + found_sample = i; + break; + } + } + if (!found_sample) return 0; + samp = gf_isom_get_sample_info(input, track, found_sample, NULL, NULL); + time = samp->DTS; + gf_isom_sample_del(&samp); + return time; +} + +static GF_Err gf_media_isom_segment_file(GF_ISOFile *input, const char *output_file, Double max_duration_sec, GF_DASHSegmenterOptions *dash_cfg, GF_DashSegInput *dash_input, Bool first_in_set) +{ + u8 NbBits; + u32 i, TrackNum, descIndex, j, count, nb_sync, ref_track_id, nb_tracks_done; + u32 defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, nb_samp, nb_done; + u32 nb_video, nb_audio, nb_text, nb_scene; + u8 defaultPadding; + u16 defaultDegradationPriority; + GF_Err e; + char sOpt[100], sKey[100]; + char szCodecs[200], szCodec[100]; + u32 cur_seg, fragment_index, max_sap_type; + GF_ISOFile *output, *bs_switch_segment; + GF_ISOSample *sample, *next; + GF_List *fragmenters; + u32 MaxFragmentDuration, MaxSegmentDuration, SegmentDuration, maxFragDurationOverSegment; + u32 presentationTimeOffset = 0; + Double segment_start_time, file_duration, period_duration, max_segment_duration; + u32 nb_segments, width, height, sample_rate, nb_channels, sar_w, sar_h, fps_num, fps_denum, startNumber, startNumberRewind; + char langCode[5]; + u32 index_start_range, index_end_range; + Bool force_switch_segment = 0; + Bool switch_segment = 0; + Bool split_seg_at_rap = dash_cfg ? dash_cfg->segments_start_with_rap : 0; + Bool split_at_rap = 0; + Bool has_rap = 0; + Bool next_sample_rap = 0; + Bool flush_all_samples = 0; + Bool simulation_pass = 0; + Bool init_segment_deleted = 0; + u64 last_ref_cts = 0; + u64 start_range, end_range, file_size, init_seg_size, ref_track_first_dts, ref_track_next_cts; + u32 tfref_timescale = 0; + u32 bandwidth = 0; + GF_ISOMTrackFragmenter *tf, *tfref; + FILE *mpd_segs = NULL; + char SegmentName[GF_MAX_PATH]; + char RepSecName[200]; + char RepURLsSecName[200]; + const char *opt; + Double max_track_duration = 0; + Bool bs_switching_is_output = 0; + Bool store_dash_params = 0; + Bool dash_moov_setup = 0; + Bool segments_start_with_sap = 1; + Bool first_sample_in_segment = 0; + u32 *segments_info = NULL; + u32 nb_segments_info = 0; + u32 timeline_timescale=1000; + Bool audio_only = 1; + Bool is_bs_switching = 0; + Bool use_url_template = dash_cfg ? dash_cfg->use_url_template : 0; + const char *seg_rad_name = dash_cfg ? dash_cfg->seg_rad_name : NULL; + const char *seg_ext = dash_cfg ? dash_cfg->seg_ext : NULL; + const char *bs_switching_segment_name = NULL; + + SegmentName[0] = 0; + SegmentDuration = 0; + nb_samp = 0; + fragmenters = NULL; + if (!seg_ext) seg_ext = "m4s"; + + bs_switch_segment = NULL; + if (dash_cfg && dash_cfg->bs_switch_segment_file) { + bs_switch_segment = gf_isom_open(dash_cfg->bs_switch_segment_file, GF_ISOM_OPEN_READ, NULL); + if (bs_switch_segment) { + bs_switching_segment_name = gf_url_get_resource_name(dash_cfg->bs_switch_segment_file); + is_bs_switching = 1; + } + } + + sprintf(RepSecName, "Representation_%s", dash_input ? dash_input->representationID : ""); + sprintf(RepURLsSecName, "URLs_%s", dash_input ? dash_input->representationID : ""); + + bandwidth = dash_input ? dash_input->bandwidth : 0; + file_duration = 0; + + startNumber = 1; + startNumberRewind = 0; + + //create output file + if (dash_cfg) { + + /*need to precompute bandwidth*/ + if (!bandwidth && seg_rad_name && strstr(seg_rad_name, "$Bandwidth$")) { + for (i=0; idash_ctx) { + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "Setup"); + if (!opt || stricmp(opt, "yes") ) { + store_dash_params=1; + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "ID", dash_input->representationID); + } + /*we are in time shift enabled mode so segments will get destroyed, set the start number to the current segment + and restore presentationTimeOffset (cf below)*/ + if (!store_dash_params && (dash_cfg->time_shift_depth >= 0)) { + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "NextSegmentIndex"); + sscanf(opt, "%u", &startNumber); + + /*adjust the startNumber according to the timeShiftBuffer depth*/ + if ((dash_cfg->time_shift_depth>0) && (startNumber>(u32)dash_cfg->time_shift_depth) ) { + startNumberRewind = dash_cfg->time_shift_depth; + } + } + } + + opt = dash_cfg->dash_ctx ? gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "InitializationSegment") : NULL; + if (opt) { + output = gf_isom_open(opt, GF_ISOM_OPEN_CAT_FRAGMENTS, NULL); + dash_moov_setup = 1; + } else { + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_INITIALIZATION, is_bs_switching, SegmentName, output_file, dash_input->representationID, seg_rad_name, !stricmp(seg_ext, "null") ? NULL : "mp4", 0, bandwidth, 0); + output = gf_isom_open(SegmentName, GF_ISOM_OPEN_WRITE, NULL); + } + if (!output) { + GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISOBMF DASH] Cannot open %s for writing\n", opt ? opt : SegmentName)); + e = gf_isom_last_error(NULL); + goto err_exit; + } + + if (store_dash_params) { + const char *name; + + if (!gf_cfg_get_key(dash_cfg->dash_ctx, "DASH", "SegmentTemplate")) + gf_cfg_set_key(dash_cfg->dash_ctx, "DASH", "SegmentTemplate", seg_rad_name); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "Source", gf_isom_get_filename(input) ); + + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "Setup", "yes"); + name = SegmentName; + if (bs_switch_segment) name = gf_isom_get_filename(bs_switch_segment); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "InitializationSegment", name); + + /*store BS flag per rep - it should be stored per adaptation set but we dson't have a key for adaptation sets right now*/ + if (/*first_in_set && */ is_bs_switching) + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "BitstreamSwitching", "yes"); + } else if (dash_cfg->dash_ctx) { + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "BitstreamSwitching"); + if (opt && !strcmp(opt, "yes")) { + is_bs_switching = 1; + bs_switch_segment = output; + bs_switching_is_output = 1; + bs_switching_segment_name = gf_url_get_resource_name(gf_isom_get_filename(bs_switch_segment)); + } + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "Bandwidth"); + if (opt) sscanf(opt, "%u", &bandwidth); + } + mpd_segs = gf_temp_file_new(); + } else { + output = gf_isom_open(output_file, GF_ISOM_OPEN_WRITE, NULL); + if (!output) return gf_isom_last_error(NULL); + } + + nb_sync = 0; + nb_samp = 0; + fragmenters = gf_list_new(); + + if (! dash_moov_setup) { + e = gf_isom_clone_movie(input, output, 0, 0); + if (e) goto err_exit; + + /*because of movie fragments MOOF based offset, ISOM <4 is forbidden*/ + gf_isom_set_brand_info(output, GF_4CC('i','s','o','5'), 1); + gf_isom_modify_alternate_brand(output, GF_4CC('i','s','o','m'), 0); + gf_isom_modify_alternate_brand(output, GF_4CC('i','s','o','1'), 0); + gf_isom_modify_alternate_brand(output, GF_4CC('i','s','o','2'), 0); + gf_isom_modify_alternate_brand(output, GF_4CC('i','s','o','3'), 0); + gf_isom_modify_alternate_brand(output, GF_ISOM_BRAND_MP41, 0); + gf_isom_modify_alternate_brand(output, GF_ISOM_BRAND_MP42, 0); + } + + MaxFragmentDuration = (u32) (max_duration_sec * 1000); + MaxSegmentDuration = (u32) (1000 * (dash_cfg ? dash_cfg->segment_duration : max_duration_sec)); + + if (dash_cfg) { + /*in single segment mode, only one big SIDX is written between the end of the moov and the first fragment. + To speed-up writing, we do a first fragmentation pass without writing any sample to compute the number of segments and fragments per segment + in order to allocate / write to file the sidx before the fragmentation. The sidx will then be rewritten when closing the last segment*/ + if (dash_cfg->single_file_mode==1) { + simulation_pass = 1; + seg_rad_name = NULL; + } + /*if single file is requested, store all segments in the same file*/ + else if (dash_cfg->single_file_mode==2) { + seg_rad_name = NULL; + } + } + index_start_range = index_end_range = 0; + + tfref = NULL; + file_duration = 0; + width = height = sample_rate = nb_channels = sar_w = sar_h = fps_num = fps_denum = 0; + langCode[0]=0; + langCode[4]=0; + szCodecs[0] = 0; + + nb_video = nb_audio = nb_text = nb_scene = 0; + //duplicates all tracks + for (i=0; iTrackID = gf_isom_get_track_id(output, TrackNum); + tf->SampleCount = gf_isom_get_sample_count(input, i+1); + tf->OriginalTrack = i+1; + tf->TimeScale = gf_isom_get_media_timescale(input, i+1); + tf->MediaType = gf_isom_get_media_type(input, i+1); + tf->DefaultDuration = defaultDuration; + + if (max_track_duration < gf_isom_get_track_duration(input, i+1)) { + max_track_duration = (Double) gf_isom_get_track_duration(input, i+1); + } + + if (gf_isom_get_sync_point_count(input, i+1)>nb_sync) { + tfref = tf; + nb_sync = gf_isom_get_sync_point_count(input, i+1); + } else if (!gf_isom_has_sync_points(input, i+1)) { + tf->all_sample_raps = 1; + } + + tf->finalSampleDescriptionIndex = 1; + + /*figure out if we have an initial TS*/ + if (!dash_moov_setup) { + if (gf_isom_get_edit_segment_count(input, i+1)) { + u64 EditTime, SegDuration, MediaTime; + u8 EditMode; + gf_isom_get_edit_segment(input, i+1, 1, &EditTime, &SegDuration, &MediaTime, &EditMode); + if (EditMode==GF_ISOM_EDIT_EMPTY) { + tf->InitialTSOffset = (u32) (SegDuration * tf->TimeScale / gf_isom_get_timescale(input)); + } + /*and remove edit segments*/ + gf_isom_remove_edit_segments(output, TrackNum); + } + + gf_isom_set_brand_info(output, GF_4CC('i','s','o','5'), 1); + gf_isom_modify_alternate_brand(output, GF_4CC('d','a','s','h'), 1); + + /*locate sample description in list if given*/ + if (bs_switch_segment) { + u32 s_count; + u32 sample_descs_track = gf_isom_get_track_by_id(bs_switch_segment, tf->TrackID); + if (!sample_descs_track) { + e = GF_BAD_PARAM; + goto err_exit; + + } + + //the initialization segment is not yet setup for fragmentation + if (! gf_isom_is_track_fragmented(bs_switch_segment, tf->TrackID)) { + e = GF_BAD_PARAM; + if (e) goto err_exit; + } + /*otherwise override the fragment defauls so that we are consistent with the shared init segment*/ + else { + e = gf_isom_get_fragment_defaults(bs_switch_segment, sample_descs_track, + &defaultDuration, &defaultSize, &defaultDescriptionIndex, &defaultRandomAccess, &defaultPadding, &defaultDegradationPriority); + if (e) goto err_exit; + + e = gf_isom_change_track_fragment_defaults(output, tf->TrackID, + defaultDescriptionIndex, defaultDuration, defaultSize, defaultRandomAccess, defaultPadding, defaultDegradationPriority); + if (e) goto err_exit; + } + + /*and search in new ones the new index*/ + s_count = gf_isom_get_sample_description_count(bs_switch_segment, sample_descs_track); + + /*more than one sampleDesc, we will need to indicate all the sample descs in the file in case we produce a single file, + otherwise the file would not be compliant*/ + if (s_count > 1) { + gf_isom_clone_sample_descriptions(output, TrackNum, bs_switch_segment, sample_descs_track, 1); + } + + /*and search in new ones the new index*/ + s_count = gf_isom_get_sample_description_count(bs_switch_segment, sample_descs_track); + if (s_count>1) { + u32 k; + /*remove all sample descs*/ + for (k=0; kfinalSampleDescriptionIndex = k+1; + } + } + } + } + } + /*restore track decode times*/ + else { + char *opt, sKey[100]; + sprintf(sKey, "TKID_%d_NextDecodingTime", tf->TrackID); + opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey); + if (opt) tf->InitialTSOffset = atoi(opt); + + /*in time shift enabled, restore presentationTimeOffset */ + if (dash_cfg->time_shift_depth>=0) + presentationTimeOffset = tf->InitialTSOffset; + } + + /*get language, width/height/layout info, audio info*/ + switch (mtype) { + case GF_ISOM_MEDIA_TEXT: + tf->splitable = 1; + gf_isom_get_media_language(input, i+1, langCode); + case GF_ISOM_MEDIA_VISUAL: + case GF_ISOM_MEDIA_SCENE: + case GF_ISOM_MEDIA_DIMS: + gf_isom_get_track_layout_info(input, i+1, &_w, &_h, NULL, NULL, NULL); + if (_w>width) width = _w; + if (_h>height) height = _h; + break; + case GF_ISOM_MEDIA_AUDIO: + gf_isom_get_audio_info(input, i+1, 1, &_sr, &_nb_ch, NULL); + if (_sr>sample_rate) sample_rate=_sr; + if (_nb_ch>nb_channels) nb_channels = _nb_ch; + gf_isom_get_media_language(input, i+1, langCode); + break; + } + + if (mtype==GF_ISOM_MEDIA_VISUAL) { + /*get duration of 2nd sample*/ + u32 sample_dur = gf_isom_get_sample_duration(input, i+1, 2); + gf_isom_get_pixel_aspect_ratio(input, i+1, 1, &sar_w, &sar_h); + if (! fps_num || ! fps_denum) { + fps_num = tf->TimeScale; + fps_denum = sample_dur; + } + else if (fps_num *sample_dur < tf->TimeScale * fps_denum) { + fps_num = tf->TimeScale; + fps_denum = sample_dur; + } + } + + + if (file_duration < ((Double) gf_isom_get_media_duration(input, i+1)) / tf->TimeScale ) { + file_duration = ((Double) gf_isom_get_media_duration(input, i+1)) / tf->TimeScale; + } + gf_list_add(fragmenters, tf); + + nb_samp += count; + } + + + if (!tfref) tfref = gf_list_get(fragmenters, 0); + tfref->is_ref_track = 1; + tfref_timescale = tfref->TimeScale; + ref_track_id = tfref->TrackID; + if (tfref->all_sample_raps) split_seg_at_rap = 1; + + + if (!dash_moov_setup) { + max_track_duration /= gf_isom_get_timescale(input); + max_track_duration *= gf_isom_get_timescale(output); + gf_isom_set_movie_duration(output, (u64) max_track_duration); + } + + //if single segment, add msix brand if we use indexes + gf_isom_modify_alternate_brand(output, GF_4CC('m','s','i','x'), (dash_cfg && (dash_cfg->single_file_mode==1) && (dash_cfg->subsegs_per_sidx>=0)) ? 1 : 0); + + //flush movie + e = gf_isom_finalize_for_fragment(output, dash_cfg ? 1 : 0); + if (e) goto err_exit; + + start_range = 0; + file_size = gf_isom_get_file_size(bs_switch_segment ? bs_switch_segment : output); + end_range = file_size - 1; + init_seg_size = file_size; + + if (dash_cfg->dash_ctx) { + if (store_dash_params) { + char szVal[1024]; + sprintf(szVal, LLU, init_seg_size); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "InitializationSegmentSize", szVal); + } else { + const char *opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "InitializationSegmentSize"); + if (opt) init_seg_size = atoi(opt); + } + } + +restart_fragmentation_pass: + + for (i=0; isplit_sample_dts_shift = 0; + } + segment_start_time = 0; + nb_segments = 0; + + nb_tracks_done = 0; + ref_track_first_dts = (u64) -1; + nb_done = 0; + + maxFragDurationOverSegment=0; + if (dash_cfg) switch_segment=1; + + if (!seg_rad_name) use_url_template = 0; + + cur_seg=1; + fragment_index=1; + period_duration = 0; + split_at_rap = 0; + has_rap = 0; + next_sample_rap = 0; + flush_all_samples = 0; + force_switch_segment = 0; + max_sap_type = 0; + ref_track_next_cts = 0; + + /*setup previous URL list*/ + if (dash_cfg->dash_ctx) { + const char *opt; + char sKey[100]; + count = gf_cfg_get_key_count(dash_cfg->dash_ctx, RepURLsSecName); + for (i=0; idash_ctx, RepURLsSecName, i); + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepURLsSecName, key_name); + fprintf(mpd_segs, " %s\n", opt); + } + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "NextSegmentIndex"); + if (opt) cur_seg = atoi(opt); + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "NextFragmentIndex"); + if (opt) fragment_index = atoi(opt); + opt = gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, "CumulatedDuration"); + if (opt) period_duration = atof(opt); + + sprintf(sKey, "TKID_%d_NextSampleNum", tf->TrackID); + opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey); + if (opt) tf->SampleNum = atoi(opt); + + sprintf(sKey, "TKID_%d_LastSampleCTS", tf->TrackID); + opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey); + if (opt) sscanf(opt, LLU, &tf->last_sample_cts); + + sprintf(sKey, "TKID_%d_NextSampleDTS", tf->TrackID); + opt = (char *)gf_cfg_get_key(dash_cfg->dash_ctx, RepSecName, sKey); + if (opt) { + sscanf(opt, LLU, &tf->next_sample_dts); + } + } + gf_isom_set_next_moof_number(output, fragment_index); + + + max_segment_duration = 0; + + while ( (count = gf_list_count(fragmenters)) ) { + + if (switch_segment) { + SegmentDuration = 0; + switch_segment = 0; + first_sample_in_segment = 1; + + if (dash_cfg && dash_cfg->subduration && (segment_start_time>=1000*dash_cfg->subduration)) { + /*done with file (exceeded the requested duration) : store all fragmenters state and abord*/ + break; + } + + if (simulation_pass) { + segments_info = gf_realloc(segments_info, sizeof(u32) * (nb_segments_info+1) ); + segments_info[nb_segments_info] = 0; + nb_segments_info++; + e = GF_OK; + } else { + start_range = gf_isom_get_file_size(output); + if (seg_rad_name) { + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, is_bs_switching, SegmentName, output_file, dash_input->representationID, seg_rad_name, !stricmp(seg_ext, "null") ? NULL : seg_ext, (u64) ( period_duration * timeline_timescale + segment_start_time), bandwidth, cur_seg); + e = gf_isom_start_segment(output, SegmentName); + + gf_dasher_store_segment_info(dash_cfg, SegmentName, period_duration + segment_start_time / 1000.0); + + /*we are in bitstream switching mode, delete init segment*/ + if (is_bs_switching && !init_segment_deleted) { + init_segment_deleted = 1; + gf_delete_file(gf_isom_get_filename(output)); + } + + if (!use_url_template) { + const char *name = gf_url_get_resource_name(SegmentName); + fprintf(mpd_segs, " \n", name ); + if (dash_cfg->dash_ctx) { + char szKey[100], szVal[4046]; + sprintf(szKey, "UrlInfo%d", cur_seg ); + sprintf(szVal, "", name); + gf_cfg_set_key(dash_cfg->dash_ctx, RepURLsSecName, szKey, szVal); + } + } + } else { + e = gf_isom_start_segment(output, NULL); + } + } + + cur_seg++; + if (e) goto err_exit; + } + + maxFragDurationOverSegment=0; + + sample = NULL; + + if (simulation_pass) { + segments_info[nb_segments_info-1] ++; + e = GF_OK; + } else { + e = gf_isom_start_fragment(output, 1); + if (e) goto err_exit; + + + for (i=0; idone) continue; + /*FIXME - we need a way in the spec to specify "past" DTS for splitted sample*/ + gf_isom_set_traf_base_media_decode_time(output, tf->TrackID, tf->InitialTSOffset + tf->next_sample_dts); + } + + } + + //process track by track + for (i=0; idone) continue; + + //ok write samples + while (1) { + Bool stop_frag = 0; + Bool is_redundant_sample = 0; + u32 split_sample_duration = 0; + + /*first sample*/ + if (!sample) { + sample = gf_isom_get_sample(input, tf->OriginalTrack, tf->SampleNum + 1, &descIndex); + if (!sample) { + e = gf_isom_last_error(input); + goto err_exit; + } + if (tf->split_sample_dts_shift) { + sample->DTS += tf->split_sample_dts_shift; + is_redundant_sample = 1; + } + + /*also get SAP type - this is not needed if sample is not NULL as SAP tye was computed for "next sample" in previous loop*/ + if (sample->IsRAP) { + SAP_type = 1; + } else { + SAP_type = 0; + e = gf_isom_get_sample_rap_roll_info(input, tf->OriginalTrack, tf->SampleNum + 1, &is_rap, &has_roll, &roll_distance); + if (e==GF_OK) { + if (is_rap) SAP_type = 3; + else if (has_roll && (roll_distance>=0) ) SAP_type = 4; + } + } + } + gf_isom_get_sample_padding_bits(input, tf->OriginalTrack, tf->SampleNum+1, &NbBits); + + next = gf_isom_get_sample(input, tf->OriginalTrack, tf->SampleNum + 2, &j); + if (next) { + defaultDuration = (u32) (next->DTS - sample->DTS); + } else { + defaultDuration = tf->DefaultDuration; + } + + if (tf->splitable) { + if (tfref==tf) { + u32 frag_dur = (tf->FragmentLength + defaultDuration) * 1000 / tf->TimeScale; + /*if media segment about to be produced is longer than max segment length, force segment split*/ + if (SegmentDuration + frag_dur > MaxSegmentDuration) { + split_sample_duration = defaultDuration; + defaultDuration = tf->TimeScale * (MaxSegmentDuration - SegmentDuration) / 1000 - tf->FragmentLength; + split_sample_duration -= defaultDuration; + } + } else if ((tf->last_sample_cts + defaultDuration) * tfref_timescale > tfref->next_sample_dts * tf->TimeScale) { + split_sample_duration = defaultDuration; + defaultDuration = (u32) ( (last_ref_cts * tf->TimeScale)/tfref_timescale - tf->last_sample_cts ); + split_sample_duration -= defaultDuration; + } + } + + if (tf==tfref) { + if (segments_start_with_sap && first_sample_in_segment ) { + first_sample_in_segment = 0; + if (! SAP_type) segments_start_with_sap = 0; + } + if (ref_track_first_dts > sample->DTS) + ref_track_first_dts = sample->DTS; + + if (next) { + u64 next_cts = next->DTS + next->CTS_Offset; + if (split_sample_duration) + next_cts -= split_sample_duration; + + if (ref_track_next_ctsOriginalTrack); + if (cts>ref_track_next_cts) ref_track_next_cts = cts; + else ref_track_next_cts += defaultDuration; + } + } + + if (SAP_type > max_sap_type) max_sap_type = SAP_type; + + if (simulation_pass) { + e = GF_OK; + } else { + /*override descIndex with final index used in file*/ + descIndex = tf->finalSampleDescriptionIndex; + e = gf_isom_fragment_add_sample(output, tf->TrackID, sample, descIndex, + defaultDuration, NbBits, 0, is_redundant_sample); + if (e) + goto err_exit; + + /*copy subsample information*/ + e = gf_isom_fragment_copy_subsample(output, tf->TrackID, input, tf->OriginalTrack, tf->SampleNum + 1); + if (e) + goto err_exit; + + gf_set_progress("ISO File Fragmenting", nb_done, nb_samp); + nb_done++; + } + + tf->last_sample_cts = sample->DTS + sample->CTS_Offset; + tf->next_sample_dts = sample->DTS + defaultDuration; + + if (split_sample_duration) { + gf_isom_sample_del(&next); + sample->DTS += defaultDuration; + } else { + gf_isom_sample_del(&sample); + sample = next; + tf->SampleNum += 1; + tf->split_sample_dts_shift = 0; + } + tf->FragmentLength += defaultDuration; + + /*compute SAP type*/ + if (sample) { + if (sample->IsRAP) { + SAP_type = 1; + } else { + SAP_type = 0; + e = gf_isom_get_sample_rap_roll_info(input, tf->OriginalTrack, tf->SampleNum + 1, &is_rap, &has_roll, NULL); + if (e==GF_OK) { + if (is_rap) + SAP_type = 3; + else if (has_roll && (roll_distance>=0) ) + SAP_type = 4; + } + } + } + + if (next && SAP_type) { + if (tf==tfref) { + if (split_sample_duration) { + stop_frag = 1; + } + else if (split_seg_at_rap) { + u64 next_sap_time; + u32 frag_dur, next_dur; + next_dur = gf_isom_get_sample_duration(input, tf->OriginalTrack, tf->SampleNum + 1); + if (!next_dur) next_dur = defaultDuration; + /*duration of fragment if we add this rap*/ + frag_dur = (tf->FragmentLength+next_dur)*1000/tf->TimeScale; + next_sample_rap = 1; + next_sap_time = isom_get_next_sap_time(input, tf->OriginalTrack, tf->SampleCount, tf->SampleNum + 2); + /*if no more SAP after this one, do not switch segment*/ + if (next_sap_time) { + u32 scaler; + /*this is the fragment duration from last sample added to next SAP*/ + frag_dur += (u32) (next_sap_time - tf->next_sample_dts - next_dur)*1000/tf->TimeScale; + /*if media segment about to be produced is longer than max segment length, force segment split*/ + if (SegmentDuration + frag_dur > MaxSegmentDuration) { + split_at_rap = 1; + /*force new segment*/ + force_switch_segment = 1; + } + + if (tf->all_sample_raps) { + /*if adding this SAP will result in stoping the fragment "soon" after it, stop now and start with SAP + if all samples are RAPs, just stop fragment if we exceed the requested duration by adding the next sample + otherwise, take 3 samples (should be refined of course)*/ + scaler = 3; + if ( (tf->FragmentLength + scaler * next_dur)*1000 >= MaxFragmentDuration * tf->TimeScale) + stop_frag = 1; + } + } + } else if (!has_rap) { + if (tf->FragmentLength == defaultDuration) has_rap = 2; + else has_rap = 1; + } + } + } else { + next_sample_rap = 0; + } + + if (tf->SampleNum==tf->SampleCount) { + stop_frag = 1; + } else if (tf==tfref) { + /*fragmenting on "clock" track: no drift control*/ + if (!(dash_cfg ? dash_cfg->fragments_start_with_rap : 0) || ( (next && next->IsRAP) || split_at_rap) ) { + if (tf->FragmentLength*1000 >= MaxFragmentDuration*tf->TimeScale) { + stop_frag = 1; + } + } + } + /*do not abort fragment if ref track is done, put everything in the last fragment*/ + else if (!flush_all_samples) { + /*fragmenting on "non-clock" track: drift control*/ + if (tf->last_sample_cts * tfref_timescale >= last_ref_cts * tf->TimeScale) + stop_frag = 1; + } + + if (stop_frag) { + gf_isom_sample_del(&sample); + sample = next = NULL; + if (maxFragDurationOverSegment<=tf->FragmentLength*1000/tf->TimeScale) { + maxFragDurationOverSegment = tf->FragmentLength*1000/tf->TimeScale; + } + tf->FragmentLength = 0; + if (split_sample_duration) + tf->split_sample_dts_shift += defaultDuration; + + if (tf==tfref) last_ref_cts = tf->last_sample_cts; + + break; + } + } + + if (tf->SampleNum==tf->SampleCount) { + tf->done = 1; + nb_tracks_done++; + if (tf == tfref) { + tfref = NULL; + flush_all_samples = 1; + } + } + } + + if (dash_cfg) { + + SegmentDuration += maxFragDurationOverSegment; + maxFragDurationOverSegment=0; + + /*next fragment will exceed segment length, abort fragment now (all samples RAPs)*/ + if (tfref && tfref->all_sample_raps && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) { + force_switch_segment = 1; + } + + if (force_switch_segment || ((SegmentDuration >= MaxSegmentDuration) && (!split_seg_at_rap || next_sample_rap))) { + segment_start_time += SegmentDuration; + nb_segments++; + if (max_segment_duration * 1000 <= SegmentDuration) { + max_segment_duration = SegmentDuration; + max_segment_duration /= 1000; + } + force_switch_segment=0; + switch_segment=1; + SegmentDuration=0; + split_at_rap = 0; + has_rap = 0; + /*restore fragment duration*/ + MaxFragmentDuration = (u32) (max_duration_sec * 1000); + + if (!simulation_pass) { + u64 idx_start_range, idx_end_range; + + gf_isom_close_segment(output, dash_cfg->subsegs_per_sidx, ref_track_id, ref_track_first_dts, ref_track_next_cts, dash_cfg->daisy_chain_sidx, flush_all_samples ? 1 : 0, &idx_start_range, &idx_end_range); + ref_track_first_dts = (u64) -1; + + if (!seg_rad_name) { + file_size = gf_isom_get_file_size(output); + end_range = file_size - 1; + if (dash_cfg->single_file_mode!=1) { + fprintf(mpd_segs, " \n"); + if (dash_cfg->dash_ctx) { + char szKey[100], szVal[4046]; + sprintf(szKey, "UrlInfo%d", cur_seg ); + sprintf(szVal, "", start_range, end_range, idx_start_range, idx_end_range); + gf_cfg_set_key(dash_cfg->dash_ctx, RepURLsSecName, szKey, szVal); + } + } + } else { + file_size += gf_isom_get_file_size(output); + } + } + } + /*next fragment will exceed segment length, abort fragment at next rap (possibly after MaxSegmentDuration)*/ + if (split_seg_at_rap && SegmentDuration && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) { + if (!split_at_rap) { + split_at_rap = 1; + MaxFragmentDuration = MaxSegmentDuration - SegmentDuration; + } + } + } + if (nb_tracks_done==count) break; + } + + if (simulation_pass) { + /*OK, we have all segments and frags per segments*/ + gf_isom_allocate_sidx(output, dash_cfg->subsegs_per_sidx, dash_cfg->daisy_chain_sidx, nb_segments_info, segments_info, &index_start_range, &index_end_range ); + gf_free(segments_info); + segments_info = NULL; + simulation_pass = 0; + /*reset fragmenters*/ + for (i=0; idone = 0; + tf->last_sample_cts = 0; + tf->next_sample_dts = 0; + tf->FragmentLength = 0; + tf->SampleNum = 0; + if (tf->is_ref_track) tfref = tf; + } + goto restart_fragmentation_pass; + } + + if (dash_cfg) { + char buffer[1000]; + + /*flush last segment*/ + if (!switch_segment) { + u64 idx_start_range, idx_end_range; + + if (max_segment_duration * 1000 <= SegmentDuration) { + max_segment_duration = SegmentDuration; + max_segment_duration /= 1000; + } + + segment_start_time += SegmentDuration; + + gf_isom_close_segment(output, dash_cfg->subsegs_per_sidx, ref_track_id, ref_track_first_dts, ref_track_next_cts, dash_cfg->daisy_chain_sidx, 1, &idx_start_range, &idx_end_range); + nb_segments++; + + if (!seg_rad_name) { + file_size = gf_isom_get_file_size(output); + end_range = file_size - 1; + if (dash_cfg->single_file_mode!=1) { + fprintf(mpd_segs, " \n"); + + if (dash_cfg->dash_ctx) { + char szKey[100], szVal[4046]; + sprintf(szKey, "UrlInfo%d", cur_seg ); + sprintf(szVal, "", start_range, end_range, idx_start_range, idx_end_range); + gf_cfg_set_key(dash_cfg->dash_ctx, RepURLsSecName, szKey, szVal); + } + } + } else { + file_size += gf_isom_get_file_size(output); + } + } + + if (!bandwidth) + bandwidth = (u32) (file_size * 8 / file_duration); + + if (use_url_template) { + /*segment template does not depend on file name, write the template at the adaptationSet level*/ + if (!dash_cfg->variable_seg_rad_name && first_in_set) { + const char *rad_name = gf_url_get_resource_name(seg_rad_name); + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_TEMPLATE, is_bs_switching, SegmentName, output_file, dash_input->representationID, rad_name, !stricmp(seg_ext, "null") ? NULL : seg_ext, 0, 0, 0); + fprintf(dash_cfg->mpd, " representationID, rad_name, !stricmp(seg_ext, "null") ? NULL : "mp4", 0, 0, 0); + } + fprintf(dash_cfg->mpd, " initialization=\"%s\"", SegmentName); + if (presentationTimeOffset) + fprintf(dash_cfg->mpd, " presentationTimeOffset=\"%d\"", presentationTimeOffset); + fprintf(dash_cfg->mpd, "/>\n"); + } + /*in BS switching we share the same IS for all reps, write the SegmentTemplate for the init segment*/ + else if (is_bs_switching && first_in_set) { + fprintf(dash_cfg->mpd, " mpd, " presentationTimeOffset=\"%d\"", presentationTimeOffset); + fprintf(dash_cfg->mpd, "/>\n"); + } + } + + + fprintf(dash_cfg->mpd, " representationID) fprintf(dash_cfg->mpd, "id=\"%s\"", dash_input->representationID); + else fprintf(dash_cfg->mpd, "id=\"%p\"", output); + + fprintf(dash_cfg->mpd, " mimeType=\"%s/mp4\" codecs=\"%s\"", audio_only ? "audio" : "video", szCodecs); + if (width && height) { + fprintf(dash_cfg->mpd, " width=\"%d\" height=\"%d\"", width, height); + gf_media_get_reduced_frame_rate(&fps_num, &fps_denum); + if (fps_denum>1) + fprintf(dash_cfg->mpd, " frameRate=\"%d/%d\"", fps_num, fps_denum); + else + fprintf(dash_cfg->mpd, " frameRate=\"%d\"", fps_num); + + if (!sar_w) sar_w = 1; + if (!sar_h) sar_h = 1; + fprintf(dash_cfg->mpd, " sar=\"%d:%d\"", sar_w, sar_h); + + } + if (sample_rate) fprintf(dash_cfg->mpd, " audioSamplingRate=\"%d\"", sample_rate); + if (segments_start_with_sap || split_seg_at_rap) { + fprintf(dash_cfg->mpd, " startWithSAP=\"%d\"", max_sap_type); + } else { + fprintf(dash_cfg->mpd, " startWithSAP=\"0\""); + } + //only appears at AdaptationSet level - need to rewrite the DASH segementer to allow writing this at the proper place +// if ((single_file_mode==1) && segments_start_with_sap) fprintf(dash_cfg->mpd, " subsegmentStartsWithSAP=\"%d\"", max_sap_type); + + fprintf(dash_cfg->mpd, " bandwidth=\"%d\"", bandwidth); + fprintf(dash_cfg->mpd, ">\n"); + + if (nb_channels && !is_bs_switching) + fprintf(dash_cfg->mpd, " \n", nb_channels); + + if (dash_cfg->dash_ctx) { + Double seg_dur; + opt = gf_cfg_get_key(dash_cfg->dash_ctx, "DASH", "MaxSegmentDuration"); + if (opt) { + seg_dur = atof(opt); + if (seg_dur < max_segment_duration) { + sprintf(sOpt, "%f", max_segment_duration); + gf_cfg_set_key(dash_cfg->dash_ctx, "DASH", "MaxSegmentDuration", sOpt); + seg_dur = max_segment_duration; + } else { + max_segment_duration = seg_dur; + } + } else { + sprintf(sOpt, "%f", max_segment_duration); + gf_cfg_set_key(dash_cfg->dash_ctx, "DASH", "MaxSegmentDuration", sOpt); + } + } + + if (use_url_template) { + /*segment template depends on file name, but the template at the representation level*/ + if (dash_cfg->variable_seg_rad_name) { + const char *rad_name = gf_url_get_resource_name(seg_rad_name); + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_TEMPLATE, is_bs_switching, SegmentName, output_file, dash_input->representationID, rad_name, !stricmp(seg_ext, "null") ? NULL : seg_ext, 0, bandwidth, 0); + fprintf(dash_cfg->mpd, " representationID, rad_name, !stricmp(seg_ext, "null") ? NULL : "mp4", 0, 0, 0); + fprintf(dash_cfg->mpd, " initialization=\"%s\"", SegmentName); + } + if (presentationTimeOffset) + fprintf(dash_cfg->mpd, " presentationTimeOffset=\"%d\"", presentationTimeOffset); + fprintf(dash_cfg->mpd, "/>\n"); + } + } else if (dash_cfg->single_file_mode==1) { + fprintf(dash_cfg->mpd, " %s\n", gf_url_get_resource_name( gf_isom_get_filename(output) ) ); + fprintf(dash_cfg->mpd, " mpd, " presentationTimeOffset=\"%d\"", presentationTimeOffset); + fprintf(dash_cfg->mpd, "/>\n"); + } else { + if (!seg_rad_name) { + fprintf(dash_cfg->mpd, " %s\n", gf_url_get_resource_name( gf_isom_get_filename(output) ) ); + } + fprintf(dash_cfg->mpd, " mpd, " presentationTimeOffset=\"%d\"", presentationTimeOffset); + fprintf(dash_cfg->mpd, ">\n"); + /*we are not in bitstreamSwitching mode*/ + if (!is_bs_switching) { + fprintf(dash_cfg->mpd, " mpd, " range=\"0-"LLD"\"", init_seg_size-1); + } else { + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_INITIALIZATION, is_bs_switching, SegmentName, output_file, dash_input->representationID, gf_url_get_resource_name( seg_rad_name) , !stricmp(seg_ext, "null") ? NULL : "mp4", 0, bandwidth, 0); + fprintf(dash_cfg->mpd, " sourceURL=\"%s\"", SegmentName); + } + fprintf(dash_cfg->mpd, "/>\n"); + } + } + + gf_f64_seek(mpd_segs, 0, SEEK_SET); + while (!feof(mpd_segs)) { + u32 r = fread(buffer, 1, 100, mpd_segs); + gf_fwrite(buffer, 1, r, dash_cfg->mpd); + } + + if (!use_url_template && (dash_cfg->single_file_mode!=1)) { + fprintf(dash_cfg->mpd, " \n"); + } + + fprintf(dash_cfg->mpd, " \n"); + } + + /*store context*/ + if (dash_cfg && dash_cfg->dash_ctx) { + period_duration += (Double)segment_start_time / 1000; + + for (i=0; idone) { + sprintf(sKey, "TKID_%d_NextDecodingTime", tf->TrackID); + sprintf(sOpt, LLU, tf->InitialTSOffset + tf->next_sample_dts); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, sKey, sOpt); + } + + if (dash_cfg->subduration) { + sprintf(sKey, "TKID_%d_NextSampleNum", tf->TrackID); + sprintf(sOpt, "%d", tf->SampleNum); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, sKey, tf->done ? NULL : sOpt); + + sprintf(sKey, "TKID_%d_LastSampleCTS", tf->TrackID); + sprintf(sOpt, LLU, tf->last_sample_cts); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, sKey, tf->done ? NULL : sOpt); + + sprintf(sKey, "TKID_%d_NextSampleDTS", tf->TrackID); + sprintf(sOpt, LLU, tf->next_sample_dts); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, sKey, tf->done ? NULL : sOpt); + } + } + sprintf(sOpt, "%d", cur_seg); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "NextSegmentIndex", sOpt); + + fragment_index = gf_isom_get_next_moof_number(output); + sprintf(sOpt, "%d", fragment_index); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "NextFragmentIndex", sOpt); + + + sprintf(sOpt, "%f", period_duration); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "CumulatedDuration", sOpt); + + if (store_dash_params) { + sprintf(sOpt, "%u", bandwidth); + gf_cfg_set_key(dash_cfg->dash_ctx, RepSecName, "Bandwidth", sOpt); + } + } + +err_exit: + if (fragmenters){ + while (gf_list_count(fragmenters)) { + tf = (GF_ISOMTrackFragmenter *)gf_list_get(fragmenters, 0); + gf_free(tf); + gf_list_rem(fragmenters, 0); + } + gf_list_del(fragmenters); + } + if (output) { + if (e) gf_isom_delete(output); + else gf_isom_close(output); + } + if (!bs_switching_is_output && bs_switch_segment) + gf_isom_delete(bs_switch_segment); + gf_set_progress("ISO File Fragmenting", nb_samp, nb_samp); + if (mpd_segs) fclose(mpd_segs); + return e; +} + + +static GF_Err dasher_isom_get_input_components_info(GF_DashSegInput *input, GF_DASHSegmenterOptions *opts) +{ + u32 i; + GF_ISOFile *in; + Double dur; + + in = gf_isom_open(input->file_name, GF_ISOM_OPEN_READ, NULL); + input->duration = 0; + for (i=0; i input->duration) input->duration = dur; + + input->components[input->nb_components].ID = gf_isom_get_track_id(in, i+1); + input->components[input->nb_components].media_type = mtype; + if (mtype == GF_ISOM_MEDIA_VISUAL) { + gf_isom_get_visual_info(in, i+1, 1, &input->components[input->nb_components].width, &input->components[input->nb_components].height); + + input->components[input->nb_components].fps_num = gf_isom_get_media_timescale(in, i+1); + /*get duration of 2nd sample*/ + input->components[input->nb_components].fps_denum = gf_isom_get_sample_duration(in, i+1, 2); + + } + /*non-video tracks, get lang*/ + else if (mtype == GF_ISOM_MEDIA_AUDIO) { + u8 bps; + gf_isom_get_audio_info(in, i+1, 1, &input->components[input->nb_components].sample_rate, &input->components[input->nb_components].channels, &bps); + } + gf_isom_get_media_language(in, i+1, input->components[input->nb_components].szLang); + + input->nb_components++; + } + return gf_isom_close(in); +} + +static GF_Err dasher_isom_classify_input(GF_DashSegInput *dash_inputs, u32 nb_dash_inputs, u32 input_idx, u32 *current_group_id, u32 *max_sap_type) +{ + u32 i, j; + GF_ISOFile *set_file = gf_isom_open(dash_inputs[input_idx].file_name, GF_ISOM_OPEN_READ, NULL); + + for (i=input_idx+1; istreamType==dcd2->streamType) && (dcd1->objectTypeIndication==dcd2->objectTypeIndication)) { + same_codec = 1; + } else { + same_codec = 0; + } + if (dcd1) gf_odf_desc_del((GF_Descriptor *)dcd1); + if (dcd2) gf_odf_desc_del((GF_Descriptor *)dcd2); + } + + if (!same_codec) { + valid_in_adaptation_set = 0; + break; + } + + if ((mtype!=GF_ISOM_MEDIA_VISUAL) && (mtype!=GF_ISOM_MEDIA_HINT)) { + char szLang1[4], szLang2[4]; + szLang1[3] = szLang2[3] = 0; + gf_isom_get_media_language(set_file, j+1, szLang1); + gf_isom_get_media_language(in, j+1, szLang2); + if (stricmp(szLang1, szLang2)) { + valid_in_adaptation_set = 0; + break; + } + } + if (mtype==GF_ISOM_MEDIA_VISUAL) { + u32 w1, h1, w2, h2; + Bool rap, roll; + u32 roll_dist, sap_type; + + gf_isom_get_track_layout_info(set_file, j+1, &w1, &h1, NULL, NULL, NULL); + gf_isom_get_track_layout_info(in, j+1, &w2, &h2, NULL, NULL, NULL); + + if (h1*w2 != h2*w1) { + valid_in_adaptation_set = 0; + break; + } + + gf_isom_get_sample_rap_roll_info(in, j+1, 0, &rap, &roll, &roll_dist); + if (roll_dist>0) sap_type = 4; + else if (roll) sap_type = 3; + else if (rap) sap_type = 1; + else sap_type = 1; + if (*max_sap_type < sap_type) *max_sap_type = sap_type; + } + } + gf_isom_close(in); + if (valid_in_adaptation_set) { + dash_inputs[i].adaptation_set = dash_inputs[input_idx].adaptation_set; + dash_inputs[input_idx].nb_rep_in_adaptation_set ++; + } else if (assign_to_group) { + if (!dash_inputs[input_idx].group_id) { + (*current_group_id) ++; + dash_inputs[input_idx].group_id = (*current_group_id); + } + dash_inputs[i].group_id = (*current_group_id); + } + } + return GF_OK; +} + +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) +{ + GF_Err e = GF_OK; + u32 i; + Bool sps_merge_failed = 0; + GF_ISOFile *init_seg = gf_isom_open(szInitName, GF_ISOM_OPEN_WRITE, tmpdir); + + for (i=0; isequenceParameterSets); k++) { + GF_AVCConfigSlot *slc = gf_list_get(avccfg2->sequenceParameterSets, k); + gf_avc_get_sps_info(slc->data, slc->size, &sps_id1, NULL, NULL, NULL, NULL); + for (l=0; lsequenceParameterSets); l++) { + GF_AVCConfigSlot *slc_orig = gf_list_get(avccfg1->sequenceParameterSets, l); + gf_avc_get_sps_info(slc_orig->data, slc_orig->size, &sps_id2, NULL, NULL, NULL, NULL); + if (sps_id2==sps_id1) { + do_merge = 0; + break; + } + } + } +#endif + /*no conflicts in SPS ids, merge all SPS in a single sample desc*/ + if (do_merge) { + while (gf_list_count(avccfg1->sequenceParameterSets)) { + GF_AVCConfigSlot *slc = gf_list_get(avccfg1->sequenceParameterSets, 0); + gf_list_rem(avccfg1->sequenceParameterSets, 0); + gf_list_add(avccfg2->sequenceParameterSets, slc); + } + while (gf_list_count(avccfg1->pictureParameterSets)) { + GF_AVCConfigSlot *slc = gf_list_get(avccfg1->pictureParameterSets, 0); + gf_list_rem(avccfg1->pictureParameterSets, 0); + gf_list_add(avccfg2->pictureParameterSets, slc); + } + gf_isom_avc_config_update(init_seg, track, 1, avccfg2); + } else { + sps_merge_failed = 1; + } + gf_odf_avc_cfg_del(avccfg1); + gf_odf_avc_cfg_del(avccfg2); + } + + /*cannot merge, clone*/ + if (!do_merge) + gf_isom_clone_sample_description(init_seg, track, in, j+1, 1, NULL, NULL, &outDescIndex); + } + } else { + u32 defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess; + u8 defaultPadding; + u16 defaultDegradationPriority; + + gf_isom_clone_track(in, j+1, init_seg, 0, &track); + + gf_isom_get_fragment_defaults(in, j+1, &defaultDuration, &defaultSize, + &defaultDescriptionIndex, &defaultRandomAccess, + &defaultPadding, &defaultDegradationPriority); + //setup for fragmentation + e = gf_isom_setup_track_fragment(init_seg, gf_isom_get_track_id(init_seg, track), + defaultDescriptionIndex, defaultDuration, + defaultSize, (u8) defaultRandomAccess, + defaultPadding, defaultDegradationPriority); + if (e) break; + } + } + gf_isom_set_brand_info(init_seg, GF_4CC('i','s','o','5'), 1); + gf_isom_modify_alternate_brand(init_seg, GF_4CC('d','a','s','h'), 1); + if (i) gf_isom_close(in); + } + if (e) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH]: Couldn't create initialization segment: error %s\n", gf_error_to_string(e) )); + *disable_bs_switching = 1; + gf_isom_delete(init_seg); + gf_delete_file(szInitName); + return GF_OK; + } else if (sps_merge_failed) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH]: Couldnt merge AVC|H264 SPS from different files (same SPS ID used) - different sample descriptions will be used\n")); + *disable_bs_switching = 1; + gf_isom_delete(init_seg); + gf_delete_file(szInitName); + } else { + gf_isom_close(init_seg); + } + return GF_OK; +} + +static GF_Err dasher_isom_segment_file(GF_DashSegInput *dash_input, const char *szOutName, GF_DASHSegmenterOptions *dash_cfg, Bool first_in_set) +{ + GF_ISOFile *in = gf_isom_open(dash_input->file_name, GF_ISOM_OPEN_READ, dash_cfg->tmpdir); + GF_Err e = gf_media_isom_segment_file(in, szOutName, dash_cfg->fragment_duration, dash_cfg, dash_input, first_in_set); + gf_isom_close(in); + return e; +} +#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ + +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) +{ +#ifdef GPAC_DISABLE_MEDIA_IMPORT + return GF_NOT_SUPPORTED; +#else + GF_Err e; + u32 i, j, k; + GF_MediaImporter in, probe; + + memset(&in, 0, sizeof(GF_MediaImporter)); + in.flags = GF_IMPORT_PROBE_ONLY; + in.in_name = (char *)dash_inputs[input_idx].file_name; + e = gf_media_import(&in); + if (e) return e; + + for (i=input_idx+1; itype != probe_tk->type) { + valid_in_adaptation_set = 0; + assign_to_group = 0; + break; + } + /*make sure we use the same codec type*/ + if (src_tk->media_type != probe_tk->media_type) { + valid_in_adaptation_set = 0; + break; + } + /*make sure we use the same aspect ratio*/ + if (src_tk->type==GF_ISOM_MEDIA_VISUAL) { + if (src_tk->video_info.width * probe_tk->video_info.height != src_tk->video_info.height * probe_tk->video_info.width) { + valid_in_adaptation_set = 0; + break; + } + } else if (src_tk->lang != probe_tk->lang) { + valid_in_adaptation_set = 0; + break; + } + + if (!valid_in_adaptation_set) break; + } + if (valid_in_adaptation_set) { + dash_inputs[i].adaptation_set = dash_inputs[input_idx].adaptation_set; + dash_inputs[input_idx].nb_rep_in_adaptation_set ++; + } else if (assign_to_group) { + if (!dash_inputs[input_idx].group_id) { + (*current_group_id) ++; + dash_inputs[input_idx].group_id = (*current_group_id); + } + dash_inputs[i].group_id = (*current_group_id); + } + } +#endif + return GF_OK; +} + +static GF_Err dasher_generic_get_components_info(GF_DashSegInput *input, GF_DASHSegmenterOptions *opts) +{ +#ifdef GPAC_DISABLE_MEDIA_IMPORT + return GF_NOT_SUPPORTED; +#else + u32 i; + GF_Err e; + GF_MediaImporter in; + memset(&in, 0, sizeof(GF_MediaImporter)); + in.flags = GF_IMPORT_PROBE_ONLY; + in.in_name = (char *)input->file_name; + e = gf_media_import(&in); + if (e) return e; + + input->nb_components = in.nb_tracks; + for (i=0; icomponents[i].width = in.tk_info[i].video_info.width; + input->components[i].height = in.tk_info[i].video_info.height; + input->components[i].media_type = in.tk_info[i].type; + input->components[i].channels = in.tk_info[i].audio_info.nb_channels; + input->components[i].sample_rate = in.tk_info[i].audio_info.sample_rate; + input->components[i].ID = in.tk_info[i].track_num; + if (in.tk_info[i].lang) + strcpy(input->components[i].szLang, gf_4cc_to_str(in.tk_info[i].lang) ); + strcpy(input->components[i].szCodec, in.tk_info[i].szCodecProfile); + input->components[i].fps_denum = 1000; + input->components[i].fps_num = (u32) (in.tk_info[i].video_info.FPS*1000); + } +#endif + return GF_OK; +} + +#ifndef GPAC_DISABLE_MPEG2TS + +typedef struct +{ + FILE *src; + GF_M2TS_Demuxer *ts; + u64 file_size; + u32 bandwidth; + Bool has_seen_pat; + + u64 suspend_indexing; + + /* For indexing the TS*/ + Double segment_duration; + Bool segment_at_rap; + + FILE *index_file; + GF_BitStream *index_bs; + + u32 subduration; + u32 skip_nb_segments; + u32 cumulated_duration; + + GF_SegmentIndexBox *sidx; + GF_PcrInfoBox *pcrb; + + u32 reference_pid; + GF_M2TS_PES *reference_stream; + + u32 nb_pes_in_segment; + /* earliest presentation time for the whole segment */ + u64 first_PTS; + /* DTS-PCR diff for the first PES packet */ + u64 PCR_DTS_initial_diff; + + /* earliest presentation time for the subsegment being processed */ + u64 base_PTS; + /* byte offset for the start of subsegment being processed */ + u64 base_offset; + /* last presentation time for the subsegment being processed (before the next subsegment is started) */ + u64 last_PTS; + /* last decoding time for the subsegment being processed */ + u64 last_DTS; + /* byte offset for the last PES packet for the subsegment being processed */ + u32 last_offset; + u32 last_frame_duration; + + /* earliest presentation time for the previous subsegment */ + u64 prev_base_PTS; + /* byte offset for the start of the previous subsegment */ + u64 prev_base_offset; + /* last presentation time for the previous subsegment */ + u64 prev_last_PTS; + /* byte offset for the last PES packet for the previous subsegment */ + u32 prev_last_offset; + + /* indicates if the current subsegment contains a SAP and its SAP type*/ + u32 SAP_type; + /* indicates if the first PES in the current subsegment is a SAP*/ + Bool first_pes_sap; + /* Presentation time for the first RAP encountered in the subsegment */ + u64 first_SAP_PTS; + /* byte offset for the first RAP encountered in the subsegment */ + u32 first_SAP_offset; + u64 prev_last_SAP_PTS; + u32 prev_last_SAP_offset; + u64 last_SAP_PTS; + u32 last_SAP_offset; + + /*Interpolated PCR value for the pcrb*/ + u64 interpolated_pcr_value; + u64 last_pcr_value; + + /* information about the first PAT found in the subsegment */ + u32 last_pat_position; + u32 first_pat_position; + u32 prev_last_pat_position; + Bool first_pat_position_valid; + u32 pat_version; + + /* information about the first CAT found in the subsegment */ + u32 last_cat_position; + u32 first_cat_position; + u32 prev_last_cat_position; + Bool first_cat_position_valid; + u32 cat_version; + + /* information about the first PMT found in the subsegment */ + u32 last_pmt_position; + u32 first_pmt_position; + u32 prev_last_pmt_position; + Bool first_pmt_position_valid; + u32 pmt_version; + + /* information about the first PCR found in the subsegment */ + u32 last_pcr_position; + u32 first_pcr_position; + Bool first_pcr_position_valid; + u32 prev_last_pcr_position; + +} GF_TSSegmenter; + +static void m2ts_sidx_add_entry(GF_SegmentIndexBox *sidx, Bool ref_type, + u32 size, u32 duration, Bool first_is_SAP, u32 sap_type, u32 RAP_delta_time) +{ + GF_SIDXReference *ref; + sidx->nb_refs++; + sidx->refs = gf_realloc(sidx->refs, sidx->nb_refs*sizeof(GF_SIDXReference)); + ref = &(sidx->refs[sidx->nb_refs-1]); + ref->reference_type = ref_type; + ref->reference_size = size; + ref->subsegment_duration = duration; + ref->starts_with_SAP = first_is_SAP; + ref->SAP_type = sap_type; + ref->SAP_delta_time = (sap_type ? RAP_delta_time: 0); +} + +static void m2ts_sidx_finalize_size(GF_TSSegmenter *index_info, u64 file_size) +{ + GF_SIDXReference *ref; + if (index_info->suspend_indexing) return; + if (index_info->sidx->nb_refs == 0) return; + ref = &(index_info->sidx->refs[index_info->sidx->nb_refs-1]); + ref->reference_size = (u32)(file_size - index_info->prev_base_offset); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Subsegment: position-range ajdustment:%d-%d (%d bytes)\n", index_info->prev_base_offset, (u32)file_size, ref->reference_size)); +} + +static void m2ts_sidx_flush_entry(GF_TSSegmenter *index_info) +{ + u32 end_offset, size, duration; + Bool store_segment = 1; + + if (index_info->suspend_indexing) + return; + + if (index_info->skip_nb_segments) { + index_info->skip_nb_segments --; + store_segment = 0; + } + + /* determine the end of the current index */ + if (index_info->segment_at_rap) { + /*split at PAT*/ + end_offset = index_info->last_pat_position; + } else { + /* split at PES header */ + end_offset = index_info->last_offset; + } + size = (u32)(end_offset - index_info->base_offset); + duration = (u32)(index_info->last_PTS - index_info->base_PTS); + + if (store_segment) { + u32 prev_duration, SAP_delta_time, SAP_offset; + if (!index_info->sidx) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Segment: Reference PID: %d, EPTime: "LLU", Start Offset: %d bytes\n", index_info->reference_pid, index_info->base_PTS, index_info->base_offset)); + index_info->sidx = (GF_SegmentIndexBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_SIDX); + index_info->sidx->reference_ID = index_info->reference_pid; + /* timestamps in MPEG-2 are expressed in 90 kHz timescale */ + index_info->sidx->timescale = 90000; + /* first encountered PTS on the PID for this subsegment */ + index_info->sidx->earliest_presentation_time = index_info->base_PTS; + index_info->sidx->first_offset = index_info->base_offset; + + } + + if (!index_info->pcrb) { + index_info->pcrb = (GF_PcrInfoBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_PCRB); + } + + /* close the current index */ + SAP_delta_time = (u32)(index_info->first_SAP_PTS - index_info->base_PTS); + SAP_offset = (u32)(index_info->first_SAP_offset - index_info->base_offset); + m2ts_sidx_add_entry(index_info->sidx, 0, size, duration, index_info->first_pes_sap, index_info->SAP_type, SAP_delta_time); + + /*add pcrb entry*/ + index_info->pcrb->subsegment_count++; + index_info->pcrb->pcr_values = gf_realloc(index_info->pcrb->pcr_values, index_info->pcrb->subsegment_count*sizeof(u64)); + index_info->pcrb->pcr_values[index_info->pcrb->subsegment_count-1] = index_info->interpolated_pcr_value; + + /* adjust the previous index duration */ + if (index_info->sidx->nb_refs > 0 && (index_info->base_PTS < index_info->prev_last_PTS) ) { + prev_duration = (u32)(index_info->base_PTS-index_info->prev_base_PTS); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" time-range adj.: %.03f-%.03f / %.03f sec.\n", + (index_info->prev_base_PTS - index_info->first_PTS)/90000.0, + (index_info->base_PTS - index_info->first_PTS)/90000.0, prev_duration/90000.0)); + + /*update previous duration*/ + if (index_info->sidx->nb_refs) { + index_info->sidx->refs[index_info->sidx->nb_refs-1].subsegment_duration = prev_duration; + } + + } + + /* Printing result */ + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Subsegment:")); + //time-range:position-range: + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (" %.03f-%0.3f / %.03f sec., %d-%d / %d bytes, ", + (index_info->base_PTS - index_info->first_PTS)/90000.0, + (index_info->last_PTS - index_info->first_PTS)/90000.0, duration/90000.0, + index_info->base_offset, end_offset, size)); + if (index_info->SAP_type) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("RAP @ %.03f sec. / %d bytes", (index_info->first_SAP_PTS - index_info->first_PTS)/90000.0, + SAP_offset)); + } + if (index_info->first_pat_position_valid) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PAT @ %d bytes", (u32)(index_info->first_pat_position - index_info->base_offset))); + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PAT")); + } + if (index_info->first_cat_position_valid) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", CAT @ %d bytes", (u32)(index_info->first_cat_position - index_info->base_offset))); + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No CAT")); + } + if (index_info->first_pmt_position_valid) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PMT @ %d bytes", (u32)(index_info->first_pmt_position - index_info->base_offset))); + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PMT")); + } + if (index_info->first_pcr_position_valid) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", PCR @ %d bytes", (u32)(index_info->first_pcr_position - index_info->base_offset))); + } else { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, (", No PCR")); + } + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n")); + + } + + /* save the current values for later adjustments */ + index_info->prev_last_SAP_PTS = index_info->last_SAP_PTS; + index_info->prev_last_SAP_offset = index_info->last_SAP_offset; + index_info->prev_last_PTS = index_info->last_PTS; + index_info->prev_last_offset = index_info->last_offset; + index_info->prev_base_PTS = index_info->base_PTS; + index_info->base_PTS = index_info->last_PTS; + index_info->prev_base_offset = index_info->base_offset; + index_info->prev_last_pat_position = index_info->last_pat_position; + index_info->prev_last_cat_position = index_info->last_cat_position; + index_info->prev_last_pmt_position = index_info->last_pmt_position; + index_info->prev_last_pcr_position = index_info->last_pcr_position; + + /* update the values for the new index*/ + index_info->base_offset = end_offset; + index_info->SAP_type = 0; + index_info->first_SAP_PTS = 0; + index_info->first_SAP_offset = 0; + index_info->first_pes_sap = 0; + index_info->nb_pes_in_segment = 0; + index_info->last_DTS = 0; + + if (index_info->last_pat_position >= index_info->base_offset) { + index_info->first_pat_position_valid = 1; + index_info->first_pat_position = index_info->last_pat_position; + } else { + index_info->first_pat_position_valid = 0; + index_info->first_pat_position = 0; + } + if (index_info->last_cat_position >= index_info->base_offset) { + index_info->first_cat_position_valid = 1; + index_info->first_cat_position = index_info->last_cat_position; + } else { + index_info->first_cat_position_valid = 0; + index_info->first_cat_position = 0; + } + if (index_info->last_pmt_position >= index_info->base_offset) { + index_info->first_pmt_position_valid = 1; + index_info->first_pmt_position = index_info->last_pmt_position; + } else { + index_info->first_pmt_position_valid = 0; + index_info->first_pmt_position = 0; + } + if (index_info->last_pcr_position >= index_info->base_offset) { + index_info->first_pcr_position_valid = 1; + index_info->first_pcr_position = index_info->last_pcr_position; + } else { + index_info->first_pcr_position_valid = 0; + index_info->first_pcr_position = 0; + } + + index_info->cumulated_duration += duration; + if (index_info->subduration && (index_info->cumulated_duration >= index_info->subduration)) + index_info->suspend_indexing = end_offset; +} + +static void m2ts_check_indexing(GF_TSSegmenter *index_info) +{ + u32 delta_time = (u32)(index_info->last_PTS - index_info->base_PTS); + u32 segment_duration = (u32)(index_info->segment_duration*90000); + /* we exceed the segment duration flush sidx entry*/ + if (delta_time >= segment_duration) { + m2ts_sidx_flush_entry(index_info); + } +} +static void dash_m2ts_event_check_pat(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) +{ + GF_TSSegmenter *ts_seg = (GF_TSSegmenter*)ts->user; + GF_M2TS_PES_PCK *pck; + switch (evt_type) { + case GF_M2TS_EVT_PAT_REPEAT: + ts_seg->has_seen_pat = 1; + break; + case GF_M2TS_EVT_PMT_FOUND: + { + u32 i, count; + GF_M2TS_Program *prog = (GF_M2TS_Program*)par; + count = gf_list_count(prog->streams); + for (i=0; istreams, i); + gf_m2ts_set_pes_framing((GF_M2TS_PES *)es, GF_M2TS_PES_FRAMING_DEFAULT); + } + } + break; + case GF_M2TS_EVT_PES_PCK: + pck = par; + /* we process packets only for the given PID */ + if (pck->stream->pid == pck->stream->program->pcr_pid) { + if (!ts_seg->nb_pes_in_segment || (ts_seg->first_PTS > pck->PTS)) { + ts_seg->first_PTS = pck->PTS; + ts_seg->nb_pes_in_segment++; + } + if (pck->PTS > ts_seg->last_PTS) { + ts_seg->last_PTS = pck->PTS; + } + if (ts_seg->last_DTS != pck->DTS) { + ts_seg->last_frame_duration = (u32) (pck->DTS - ts_seg->last_DTS); + ts_seg->last_DTS = pck->DTS; + } + } + break; + } +} + +static void dash_m2ts_event(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) +{ + GF_M2TS_Program *prog; + GF_M2TS_PES_PCK *pck; + GF_M2TS_PES *pes; + u64 interpolated_pcr_value; + u32 count, i; + GF_TSSegmenter *ts_seg = (GF_TSSegmenter*)ts->user; + + switch (evt_type) { + case GF_M2TS_EVT_PAT_FOUND: + if (!ts_seg->first_pat_position_valid) { + ts_seg->first_pat_position_valid = 1; + ts_seg->first_pat_position = (ts->pck_number-1)*188; + } + ts_seg->last_pat_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_PAT_UPDATE: + if (!ts_seg->first_pat_position_valid) { + ts_seg->first_pat_position_valid = 1; + ts_seg->first_pat_position = (ts->pck_number-1)*188; + } + ts_seg->last_pat_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_PAT_REPEAT: + if (!ts_seg->first_pat_position_valid) { + ts_seg->first_pat_position_valid = 1; + ts_seg->first_pat_position = (ts->pck_number-1)*188; + } + ts_seg->last_pat_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_CAT_FOUND: + if (!ts_seg->first_cat_position_valid) { + ts_seg->first_cat_position_valid = 1; + ts_seg->first_cat_position = (ts->pck_number-1)*188; + } + ts_seg->last_cat_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_CAT_UPDATE: + if (!ts_seg->first_cat_position_valid) { + ts_seg->first_cat_position_valid = 1; + ts_seg->first_cat_position = (ts->pck_number-1)*188; + } + break; + case GF_M2TS_EVT_CAT_REPEAT: + if (!ts_seg->first_cat_position_valid) { + ts_seg->first_cat_position_valid = 1; + ts_seg->first_cat_position = (ts->pck_number-1)*188; + } + ts_seg->last_cat_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_PMT_FOUND: + ts_seg->has_seen_pat = 1; + prog = (GF_M2TS_Program*)par; + if (!ts_seg->first_pmt_position_valid) { + ts_seg->first_pmt_position_valid = 1; + ts_seg->first_pmt_position = (ts->pck_number-1)*188; + } + ts_seg->last_pmt_position = (ts->pck_number-1)*188; + /* we create indexing information on the stream used for carrying the PCR */ + ts_seg->reference_pid = prog->pcr_pid; + ts_seg->reference_stream = (GF_M2TS_PES *) ts_seg->ts->ess[prog->pcr_pid]; + count = gf_list_count(prog->streams); + + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("Program number %d found - %d streams:\n", prog->number, count)); + for (i=0; istreams, i); + gf_m2ts_set_pes_framing((GF_M2TS_PES *)es, GF_M2TS_PES_FRAMING_DEFAULT); + } + break; + case GF_M2TS_EVT_PMT_UPDATE: + if (!ts_seg->first_pmt_position_valid) { + ts_seg->first_pmt_position_valid = 1; + ts_seg->first_pmt_position = (ts->pck_number-1)*188; + } + ts_seg->last_pmt_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_PMT_REPEAT: + if (!ts_seg->first_pmt_position_valid) { + ts_seg->first_pmt_position_valid = 1; + ts_seg->first_pmt_position = (ts->pck_number-1)*188; + } + ts_seg->last_pmt_position = (ts->pck_number-1)*188; + break; + case GF_M2TS_EVT_PES_PCK: + pck = par; + /*We need the interpolated PCR for the pcrb, hence moved this calculus out, and saving the calculated value in ts_seg to put it in the pcrb*/ + pes = pck->stream; + /* Interpolated PCR value for the TS packet containing the PES header start */ + interpolated_pcr_value = 0; + if (pes->last_pcr_value && pes->before_last_pcr_value_pck_number && pes->last_pcr_value > pes->before_last_pcr_value) { + u32 delta_pcr_pck_num = pes->last_pcr_value_pck_number - pes->before_last_pcr_value_pck_number; + u32 delta_pts_pcr_pck_num = pes->pes_start_packet_number - pes->last_pcr_value_pck_number; + u64 delta_pcr_value = pes->last_pcr_value - pes->before_last_pcr_value; + if ((pes->pes_start_packet_number > pes->last_pcr_value_pck_number) + && (pes->last_pcr_value > pes->before_last_pcr_value)) { + + pes->last_pcr_value = pes->before_last_pcr_value; + } + /* we can compute the interpolated pcr value for the packet containing the PES header */ + interpolated_pcr_value = pes->last_pcr_value + (u64)((delta_pcr_value*delta_pts_pcr_pck_num*1.0)/delta_pcr_pck_num); + ts_seg->interpolated_pcr_value = interpolated_pcr_value; + ts_seg->last_pcr_value = pes->last_pcr_value; + } + /* we process packets only for the given PID */ + if (pck->stream->pid != ts_seg->reference_pid) { + break; + } else { + if (ts_seg->last_DTS != pck->DTS) { + if (ts_seg->last_DTS) + ts_seg->last_frame_duration = (u32) (pck->DTS - ts_seg->last_DTS); + ts_seg->last_DTS = pck->DTS; + ts_seg->nb_pes_in_segment++; + } + + /* we store the fact that there is at least a RAP for the index + and we store the PTS of the first encountered RAP in the index*/ + if (pck->flags & GF_M2TS_PES_PCK_RAP) { + ts_seg->SAP_type = 1; + if (!ts_seg->first_SAP_PTS || (ts_seg->first_SAP_PTS > pck->PTS)) { + ts_seg->first_SAP_PTS = pck->PTS; + ts_seg->first_SAP_offset = (pck->stream->pes_start_packet_number-1)*188; + } + ts_seg->last_SAP_PTS = pck->PTS; + ts_seg->last_SAP_offset = (pck->stream->pes_start_packet_number-1)*188; + + if (ts_seg->nb_pes_in_segment==1) { + ts_seg->first_pes_sap = 1; + } + } + /* we need to know the earliest PTS value (RAP or not) in the index*/ + if (!ts_seg->base_PTS || (ts_seg->base_PTS > pck->PTS)) { + ts_seg->base_PTS = pck->PTS; + } + /* we need to know the earliest PTS value for the whole file (segment) */ + if (!ts_seg->first_PTS || (ts_seg->first_PTS > pck->PTS)) { + ts_seg->first_PTS = pck->PTS; + } + if (pck->PTS > ts_seg->last_PTS) { + /* we use the last PTS for first approximation of the duration */ + ts_seg->last_PTS = pck->PTS; + ts_seg->last_offset = (ts_seg->reference_stream->pes_start_packet_number-1)*188; + } + + if (ts_seg->PCR_DTS_initial_diff == (u64) -1) { + ts_seg->PCR_DTS_initial_diff = ts_seg->last_DTS - pes->last_pcr_value / 300; + } + + m2ts_check_indexing(ts_seg); + } + break; + case GF_M2TS_EVT_PES_PCR: + pck = par; + if (!ts_seg->first_pcr_position_valid) { + ts_seg->first_pcr_position_valid = 1; + ts_seg->first_pcr_position = (ts->pck_number-1)*188; + } + ts_seg->last_pcr_position = (ts->pck_number-1)*188; + break; + } +} + +static GF_Err dasher_get_ts_demux(GF_TSSegmenter *ts_seg, const char *file, u32 probe_mode) +{ + memset(ts_seg, 0, sizeof(GF_TSSegmenter)); + ts_seg->src = gf_f64_open(file, "rb"); + if (!ts_seg->src) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: Cannot open input %s: no such file\n", file)); + return GF_URL_ERROR; + } + ts_seg->ts = gf_m2ts_demux_new(); + ts_seg->ts->on_event = dash_m2ts_event_check_pat; + ts_seg->ts->notify_pes_timing = 1; + ts_seg->ts->user = ts_seg; + + gf_f64_seek(ts_seg->src, 0, SEEK_END); + ts_seg->file_size = gf_f64_tell(ts_seg->src); + gf_f64_seek(ts_seg->src, 0, SEEK_SET); + + if (probe_mode) { + /* first loop to process all packets between two PAT, and assume all signaling was found between these 2 PATs */ + while (!feof(ts_seg->src)) { + char data[188]; + u32 size = fread(data, 1, 188, ts_seg->src); + if (size<188) break; + + gf_m2ts_process_data(ts_seg->ts, data, size); + if ((probe_mode ==1) && ts_seg->has_seen_pat) break; + } + gf_m2ts_reset_parsers(ts_seg->ts); + gf_f64_seek(ts_seg->src, 0, SEEK_SET); + } + ts_seg->ts->on_event = dash_m2ts_event; + return GF_OK; +} + +static void dasher_del_ts_demux(GF_TSSegmenter *ts_seg) +{ + if (ts_seg->ts) gf_m2ts_demux_del(ts_seg->ts); + if (ts_seg->src) fclose(ts_seg->src); + memset(ts_seg, 0, sizeof(GF_TSSegmenter)); +} + +static GF_Err dasher_mp2t_get_components_info(GF_DashSegInput *dash_input, GF_DASHSegmenterOptions *opts) +{ + GF_TSSegmenter ts_seg; + GF_Err e = dasher_generic_get_components_info(dash_input, opts); + if (e) return e; + + e = dasher_get_ts_demux(&ts_seg, dash_input->file_name, 2); + if (e) return e; + + dash_input->duration = (ts_seg.last_PTS + ts_seg.last_frame_duration - ts_seg.first_PTS)/90000.0; + dasher_del_ts_demux(&ts_seg); + + return GF_OK; +} + +static GF_Err dasher_mp2t_segment_file(GF_DashSegInput *dash_input, const char *szOutName, GF_DASHSegmenterOptions *dash_cfg, Bool first_in_set) +{ + GF_TSSegmenter ts_seg; + Bool rewrite_input = 0; + u8 is_pes[GF_M2TS_MAX_STREAMS]; + char szOpt[100]; + char SegName[GF_MAX_PATH], IdxName[GF_MAX_PATH]; + char szSectionName[100], szRepURLsSecName[100]; + char szCodecs[100]; + const char *opt; + u32 i, startNumberRewind; + GF_Err e; + u64 start, pcr_shift, next_pcr_shift, next_dts; + Bool store_params=0; + Double cumulated_duration = 0; + u32 bandwidth = 0; + u32 segment_index; + /*compute name for indexed segments*/ + const char *basename = gf_url_get_resource_name(szOutName); + + /*perform indexation of the file, this info will be destroyed at the end of the segment file routine*/ + e = dasher_get_ts_demux(&ts_seg, dash_input->file_name, 0); + if (e) return e; + + ts_seg.segment_duration = dash_cfg->segment_duration; + ts_seg.segment_at_rap = dash_cfg->segments_start_with_rap; + + ts_seg.bandwidth = (u32) (ts_seg.file_size * 8 / dash_input->duration); + + /*create bitstreams*/ + 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); + + segment_index = 1; + startNumberRewind = 0; + + ts_seg.index_file = NULL; + ts_seg.index_bs = NULL; + if (!dash_cfg->dash_ctx && (dash_cfg->use_url_template != 2)) { +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + GF_SegmentTypeBox *styp; + ts_seg.index_file = gf_f64_open(IdxName, "wb"); + ts_seg.index_bs = gf_bs_from_file(ts_seg.index_file, GF_BITSTREAM_WRITE); + + styp = (GF_SegmentTypeBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_STYP); + styp->majorBrand = GF_4CC('r','i','s','x'); + styp->minorVersion = 0; + styp->altBrand = (u32*)gf_malloc(sizeof(u32)); + styp->altBrand[0] = styp->majorBrand; + styp->altCount = 1; + gf_isom_box_size((GF_Box *)styp); + gf_isom_box_write((GF_Box *)styp, ts_seg.index_bs); + gf_isom_box_del((GF_Box *)styp); +#endif + } + + ts_seg.PCR_DTS_initial_diff = (u64) -1; + ts_seg.subduration = (u32) (dash_cfg->subduration * 90000); + + szSectionName[0] = 0; + if (dash_cfg->dash_ctx) { + sprintf(szSectionName, "Representation_%s", dash_input->representationID); + sprintf(szRepURLsSecName, "URLs_%s", dash_input->representationID); + + /*restart where we left last time*/ + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "ByteOffset"); + if (opt) { + u64 offset; + sscanf(opt, LLU, &offset); + + while (!feof(ts_seg.src) && !ts_seg.has_seen_pat) { + char data[188]; + u32 size = fread(data, 1, 188, ts_seg.src); + if (size<188) break; + gf_m2ts_process_data(ts_seg.ts, data, size); + } + gf_m2ts_reset_parsers(ts_seg.ts); + + gf_f64_seek(ts_seg.src, offset, SEEK_SET); + ts_seg.base_offset = offset; + ts_seg.ts->pck_number = (u32) (offset/188); + } + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "InitialDTSOffset"); + if (opt) sscanf(opt, LLU, &ts_seg.PCR_DTS_initial_diff); + } + + /*index the file*/ + while (!feof(ts_seg.src) && !ts_seg.suspend_indexing) { + char data[188]; + u32 size = fread(data, 1, 188, ts_seg.src); + if (size<188) break; + gf_m2ts_process_data(ts_seg.ts, data, size); + } + if (feof(ts_seg.src)) ts_seg.suspend_indexing = 0; + + next_pcr_shift = 0; + if (!ts_seg.suspend_indexing) { + next_pcr_shift = ts_seg.last_DTS + ts_seg.last_frame_duration - ts_seg.PCR_DTS_initial_diff; + } + next_dts = ts_seg.last_DTS + ts_seg.last_frame_duration; + + /* flush SIDX entry for the last packets */ + m2ts_sidx_flush_entry(&ts_seg); + m2ts_sidx_finalize_size(&ts_seg, ts_seg.file_size); + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[DASH]: Indexing done (1 sidx, %d entries).\n", ts_seg.sidx->nb_refs)); + + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_REPINDEX, 1, IdxName, basename, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "six", 0, 0, 0); + + + memset(is_pes, 0, sizeof(u8)*GF_M2TS_MAX_STREAMS); + for (i=0; inb_components; i++) { + is_pes[ dash_input->components[i].ID ] = 1; + } + pcr_shift = 0; + + bandwidth = dash_input->bandwidth; + if (!bandwidth) bandwidth = ts_seg.bandwidth; + + if (dash_cfg->dash_ctx) { + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "Setup"); + if (!opt || strcmp(opt, "yes")) { + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "Setup", "yes"); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "ID", dash_input->representationID); + store_params = 1; + } else { + if (!bandwidth) { + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "Bandwidth"); + if (opt) sscanf(opt, "%u", &bandwidth); + } + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "StartIndex"); + if (opt) sscanf(opt, "%u", &segment_index); + + /*adjust the startNumber according to the timeShiftBuffer depth*/ + if ((dash_cfg->time_shift_depth>0) && (segment_index > (u32)dash_cfg->time_shift_depth) ) { + startNumberRewind = dash_cfg->time_shift_depth; + } + + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "PCR90kOffset"); + if (opt) sscanf(opt, LLU, &pcr_shift); + + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szSectionName, "CumulatedDuration"); + if (opt) cumulated_duration = atof(opt); + } + } + + /*write segment template for all representations*/ + if (first_in_set && dash_cfg->seg_rad_name && dash_cfg->use_url_template && !dash_cfg->variable_seg_rad_name) { + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_TEMPLATE, 1, SegName, basename, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "ts", 0, bandwidth, segment_index); + fprintf(dash_cfg->mpd, " segment_duration), segment_index - startNumberRewind, SegName); + if (!dash_cfg->dash_ctx) { + 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); + fprintf(dash_cfg->mpd, " index=\"%s\"", IdxName); + } + fprintf(dash_cfg->mpd, "/>\n", (u32) (90000*dash_cfg->segment_duration), segment_index, SegName); + } + + + fprintf(dash_cfg->mpd, " representationID); + szCodecs[0] = 0; + for (i=0; inb_components; i++) { + if (strlen(dash_input->components[i].szCodec)) + if (strlen(szCodecs)) + strcat(szCodecs, ","); + strcat(szCodecs, dash_input->components[i].szCodec); + + if (dash_input->components[i].width && dash_input->components[i].height) + fprintf(dash_cfg->mpd, " width=\"%d\" height=\"%d\"", dash_input->components[i].width, dash_input->components[i].height); + + if (dash_input->components[i].sample_rate) + fprintf(dash_cfg->mpd, " audioSamplingRate=\"%d\"", dash_input->components[i].sample_rate); + + if (dash_input->components[i].szLang[0]) + fprintf(dash_cfg->mpd, " lang=\"%s\"", dash_input->components[i].szLang); + } + if (strlen(szCodecs)) + fprintf(dash_cfg->mpd, " codecs=\"%s\"", szCodecs); + + fprintf(dash_cfg->mpd, " startWithSAP=\"%d\"", dash_cfg->segments_start_with_rap ? 1 : 0); + fprintf(dash_cfg->mpd, " bandwidth=\"%d\"", bandwidth); + fprintf(dash_cfg->mpd, ">\n"); + + if (dash_cfg->single_file_mode==1) { + 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); + fprintf(dash_cfg->mpd, " %s\n", dash_cfg->seg_rad_name ? SegName : dash_input->file_name); + + fprintf(dash_cfg->mpd, " \n"); + fprintf(dash_cfg->mpd, " \n", IdxName); + fprintf(dash_cfg->mpd, " \n"); + + /*we rewrite the file*/ + if (dash_cfg->seg_rad_name) rewrite_input = 1; + } else { + if (dash_cfg->seg_rad_name && dash_cfg->use_url_template) { + if (dash_cfg->variable_seg_rad_name) { + gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_TEMPLATE, 1, SegName, basename, dash_input->representationID, gf_url_get_resource_name(dash_cfg->seg_rad_name), "ts", 0, bandwidth, segment_index); + fprintf(dash_cfg->mpd, " segment_duration), segment_index, SegName); + if (!dash_cfg->dash_ctx) { + 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); + fprintf(dash_cfg->mpd, " index=\"%s\"", IdxName); + } + + if (dash_cfg->time_shift_depth>=0) + fprintf(dash_cfg->mpd, " presentationTimeOffset=\"%d\"", ts_seg.sidx->earliest_presentation_time + pcr_shift); + fprintf(dash_cfg->mpd, "/>\n"); + } else if (dash_cfg->time_shift_depth>=0) { + fprintf(dash_cfg->mpd, " \n", ts_seg.sidx->earliest_presentation_time + pcr_shift); + 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)); + } + } else { + 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); + fprintf(dash_cfg->mpd, " %s\n", dash_cfg->seg_rad_name ? SegName : dash_input->file_name); + fprintf(dash_cfg->mpd, " segment_duration)); + if (dash_cfg->time_shift_depth>=0) + fprintf(dash_cfg->mpd, " presentationTimeOffset=\"%d\"", ts_seg.sidx->earliest_presentation_time + pcr_shift); + fprintf(dash_cfg->mpd, ">\n"); + + if (!dash_cfg->dash_ctx) { + fprintf(dash_cfg->mpd, " \n", IdxName); + } + } + + /*rewrite previous SegmentList entries*/ + if ((dash_cfg->single_file_mode==2) || (!dash_cfg->single_file_mode && !dash_cfg->use_url_template)) { + /*rewrite previous URLs*/ + const char *opt; + u32 count, i; + count = gf_cfg_get_key_count(dash_cfg->dash_ctx, szRepURLsSecName); + for (i=0; idash_ctx, szRepURLsSecName, i); + opt = gf_cfg_get_key(dash_cfg->dash_ctx, szRepURLsSecName, key_name); + fprintf(dash_cfg->mpd, " %s\n", opt); + } + } + + if (dash_cfg->single_file_mode==2) { + + start = ts_seg.sidx->first_offset; + for (i=0; inb_refs; i++) { + GF_SIDXReference *ref = &ts_seg.sidx->refs[i]; + fprintf(dash_cfg->mpd, " \n", start, start+ref->reference_size-1); + start += ref->reference_size; + } + if (dash_cfg->seg_rad_name) rewrite_input = 1; + + } else { + FILE *src, *dst; + u64 pos, end; + Double current_time = cumulated_duration, dur; + src = gf_f64_open(dash_input->file_name, "rb"); + start = ts_seg.sidx->first_offset; + for (i=0; inb_refs; i++) { + char buf[4096]; + GF_SIDXReference *ref = &ts_seg.sidx->refs[i]; + + 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); + + /*warning - we may introduce repeated sequence number when concatenating files. We should use switching + segments to force reset of the continuity counter for all our pids - we don't because most players don't car ...*/ + if (dash_cfg->use_url_template != 2) { + dst = gf_f64_open(SegName, "wb"); + + gf_dasher_store_segment_info(dash_cfg, SegName, current_time); + dur = ref->subsegment_duration; + dur /= 90000; + current_time += dur; + + gf_f64_seek(src, start, SEEK_SET); + pos = start; + end = start+ref->reference_size; + while (pos= end) { + to_read = (u32) (end-pos); + } + res = fread(buf, 1, to_read, src); + if (res==to_read) { + gf_m2ts_restamp(buf, res, pcr_shift, is_pes); + res = fwrite(buf, 1, to_read, dst); + } + if (res!=to_read) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: IO error while Extracting segment %03d / %03d\r", i+1, ts_seg.sidx->nb_refs)); + break; + } + pos += res; + } + fclose(dst); + } + start += ref->reference_size; + segment_index++; + + if (!dash_cfg->use_url_template) { + fprintf(dash_cfg->mpd, " \n", SegName); + + if (dash_cfg->dash_ctx) { + char szKey[100], szVal[4046]; + sprintf(szKey, "UrlInfo%d", segment_index); + sprintf(szVal, "", SegName); + gf_cfg_set_key(dash_cfg->dash_ctx, szRepURLsSecName, szKey, szVal); + } + } + + gf_set_progress("Extracting segment ", i+1, ts_seg.sidx->nb_refs); + } + fclose(src); + cumulated_duration = current_time; + } + if (!dash_cfg->seg_rad_name || !dash_cfg->use_url_template) { + fprintf(dash_cfg->mpd, " \n"); + } + } + + if (rewrite_input) { + FILE *in, *out; + char buf[3760]; + + in = gf_f64_open(dash_input->file_name, "rb"); + out = gf_f64_open(SegName, "wb"); + while (1) { + u32 read = fread(buf, 1, 3760, in); + if (!read) break; + gf_m2ts_restamp(buf, read, pcr_shift, is_pes); + fwrite(buf, 1, read, out); + } + fclose(in); + fclose(out); + } + + fprintf(dash_cfg->mpd, " \n"); + + if (dash_cfg->dash_ctx) { + sprintf(szOpt, "%u", bandwidth); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "Bandwidth", szOpt); + + sprintf(szOpt, "%u", segment_index); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "StartIndex", szOpt); + + sprintf(szOpt, "%g", ts_seg.segment_duration); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "CumulatedDuration", szOpt); + + sprintf(szOpt, LLU, next_pcr_shift + pcr_shift); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "PCR90kOffset", szOpt); + + sprintf(szOpt, LLU, ts_seg.suspend_indexing); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "ByteOffset", ts_seg.suspend_indexing ? szOpt : NULL); + + sprintf(szOpt, LLU, ts_seg.PCR_DTS_initial_diff); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "InitialDTSOffset", ts_seg.suspend_indexing ? szOpt : NULL); + + sprintf(szOpt, "%g", cumulated_duration); + gf_cfg_set_key(dash_cfg->dash_ctx, szSectionName, "CumulatedDuration", szOpt); + } + + if (ts_seg.sidx && ts_seg.index_bs) { + gf_isom_box_size((GF_Box *)ts_seg.sidx); + gf_isom_box_write((GF_Box *)ts_seg.sidx, ts_seg.index_bs); + } + if (ts_seg.pcrb && ts_seg.index_bs) { + gf_isom_box_size((GF_Box *)ts_seg.pcrb); + gf_isom_box_write((GF_Box *)ts_seg.pcrb, ts_seg.index_bs); + } + + if (ts_seg.sidx) gf_isom_box_del((GF_Box *)ts_seg.sidx); + if (ts_seg.pcrb) gf_isom_box_del((GF_Box *)ts_seg.pcrb); + if (ts_seg.index_file) fclose(ts_seg.index_file); + if (ts_seg.index_bs) gf_bs_del(ts_seg.index_bs); + dasher_del_ts_demux(&ts_seg); + + return GF_OK; +} + +#endif //GPAC_DISABLE_MPEG2TS + +GF_Err gf_dash_segmenter_probe_input(GF_DashSegInput *dash_input) +{ + FILE *t = gf_f64_open(dash_input->file_name, "rb"); + if (!t) return GF_URL_ERROR; + fclose(t); +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS + if (gf_isom_probe_file(dash_input->file_name)) { + strcpy(dash_input->szMime, "video/mp4"); + dash_input->dasher_create_init_segment = dasher_isom_create_init_segment; + dash_input->dasher_input_classify = dasher_isom_classify_input; + dash_input->dasher_get_components_info = dasher_isom_get_input_components_info; + dash_input->dasher_segment_file = dasher_isom_segment_file; + return GF_OK; + } +#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ + +#ifndef GPAC_DISABLE_MPEG2TS + if (gf_m2ts_probe_file(dash_input->file_name)) { + GF_TSSegmenter ts_seg; + u32 count = 0; + GF_Err e = dasher_get_ts_demux(&ts_seg, dash_input->file_name, 1); + if (e) return e; + count = gf_list_count(ts_seg.ts->programs); + dasher_del_ts_demux(&ts_seg); + if (count>1) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: MPEG-2 TS file %s has several programs - this is not supported in MPEG-DASH - skipping\n", dash_input->file_name)); + return GF_NOT_SUPPORTED; + } + + strcpy(dash_input->szMime, "video/mp2t"); + /*we don't use init segments with MPEG-2 TS*/ + dash_input->dasher_create_init_segment = NULL; + dash_input->dasher_input_classify = dasher_generic_classify_input; + dash_input->dasher_get_components_info = dasher_mp2t_get_components_info; + dash_input->dasher_segment_file = dasher_mp2t_segment_file; + return GF_OK; + } +#endif + + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH]: File %s not supported for dashing - skipping\n", dash_input->file_name)); + return GF_NOT_SUPPORTED; +} + +static GF_Err write_mpd_header(FILE *mpd, const char *mpd_name, GF_Config *dash_ctx, GF_DashProfile profile, Bool is_mpeg2, const char *title, const char *source, const char *copyright, const char *moreInfoURL, const char **mpd_base_urls, u32 nb_mpd_base_urls, Bool dash_dynamic, u32 time_shift_depth, Double mpd_duration, Double mpd_update_period) +{ + u32 h, m, i; + Double s; + + fprintf(mpd, "\n"); + fprintf(mpd, "\n"); + + /*TODO what should we put for minBufferTime */ + fprintf(mpd, "=0) { + sec -= time_shift_depth; + } + /*otherwise timeshift is infinite, use original availability start time*/ + else if (dash_ctx) { + const char *opt = gf_cfg_get_key(dash_ctx, "DASH", "GenerationNTP"); + sscanf(opt, "%u", &sec); + } + gtime = sec - GF_NTP_SEC_1900_TO_1970; + t = gmtime(>ime); + 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); +#endif + + if ((s32)time_shift_depth>=0) { + h = (u32) (time_shift_depth/3600); + m = (u32) (time_shift_depth-h*60)/60; + s = time_shift_depth - h*3600 - m*60; + fprintf(mpd, " timeShiftBufferDepth=\"PT%dH%dM%.2fS\"", h, m, s); + } + if (mpd_update_period) { + h = (u32) (mpd_update_period/3600); + m = (u32) (mpd_update_period-h*60)/60; + s = mpd_update_period - h*3600 - m*60; + fprintf(mpd, " minimumUpdatePeriod=\"PT%dH%dM%.2fS\"", h, m, s); + } + + } else { + h = (u32) (mpd_duration/3600); + m = (u32) (mpd_duration-h*60)/60; + s = mpd_duration - h*3600 - m*60; + fprintf(mpd, " mediaPresentationDuration=\"PT%dH%dM%.2fS\"", h, m, s); + } + + if (profile==GF_DASH_PROFILE_LIVE) { + fprintf(mpd, " profiles=\"urn:mpeg:dash:profile:%s:2011\"", is_mpeg2 ? "mp2t-simple" : "isoff-live"); + } else if (profile==GF_DASH_PROFILE_ONDEMAND) + fprintf(mpd, " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""); + else if (profile==GF_DASH_PROFILE_MAIN) + fprintf(mpd, " profiles=\"urn:mpeg:dash:profile:%s:2011\"", is_mpeg2 ? "mp2t-main" : "isoff-main"); + else + fprintf(mpd, " profiles=\"urn:mpeg:dash:profile:full:2011\""); + + fprintf(mpd, ">\n"); + + fprintf(mpd, " \n", moreInfoURL ? moreInfoURL : "http://gpac.sourceforge.net"); + if (title) + fprintf(mpd, " %s\n", title); + else + fprintf(mpd, " %s generated by GPAC\n", mpd_name); + + if (source) + fprintf(mpd, " %s\n", source); + if (copyright) + fprintf(mpd, " %s\n", copyright); + fprintf(mpd, " \n"); + + for (i=0; i%s\n", mpd_base_urls[i]); + } + fprintf(mpd, "\n"); + return GF_OK; +} + +static GF_Err write_period_header(FILE *mpd, const char *szID, Double period_start, Double period_duration, Bool dash_dynamic) +{ + u32 h, m; + Double s; + + fprintf(mpd, " \n"); + return GF_OK; +} + +static GF_Err write_adaptation_header(FILE *mpd, GF_DashProfile profile, Bool use_url_template, u32 single_file_mode, GF_DashSegInput *first_rep, Bool bitstream_switching_mode, u32 max_width, u32 max_height, char *szMaxFPS, char *szLang, const char *szInitSegment) +{ + fprintf(mpd, " group_id) { + fprintf(mpd, " group=\"%d\"", first_rep->group_id); + } + if (max_width && max_height) { + fprintf(mpd, " maxWidth=\"%d\" maxHeight=\"%d\"", max_width, max_height); + if (strlen(szMaxFPS)) + fprintf(mpd, " maxFrameRate=\"%s\"", szMaxFPS); + gf_media_reduce_aspect_ratio(&max_width, &max_height); + fprintf(mpd, " par=\"%d:%d\"", max_width, max_height); + } + if (szLang && szLang[0]) { + fprintf(mpd, " lang=\"%s\"", szLang); + } + /*this should be fixed to use info collected during segmentation process*/ + if (profile==GF_DASH_PROFILE_ONDEMAND) + fprintf(mpd, " subsegmentStartsWithSAP=\"1\""); + + if (!strcmp(first_rep->szMime, "video/mp2t")) + fprintf(mpd, " subsegmentAlignment=\"true\""); + + fprintf(mpd, ">\n"); + + if (first_rep) { + u32 i; + char langCode[4]; + langCode[3] = 0; + + if (bitstream_switching_mode) { + for (i=0; inb_components; i++) { + struct _dash_component *comp = &first_rep->components[i]; + if (comp->media_type == GF_ISOM_MEDIA_AUDIO) { + fprintf(mpd, " \n", comp->channels); + } + } + } + if (first_rep->nb_components>1) { + for (i=0; inb_components; i++) { + struct _dash_component *comp = &first_rep->components[i]; + + fprintf(mpd, " ID); + switch (comp->media_type ) { + case GF_ISOM_MEDIA_TEXT: + fprintf(mpd, "contentType=\"text\" "); + break; + case GF_ISOM_MEDIA_VISUAL: + fprintf(mpd, "contentType=\"video\" "); + break; + case GF_ISOM_MEDIA_AUDIO: + fprintf(mpd, "contentType=\"audio\" "); + break; + case GF_ISOM_MEDIA_SCENE: + case GF_ISOM_MEDIA_DIMS: + default: + fprintf(mpd, "contentType=\"application\" "); + break; + } + /*if lang not specified at adaptationSet level, put it here*/ + if ((!szLang || !szLang[0]) && comp->szLang[0]) { + fprintf(mpd, " lang=\"%s\"", langCode); + } + fprintf(mpd, "/>\n"); + } + } + + if (bitstream_switching_mode && !use_url_template && (single_file_mode!=1) && strlen(szInitSegment) ) { + fprintf(mpd, " \n"); + fprintf(mpd, " \n", gf_url_get_resource_name( szInitSegment )); + fprintf(mpd, " \n"); + } + } + return GF_OK; +} + +static GF_Err gf_dasher_init_context(GF_Config *dash_ctx, Bool *dynamic, u32 *timeShiftBufferDepth, const char *periodID) +{ + const char *opt; + char szVal[100]; + Bool first_run = 0; + u32 sec, frac; +#ifndef _WIN32_WCE + time_t gtime; +#endif + + if (!dash_ctx) return GF_BAD_PARAM; + + opt = gf_cfg_get_key(dash_ctx, "DASH", "SessionType"); + /*first run, init all options*/ + if (!opt) { + first_run = 1; + sprintf(szVal, "%d", *timeShiftBufferDepth); + gf_cfg_set_key(dash_ctx, "DASH", "SessionType", *dynamic ? "dynamic" : "static"); + gf_cfg_set_key(dash_ctx, "DASH", "TimeShiftBufferDepth", szVal); + gf_cfg_set_key(dash_ctx, "DASH", "StoreParams", "yes"); + } else { + *dynamic = !strcmp(opt, "dynamic") ? 1 : 0; + opt = gf_cfg_get_key(dash_ctx, "DASH", "TimeShiftBufferDepth"); + *timeShiftBufferDepth = atoi(opt); + gf_cfg_set_key(dash_ctx, "DASH", "StoreParams", "no"); + } + + gf_cfg_set_key(dash_ctx, "DASH", "PeriodSwitch", "no"); + + gf_net_get_ntp(&sec, &frac); + if (first_run) { +#ifndef _WIN32_WCE + gtime = sec - GF_NTP_SEC_1900_TO_1970; + gf_cfg_set_key(dash_ctx, "DASH", "GenerationTime", asctime(gmtime(>ime))); +#endif + sprintf(szVal, "%u", sec); + gf_cfg_set_key(dash_ctx, "DASH", "GenerationNTP", szVal); + sprintf(szVal, "%u", frac); + gf_cfg_set_key(dash_ctx, "DASH", "GenerationNTPFraction", szVal); + + if (periodID) + gf_cfg_set_key(dash_ctx, "DASH", "PeriodID", periodID); + } else { + + /*check if we change period*/ + if (periodID) { + opt = gf_cfg_get_key(dash_ctx, "DASH", "PeriodID"); + if (!opt || strcmp(opt, periodID)) { + gf_cfg_set_key(dash_ctx, "DASH", "PeriodID", periodID); + gf_cfg_set_key(dash_ctx, "DASH", "PeriodSwitch", "yes"); + } + } + } + + /*perform cleanup of previous representations*/ + + return GF_OK; +} + +GF_EXPORT +u32 gf_dasher_next_update_time(GF_Config *dash_ctx, u32 mpd_update_time) +{ + Double max_dur = 0; + Double safety_dur; + Double ms_ellapsed; + u32 i, ntp_sec, frac, prev_sec, prev_frac; + const char *opt, *section; + + opt = gf_cfg_get_key(dash_ctx, "DASH", "MaxSegmentDuration"); + if (!opt) return 0; + + safety_dur = atof(opt); + if (safety_dur > (Double) mpd_update_time) + safety_dur = (Double) mpd_update_time; + + + opt = gf_cfg_get_key(dash_ctx, "DASH", "GenerationNTP"); + sscanf(opt, "%u", &prev_sec); + opt = gf_cfg_get_key(dash_ctx, "DASH", "GenerationNTPFraction"); + sscanf(opt, "%u", &prev_frac); + + /*compute cumulated duration*/ + for (i=0; imax_dur) max_dur = dur; + } + } + + if (!max_dur) return 0; + gf_net_get_ntp(&ntp_sec, &frac); + + ms_ellapsed = frac; + ms_ellapsed -= prev_frac; + ms_ellapsed /= 0xFFFFFFFF; + ms_ellapsed *= 1000; + ms_ellapsed += (ntp_sec - prev_sec)*1000; + + /*check if we need to generate */ + if (ms_ellapsed < (max_dur - safety_dur)*1000 ) { + return (u32) (1000*max_dur - ms_ellapsed); + } + return 0; +} + +/*peform all file cleanup*/ +static Bool gf_dasher_cleanup(GF_Config *dash_ctx, Bool dash_dynamic, u32 mpd_update_time, u32 time_shift_depth, Double dash_duration) +{ + Double max_dur = 0; + Double ellapsed = 0; + Double safety_dur = MAX(mpd_update_time, (u32) dash_duration); + u32 i, ntp_sec, frac, prev_sec; + const char *opt, *section; + GF_Err e; + + opt = gf_cfg_get_key(dash_ctx, "DASH", "StoreParams"); + if (opt && !strcmp(opt, "yes")) return 1; + + opt = gf_cfg_get_key(dash_ctx, "DASH", "GenerationNTP"); + if (!opt) return 1; + sscanf(opt, "%u", &prev_sec); + + /*compute cumulated duration*/ + for (i=0; imax_dur) max_dur = dur; + } + } + if (!max_dur) return 1; + gf_net_get_ntp(&ntp_sec, &frac); + + ellapsed = ntp_sec; + ellapsed -= prev_sec; + /*check if we need to generate */ + if (ellapsed < max_dur - safety_dur ) { + 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 )); + return 0; + } + if (ellapsed > max_dur) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Generating segments and MPD %g seconds too late\n", ellapsed - (u32) max_dur)); + } else { + /*generate as if max_dur has been reached*/ + ellapsed = max_dur; + } + + /*cleanup old segments*/ + if ((s32) time_shift_depth >= 0) { + for (i=0; i= ellapsed ) + break; + + e = gf_delete_file(fileName); + if (e) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH] Could not remove file %s: %s\n", fileName, gf_error_to_string(e) )); + break; + } + + /*check all reps*/ + for (j=0; j1) { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Multiple periods in live mode not supported\n")); + return GF_NOT_SUPPORTED; + } + + for (cur_period=0; cur_period=3) { + if (dash_profile) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH]: WARNING! Max SAP type %d detected\n\tswitching to FULL profile\n", max_sap_type)); + } + dash_profile = 0; + } + if ((dash_profile==GF_DASH_PROFILE_LIVE) && !seg_name) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[DASH]: WARNING! DASH Live profile requested but no -segment-name\n\tusing \"%%s_dash\" by default\n\n")); + seg_name = "%s_dash"; + } + + /*if output id not in the current working dir, concatenate output path to segment name*/ + szSegName[0] = 0; + if (seg_name) { + if (gf_url_get_resource_path(mpdfile, szSegName)) { + strcat(szSegName, seg_name); + seg_name = szSegName; + } + } + + + /*adjust params based on profiles*/ + switch (dash_profile) { + case GF_DASH_PROFILE_LIVE: + seg_at_rap = 1; + use_url_template = 1; + single_segment = single_file = 0; + break; + case GF_DASH_PROFILE_ONDEMAND: + seg_at_rap = 1; + single_segment = 1; + /*BS switching is meaningless in onDemand profile*/ + bitstream_switching_mode = 0; + use_url_template = single_file = 0; + break; + case GF_DASH_PROFILE_MAIN: + seg_at_rap = 1; + single_segment = 0; + break; + default: + break; + } + + segment_mode = single_segment ? 1 : (single_file ? 2 : 0); + + if (single_segment) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("DASH-ing file%s - single segment\nSubsegment duration %.3f - Fragment duration: %.3f secs\n", (nb_dash_inputs>1) ? "s" : "", dash_duration, frag_duration)); + subsegs_per_sidx = 0; + } else { + if (!seg_ext) seg_ext = "m4s"; + + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("DASH-ing file%s: %.2fs segments %.2fs fragments ", (nb_dash_inputs>1) ? "s" : "", dash_duration, frag_duration)); + if (subsegs_per_sidx<0) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("no sidx used")); + } else if (subsegs_per_sidx) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("%d subsegments per sidx", subsegs_per_sidx)); + } else { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("single sidx per segment")); + } + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("\n")); + } + if (frag_at_rap) seg_at_rap = 1; + + if (seg_at_rap) { + GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("Spliting segments %sat GOP boundaries\n", frag_at_rap ? "and fragments " : "")); + } + + + dash_opts.mpd_name = mpdfile; + dash_opts.segments_start_with_rap = seg_at_rap; + dash_opts.segment_duration = dash_duration; + dash_opts.seg_ext = seg_ext; + dash_opts.daisy_chain_sidx = daisy_chain_sidx; + dash_opts.subsegs_per_sidx = subsegs_per_sidx; + dash_opts.use_url_template = use_url_template; + dash_opts.single_file_mode = segment_mode; + dash_opts.fragments_start_with_rap = frag_at_rap; + dash_opts.fragment_duration = frag_duration; + dash_opts.tmpdir = tmpdir; + dash_opts.dash_ctx = dash_ctx; + dash_opts.time_shift_depth = (s32) time_shift_depth; + dash_opts.subduration = subduration; + + for (cur_period=0; cur_period period_duration) + period_duration = dash_inputs[i].duration; + } + if (first_in_period) + dash_inputs[first_in_period-1].period_duration = period_duration; + + presentation_duration += period_duration; + } + + strcpy(szTempMPD, mpdfile); + if (dash_dynamic) strcat(szTempMPD, ".tmp"); + + mpd = gf_f64_open(mpdfile, "wt"); + if (!mpd) { + GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[MPD] Cannot open MPD file %s for writing\n", szTempMPD)); + return GF_IO_ERR; + } + + dash_opts.mpd = mpd; + + e = write_mpd_header(mpd, mpdfile, dash_ctx, dash_profile, has_mpeg2, mpd_title, mpd_source, mpd_copyright, mpd_moreInfoURL, (const char **) mpd_base_urls, nb_mpd_base_urls, dash_dynamic, time_shift_depth, presentation_duration, mpd_update_time); + if (e) goto exit; + + for (cur_period=0; cur_period max_width) + max_width = dash_inputs[i].components[j].width; + if (dash_inputs[i].components[j].height > max_height) + max_height = dash_inputs[i].components[j].height; + + if (! fps_num || !fps_denum) { + fps_num = dash_inputs[i].components[j].fps_num; + fps_denum = dash_inputs[i].components[j].fps_denum; + } + else if (fps_num * dash_inputs[i].components[j].fps_denum < dash_inputs[i].components[j].fps_num * fps_denum) { + fps_num = dash_inputs[i].components[j].fps_num; + fps_denum = dash_inputs[i].components[j].fps_denum; + } + } + } + + if (max_width && max_height) { + gf_media_get_reduced_frame_rate(&fps_num, &fps_denum); + if (fps_denum>1) + sprintf(szFPS, "%d/%d", fps_num, fps_denum); + else if (fps_num) + sprintf(szFPS, "%d", fps_num); + } + + e = write_adaptation_header(mpd, dash_profile, use_url_template, segment_mode, &dash_inputs[first_rep_in_set], use_bs_switching, max_width, max_height, szFPS, szLang, szInit); + if (e) goto exit; + + is_first_rep = 1; + for (i=0; i\n"); + } + + fprintf(mpd, " \n"); + } + fprintf(mpd, ""); + +exit: + + if (mpd) { + fclose(mpd); + if (!e && dash_dynamic) + gf_move_file(szTempMPD, mpdfile); + } + return e; +} + + + +#ifndef GPAC_DISABLE_ISOM_FRAGMENTS +GF_EXPORT +GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file, Double max_duration_sec) +{ + return gf_media_isom_segment_file(input, output_file, max_duration_sec, NULL, NULL, 0); +} + +#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ + + diff --git a/src/media_tools/dsmcc.c b/src/media_tools/dsmcc.c index ed764fb..614d9fa 100644 --- a/src/media_tools/dsmcc.c +++ b/src/media_tools/dsmcc.c @@ -1,12 +1,34 @@ -/* - * Copyright (c) TELECOM ParisTech 2011 +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Jonathan Sillan + * Copyright (c) Telecom ParisTech 2011-2012 + * All rights reserved + * + * This file is part of GPAC / media tools sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * */ + #include -#ifndef GPAC_DISABLE_MPEG2TS -/* DSMCC */ +#ifdef GPAC_ENABLE_DSMCC +/* DSMCC */ /* static functions */ @@ -150,8 +172,8 @@ GF_Err gf_m2ts_process_dsmcc(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMC } *first_section_received = 1;*/ dsmcc->last_section_number = gf_bs_read_int(bs,8); - //printf("\nsection_number %d last_section_number %d\n",dsmcc->section_number,dsmcc->last_section_number); - //printf("dsmcc->table_id %d \n",dsmcc->table_id); + //fprintf(stderr, "\nsection_number %d last_section_number %d\n",dsmcc->section_number,dsmcc->last_section_number); + //fprintf(stderr, "dsmcc->table_id %d \n",dsmcc->table_id); switch (dsmcc->table_id) { case GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA: { @@ -205,7 +227,7 @@ static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord gf_m2ts_dsmcc_process_message_header(&DataMessage->DownloadDataHeader,data,bs,data_shift,1); dsmcc->DSMCC_Extension = DataMessage; - //printf("DataMessage->DownloadDataHeader.messageId %d \n",DataMessage->DownloadDataHeader.messageId); + //fprintf(stderr, "DataMessage->DownloadDataHeader.messageId %d \n",DataMessage->DownloadDataHeader.messageId); switch (DataMessage->DownloadDataHeader.messageId) { @@ -292,7 +314,7 @@ static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord DownloadDataBlock->moduleId = gf_bs_read_int(bs,16); - //printf("DownloadDataBlock->moduleId %d \n",DownloadDataBlock->moduleId); + //fprintf(stderr, "DownloadDataBlock->moduleId %d \n",DownloadDataBlock->moduleId); DownloadDataBlock->moduleVersion = gf_bs_read_int(bs,8); DownloadDataBlock->reserved = gf_bs_read_int(bs,8); if(DownloadDataBlock->reserved != 0xFF){ @@ -305,7 +327,7 @@ static GF_Err gf_m2ts_dsmcc_download_data(GF_M2TS_DSMCC_OVERLORD *dsmcc_overlord GF_M2TS_DSMCC_MODULE* dsmcc_module = gf_list_get(dsmcc_overlord->dsmcc_modules,i); /* Test if the data are compatible with the module configuration */ if(!dsmcc_download_data_validation(dsmcc_overlord,DownloadDataBlock,dsmcc_module,DataMessage->DownloadDataHeader.downloadId)){ - //printf("DownloadDataBlock->blockNumber %d \n\n",DownloadDataBlock->blockNumber); + //fprintf(stderr, "DownloadDataBlock->blockNumber %d \n\n",DownloadDataBlock->blockNumber); DownloadDataBlock->dataBlocksize = (DataMessage->DownloadDataHeader.messageLength - 6); if(dsmcc_module->block_size < DownloadDataBlock->dataBlocksize){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] Error block_size should be >= to DownloadDataBlock->dataBlocksize , abording the processing \n")); @@ -447,7 +469,7 @@ static GF_Err gf_m2ts_dsmcc_process_message_header(GF_M2TS_DSMCC_MESSAGE_DATA_HE } else if (mode == 1) { MessageHeader->downloadId = gf_bs_read_int(bs,32); } - //printf("MessageHeader->downloadId %d \n",MessageHeader->downloadId); + //fprintf(stderr, "MessageHeader->downloadId %d \n",MessageHeader->downloadId); MessageHeader->reserved = gf_bs_read_int(bs,8); if (MessageHeader->reserved != 0xFF) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process DSMCC] DataHeader reserved slot does not have the correct value, abording the processing \n")); @@ -1915,4 +1937,4 @@ static void dsmcc_free_biop_context(GF_M2TS_DSMCC_SERVICE_CONTEXT* Context,u32 s gf_free(Context); } -#endif //GPAC_DISABLE_MPEG2TS \ No newline at end of file +#endif //GPAC_ENABLE_DSMCC diff --git a/src/media_tools/dvb_mpe.c b/src/media_tools/dvb_mpe.c index 1882d24..7ef620e 100644 --- a/src/media_tools/dvb_mpe.c +++ b/src/media_tools/dvb_mpe.c @@ -3,8 +3,7 @@ #include -#ifndef GPAC_DISABLE_MPEG2TS - +#ifdef GPAC_ENABLE_MPE static void gf_m2ts_Delete_IpPacket(GF_M2TS_IP_Packet *ip_packet); @@ -45,7 +44,7 @@ static void on_dvb_mpe_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par) gf_m2ts_process_mpe(ts, mpe, data, u32_data_size, u32_table_id); } else { - //printf("Time Slice Parameters for MPE-FEC have not been found yet \n"); + //fprintf(stderr, "Time Slice Parameters for MPE-FEC have not been found yet \n"); } break; default: @@ -142,16 +141,16 @@ void gf_dvb_mpe_section_del(GF_M2TS_ES *es) u32 i; for (i = 0; i < length; i ++) { if (i%line_length == 0) { - printf("%2d: ", i/line_length); + fprintf(stderr, "%2d: ", i/line_length); } else if (i%8 == 0) { - printf(" "); + fprintf(stderr, " "); } - printf("%02x", data[i]); + fprintf(stderr, "%02x", data[i]); if ((i+1)%line_length == 0) { - printf("\n"); + fprintf(stderr, "\n"); } } - if (last_line) printf("\n"); + if (last_line) fprintf(stderr, "\n"); } */ @@ -170,7 +169,7 @@ void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_MPE *mpe, unsigned i_streams = 0; -// printf("Processing MPE/MPE-FEC data PID %d (%d/%d)\n",mpe->pid, data[6],data[7]); +// fprintf(stderr, "Processing MPE/MPE-FEC data PID %d (%d/%d)\n",mpe->pid, data[6],data[7]); if (!gf_m2ts_crc32_check(data, data_size - 4)) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("CRC error in the MPE/MPE-FEC data \n")); @@ -179,12 +178,12 @@ void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_MPE *mpe, unsigned /*get number of rows of mpe_fec_frame from descriptor*/ section_number = data[6]; last_section_number = data[7]; - //printf( "table_id: %x section_length: %d section_number: %d last : %d \n", data[0], (data[1] & 0xF)<<8|data[2], section_number, last_section_number); + //fprintf(stderr, "table_id: %x section_length: %d section_number: %d last : %d \n", data[0], (data[1] & 0xF)<<8|data[2], section_number, last_section_number); if (ts->direct_mpe) { if (table_id != GF_M2TS_TABLE_ID_DSM_CC_PRIVATE) return; if (section_number != last_section_number) { - fprintf(stdout, "MPE IP datagram on several section not supported\n"); + fprintf(stderr, "MPE IP datagram on several section not supported\n"); return; } /* send the IP data : @@ -271,7 +270,7 @@ void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_MPE *mpe, unsigned //data += (mff->rows +12+4 ); break; default: - // printf ("Unknown table id %x \n", table_id ); + // fprintf(stderr, "Unknown table id %x \n", table_id ); len_left = 0; } @@ -350,13 +349,13 @@ void gf_m2ts_process_ipdatagram(MPE_FEC_FRAME *mff,GF_M2TS_Demuxer *ts) socket_simu(ip_packet,ts, 1); if(ip_packet->u8_rx_adr[3] == 8){ - printf("\n"); + fprintf(stderr, "\n"); } /* compare the destination ip adress and the ESG Bootstrap adress */ Boostrap_ip = gf_m2ts_compare_ip(ip_packet->u8_rx_adr,ip_adress_bootstrap); if(Boostrap_ip){ - printf("ESG Bootstrap found !\n"); + fprintf(stderr, "ESG Bootstrap found !\n"); } }else{ offset += (ip_packet->u32_total_length); @@ -470,7 +469,7 @@ u32 gf_m2ts_ipdatagram_reader(u8 *datagram,GF_M2TS_IP_Packet *ip_packet, u32 off /*ip_packet->data = gf_malloc((ip_packet->u32_total_length-ip_packet->u32_hdr_length)*sizeof(char)); memcpy(ip_packet->data,datagram+offset+20,(ip_packet->u32_total_length-ip_packet->u32_hdr_length)*sizeof(char));*/ - printf("TX addr: %d.%d.%d.%d RX addr : %d.%d.%d.%d port:%d(0x%x) \n",ip_packet->u8_tx_adr[0],ip_packet->u8_tx_adr[1],ip_packet->u8_tx_adr[2],ip_packet->u8_tx_adr[3],ip_packet->u8_rx_adr[0],ip_packet->u8_rx_adr[1],ip_packet->u8_rx_adr[2],ip_packet->u8_rx_adr[3],ip_packet->u32_rx_udp_port,ip_packet->u32_rx_udp_port); + fprintf(stderr, "TX addr: %d.%d.%d.%d RX addr : %d.%d.%d.%d port:%d(0x%x) \n",ip_packet->u8_tx_adr[0],ip_packet->u8_tx_adr[1],ip_packet->u8_tx_adr[2],ip_packet->u8_tx_adr[3],ip_packet->u8_rx_adr[0],ip_packet->u8_rx_adr[1],ip_packet->u8_rx_adr[2],ip_packet->u8_rx_adr[3],ip_packet->u32_rx_udp_port,ip_packet->u32_rx_udp_port); return 1; @@ -506,17 +505,17 @@ void gf_m2ts_process_int(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ip_table, unsi GF_M2TS_IP_PLATFORM * ip_platform = ts->ip_platform ; assert( ts ); -// fprintf(stdout, "Processing IP/MAC Notification table (PID %d) %s\n", ip_table->pid, (status==GF_M2TS_TABLE_REPEAT)?"repeated":""); +// fprintf(stderr, "Processing IP/MAC Notification table (PID %d) %s\n", ip_table->pid, (status==GF_M2TS_TABLE_REPEAT)?"repeated":""); //if ( status == GF_M2TS_TABLE_REPEAT ) return ; if ( ip_platform == NULL ) { GF_SAFEALLOC(ip_platform,GF_M2TS_IP_PLATFORM ); ip_platform->ip_streams= gf_list_new(); - //printf ( " \n initialize the Iip_platform \n"); + //fprintf(stderr, " \n initialize the Iip_platform \n"); section_DSMCC_INT (ip_platform, data, data_size); ts->ip_platform = ip_platform; } - //printf ("processing the INT table \n"); + //fprintf(stderr, "processing the INT table \n"); @@ -596,12 +595,12 @@ u32 platform_descriptorDSMCC_INT_UNT(GF_M2TS_IP_PLATFORM* ip_platform, u8 *data case GF_M2TS_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR: { - //printf (" Information on the ip platform found \n"); + //fprintf(stderr, " Information on the ip platform found \n"); gf_ip_platform_descriptor(ip_platform, data); }break; case GF_M2TS_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR: { - //printf (" Information on the ip platform found \n"); + //fprintf(stderr, " Information on the ip platform found \n"); gf_ip_platform_provider_descriptor(ip_platform, data); }break; @@ -757,8 +756,8 @@ void encode_fec(MPE_FEC_FRAME * mff) /* ************** */ /* Encode data into codeword, adding NPAR parity bytes */ encode_data(adt_rs_en_buffer, cols, adt_rs_en_buffer); - printf("Encoded data is : \"%s\"\n", adt_rs_en_buffer); - printf("data with error is: \"%s\"\n", adt_rs_en_buffer); + fprintf(stderr, "Encoded data is : \"%s\"\n", adt_rs_en_buffer); + fprintf(stderr, "data with error is: \"%s\"\n", adt_rs_en_buffer); /*set a row of RS into RS table*/ setRowRS ( mff, i , (unsigned char *)(adt_rs_en_buffer + cols) ); } @@ -772,7 +771,7 @@ void decode_fec(MPE_FEC_FRAME * mff) u8 *data; u8 linebuffer[255]; - //printf("Starting FEC decoding ...\n"); + //fprintf(stderr, "Starting FEC decoding ...\n"); data = gf_malloc((mff->rows*191)*sizeof(char)); memset(data,0,sizeof(data)); @@ -782,12 +781,12 @@ void decode_fec(MPE_FEC_FRAME * mff) memset(linebuffer, 0, 255); offset = 0; - /*printf("ADT data\n"); + /*fprintf(stderr, "ADT data\n"); print_bytes(mff->p_adt, 32, 1, 0); print_bytes(mff->p_adt+512, 32, 1, 0); print_bytes(mff->p_adt+512+512, 32, 1, 0); print_bytes(mff->p_adt+512+512+512, 32, 1, 1); - printf("RS data\n"); + fprintf(stderr, "RS data\n"); print_bytes(mff->p_rs, 32, 1, 0); print_bytes(mff->p_rs+512, 32, 1, 0); print_bytes(mff->p_rs+512+512, 32, 1, 0); @@ -809,7 +808,7 @@ void decode_fec(MPE_FEC_FRAME * mff) /* TODO: set the erasures and errors based on the MFF */ if(correct_errors_erasures (linebuffer, ML, nerasures, erasures) == 0) { - //printf("Correction Error line %d \n", i); + //fprintf(stderr, "Correction Error line %d \n", i); } /* TODO: replace the current line in MFF */ @@ -818,7 +817,7 @@ void decode_fec(MPE_FEC_FRAME * mff) memcpy(data+offset,linebuffer,sizeof(data)); offset += 191; } - //printf("FEC decoding done.\n"); + //fprintf(stderr, "FEC decoding done.\n"); memcpy(mff->p_adt,data,sizeof(data)); //gf_m2ts_ipdatagram_reader(mff->p_adt,ip_datagram); @@ -939,7 +938,7 @@ void gf_m2ts_print_mpe_info(GF_M2TS_Demuxer *ts) if (!ts->ip_platform) return; /* provider and ip platform name */ - printf(" IP Platform : %s provided by %s \n",ip_platform->name,ip_platform->provider_name); + fprintf(stderr, " IP Platform : %s provided by %s \n",ip_platform->name,ip_platform->provider_name); i_streams = 0; i_targets = 0; @@ -950,8 +949,8 @@ void gf_m2ts_print_mpe_info(GF_M2TS_Demuxer *ts) for(i=0;iip_streams, i); - printf("PID:%d \n",ip_stream_buff->PID); - printf("Target IP Adress : \n"); + fprintf(stderr, "PID:%d \n",ip_stream_buff->PID); + fprintf(stderr, "Target IP Adress : \n"); /*Print the target IP adress */ i_targets = gf_list_count(ip_stream_buff->targets); for(j=0;jaddress; - printf("%d.%d.%d.%d/%d ",ip_adress[0],ip_adress[1],ip_adress[2],ip_adress[3],ip_targets->slash_mask); - printf("RX port :"); + fprintf(stderr, "%d.%d.%d.%d/%d ",ip_adress[0],ip_adress[1],ip_adress[2],ip_adress[3],ip_targets->slash_mask); + fprintf(stderr, "RX port :"); while(ip_targets->rx_port[l] != 0) { - printf(" %d ",ip_targets->rx_port[l]); + fprintf(stderr, " %d ",ip_targets->rx_port[l]); l++; } - printf("\n"); + fprintf(stderr, "\n"); } /*Print the time slice fec descriptor */ - printf("Time Slice Fec Descriptor : \n"); + fprintf(stderr, "Time Slice Fec Descriptor : \n"); if(ip_stream_buff->time_slice_fec.time_slicing==0) { - printf(" No Time Slicing \n"); + fprintf(stderr, " No Time Slicing \n"); }else { - printf(" Time Slicing\n"); + fprintf(stderr, " Time Slicing\n"); } if(ip_stream_buff->time_slice_fec.mpe_fec==0) { - printf(" No MPE FEC used \n"); + fprintf(stderr, " No MPE FEC used \n"); }else { - printf(" MPE FEC used \n"); + fprintf(stderr, " MPE FEC used \n"); } switch(ip_stream_buff->time_slice_fec.frame_size) { case 0: { - printf(" Frame size : 256 rows \n"); - printf(" Max Burst Duration 512 kbits\n"); + fprintf(stderr, " Frame size : 256 rows \n"); + fprintf(stderr, " Max Burst Duration 512 kbits\n"); }break; case 1: { - printf(" Frame size : 512 rows \n"); - printf(" Max Burst Duration 1024 kbits\n"); + fprintf(stderr, " Frame size : 512 rows \n"); + fprintf(stderr, " Max Burst Duration 1024 kbits\n"); }break; case 2: { - printf(" Frame size : 768 rows \n"); - printf(" Max Burst Duration 1536 kbits\n"); + fprintf(stderr, " Frame size : 768 rows \n"); + fprintf(stderr, " Max Burst Duration 1536 kbits\n"); }break; case 3: { - printf(" Frame size : 1024 rows \n"); - printf(" Max Burst Duration 2048 kbits\n"); + fprintf(stderr, " Frame size : 1024 rows \n"); + fprintf(stderr, " Max Burst Duration 2048 kbits\n"); }break; default: break; } - printf(" Time Slice Fec ID : %x\n",ip_stream_buff->time_slice_fec.time_slice_fec_id); + fprintf(stderr, " Time Slice Fec ID : %x\n",ip_stream_buff->time_slice_fec.time_slice_fec_id); /* Locayion descriptor */ - printf("Location Descriptor \n"); - printf("Network ID:%d \n",ip_stream_buff->location.network_id); - printf("Original Network ID:%d \n",ip_stream_buff->location.original_network_id); - printf("Transport Stream ID:%d \n",ip_stream_buff->location.transport_stream_id); - printf("Service ID:%d \n",ip_stream_buff->location.service_id); - printf("Component Tag:%d \n",ip_stream_buff->location.component_tag); + fprintf(stderr, "Location Descriptor \n"); + fprintf(stderr, "Network ID:%d \n",ip_stream_buff->location.network_id); + fprintf(stderr, "Original Network ID:%d \n",ip_stream_buff->location.original_network_id); + fprintf(stderr, "Transport Stream ID:%d \n",ip_stream_buff->location.transport_stream_id); + fprintf(stderr, "Service ID:%d \n",ip_stream_buff->location.service_id); + fprintf(stderr, "Component Tag:%d \n",ip_stream_buff->location.component_tag); getchar(); // attendre l'appuie d'une touche @@ -1100,7 +1099,7 @@ void socket_simu(GF_M2TS_IP_Packet *ip_packet, GF_M2TS_Demuxer *ts, Bool yield) e = gf_sk_send(Sock_Struct->sock, ip_packet->data, ip_packet->u32_udp_data_size - 8); if (e != GF_OK){ - fprintf(stdout, "Error sending to \n"); + fprintf(stderr, "Error sending to \n"); } if (yield) gf_sleep(10); @@ -1123,7 +1122,7 @@ Bool init_frame(MPE_FEC_FRAME * mff, u32 rows) mff->p_rs = (u8 *)gf_calloc(MPE_RS_COLS*rows,sizeof(u8)); - printf("MPE_RS_COLS*rows :%d \n",MPE_RS_COLS*rows); + fprintf(stderr, "MPE_RS_COLS*rows :%d \n",MPE_RS_COLS*rows); mff->capacity_total = mff->col_adt*rows; mff->p_error_adt = (u32 *)gf_calloc(mff->col_adt*rows,sizeof(u32)); @@ -1132,7 +1131,7 @@ Bool init_frame(MPE_FEC_FRAME * mff, u32 rows) mff->current_offset_rs = 0; mff->ADT_done = 0; mff->PID = 0; -// printf("MFF: rows: %d, adt_col: %d, rs_col : %d, capacity : %d\n", mff->rows, mff->col_adt, mff->col_rs, mff->capacity_total ); +// fprintf(stderr, "MFF: rows: %d, adt_col: %d, rs_col : %d, capacity : %d\n", mff->rows, mff->col_adt, mff->col_rs, mff->capacity_total ); mff->mpe_holes = gf_list_new(); mff->initialized = 1; return 1; @@ -1195,7 +1194,7 @@ void setRowRS(MPE_FEC_FRAME *mff, u32 index, u8 *p_rs) void addPadding(MPE_FEC_FRAME *mff , u32 offset) { u32 i = 0; - printf("add paddings from %d to the end %d\n", offset, mff->capacity_total ); + fprintf(stderr, "add paddings from %d to the end %d\n", offset, mff->capacity_total ); for ( i = offset ; i capacity_total; i ++ ) mff -> p_adt [i] = 0xff ; } @@ -1207,13 +1206,13 @@ static void print_bytes2(u8 * data, u32 length ) /*print_bytes2 */ u32 k = 0; for ( i = 0; i < length ; i ++ ) { if (k == 0) { - printf("%x0 : ", row_num); + fprintf(stderr, "%x0 : ", row_num); k = 0; } - printf("%#x ", data[i]); + fprintf(stderr, "%#x ", data[i]); k++; if (k == 16) { - printf("\n"); + fprintf(stderr, "\n"); k = 0; row_num ++; } @@ -1230,17 +1229,17 @@ void setIpDatagram(MPE_FEC_FRAME * mff, u32 offset, u8* dgram, u32 length ) if (offset >= mff->capacity_total) { - printf ("Offset %d bigger than capacity %d \n", offset, mff->capacity_total ); + fprintf(stderr, "Offset %d bigger than capacity %d \n", offset, mff->capacity_total ); } if (offset+length >= mff->capacity_total) { - printf ("Offset+length %d+%d bigger than capacity %d \n", offset, length, mff->capacity_total ); + fprintf(stderr, "Offset+length %d+%d bigger than capacity %d \n", offset, length, mff->capacity_total ); } if (mff->current_offset_adt != offset) { if (mff->current_offset_adt > offset) { - printf ("We missed an offset reset (%d to %d)\n", mff->current_offset_adt, offset); + fprintf(stderr, "We missed an offset reset (%d to %d)\n", mff->current_offset_adt, offset); mff->current_offset_adt = offset; } else { - printf ("there is an error hole in the ADT from %d to %d \n", mff->current_offset_adt, offset); + fprintf(stderr, "there is an error hole in the ADT from %d to %d \n", mff->current_offset_adt, offset); } setErrorIndicator( mff->p_error_adt , mff->current_offset_adt , (offset - mff->current_offset_adt)*sizeof(u32) ) ; mpe_error_holes->offset = mff->current_offset_adt; @@ -1257,7 +1256,7 @@ void setIpDatagram(MPE_FEC_FRAME * mff, u32 offset, u8* dgram, u32 length ) void setColRS( MPE_FEC_FRAME * mff, u32 offset, u8 * pds, u32 length ) { if ( mff->current_offset_rs != offset) { - printf ("there is an error hole in the RS from %d to %d \n", mff->current_offset_rs, offset ); + fprintf(stderr, "there is an error hole in the RS from %d to %d \n", mff->current_offset_rs, offset ); setErrorIndicator( mff->p_error_rs , mff->current_offset_rs , (offset - mff->current_offset_rs)*sizeof(u32)); mff->current_offset_rs = offset; } @@ -1301,23 +1300,23 @@ u32 getErrasurePositions( MPE_FEC_FRAME *mff , u32 row, u32 *errasures) } base += mff->rows ; } - printf (" the erasure locations is:\n"); + fprintf(stderr, " the erasure locations is:\n"); for ( i = 0; i < nb ; i ++ ) - printf("%d ", errasures[i]); + fprintf(stderr, "%d ", errasures[i]); return nb; } void setErrorIndicator(u32 * data , u32 offset, u32 length) { -// printf("setting the error indication \n"); +// fprintf(stderr, "setting the error indication \n"); memset(data+offset, 1, length); } /*void descriptor_PRIVATE (u8 *b, DTAG_SCOPE tag_scope){ - printf ("private descriptor \n"); + fprintf(stderr, "private descriptor \n"); return ; }*/ -#endif //GPAC_DISABLE_MPEG2TS +#endif //GPAC_ENABLE_MPE diff --git a/src/media_tools/filestreamer.c b/src/media_tools/filestreamer.c index 4a15a7b..e3072e8 100644 --- a/src/media_tools/filestreamer.c +++ b/src/media_tools/filestreamer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato / Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre, Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / mp4 simple streamer application diff --git a/src/media_tools/img.c b/src/media_tools/img.c index fdf04ee..6e2ef1c 100644 --- a/src/media_tools/img.c +++ b/src/media_tools/img.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project diff --git a/src/media_tools/ismacryp.c b/src/media_tools/ismacryp.c index 39e9d8f..d4263e5 100644 --- a/src/media_tools/ismacryp.c +++ b/src/media_tools/ismacryp.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre - 2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project diff --git a/src/media_tools/isom_hinter.c b/src/media_tools/isom_hinter.c index 7ce1c69..05ebaee 100644 --- a/src/media_tools/isom_hinter.c +++ b/src/media_tools/isom_hinter.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -67,7 +68,8 @@ void gf_media_get_sample_average_infos(GF_ISOFile *file, u32 Track, u32 *avgSize bw += 8*samp->dataLength; //get the CTS delta - if (samp->CTS_Offset > *maxCTSDelta) *maxCTSDelta = samp->CTS_Offset; + if ((samp->CTS_Offset>=0) && ((u32)samp->CTS_Offset > *maxCTSDelta)) + *maxCTSDelta = samp->CTS_Offset; gf_isom_sample_del(&samp); } if (count>1) *TimeDelta = (u32) (tdelta/ (count-1) ); diff --git a/src/media_tools/isom_tools.c b/src/media_tools/isom_tools.c index 9b8f189..1d98204 100644 --- a/src/media_tools/isom_tools.c +++ b/src/media_tools/isom_tools.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -24,14 +25,70 @@ -#include +#include #include #include +#ifndef GPAC_DISABLE_ISOM_WRITE +GF_EXPORT +GF_Err gf_media_change_par(GF_ISOFile *file, u32 track, s32 ar_num, s32 ar_den) +{ + u32 tk_w, tk_h, stype; + GF_Err e; + + e = gf_isom_get_visual_info(file, track, 1, &tk_w, &tk_h); + 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) ) { +#ifndef GPAC_DISABLE_AV_PARSERS + GF_AVCConfig *avcc = gf_isom_avc_config_get(file, track, 1); + AVC_ChangePAR(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; +#endif + } + else if (stype==GF_ISOM_SUBTYPE_MPEG4) { + GF_ESD *esd = gf_isom_get_esd(file, track, 1); + if (!esd || !esd->decoderConfig || (esd->decoderConfig->streamType!=4) ) { + if (esd) gf_odf_desc_del((GF_Descriptor *) esd); + return GF_NOT_SUPPORTED; + } +#ifndef GPAC_DISABLE_AV_PARSERS + if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) { + e = gf_m4v_rewrite_par(&esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength, ar_num, ar_den); + if (!e) e = gf_isom_change_mpeg4_description(file, track, 1, esd); + gf_odf_desc_del((GF_Descriptor *) esd); + if (e) return e; + } +#endif + } else { + return GF_BAD_PARAM; + } + + e = gf_isom_set_pixel_aspect_ratio(file, track, 1, ar_num, ar_den); + if (e) return e; + + if ((ar_den>=0) && (ar_num>=0)) { + if (ar_den) tk_w = tk_w * ar_num / ar_den; + else if (ar_num) tk_h = tk_h * ar_den / ar_num; + } + /*revert to full frame for track layout*/ + else { + e = gf_isom_get_visual_info(file, track, 1, &tk_w, &tk_h); + if (e) return e; + } + return gf_isom_set_track_layout_info(file, track, tk_w<<16, tk_h<<16, 0, 0, 0); +} +#endif /*GPAC_DISABLE_ISOM_WRITE*/ GF_EXPORT GF_Err gf_media_get_file_hash(const char *file, u8 hash[20]) { +#ifdef GPAC_DISABLE_CORE_TOOLS + return GF_NOT_SUPPORTED; +#else u8 block[1024]; u32 read; u64 size, tot; @@ -92,66 +149,11 @@ GF_Err gf_media_get_file_hash(const char *file, u8 hash[20]) #endif fclose(in); return GF_OK; +#endif } #ifndef GPAC_DISABLE_ISOM -GF_Err gf_media_get_rfc_6381_codec_name(GF_ISOFile *movie, u32 track, char *szCodec) -{ - GF_ESD *esd; - GF_AVCConfig *avcc; - GF_AVCConfigSlot *sps; - u32 subtype = gf_isom_get_media_subtype(movie, track, 1); - - switch (subtype) { - case GF_ISOM_SUBTYPE_MPEG4: - esd = gf_isom_get_esd(movie, track, 1); - switch (esd->decoderConfig->streamType) { - case GF_STREAM_AUDIO: - if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) { - /*5 first bits of AAC config*/ - u8 audio_object_type = (esd->decoderConfig->decoderSpecificInfo->data[0] & 0xF8) >> 3; - sprintf(szCodec, "mp4a.%02x.%02x", esd->decoderConfig->objectTypeIndication, audio_object_type); - } else { - sprintf(szCodec, "mp4a.%02x", esd->decoderConfig->objectTypeIndication); - } - break; - case GF_STREAM_VISUAL: -#ifndef GPAC_DISABLE_AV_PARSERS - if (esd->decoderConfig->decoderSpecificInfo) { - GF_M4VDecSpecInfo dsi; - gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); - sprintf(szCodec, "mp4v.%02x.%02x", esd->decoderConfig->objectTypeIndication, dsi.VideoPL); - } else -#endif - { - sprintf(szCodec, "mp4v.%02x", esd->decoderConfig->objectTypeIndication); - } - break; - default: - sprintf(szCodec, "mp4s.%02x", esd->decoderConfig->objectTypeIndication); - break; - } - gf_odf_desc_del((GF_Descriptor *)esd); - return GF_OK; - - case GF_ISOM_SUBTYPE_AVC_H264: - case GF_ISOM_SUBTYPE_AVC2_H264: - case GF_ISOM_SUBTYPE_SVC_H264: - avcc = gf_isom_avc_config_get(movie, track, 1); - sps = gf_list_get(avcc->sequenceParameterSets, 0); - sprintf(szCodec, "%s.%02x%02x%02x", gf_4cc_to_str(subtype), (u8) sps->data[1], (u8) sps->data[2], (u8) sps->data[3]); - gf_odf_avc_cfg_del(avcc); - return GF_OK; - - default: - GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISOM Tools] codec parameters not known - setting codecs string to default value \"%s\"\n", gf_4cc_to_str(subtype) )); - sprintf(szCodec, "%s", gf_4cc_to_str(subtype)); - return GF_OK; - } - return GF_OK; -} - #ifndef GPAC_DISABLE_ISOM_WRITE static const u32 ISMA_VIDEO_OD_ID = 20; @@ -728,1191 +730,6 @@ GF_Err gf_media_make_psp(GF_ISOFile *mp4) return GF_OK; } -typedef struct -{ - Bool is_ref_track; - Bool done; - u32 TrackID; - u32 SampleNum, SampleCount; - u32 FragmentLength; - u32 OriginalTrack; - u32 finalSampleDescriptionIndex; - u32 TimeScale, MediaType, DefaultDuration, InitialTSOffset; - u64 last_sample_cts, next_sample_dts; - Bool all_sample_raps; -} TrackFragmenter; - -static u64 get_next_sap_time(GF_ISOFile *input, u32 track, u32 sample_count, u32 sample_num) -{ - GF_ISOSample *samp; - u64 time; - Bool is_rap, has_roll; - u32 i, found_sample = 0; - for (i=sample_num; i<=sample_count; i++) { - if (gf_isom_get_sample_sync(input, track, i)) { - found_sample = i; - break; - } - gf_isom_get_sample_rap_roll_info(input, track, i, &is_rap, &has_roll, NULL); - if (is_rap || has_roll) { - found_sample = i; - break; - } - } - if (!found_sample) return 0; - samp = gf_isom_get_sample_info(input, track, found_sample, NULL, NULL); - time = samp->DTS; - gf_isom_sample_del(&samp); - return time; -} - - -#ifndef GPAC_DISABLE_ISOM_FRAGMENTS - -GF_EXPORT -GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool single_segment_mode, const char *dash_ctx_file, GF_ISOFile *sample_descs, u32 rep_idx) -{ - u8 NbBits; - u32 i, TrackNum, descIndex, j, count, nb_sync, ref_track_id, nb_tracks_done; - u32 defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, nb_samp, nb_done; - u32 nb_video, nb_audio, nb_text, nb_scene; - u8 defaultPadding; - u16 defaultDegradationPriority; - GF_Err e; - char sOpt[100], sKey[100]; - char szCodecs[200], szCodec[100]; - u32 cur_seg, fragment_index, max_sap_type; - GF_ISOFile *output; - GF_ISOSample *sample, *next; - GF_List *fragmenters; - u32 MaxFragmentDuration, MaxSegmentDuration, SegmentDuration, maxFragDurationOverSegment; - Double average_duration, file_duration, period_duration, max_segment_duration; - u32 nb_segments, width, height, sample_rate, nb_channels; - char langCode[5]; - u32 index_start_range, index_end_range; - Bool force_switch_segment = 0; - Bool switch_segment = 0; - Bool split_seg_at_rap = (dash_mode==2) ? 1 : 0; - Bool split_at_rap = 0; - Bool has_rap = 0; - Bool next_sample_rap = 0; - Bool flush_all_samples = 0; - Bool simulation_pass = 0; - u64 last_ref_cts = 0; - u64 start_range, end_range, file_size, init_seg_size, ref_track_first_dts, ref_track_next_cts; - u32 tfref_timescale = 0; - u32 bandwidth = 0; - TrackFragmenter *tf, *tfref; - FILE *mpd = NULL; - FILE *mpd_segs = NULL; - char *SegName = NULL; - const char *opt; - GF_Config *dash_ctx = NULL; - Bool store_dash_params = 0; - Bool dash_moov_setup = 0; - Bool segments_start_with_sap = 1; - Bool first_sample_in_segment = 0; - u32 *segments_info = NULL; - u32 nb_segments_info = 0; - Bool audio_only = 1; - - - SegmentDuration = 0; - nb_samp = 0; - fragmenters = NULL; - if (!seg_ext) seg_ext = "m4s"; - - //create output file - if (dash_mode) { - u32 len; - - if (dash_ctx_file) { - dash_ctx = gf_cfg_new(NULL, dash_ctx_file); - if (!dash_ctx) { - FILE *t = fopen(dash_ctx_file, "wt"); - if (t) fclose(t); - dash_ctx = gf_cfg_new(NULL, dash_ctx_file); - - if (dash_ctx) store_dash_params=1; - } - } - len = strlen(output_file); - len += 100; - SegName = gf_malloc(sizeof(char)*len); - if (!SegName) return GF_OUT_OF_MEM; - - opt = dash_ctx ? gf_cfg_get_key(dash_ctx, "DASH", "InitializationSegment") : NULL; - if (opt) { - output = gf_isom_open(opt, GF_ISOM_OPEN_CAT_FRAGMENTS, NULL); - dash_moov_setup = 1; - } else { - strcpy(SegName, output_file); - strcat(SegName, ".mp4"); - output = gf_isom_open(SegName, GF_ISOM_OPEN_WRITE, NULL); - } - if (!output) { - e = gf_isom_last_error(NULL); - goto err_exit; - } - - if (store_dash_params) { - gf_cfg_set_key(dash_ctx, "DASH", "InitializationSegment", SegName); - } - mpd = gf_f64_open(mpd_name, "a+t"); - mpd_segs = gf_temp_file_new(); - } else { - output = gf_isom_open(output_file, GF_ISOM_OPEN_WRITE, NULL); - if (!output) return gf_isom_last_error(NULL); - } - - nb_sync = 0; - nb_samp = 0; - fragmenters = gf_list_new(); - - if (! dash_moov_setup) { - e = gf_isom_clone_movie(input, output, 0, 0); - if (e) goto err_exit; - } - - MaxFragmentDuration = (u32) (max_duration_sec * 1000); - MaxSegmentDuration = (u32) (dash_duration_sec * 1000); - - /*in single segment mode, only one big SIDX is written between the end of the moov and the first fragment. - To speed-up writing, we do a first fragmentation pass without writing any sample to compute the number of segments and fragments per segment - in order to allocate / write to file the sidx before the fragmentation. The sidx will then be rewritten when closing the last segment*/ - if (single_segment_mode) simulation_pass = 1; - index_start_range = index_end_range = 0; - - tfref = NULL; - file_duration = 0; - width = height = sample_rate = nb_channels = 0; - langCode[0]=0; - langCode[4]=0; - szCodecs[0] = 0; - - nb_video = nb_audio = nb_text = nb_scene = 0; - //duplicates all tracks - for (i=0; iTrackID = gf_isom_get_track_id(output, TrackNum); - tf->SampleCount = gf_isom_get_sample_count(input, i+1); - tf->OriginalTrack = i+1; - tf->TimeScale = gf_isom_get_media_timescale(input, i+1); - tf->MediaType = gf_isom_get_media_type(input, i+1); - tf->DefaultDuration = defaultDuration; - - if (gf_isom_get_sync_point_count(input, i+1)>nb_sync) { - tfref = tf; - nb_sync = gf_isom_get_sync_point_count(input, i+1); - } else if (!gf_isom_has_sync_points(input, i+1)) { - tf->all_sample_raps = 1; - } - - tf->finalSampleDescriptionIndex = 1; - - /*figure out if we have an initial TS*/ - if (!dash_moov_setup) { - if (gf_isom_get_edit_segment_count(input, i+1)) { - u64 EditTime, SegmentDuration, MediaTime; - u8 EditMode; - gf_isom_get_edit_segment(input, i+1, 1, &EditTime, &SegmentDuration, &MediaTime, &EditMode); - if (EditMode==GF_ISOM_EDIT_EMPTY) { - tf->InitialTSOffset = (u32) (SegmentDuration * tf->TimeScale / gf_isom_get_timescale(input)); - } - /*and remove edit segments*/ - gf_isom_remove_edit_segments(output, TrackNum); - } - /*locate sample description in list if given*/ - if (sample_descs) { - u32 s_count; - u32 sample_descs_track = gf_isom_get_track_by_id(sample_descs, tf->TrackID); - if (!sample_descs_track) { - e = GF_BAD_PARAM; - goto err_exit; - - } - -#ifndef GPAC_DISABLE_ISOM_FRAGMENTS - //the initialization segment is not yet setup for fragmentation - if (! gf_isom_is_track_fragmented(sample_descs, tf->TrackID)) { - e = gf_isom_setup_track_fragment(sample_descs, sample_descs_track, - defaultDescriptionIndex, defaultDuration, - defaultSize, (u8) defaultRandomAccess, - defaultPadding, defaultDegradationPriority); - if (e) goto err_exit; - } - /*otherwise override the fragment defauls so that we are consistent with the shared init segment*/ - else { - e = gf_isom_get_fragment_defaults(sample_descs, sample_descs_track, - &defaultDuration, &defaultSize, &defaultDescriptionIndex, &defaultRandomAccess, &defaultPadding, &defaultDegradationPriority); - if (e) goto err_exit; - - e = gf_isom_change_track_fragment_defaults(output, TrackNum, - defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, defaultPadding, defaultDegradationPriority); - if (e) goto err_exit; - } -#endif - - /*reset all sample desc and clone with new ones*/ - gf_isom_clone_sample_descriptions(output, TrackNum, sample_descs, sample_descs_track, 1); - - /*and search in new ones the new index*/ - s_count = gf_isom_get_sample_description_count(sample_descs, sample_descs_track); - if (s_count>1) { - u32 k; - /*remove all sample descs*/ - for (k=0; kfinalSampleDescriptionIndex = k+1; - } - } - } - } - } - /*restore track decode times*/ - else { - char *opt, sKey[100]; - sprintf(sKey, "TrackID_%d", tf->TrackID); - opt = (char *)gf_cfg_get_key(dash_ctx, sKey, "NextDecodingTime"); - if (opt) tf->InitialTSOffset = atoi(opt); - } - - switch (mtype) { - case GF_ISOM_MEDIA_TEXT: - gf_isom_get_media_language(input, i+1, langCode); - case GF_ISOM_MEDIA_VISUAL: - if (!tfref && (count >=10)) { - tfref = tf; - } - case GF_ISOM_MEDIA_SCENE: - case GF_ISOM_MEDIA_DIMS: - gf_isom_get_track_layout_info(input, i+1, &_w, &_h, NULL, NULL, NULL); - if (_w>width) width = _w; - if (_h>height) height = _h; - break; - case GF_ISOM_MEDIA_AUDIO: - gf_isom_get_audio_info(input, i+1, 1, &_sr, &_nb_ch, NULL); - if (_sr>sample_rate) sample_rate=_sr; - if (_nb_ch>nb_channels) nb_channels = _nb_ch; - gf_isom_get_media_language(input, i+1, langCode); - break; - } - - if (file_duration < ((Double) gf_isom_get_media_duration(input, i+1)) / tf->TimeScale ) { - file_duration = ((Double) gf_isom_get_media_duration(input, i+1)) / tf->TimeScale; - } - gf_list_add(fragmenters, tf); - - nb_samp += count; - } - - if (!tfref) tfref = gf_list_get(fragmenters, 0); - tfref->is_ref_track = 1; - tfref_timescale = tfref->TimeScale; - ref_track_id = tfref->TrackID; - if (tfref->all_sample_raps) split_seg_at_rap = 1; - - //flush movie -#ifndef GPAC_DISABLE_ISOM_FRAGMENTS - e = gf_isom_finalize_for_fragment(output, dash_mode ? 1 : 0); - if (e) goto err_exit; -#endif - - start_range = 0; - file_size = gf_isom_get_file_size(output); - end_range = file_size - 1; - init_seg_size = file_size; - - if (dash_ctx) { - if (store_dash_params) { - char szVal[1024]; - sprintf(szVal, LLU, init_seg_size); - gf_cfg_set_key(dash_ctx, "DASH", "InitializationSegmentSize", szVal); - } else { - const char *opt = gf_cfg_get_key(dash_ctx, "DASH", "InitializationSegmentSize"); - if (opt) init_seg_size = atoi(opt); - } - } - -restart_fragmentation_pass: - - average_duration = 0; - nb_segments = 0; - - nb_tracks_done = 0; - ref_track_first_dts = (u64) -1; - nb_done = 0; - - maxFragDurationOverSegment=0; - if (dash_mode) switch_segment=1; - - if (!seg_rad_name) use_url_template = 0; - - cur_seg=1; - fragment_index=1; - period_duration = 0; - split_at_rap = 0; - has_rap = 0; - next_sample_rap = 0; - flush_all_samples = 0; - force_switch_segment = 0; - max_sap_type = 0; - ref_track_next_cts = 0; - - /*setup previous URL list*/ - if (dash_ctx) { - const char *opt; - count = gf_cfg_get_key_count(dash_ctx, "URLs"); - for (i=0; i\n", SegName); - if (dash_ctx) { - char szKey[100], szVal[4046]; - sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 ); - sprintf(szVal, "", SegName); - gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal); - } - } - } else { - e = gf_isom_start_segment(output, NULL); - } - } - - cur_seg++; - if (e) goto err_exit; - } - - maxFragDurationOverSegment=0; - - sample = NULL; - - if (simulation_pass) { - segments_info[nb_segments_info-1] ++; - e = GF_OK; - } else { - e = gf_isom_start_fragment(output, 1); - if (e) goto err_exit; - - - for (i=0; idone) continue; - gf_isom_set_traf_base_media_decode_time(output, tf->TrackID, tf->InitialTSOffset + tf->next_sample_dts); - } - - } - - //process track by track - for (i=0; idone) continue; - - //ok write samples - while (1) { - Bool stop_frag = 0; - - /*first sample*/ - if (!sample) { - sample = gf_isom_get_sample(input, tf->OriginalTrack, tf->SampleNum + 1, &descIndex); - if (!sample) { - e = gf_isom_last_error(input); - goto err_exit; - } - - /*also get SAP type - this is not needed if sample is not NULL as SAP tye was computed for "next sample" in previous loop*/ - if (sample->IsRAP) { - SAP_type = 1; - } else { - SAP_type = 0; - e = gf_isom_get_sample_rap_roll_info(input, tf->OriginalTrack, tf->SampleNum + 1, &is_rap, &has_roll, &roll_distance); - if (e==GF_OK) { - if (is_rap) SAP_type = 3; - else if (has_roll && (roll_distance>=0) ) SAP_type = 4; - } - } - } - gf_isom_get_sample_padding_bits(input, tf->OriginalTrack, tf->SampleNum+1, &NbBits); - - next = gf_isom_get_sample(input, tf->OriginalTrack, tf->SampleNum + 2, &j); - if (next) { - defaultDuration = (u32) (next->DTS - sample->DTS); - } else { - defaultDuration = tf->DefaultDuration; - } - - if (tf==tfref) { - if (segments_start_with_sap && first_sample_in_segment ) { - first_sample_in_segment = 0; - if (! SAP_type) segments_start_with_sap = 0; - } - if (ref_track_first_dts > sample->DTS) - ref_track_first_dts = sample->DTS; - - if (next) { - u64 next_cts = next->DTS + next->CTS_Offset; - if (ref_track_next_ctsOriginalTrack); - if (cts>ref_track_next_cts) ref_track_next_cts = cts; - else ref_track_next_cts += defaultDuration; - } - } - - if (SAP_type > max_sap_type) max_sap_type = SAP_type; - - if (simulation_pass) { - e = GF_OK; - } else { - /*override descIndex with final index used in file*/ - descIndex = tf->finalSampleDescriptionIndex; - e = gf_isom_fragment_add_sample(output, tf->TrackID, sample, descIndex, - defaultDuration, NbBits, 0); - if (e) - goto err_exit; - - /*copy subsample information*/ - e = gf_isom_fragment_copy_subsample(output, tf->TrackID, input, tf->OriginalTrack, tf->SampleNum + 1); - if (e) - goto err_exit; - - gf_set_progress("ISO File Fragmenting", nb_done, nb_samp); - nb_done++; - } - - tf->last_sample_cts = sample->DTS + sample->CTS_Offset; - tf->next_sample_dts = sample->DTS + defaultDuration; - - gf_isom_sample_del(&sample); - sample = next; - tf->FragmentLength += defaultDuration; - tf->SampleNum += 1; - - /*compute SAP type*/ - if (sample) { - if (sample->IsRAP) { - SAP_type = 1; - } else { - SAP_type = 0; - e = gf_isom_get_sample_rap_roll_info(input, tf->OriginalTrack, tf->SampleNum + 1, &is_rap, &has_roll, NULL); - if (e==GF_OK) { - if (is_rap) - SAP_type = 3; - else if (has_roll && (roll_distance>=0) ) - SAP_type = 4; - } - } - } - - if (next && SAP_type) { - if (tf==tfref) { - if (split_seg_at_rap) { - u64 next_sap_time; - /*duration of fragment if we add this rap*/ - u32 frag_dur = (tf->FragmentLength+defaultDuration)*1000/tf->TimeScale; - next_sample_rap = 1; - next_sap_time = get_next_sap_time(input, tf->OriginalTrack, tf->SampleCount, tf->SampleNum + 2); - /*if no more SAP after this one, do not switch segment*/ - if (next_sap_time) { - u32 scaler; - /*this is the fragment duration from last sample added to next SAP*/ - frag_dur += (u32) (next_sap_time - tf->next_sample_dts - defaultDuration)*1000/tf->TimeScale; - /*if media segment about to be produced is longer than max segment length, force segment split*/ - if (SegmentDuration + frag_dur > MaxSegmentDuration) { - split_at_rap = 1; - /*force new segment*/ - force_switch_segment = 1; - } - - /*if adding this SAP will result in stoping the fragment "soon" after it, stop now and start with SAP - if all samples are RAPs, just stop fragment if we exceed the requested duration by adding the next sample - otherwise, take 3 samples (should be refined of course)*/ - scaler = 3; - if (tf->all_sample_raps) scaler = 1; - if ( (tf->FragmentLength + scaler*defaultDuration)*1000 >= MaxFragmentDuration * tf->TimeScale) - stop_frag = 1; - } - if (split_at_rap && !tf->all_sample_raps) { - stop_frag = 1; - /*override fragment duration for the rest of this fragment*/ - MaxFragmentDuration = tf->FragmentLength*1000/tf->TimeScale; - } - } else if (!has_rap) { - if (tf->FragmentLength == defaultDuration) has_rap = 2; - else has_rap = 1; - } - } - } else { - next_sample_rap = 0; - } - - if (tf->SampleNum==tf->SampleCount) { - stop_frag = 1; - } else if (tf==tfref) { - /*fragmenting on "clock" track: no drift control*/ - if (tf->FragmentLength*1000 >= MaxFragmentDuration*tf->TimeScale) - stop_frag = 1; - } - /*do not abort fragment if ref track is done, put everything in the last fragment*/ - else if (!flush_all_samples) { - /*fragmenting on "non-clock" track: drift control*/ - if (tf->last_sample_cts * tfref_timescale >= last_ref_cts * tf->TimeScale) - stop_frag = 1; - } - - if (stop_frag) { - gf_isom_sample_del(&next); - sample = next = NULL; - if (maxFragDurationOverSegment<=tf->FragmentLength*1000/tf->TimeScale) { - maxFragDurationOverSegment = tf->FragmentLength*1000/tf->TimeScale; - } - tf->FragmentLength = 0; - - if (tf==tfref) last_ref_cts = tf->last_sample_cts; - - break; - } - } - - if (tf->SampleNum==tf->SampleCount) { - tf->done = 1; - nb_tracks_done++; - if (tf == tfref) { - tfref = NULL; - flush_all_samples = 1; - } - } - } - - if (dash_mode) { - - SegmentDuration += maxFragDurationOverSegment; - maxFragDurationOverSegment=0; - - /*next fragment will exceed segment length, abort fragment now (all samples RAPs)*/ - if (tfref && tfref->all_sample_raps && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) { - force_switch_segment = 1; - } - - if (force_switch_segment || ((SegmentDuration >= MaxSegmentDuration) && (!split_seg_at_rap || next_sample_rap))) { - average_duration += SegmentDuration; - nb_segments++; - if (max_segment_duration * 1000 <= SegmentDuration) { - max_segment_duration = SegmentDuration; - max_segment_duration /= 1000; - } - - -#if 0 - if (split_seg_at_rap) has_rap = 0; - fprintf(stdout, "Seg#%d: Duration %d%s - Track times (ms): ", nb_segments, SegmentDuration, (has_rap == 2) ? " - Starts with RAP" : ((has_rap == 1) ? " - Contains RAP" : "") ); - for (i=0; ilast_sample_cts*1000.0)/tf->TimeScale) ); - } - fprintf(stdout, "\n "); -#endif - force_switch_segment=0; - switch_segment=1; - SegmentDuration=0; - split_at_rap = 0; - has_rap = 0; - /*restore fragment duration*/ - MaxFragmentDuration = (u32) (max_duration_sec * 1000); - - if (!simulation_pass) { - u64 idx_start_range, idx_end_range; - - gf_isom_close_segment(output, subsegs_per_sidx, ref_track_id, ref_track_first_dts, ref_track_next_cts, daisy_chain_sidx, flush_all_samples ? 1 : 0, &idx_start_range, &idx_end_range); - ref_track_first_dts = (u64) -1; - - if (!seg_rad_name) { - file_size = gf_isom_get_file_size(output); - end_range = file_size - 1; - if (!single_segment_mode) { - fprintf(mpd_segs, " \n", start_range, end_range, idx_start_range, idx_end_range); - if (dash_ctx) { - char szKey[100], szVal[4046]; - sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 ); - sprintf(szVal, "", start_range, end_range, idx_start_range, idx_end_range); - gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal); - } - } - } else { - file_size += gf_isom_get_file_size(output); - } - } - } - /*next fragment will exceed segment length, abort fragment at next rap (possibly after MaxSegmentDuration)*/ - if (split_seg_at_rap && SegmentDuration && (SegmentDuration + MaxFragmentDuration >= MaxSegmentDuration)) { - split_at_rap = 1; - } - } - - if (nb_tracks_done==count) break; - } - - if (simulation_pass) { - /*OK, we have all segments and frags per segments*/ - gf_isom_allocate_sidx(output, subsegs_per_sidx, daisy_chain_sidx, nb_segments_info, segments_info, &index_start_range, &index_end_range ); - gf_free(segments_info); - segments_info = NULL; - simulation_pass = 0; - /*reset fragmenters*/ - for (i=0; idone = 0; - tf->last_sample_cts = 0; - tf->next_sample_dts = 0; - tf->FragmentLength = 0; - tf->SampleNum = 0; - if (tf->is_ref_track) tfref = tf; - } - goto restart_fragmentation_pass; - } - - if (dash_mode) { - char buffer[1000]; - - /*flush last segment*/ - if (!switch_segment) { - u64 idx_start_range, idx_end_range; - - if (max_segment_duration * 1000 <= SegmentDuration) { - max_segment_duration = SegmentDuration; - max_segment_duration /= 1000; - } - - gf_isom_close_segment(output, subsegs_per_sidx, ref_track_id, ref_track_first_dts, ref_track_next_cts, daisy_chain_sidx, 1, &idx_start_range, &idx_end_range); - nb_segments++; - - if (!seg_rad_name) { - file_size = gf_isom_get_file_size(output); - end_range = file_size - 1; - if (!single_segment_mode) { - fprintf(mpd_segs, " \n", start_range, end_range, idx_start_range, idx_end_range); - if (dash_ctx) { - char szKey[100], szVal[4046]; - sprintf(szKey, "UrlInfo%d", gf_cfg_get_key_count(dash_ctx, "URLs") + 1 ); - sprintf(szVal, "", start_range, end_range, idx_start_range, idx_end_range); - gf_cfg_set_key(dash_ctx, "URLs", szKey, szVal); - } - } - } else { - file_size += gf_isom_get_file_size(output); - } - } - - period_duration += file_duration; - //u32 h = (u32) (period_duration/3600); - //u32 m = (u32) (period_duration-h*60)/60; - bandwidth = (u32) (file_size * 8 / file_duration); - - fprintf(mpd, " \n"); - - if (dash_ctx) { - Double seg_dur; - opt = gf_cfg_get_key(dash_ctx, "DASH", "MaxSegmentDuration"); - if (opt) { - seg_dur = atof(opt); - if (seg_dur < max_segment_duration) { - sprintf(sOpt, "%f", max_segment_duration); - gf_cfg_set_key(dash_ctx, "DASH", "MaxSegmentDuration", sOpt); - seg_dur = max_segment_duration; - } else { - max_segment_duration = seg_dur; - } - } else { - sprintf(sOpt, "%f", max_segment_duration); - gf_cfg_set_key(dash_ctx, "DASH", "MaxSegmentDuration", sOpt); - } - } - - if (use_url_template) { - sprintf(SegName, "%s$Number$.%s", seg_rad_name, seg_ext); - fprintf(mpd, " \n"); - } else if (single_segment_mode) { - fprintf(mpd, " %s\n", gf_isom_get_filename(output) ); - fprintf(mpd, " \n", index_start_range, index_end_range); - } else { - if (!seg_rad_name) { - fprintf(mpd, " %s.mp4\n", output_file ); - } - fprintf(mpd, " \n", (u32) (max_segment_duration*1000)); - //if (!sample_descs) - { - fprintf(mpd, " \n"); - } - } - - - gf_f64_seek(mpd_segs, 0, SEEK_SET); - while (!feof(mpd_segs)) { - u32 r = fread(buffer, 1, 100, mpd_segs); - gf_fwrite(buffer, 1, r, mpd); - } - - if (!use_url_template && !single_segment_mode) { - fprintf(mpd, " \n"); - } - - fprintf(mpd, " \n"); - } - - /*store context*/ - if (dash_ctx) { - for (i=0; iTrackID); - sprintf(sOpt, LLU, tf->InitialTSOffset + tf->next_sample_dts); - gf_cfg_set_key(dash_ctx, sKey, "NextDecodingTime", sOpt); - } - sprintf(sOpt, "%d", cur_seg); - gf_cfg_set_key(dash_ctx, "DASH", "NextSegmentIndex", sOpt); - - fragment_index = gf_isom_get_next_moof_number(output); - sprintf(sOpt, "%d", fragment_index); - gf_cfg_set_key(dash_ctx, "DASH", "NextFragmentIndex", sOpt); - sprintf(sOpt, "%f", period_duration); - gf_cfg_set_key(dash_ctx, "DASH", "PeriodDuration", sOpt); - } - -err_exit: - if (fragmenters){ - while (gf_list_count(fragmenters)) { - tf = (TrackFragmenter *)gf_list_get(fragmenters, 0); - gf_free(tf); - gf_list_rem(fragmenters, 0); - } - gf_list_del(fragmenters); - } - if (e) gf_isom_delete(output); - else gf_isom_close(output); - gf_set_progress("ISO File Fragmenting", nb_samp, nb_samp); - if (SegName) gf_free(SegName); - if (mpd) fclose(mpd); - if (mpd_segs) fclose(mpd_segs); - if (dash_ctx) gf_cfg_del(dash_ctx); - return e; -} - -#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ - -GF_EXPORT -GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, GF_ISOFile *init_segment, Double period_duration) -{ - u32 h, m; - Double s; - FILE *mpd = fopen(mpd_name, "wt"); - if (!mpd) return GF_IO_ERR; - - h = (u32) (period_duration/3600); - m = (u32) (period_duration-h*60)/60; - s = period_duration - h*3600 - m*60; - - /*TODO what should we put for minBufferTime */ - fprintf(mpd, "\n", - single_segment ? "urn:mpeg:dash:profile:isoff-on-demand:2011" : "urn:mpeg:dash:profile:full:2011", - h, m, s); - fprintf(mpd, " \n"); - if (title) - fprintf(mpd, " Media Presentation Description for file %s generated with GPAC \n", title); - fprintf(mpd, " \n"); - fprintf(mpd, " \n", h, m, s); - fprintf(mpd, " \n"); - - if (init_segment) { - u32 i; - char langCode[4]; - langCode[3] = 0; - - for (i=0; i\n", trackID, langCode); - break; - case GF_ISOM_MEDIA_VISUAL: - fprintf(mpd, " \n", trackID); - break; - case GF_ISOM_MEDIA_SCENE: - case GF_ISOM_MEDIA_DIMS: - fprintf(mpd, " \n", trackID, langCode); - break; - case GF_ISOM_MEDIA_AUDIO: - fprintf(mpd, " \n", trackID, langCode); - break; - } - } - - if (use_url_template) { - fprintf(mpd, " \n", gf_isom_get_filename(init_segment) ); - } else if (0 && !single_segment) { - fprintf(mpd, " \n"); - fprintf(mpd, " \n", gf_isom_get_filename(init_segment) ); - fprintf(mpd, " \n"); - } - } - - fclose(mpd); - return GF_OK; -} - -GF_EXPORT -GF_Err gf_media_mpd_end(char *mpd_name) -{ - FILE *mpd = fopen(mpd_name, "a+t"); - if (!mpd_name) return GF_IO_ERR; - - fprintf(mpd, " \n"); - fprintf(mpd, " \n"); - fprintf(mpd, ""); - - fclose(mpd); - return GF_OK; -} - -GF_EXPORT -GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, Double import_fps) -{ - int readen=0; - GF_Err e; - u32 state, offset; - u32 cur_chap; - u64 ts; - u32 i, h, m, s, ms, fr, fps; - char line[1024]; - char szTitle[1024]; - FILE *f = gf_f64_open(chap_file, "rt"); - if (!f) return GF_URL_ERROR; - - readen = fread(line, 1, 4, f); - if (readen < 4){ - e = GF_URL_ERROR; - goto err_exit; - } - offset = 0; - if ((line[0]==(char)(0xFF)) && (line[1]==(char)(0xFE))) { - if (!line[2] && !line[3]){ - e = GF_NOT_SUPPORTED; - goto err_exit; - } - offset = 2; - } else if ((line[0]==(char)(0xFE)) && (line[1]==(char)(0xFF))) { - if (!line[2] && !line[3]){ - e = GF_NOT_SUPPORTED; - goto err_exit; - } - offset = 2; - } else if ((line[0]==(char)(0xEF)) && (line[1]==(char)(0xBB)) && (line[2]==(char)(0xBF))) { - /*we handle UTF8 as asci*/ - offset = 3; - } else { - offset = 0; - } - gf_f64_seek(f, offset, SEEK_SET); - - e = gf_isom_remove_chapter(file, 0, 0); - if (e) goto err_exit; - - /*try to figure out the frame rate*/ - for (i=0; iDTS; - if (!inc) inc=1; - ts = gf_isom_get_media_timescale(file, i+1); - import_fps = ts; - import_fps /= inc; - gf_isom_sample_del(&samp); - GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[Chapter import] Guessed video frame rate %g (%u:%u)\n", import_fps, ts, inc)); - break; - } - - - cur_chap = 0; - ts = 0; - state = 0; - while (fgets(line, 1024, f) != NULL) { - char *title = NULL; - u32 off = 0; - char *sL; - while (1) { - u32 len = strlen(line); - if (!len) break; - switch (line[len-1]) { - case '\n': case '\t': case '\r': case ' ': - line[len-1] = 0; - continue; - } - break; - } - - while (line[off]==' ') off++; - if (!strlen(line+off)) continue; - sL = line+off; - - szTitle[0] = 0; - /*ZoomPlayer chapters*/ - if (!strnicmp(sL, "AddChapter(", 11)) { - u32 nb_fr; - sscanf(sL, "AddChapter(%u,%s)", &nb_fr, szTitle); - ts = nb_fr; - ts *= 1000; - if (import_fps) ts = (u64) (((s64) ts ) / import_fps); - else ts /= 25; - sL = strchr(sL, ','); strcpy(szTitle, sL+1); sL = strrchr(szTitle, ')'); if (sL) sL[0] = 0; - } else if (!strnicmp(sL, "AddChapterBySecond(", 19)) { - u32 nb_s; - sscanf(sL, "AddChapterBySecond(%u,%s)", &nb_s, szTitle); - ts = nb_s; - ts *= 1000; - sL = strchr(sL, ','); strcpy(szTitle, sL+1); sL = strrchr(szTitle, ')'); if (sL) sL[0] = 0; - } else if (!strnicmp(sL, "AddChapterByTime(", 17)) { - u32 h, m, s; - sscanf(sL, "AddChapterByTime(%u,%u,%u,%s)", &h, &m, &s, szTitle); - ts = 3600*h + 60*m + s; - ts *= 1000; - sL = strchr(sL, ','); - if (sL) sL = strchr(sL+1, ','); - if (sL) sL = strchr(sL+1, ','); - strcpy(szTitle, sL+1); sL = strrchr(szTitle, ')'); if (sL) sL[0] = 0; - } - /*regular or SMPTE time codes*/ - else if ((strlen(sL)>=8) && (sL[2]==':') && (sL[5]==':')) { - title = NULL; - if (strlen(sL)==8) { - sscanf(sL, "%02u:%02u:%02u", &h, &m, &s); - ts = (h*3600 + m*60+s)*1000; - } - else { - char szTS[20], *tok; - strncpy(szTS, sL, 18); - tok = strrchr(szTS, ' '); - if (tok) { - title = strchr(sL, ' ') + 1; - while (title[0]==' ') title++; - if (strlen(title)) strcpy(szTitle, title); - tok[0] = 0; - } - ts = 0; - h = m = s = ms = 0; - - if (sscanf(szTS, "%u:%u:%u;%u/%u", &h, &m, &s, &fr, &fps)==5) { - ts = (h*3600 + m*60+s)*1000 + 1000*fr/fps; - } else if (sscanf(szTS, "%u:%u:%u;%u", &h, &m, &s, &fr)==4) { - ts = (h*3600 + m*60+s); - if (import_fps) - ts = (s64) (((import_fps*((s64)ts) + fr) * 1000 ) / import_fps); - else - ts = ((ts*25 + fr) * 1000 ) / 25; - } else if (sscanf(szTS, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(szTS, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(szTS, "%u:%u:%u:%u", &h, &m, &s, &ms) == 4) { - ts = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(szTS, "%u:%u:%u", &h, &m, &s) == 3) { - ts = (h*3600 + m*60+s) * 1000; - } - } - } - /*CHAPTERX= and CHAPTERXNAME=*/ - else if (!strnicmp(sL, "CHAPTER", 7)) { - u32 idx; - char szTemp[20], *str; - strncpy(szTemp, sL, 19); - str = strrchr(szTemp, '='); - if (!str) continue; - str[0] = 0; - strlwr(szTemp); - idx = cur_chap; - str = strchr(sL, '='); - str++; - if (strstr(szTemp, "name")) { - sscanf(szTemp, "chapter%uname", &idx); - strcpy(szTitle, str); - if (idx!=cur_chap) { - cur_chap=idx; - state = 0; - } - state++; - } else { - sscanf(szTemp, "chapter%u", &idx); - if (idx!=cur_chap) { - cur_chap=idx; - state = 0; - } - state++; - - ts = 0; - h = m = s = ms = 0; - if (sscanf(str, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { - ts = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(str, "%u:%u:%u:%u", &h, &m, &s, &ms) == 4) { - ts = (h*3600 + m*60+s)*1000+ms; - } else if (sscanf(str, "%u:%u:%u", &h, &m, &s) == 3) { - ts = (h*3600 + m*60+s) * 1000; - } - } - if (state==2) { - e = gf_isom_add_chapter(file, 0, ts, szTitle); - if (e) goto err_exit; - state = 0; - } - continue; - } - else continue; - - if (strlen(szTitle)) { - e = gf_isom_add_chapter(file, 0, ts, szTitle); - } else { - e = gf_isom_add_chapter(file, 0, ts, NULL); - } - if (e) goto err_exit; - } - - -err_exit: - fclose(f); - return e; -} #endif /*GPAC_DISABLE_ISOM_WRITE*/ @@ -1988,14 +805,16 @@ GF_ESD *gf_media_map_esd(GF_ISOFile *mp4, u32 track) } if (subtype == GF_ISOM_SUBTYPE_AC3) { + GF_AC3Config *ac3 = gf_isom_ac3_config_get(mp4, track, 1); esd = gf_odf_desc_esd_new(0); esd->slConfig->timestampResolution = gf_isom_get_media_timescale(mp4, track); esd->ESID = gf_isom_get_track_id(mp4, track); esd->OCRESID = esd->ESID; esd->decoderConfig->streamType = GF_STREAM_AUDIO; - esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AC3; + esd->decoderConfig->objectTypeIndication = (ac3 && ac3->is_ec3) ? GPAC_OTI_AUDIO_AC3_ENHANCED : GPAC_OTI_AUDIO_AC3; gf_odf_desc_del((GF_Descriptor*)esd->decoderConfig->decoderSpecificInfo); esd->decoderConfig->decoderSpecificInfo = NULL; + if (ac3) gf_free(ac3); return esd; } @@ -2060,3 +879,726 @@ GF_ESD *gf_media_map_esd(GF_ISOFile *mp4, u32 track) #endif /*GPAC_DISABLE_ISOM*/ +#ifndef GPAC_DISABLE_MEDIA_IMPORT +static s32 gf_get_DQId(GF_ISOFile *file, u32 track) +{ + GF_AVCConfig *svccfg; + GF_ISOSample *samp; + u32 di = 0; + char *buffer; + GF_BitStream *bs; + u32 max_size = 4096; + u32 size, nalu_size_length; + u8 nal_type; + + svccfg = gf_isom_svc_config_get(file, track, 1); + if (!svccfg) + return 0; + samp = gf_isom_get_sample(file, track, 1, &di); + if (!samp) + return -1; + 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)) + { + size = gf_bs_read_int(bs, nalu_size_length); + if (size>max_size) { + buffer = (char*)gf_realloc(buffer, sizeof(char)*size); + max_size = size; + } + gf_bs_read_data(bs, buffer, size); + nal_type = buffer[0] & 0x1F; + if (nal_type == GF_AVC_NALU_SVC_SLICE) + return buffer[2] & 0x7F; + } + return -1; +} +static u32 gf_isom_get_track_id_max(GF_ISOFile *file) +{ + u32 num_track, i, trackID; + u32 max_id = 0; + + num_track = gf_isom_get_track_count(file); + for (i = 1; i <= num_track; i++) + { + trackID = gf_isom_get_track_id(file, i); + if (max_id < trackID) + max_id = trackID; + } + + return max_id; +} + +/* Split SVC layers */ +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_Err e; + GF_AVCConfigSlot *slc; + AVCState avc; + s32 sps_id, pps_id; + GF_ISOSample *samp; + GF_BitStream *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; + s32 *sps_track, *sps, *pps; + u32 num_pps, num_sps; + u64 offset; + Bool is_splited; + Bool *first_sample_track; + 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); + 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); + + num_sps = gf_list_count(svccfg->sequenceParameterSets); + num_pps = gf_list_count(svccfg->pictureParameterSets); + /*we have a splited file with 1 SVC / track*/ + if (is_splited && num_pps == 1) + { + /*use 'all' mode -> stop*/ + if (splitAll) + return GF_OK; + /*use 'base' mode -> merge SVC tracks*/ + else + return gf_media_merge_svc(file, track, 0); + } + num_svc_track = splitAll ? num_sps : 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)); + 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); + if (sps_id < 0) { + return GF_NON_COMPLIANT_BITSTREAM; + } + sps[i] = sps_id; + sps_track[i] = i; + } + /*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); + if (pps_id < 0) { + return GF_NON_COMPLIANT_BITSTREAM; + } + pps[j] = pps_id; + } + if (!is_splited) + 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); + } + /*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; + 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); + if (size>max_size) { + buffer = (char*)gf_realloc(buffer, sizeof(char)*size); + max_size = size; + } + 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_bs_read_data(bs, buffer, size); + offset += size + nalu_size_length/8; + if (nal_type == GF_AVC_NALU_SVC_SLICE) + { + /*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++) + { + /*swap two SPS*/ + if (avc.s_info.pps->sps_id == sps[i]) + { + sps[i] = sps[count]; + sps[count] = avc.s_info.pps->sps_id; + sps_track[count] = i; + 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_free(buffer); + buffer = 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; + } + 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 + e = gf_isom_svc_config_new(file, svc_track, cfg, NULL, NULL, &di); + if (e) + return e; + if (splitAll) + { + sps_id = sps[t]; + width = avc.sps[sps_id].width; + height = avc.sps[sps_id].height; + gf_isom_set_visual_info(file, svc_track, di, width, height); + cfg->configurationVersion = 1; + cfg->chroma_bit_depth = 8 + avc.sps[sps_id].chroma_bit_depth_m8; + cfg->chroma_format = avc.sps[sps_id].chroma_format; + cfg->luma_bit_depth = 8 + avc.sps[sps_id].luma_bit_depth_m8; + cfg->profile_compatibility = avc.sps[sps_id].prof_compat; + 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])); + for (j = 0; j < num_pps; j++) + { + pps_id = pps[j]; + if (avc.pps[pps_id].sps_id == sps_id) + { + gf_list_add(cfg->pictureParameterSets, gf_list_get(svccfg->pictureParameterSets, j)); + } + } + } + else + { + for (i = 0; i < num_sps; i++) + { + sps_id = sps[i]; + width = avc.sps[sps_id].width; + height = avc.sps[sps_id].height; + gf_isom_set_visual_info(file, svc_track, di, width, height); + cfg->configurationVersion = 1; + cfg->chroma_bit_depth = 8 + avc.sps[sps_id].chroma_bit_depth_m8; + cfg->chroma_format = avc.sps[sps_id].chroma_format; + cfg->luma_bit_depth = 8 + avc.sps[sps_id].luma_bit_depth_m8; + cfg->profile_compatibility = avc.sps[sps_id].prof_compat; + 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])); + 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; + } + if (avc.pps[pps_id].sps_id == sps_id) + { + gf_list_add(cfg->pictureParameterSets, gf_list_get(svccfg->pictureParameterSets, j)); + } + } + } + } + gf_isom_svc_config_update(file, svc_track, 1, cfg, 0); + } + + num_sample = gf_isom_get_sample_count(file, track); + first_sample_track = (Bool *) gf_malloc((num_svc_track+1) * sizeof(Bool)); + for (t = 0; t <= num_svc_track; t++) + first_sample_track[t] = 1; + 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; + + + samp = gf_isom_get_sample(file, track, i, &di); + if (!samp) + return GF_IO_ERR; + + /* 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); + + 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); + if (size>max_size) { + buffer = (char*)gf_realloc(buffer, sizeof(char)*size); + max_size = size; + } + 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_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: + dst_track = 0; + if (splitAll) + { + for (t = 0; t < num_svc_track; t++) // num_svc_track == num_pps + { + if (sps_track[t] == (avc.s_info.pps)->sps_id) + { + dst_track = t + 1; + break; + } + } + } + else + dst_track = 1; + dst_bs = sample_bs[dst_track]; + /*write extractor*/ + if (!gf_bs_get_position(dst_bs)) + { + //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++) + { + 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); + } + } + prev_layer[count_prev_layer] = dst_track; + count_prev_layer++; + break; + default: + dst_bs = sample_bs[0]; + } + + gf_bs_write_int(dst_bs, size, nalu_size_length); + gf_bs_write_data(dst_bs, buffer, size); + } + + for (j = 0; j <= num_svc_track; j++) + { + if (gf_bs_get_position(sample_bs[j])) + { + if (first_sample_track[j]) + { + first_sample_track[j] = 0; + first_DTS_track[j] = samp->DTS; + } + dst_samp = gf_isom_sample_new(); + dst_samp->CTS_Offset = samp->CTS_Offset; + dst_samp->DTS = samp->DTS - first_DTS_track[j]; + dst_samp->IsRAP = samp->IsRAP; + gf_bs_get_content(sample_bs[j], &dst_samp->data, &dst_samp->dataLength); + if (j) //SVC + e = gf_isom_add_sample(file, track+j, di, dst_samp); + else + e = gf_isom_update_sample(file, track, i, dst_samp, 1); + if (e) + return e; + gf_isom_sample_del(&dst_samp); + dst_samp = NULL; + } + gf_bs_del(sample_bs[j]); + sample_bs[j] = NULL; + } + gf_free(sample_bs); + gf_free(bs); + } + + /*add Editlist entry if DTS of the first sample is not zero*/ + for (t = 0; t <= num_svc_track; t++) + { + if (first_DTS_track[t]) + { + u32 media_ts, moov_ts, offset; + u64 dur; + media_ts = gf_isom_get_media_timescale(file, t); + moov_ts = gf_isom_get_timescale(file); + offset = (u32)(first_DTS_track[t]) * moov_ts / media_ts; + dur = gf_isom_get_media_duration(file, t) * moov_ts / media_ts; + gf_isom_set_edit_segment(file, t, 0, offset, 0, GF_ISOM_EDIT_EMPTY); + gf_isom_set_edit_segment(file, t, offset, dur, 0, GF_ISOM_EDIT_NORMAL); + } + } + + /*if this is a merged file: delete SVC config*/ + if (!is_splited) + gf_isom_svc_config_del(file, track, 1); + /*if this is as splited file: delete this track*/ + else + { + gf_isom_remove_track(file, track); + } + return GF_OK; +} + +/* 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_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; + u64 *DTS_offset; + u32 nb_EditList; + u32 media_ts, moov_ts; + u64 EditTime, SegmentDuration, MediaTime; + u8 EditMode; + 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); + + 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); + } + + list_track_sorted = (u32 *) gf_malloc(num_track * sizeof(u32)); + DQId = (s32 *) gf_malloc(num_track * sizeof(s32)); + count = 0; + for (t = 1; t <= num_track; t++) { + u32 pos = 0; + s32 track_DQId = gf_get_DQId(file, t); + if (track_DQId < 0) { + e = GF_ISOM_INVALID_MEDIA; + goto exit; + } + if ((t != track) && !gf_isom_has_track_reference(file, t, GF_ISOM_REF_BASE, ref_trackID)) + continue; + while ((pos < count ) && (DQId[pos] <= track_DQId)) + pos++; + for (i = count; i > pos; i--) + { + list_track_sorted[i] = list_track_sorted[i-1]; + DQId[i] = DQId[i-1]; + } + list_track_sorted[pos] = t; + DQId[pos] = track_DQId; + count++; + } + + if (mergeAll) + { + gf_isom_get_visual_info(file, list_track_sorted[0], 1, &width, &height); + } + else + { + 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); + + for (t = 0; t < count; t++) + { + cfg = gf_isom_svc_config_get(file, list_track_sorted[t], 1); + if (!cfg) + continue; + svccfg->configurationVersion = 1; + svccfg->chroma_bit_depth = cfg->chroma_bit_depth; + svccfg->chroma_format = cfg->chroma_format; + svccfg->luma_bit_depth = cfg->luma_bit_depth; + svccfg->profile_compatibility = cfg->profile_compatibility; + svccfg->AVCLevelIndication = cfg->AVCLevelIndication; + svccfg->AVCProfileIndication = cfg->AVCProfileIndication; + 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)); + } + for (i = 0; i < gf_list_count(cfg->pictureParameterSets); i++) + { + gf_list_add(svccfg->pictureParameterSets, gf_list_get(cfg->pictureParameterSets, i)); + } + 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); + } + + cur_sample = (u32 *) gf_malloc(count * sizeof(u32)); + max_sample = (u32 *) gf_malloc(count * sizeof(u32)); + for (t = 0; t < count; t++) + { + cur_sample[t] = 1; + max_sample[t] = gf_isom_get_sample_count(file, list_track_sorted[t]); + } + + DTS_offset = (u64 *) gf_malloc(count * sizeof(u64)); + for (t = 0; t < count; t++) + { + nb_EditList = gf_isom_get_edit_segment_count(file, list_track_sorted[t]); + if (!nb_EditList) + DTS_offset[t] = 0; + else + { + media_ts = gf_isom_get_media_timescale(file, list_track_sorted[t]); + moov_ts = gf_isom_get_timescale(file); + for (i = 1; i <= nb_EditList; i++) + { + e = gf_isom_get_edit_segment(file, list_track_sorted[t], i, &EditTime, &SegmentDuration, &MediaTime, &EditMode); + if (e) goto exit; + + if (!EditMode) + { + DTS_offset[t] = SegmentDuration * media_ts / moov_ts; + } + } + } + } + + num_sample = gf_isom_get_sample_count(file, ref_trackNum); + nalu_size_length = 8 * svccfg->nal_unit_size; + first_sample = 1; + first_DTS = 0; + for (i = 1; i <= num_sample; i++) + { + dst_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); + /*add extractor if nessassary*/ + if (!mergeAll) + { + u32 NALUnitHeader = 0; + u8 track_ref_index; + s8 sample_offset; + u32 data_offset; + u32 data_length; + + 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; + 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); + } + buffer = (char*)gf_malloc(sizeof(char) * max_size); + + avc_samp = gf_isom_get_sample(file, ref_trackNum, i, &di); + if (!avc_samp) { + e = gf_isom_last_error(file); + goto exit; + } + + for (t = 0; t < count; t++) + { + if (cur_sample[t] > max_sample[t]) + continue; + samp = gf_isom_get_sample(file, list_track_sorted[t], cur_sample[t], &di); + if (!samp) { + e = gf_isom_last_error(file); + goto exit; + } + + if ((samp->DTS + DTS_offset[t]) != avc_samp->DTS) + continue; + bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ); + while (gf_bs_available(bs)) + { + size = gf_bs_read_int(bs, nalu_size_length); + if (size>max_size) { + buffer = (char*)gf_realloc(buffer, sizeof(char)*size); + max_size = size; + } + gf_bs_read_data(bs, buffer, size); + nal_type = buffer[0] & 0x1F; + /*skip extractor*/ + if (nal_type == 31) + continue; + /*copy to new bitstream*/ + gf_bs_write_int(dst_bs, size, nalu_size_length); + gf_bs_write_data(dst_bs, buffer, size); + } + gf_bs_del(bs); + bs = NULL; + gf_isom_sample_del(&samp); + samp = NULL; + cur_sample[t]++; + } + + /*add sapmle to track*/ + if (gf_bs_get_position(dst_bs)) + { + if (first_sample) + { + first_DTS = avc_samp->DTS; + first_sample = 0; + } + dst_samp = gf_isom_sample_new(); + dst_samp->CTS_Offset = avc_samp->CTS_Offset; + 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); + if (e) + goto exit; + } + gf_isom_sample_del(&avc_samp); + avc_samp = NULL; + } + + /*Add EditList if nessessary*/ + if (!first_DTS) + { + media_ts = gf_isom_get_media_timescale(file, merge_track); + moov_ts = gf_isom_get_timescale(file); + offset = (u32)(first_DTS) * moov_ts / media_ts; + dur = gf_isom_get_media_duration(file, merge_track) * moov_ts / media_ts; + gf_isom_set_edit_segment(file, merge_track, 0, offset, 0, GF_ISOM_EDIT_EMPTY); + gf_isom_set_edit_segment(file, merge_track, offset, dur, 0, GF_ISOM_EDIT_NORMAL); + } + + /*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--; + } + +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 (svccfg) gf_odf_avc_cfg_del(svccfg); + return e; +} + +#endif /*GPAC_DISABLE_MEDIA_IMPORT*/ + diff --git a/src/media_tools/m2ts_mux.c b/src/media_tools/m2ts_mux.c index ac98067..ed1f578 100644 --- a/src/media_tools/m2ts_mux.c +++ b/src/media_tools/m2ts_mux.c @@ -1,8 +1,9 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c)2008-200X Telecom ParisTech - All rights reserved - * Authors: Jean Le Feuvre + * Authors: Jean Le Feuvre , Cyril Concolato, Romain Bouqueau + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved * * This file is part of GPAC / MPEG2-TS sub-project * @@ -26,7 +27,7 @@ #include #include -#if !defined(GPAC_DISABLE_MPEG2TS_MUX) && !defined(GPAC_DISABLE_MPEG2TS) +#if !defined(GPAC_DISABLE_MPEG2TS_MUX) /*num ms between PCR*/ #define PCR_UPDATE_MS 200 @@ -400,7 +401,7 @@ void gf_m2ts_mux_table_update_mpeg4(GF_M2TS_Mux_Stream *stream, u8 table_id, u16 /*MPEG-4 tables are input streams for the mux, the bitrate is updated when fetching AUs*/ } -static u32 gf_m2ts_add_adaptation(GF_BitStream *bs, u16 pid, +static u32 gf_m2ts_add_adaptation(GF_M2TS_Mux_Program *prog, GF_BitStream *bs, u16 pid, Bool has_pcr, u64 pcr_time, Bool is_rap, u32 padding_length) @@ -425,10 +426,13 @@ static u32 gf_m2ts_add_adaptation(GF_BitStream *bs, u16 pid, gf_bs_write_int(bs, 0, 6); // reserved PCR_ext = pcr_time - PCR_base*300; gf_bs_write_long_int(bs, PCR_ext, 9); - + if (prog->last_pcr > pcr_time) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Sending PCR "LLD" earlier than previous PCR "LLD" - drift %f sec\n", pid, pcr_time, prog->last_pcr, (prog->last_pcr - pcr_time) /27000000.0 )); + } + prog->last_pcr = pcr_time; #ifndef GPAC_DISABLE_LOG - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding adaptation field size %d - RAP %d - Padding %d - PCR %d\n", pid, adaptation_length, is_rap, padding_length, pcr_time)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding adaptation field size %d - RAP %d - Padding %d - PCR "LLD"\n", pid, adaptation_length, is_rap, padding_length, pcr_time)); } else { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding adaptation field size %d - RAP %d - Padding %d\n", pid, adaptation_length, is_rap, padding_length)); #endif @@ -495,7 +499,7 @@ void gf_m2ts_mux_table_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet) else stream->continuity_counter=0; if (adaptation_field_control != GF_M2TS_ADAPTATION_NONE) - gf_m2ts_add_adaptation(bs, stream->pid, 0, 0, 0, padding_length); + gf_m2ts_add_adaptation(stream->program, bs, stream->pid, 0, 0, 0, padding_length); /*pointer field*/ if (!stream->current_section_offset) { @@ -702,6 +706,10 @@ static void gf_m2ts_remap_timestamps_for_pes(GF_M2TS_Mux_Stream *stream, u32 pck GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: DTS "LLD" is less than initial DTS "LLD" - adjusting\n", stream->pid, *dts, stream->program->initial_ts)); stream->program->initial_ts = *dts; } + else if (*dts < stream->last_dts) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: DTS "LLD" is less than last sent DTS "LLD"\n", stream->pid, *dts, stream->last_dts)); + stream->last_dts = *dts; + } /*offset our timestamps*/ *cts += stream->program->pcr_offset; @@ -786,7 +794,6 @@ u32 gf_m2ts_stream_process_stream(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream if (!(stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS)) stream->curr_pck.dts = stream->curr_pck.cts; - /*initializing the PCR*/ if (!stream->program->pcr_init_time) { if (stream==stream->program->pcr) { @@ -933,6 +940,8 @@ u32 gf_m2ts_stream_process_stream(GF_M2TS_Mux *muxer, GF_M2TS_Mux_Stream *stream GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_m4a_get_config(stream->ifce->decoder_config, stream->ifce->decoder_config_size, &cfg); + if (cfg.base_object_type>=5) cfg.base_object_type = GF_M4A_AAC_LC; + gf_bs_write_int(bs, 0xFFF, 12);/*sync*/ gf_bs_write_int(bs, 0, 1);/*mpeg2 aac*/ gf_bs_write_int(bs, 0, 2); /*layer*/ @@ -1171,7 +1180,7 @@ Bool gf_m2ts_stream_compute_pes_length(GF_M2TS_Mux_Stream *stream, u32 payload_l return 1; } - +u64 last_dts=0; static u32 gf_m2ts_stream_get_pes_header_length(GF_M2TS_Mux_Stream *stream) { u32 hdr_len, flags; @@ -1229,7 +1238,7 @@ u32 gf_m2ts_stream_add_pes_header(GF_BitStream *bs, GF_M2TS_Mux_Stream *stream, gf_bs_write_int(bs, 0x2, 2); // reserved gf_bs_write_int(bs, 0x0, 2); // scrambling gf_bs_write_int(bs, 0x0, 1); // priority - gf_bs_write_int(bs, 0x1, 1); // alignment indicator + gf_bs_write_int(bs, stream->pck_offset ? 0 : 1, 1); // alignment indicator - we could also check start codes to see if we are aligned at slice/video packet level gf_bs_write_int(bs, 0x0, 1); // copyright gf_bs_write_int(bs, 0x0, 1); // original or copy @@ -1264,7 +1273,6 @@ u32 gf_m2ts_stream_add_pes_header(GF_BitStream *bs, GF_M2TS_Mux_Stream *stream, gf_bs_write_long_int(bs, t, 15); gf_bs_write_int(bs, 1, 1); // marker bit } - GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS Muxer] PID %d: Adding PES header at PCR "LLD" - has PTS %d (%d) - has DTS %d (%d)\n", stream->pid, gf_m2ts_get_pcr(stream->program)/300, use_pts, cts, use_dts, dts)); return pes_len+4; // 4 = start code + stream_id @@ -1376,24 +1384,24 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet) u64 pcr = 0; if (needs_pcr) { u32 now = gf_sys_clock(); - /*compute PCR*/ - if (stream->program->mux->real_time) { + /*compute PCR - we disabled real-time clock for now and only insert PCR based on DTS / CTS*/ + if (0 && stream->program->mux->real_time) { pcr = gf_m2ts_get_pcr(stream->program); } else { - pcr = (stream->curr_pck.dts - stream->program->pcr_offset) * 300; + pcr = ( ((stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS) ? stream->curr_pck.dts : stream->curr_pck.cts) - stream->program->pcr_offset) * 300; if (pcr>stream->program->pcr_init_time) pcr -= stream->program->pcr_init_time; else pcr = 0; } - //fprintf(stdout, "PCR Diff in ms %d - sys clock diff in ms %d - DTS diff %d\n", (u32) (pcr - stream->program->last_pcr) / 27000, now - stream->program->last_sys_clock, (stream->curr_pck.dts - stream->program->last_dts)/90); + //fprintf(stderr, "PCR Diff in ms %d - sys clock diff in ms %d - DTS diff %d\n", (u32) (pcr - stream->program->last_pcr) / 27000, now - stream->program->last_sys_clock, (stream->curr_pck.dts - stream->program->last_dts)/90); stream->program->last_sys_clock = now; - stream->program->last_dts = stream->curr_pck.dts; - stream->program->last_pcr = pcr; + /*if stream does not use DTS, use CTS as base time for PCR*/ + stream->program->last_dts = (stream->curr_pck.flags & GF_ESI_DATA_HAS_DTS) ? stream->curr_pck.dts : stream->curr_pck.cts; stream->pcr_priority = 0; } is_rap = (hdr_len && (stream->curr_pck.flags & GF_ESI_DATA_AU_RAP) ) ? 1 : 0; - gf_m2ts_add_adaptation(bs, stream->pid, needs_pcr, pcr, is_rap, padding_length); + gf_m2ts_add_adaptation(stream->program, bs, stream->pid, needs_pcr, pcr, is_rap, padding_length); if (padding_length) stream->program->mux->tot_pes_pad_bytes += padding_length; @@ -1445,7 +1453,7 @@ void gf_m2ts_mux_pes_get_next_packet(GF_M2TS_Mux_Stream *stream, u8 *packet) pos += payload_to_copy; copy_next = payload_length - payload_to_copy; /*we might need a more than one*/ - while (1) { + while (stream->pes_data_remain) { u32 remain = 0; Bool res = stream->process(stream->program->mux, stream); if (!res) { @@ -1645,6 +1653,9 @@ GF_M2TS_Mux_Stream *gf_m2ts_program_stream_add(GF_M2TS_Mux_Program *program, str stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG2; break; case GPAC_OTI_AUDIO_AAC_MPEG4: + case GPAC_OTI_AUDIO_AAC_MPEG2_MP: + case GPAC_OTI_AUDIO_AAC_MPEG2_LCP: + case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP: stream->mpeg2_stream_type = GF_M2TS_AUDIO_LATM_AAC; stream->mpeg2_stream_type = GF_M2TS_AUDIO_AAC; if (!ifce->repeat_rate) ifce->repeat_rate = 500; @@ -2070,7 +2081,7 @@ send_pck: drift += (muxer->time.sec - time.sec)*1000; assert(muxer->time.sec > time.sec); } -// fprintf(stdout, "\nMux time - Packet PID %d time: %d ms\n", stream_to_process->pid, drift); +// fprintf(stderr, "\nMux time - Packet PID %d time: %d ms\n", stream_to_process->pid, drift); } GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Send %s from PID %d at %d:%09d - mux time %d:%09d\n", stream_to_process->tables ? "table" : "PES", stream_to_process->pid, time.sec, time.nanosec, muxer->time.sec, muxer->time.nanosec)); #endif diff --git a/src/media_tools/m3u8.c b/src/media_tools/m3u8.c index 00b3cd0..b8777bc 100644 --- a/src/media_tools/m3u8.c +++ b/src/media_tools/m3u8.c @@ -1,7 +1,7 @@ /** * GPAC - Multimedia Framework C SDK * -* Authors: Pierre Souchay, Jean Le Feuvre +* Authors: Pierre Souchay, Jean Le Feuvre * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * @@ -30,8 +30,7 @@ #include #include -/*#define MYLOG(xx) GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, xx )*/ -//#define MYLOG(xx) printf xx +/*#define MYLOG(xx) GF_LOG(GF_LOG_INFO, GF_LOG_DASH, xx )*/ #define MYLOG(xx) @@ -233,19 +232,19 @@ GF_Err playlist_element_dump(const PlaylistElement * e, int indent) { int i; GF_Err r = GF_OK; for (i = 0 ; i < indent; i++) - printf(" "); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, (" ") ); if (e == NULL) { - printf("NULL PlaylistElement\n"); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8] NULL PlaylistElement\n")); return r; } - printf("PlayListElement[%p, title=%s, codecs=%s, duration=%d, bandwidth=%d, url=%s, type=%s]\n", + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8] PlayListElement[%p, title=%s, codecs=%s, duration=%d, bandwidth=%d, url=%s, type=%s]\n", (void*)e, e->title, e->codecs, e->durationInfo, e->bandwidth, e->url, - e->elementType == TYPE_STREAM ? "stream" : "playlist"); + e->elementType == TYPE_STREAM ? "stream" : "playlist")); if (TYPE_PLAYLIST == e->elementType) { int sz; assert( e->element.playlist.elements); @@ -264,17 +263,17 @@ GF_Err variant_playlist_dump(const VariantPlaylist * pl) { int i, count; GF_Err e = GF_OK; if (pl == NULL) { - printf("VariantPlaylist = NULL\n"); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8] VariantPlaylist = NULL\n")); return e; } - printf("VariantPlaylist = {\n"); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8] VariantPlaylist = {\n")); assert( pl->programs); count = gf_list_count( pl->programs); for (i = 0 ; i < count ; i++) { int j, countj; Program * p = gf_list_get(pl->programs, i); assert( p ); - printf(" program[programId=%d]{\n", p->programId); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8] program[programId=%d]{\n", p->programId)); assert( p->bitrates ); countj = gf_list_count(p->bitrates); for (j = 0; j < countj; j++) { @@ -282,9 +281,9 @@ GF_Err variant_playlist_dump(const VariantPlaylist * pl) { assert(el); e |= playlist_element_dump( el, 4); } - printf(" }\n"); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8] }\n")); } - printf("}\n"); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[M3U8]}\n")); return e; } @@ -316,6 +315,7 @@ typedef struct _s_accumulated_attributes { char * title; int durationInSeconds; int bandwidth; + int width, height; int programId; char * codecs; int targetDurationInSeconds; @@ -433,7 +433,7 @@ static char ** parseAttributes(const char * line, s_accumulated_attributes * att /* Not Supported for now */ return ret; } - ret = extractAttributes("#EXT-X-STREAM-INF:", line, 3); + ret = extractAttributes("#EXT-X-STREAM-INF:", line, 10); if (ret) { /* #EXT-X-STREAM-INF:[attribute=value][,attribute=value]* */ i = 0; @@ -454,6 +454,13 @@ static char ** parseAttributes(const char * line, s_accumulated_attributes * att if (ret[i][intValue-1] == '"') { attributes->codecs = gf_strdup(&(ret[i][7])); } + } else if (safe_start_equals("RESOLUTION=", ret[i])) { + u32 w, h; + utility = &(ret[i][11]); + if ((sscanf(utility, "%dx%d", &w, &h)==2) || (sscanf(utility, "%dx%d,", &w, &h)==2)) { + attributes->width = w; + attributes->height = h; + } } i++; } @@ -469,7 +476,7 @@ static char ** parseAttributes(const char * line, s_accumulated_attributes * att attributes->byteRangeStart = begin; attributes->byteRangeEnd = begin + size - 1; } else { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER,("[M3U8] Invalid byte range %s\n", ret[0])); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH,("[M3U8] Invalid byte range %s\n", ret[0])); } } } @@ -495,7 +502,7 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const s_accumulated_attributes attribs; f = gf_f64_open(file, "rt"); if (!f) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER,("[M3U8] Cannot Open m3u8 file %s for reading\n", file)); + 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) { @@ -529,14 +536,14 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const continue; if (currentLineNumber == 1) { /* Playlist MUST start with #EXTM3U */ - if (len < 7 || strncmp("#EXTM3U", currentLine, 7)!=0) { +/* if (len < 7 || strncmp("#EXTM3U", currentLine, 7)!=0) { fclose(f); variant_playlist_del(pl); - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Failed to parse M3U8 File, it should start with #EXTM3U, but was : %s\n", currentLine)); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Failed to parse M3U8 File, it should start with #EXTM3U, but was : %s\n", currentLine)); return GF_STREAM_NOT_FOUND; } continue; - } +*/ } if (currentLine[0] == '#') { /* A comment or a directive */ if (strncmp("#EXT", currentLine, 4)==0) { @@ -562,7 +569,6 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const } } else { char * fullURL = currentLine; - //printf("Line %d: '%s'\n", currentLineNumber, currentLine); if (gf_url_is_local(currentLine)) { /* @@ -582,7 +588,6 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const fullURL = gf_url_concatenate(baseURL, currentLine); } assert( fullURL ); - /*printf("*** calculated full path = %s from %s and %s\n", fullURL, currentLine, baseURL);*/ } { u32 count; @@ -646,6 +651,8 @@ GF_Err parse_sub_playlist(const char * file, VariantPlaylist ** playlist, const currentPlayList->title = attribs.title ? gf_strdup(attribs.title):NULL; currentPlayList->codecs = attribs.codecs ? gf_strdup(attribs.codecs):NULL; gf_list_add(program->bitrates, currentPlayList); + currentPlayList->width = attribs.width; + currentPlayList->height = attribs.height; } else { /* Normal Playlist */ assert( pl->programs); diff --git a/src/media_tools/media_export.c b/src/media_tools/media_export.c index bf6b6cb..d112e28 100644 --- a/src/media_tools/media_export.c +++ b/src/media_tools/media_export.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -86,7 +87,7 @@ static GF_Err gf_dump_to_ogg(GF_MediaExporter *dumper, char *szName, u32 track) op.b_o_s = 1; op.e_o_s = 0; - out = gf_f64_open(szName, "wb"); + out = szName ? gf_f64_open(szName, "wb") : stdout; if (!out) return gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName); theora_kgs = 0; @@ -178,7 +179,7 @@ static GF_Err gf_dump_to_ogg(GF_MediaExporter *dumper, char *szName, u32 track) gf_fwrite(og.body, 1, og.body_len, out); } ogg_stream_clear(&os); - fclose(out); + if (szName) fclose(out); return GF_OK; #endif } @@ -252,7 +253,9 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper) GF_DecoderConfig *dcfg; GF_GenericSampleDescription *udesc; char szName[1000], szEXT[10], szNum[1000], *dsi; + char *ext_start = NULL; FILE *out; + Bool is_stdout=0; GF_BitStream *bs; u32 track, i, di, count, m_type, m_stype, dsi_size, is_mj2k; @@ -403,11 +406,22 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper) } if (dumper->flags & GF_EXPORT_PROBE_ONLY) return GF_OK; + ext_start = strrchr(dumper->out_name, '.'); + + if (dumper->out_name && !strcmp(dumper->out_name, "std")) + is_stdout = 1; + if (dumper->sample_num) { GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, dumper->sample_num, &di); if (!samp) return GF_BAD_PARAM; - sprintf(szName, "%s_%d%s", dumper->out_name, dumper->sample_num, szEXT); - out = gf_f64_open(szName, "wb"); + if (ext_start) { + ext_start[0]=0; + sprintf(szName, "%s_%d%s", dumper->out_name, dumper->sample_num, ext_start+1); + ext_start[0]='.'; + } else { + sprintf(szName, "%s_%d%s", dumper->out_name, dumper->sample_num, szEXT); + } + out = is_stdout ? stdout : gf_f64_open(szName, "wb"); bs = gf_bs_from_file(out, GF_BITSTREAM_WRITE); if (is_mj2k) write_jp2_file(bs, samp->data, samp->dataLength, dsi, dsi_size); @@ -415,8 +429,11 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper) gf_bs_write_data(bs, samp->data, samp->dataLength); gf_isom_sample_del(&samp); gf_bs_del(bs); - fclose(out); - if (dsi) gf_free(dsi); + + if (!is_stdout) + fclose(out); + if (dsi) + gf_free(dsi); return GF_OK; } @@ -425,12 +442,23 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper) GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di); if (!samp) break; - if (count>=1000) { - sprintf(szName, "%s_%08d%s", dumper->out_name, i+1, szEXT); + if (ext_start) { + ext_start[0]=0; + if (count>=1000) { + sprintf(szName, "%s_%08d%s", dumper->out_name, dumper->sample_num, ext_start+1); + } else { + sprintf(szName, "%s_%03d%s", dumper->out_name, dumper->sample_num, ext_start+1); + } + ext_start[0]='.'; } else { - sprintf(szName, "%s_%03d%s", dumper->out_name, i+1, szEXT); + if (count>=1000) { + sprintf(szName, "%s_%08d%s", dumper->out_name, i+1, szEXT); + } else { + sprintf(szName, "%s_%03d%s", dumper->out_name, i+1, szEXT); + } } - out = gf_f64_open(szName, "wb"); + + out = is_stdout ? stdout : gf_f64_open(szName, "wb"); bs = gf_bs_from_file(out, GF_BITSTREAM_WRITE); if (dsi) gf_bs_write_data(bs, dsi, dsi_size); if (is_mj2k) @@ -440,7 +468,8 @@ GF_Err gf_media_export_samples(GF_MediaExporter *dumper) gf_isom_sample_del(&samp); gf_set_progress("Media Export", i+1, count); gf_bs_del(bs); - fclose(out); + if (!is_stdout) + fclose(out); if (dumper->flags & GF_EXPORT_DO_ABORT) break; } if (dsi) gf_free(dsi); @@ -582,6 +611,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) return GF_NOT_SUPPORTED; #else GF_Err e = GF_OK; + Bool add_ext; GF_DecoderConfig *dcfg; GF_GenericSampleDescription *udesc; char szName[1000], szEXT[5], GUID[16]; @@ -595,6 +625,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) u32 aac_type, is_aac; char *dsi; QCPRateTable rtable[8]; + Bool is_stdout=0; dsi_size = 0; dsi = NULL; @@ -608,6 +639,8 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) m_type = gf_isom_get_media_type(dumper->file, track); m_stype = gf_isom_get_media_subtype(dumper->file, track, 1); has_qcp_pad = 0; + if (dumper->out_name && !strcmp(dumper->out_name, "std")) + is_stdout = 1; is_aac = aac_type = 0; qcp_type = 0; @@ -618,6 +651,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) if ((m_stype==GF_ISOM_SUBTYPE_MPEG4) || (m_stype==GF_ISOM_SUBTYPE_MPEG4_CRYP)) dcfg = gf_isom_get_decoder_config(dumper->file, track, 1); + add_ext = (dumper->out_name && strrchr(dumper->out_name , '.')==NULL) ? 1 : 0; strcpy(szName, dumper->out_name ? dumper->out_name : ""); if (dcfg) { switch (dcfg->streamType) { @@ -627,16 +661,19 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; - strcat(szName, ".cmp"); + if (add_ext) + strcat(szName, ".cmp"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 Visual stream to cmp"); break; case GPAC_OTI_VIDEO_AVC: avccfg = gf_isom_avc_config_get(dumper->file, track, 1); - strcat(szName, ".h264"); + 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_MPEG1: - strcat(szName, ".m1v"); + if (add_ext) + strcat(szName, ".m1v"); gf_export_message(dumper, GF_OK, "Extracting MPEG-1 Visual stream to m1v"); break; case GPAC_OTI_VIDEO_MPEG2_SIMPLE: @@ -645,19 +682,23 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) case GPAC_OTI_VIDEO_MPEG2_SPATIAL: case GPAC_OTI_VIDEO_MPEG2_HIGH: case GPAC_OTI_VIDEO_MPEG2_422: - strcat(szName, ".m2v"); + if (add_ext) + strcat(szName, ".m2v"); gf_export_message(dumper, GF_OK, "Extracting MPEG-2 Visual stream to m2v"); break; case GPAC_OTI_IMAGE_JPEG: - strcat(szName, ".jpg"); + if (add_ext) + strcat(szName, ".jpg"); gf_export_message(dumper, GF_OK, "Extracting JPEG image"); break; case GPAC_OTI_IMAGE_PNG: - strcat(szName, ".png"); + if (add_ext) + strcat(szName, ".png"); gf_export_message(dumper, GF_OK, "Extracting PNG image"); break; case GPAC_OTI_MEDIA_OGG: - strcat(szName, ".ogg"); + if (add_ext) + strcat(szName, ".ogg"); gf_export_message(dumper, GF_OK, "Extracting Ogg video"); is_ogg = 1; break; @@ -674,7 +715,8 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; - strcat(szName, ".aac"); + if (add_ext) + strcat(szName, ".aac"); is_aac = 1; aac_type = dcfg->objectTypeIndication - GPAC_OTI_AUDIO_AAC_MPEG2_MP; gf_export_message(dumper, GF_OK, "Extracting MPEG-2 AAC"); @@ -689,21 +731,25 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; is_aac = 2; - strcat(szName, ".aac"); + if (add_ext) + strcat(szName, ".aac"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AAC"); break; case GPAC_OTI_AUDIO_MPEG2_PART3: case GPAC_OTI_AUDIO_MPEG1: - strcat(szName, ".mp3"); + if (add_ext) + strcat(szName, ".mp3"); gf_export_message(dumper, GF_OK, "Extracting MPEG-1/2 Audio (MP3)"); break; case GPAC_OTI_MEDIA_OGG: - strcat(szName, ".ogg"); + if (add_ext) + strcat(szName, ".ogg"); is_ogg = 1; gf_export_message(dumper, GF_OK, "Extracting Ogg audio"); break; case GPAC_OTI_AUDIO_13K_VOICE: - strcat(szName, ".qcp"); qcp_type = 1; + if (add_ext) + strcat(szName, ".qcp"); qcp_type = 1; memcpy(GUID, QCP_QCELP_GUID_1, sizeof(char)*16); gf_export_message(dumper, GF_OK, "Extracting QCELP-13K (QCP file)"); break; @@ -739,7 +785,8 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; - strcat(szName, ".idx"); + if (add_ext) + strcat(szName, ".idx"); gf_export_message(dumper, GF_OK, "Extracting NeroDigital VobSub subpicture stream"); break; default: @@ -754,13 +801,16 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) gf_odf_desc_del((GF_Descriptor *) dcfg); } else { if (m_stype==GF_ISOM_SUBTYPE_3GP_AMR) { - strcat(szName, ".amr"); + if (add_ext) + strcat(szName, ".amr"); gf_export_message(dumper, GF_OK, "Extracting AMR Audio"); } else if (m_stype==GF_ISOM_SUBTYPE_3GP_AMR_WB) { - strcat(szName, ".awb"); + if (add_ext) + strcat(szName, ".awb"); gf_export_message(dumper, GF_OK, "Extracting AMR WideBand Audio"); } else if (m_stype==GF_ISOM_SUBTYPE_3GP_QCELP) { - strcat(szName, ".qcp"); qcp_type = 1; + if (add_ext) + strcat(szName, ".qcp"); qcp_type = 1; memcpy(GUID, QCP_QCELP_GUID_1, sizeof(char)*16); gf_export_message(dumper, GF_OK, "Extracting QCELP-13K (QCP file)"); } else if (m_stype==GF_ISOM_SUBTYPE_3GP_EVRC) { @@ -773,22 +823,28 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) if (dumper->flags & GF_EXPORT_PROBE_ONLY) dumper->flags |= GF_EXPORT_USE_QCP; } else if (m_stype==GF_ISOM_SUBTYPE_3GP_H263) { gf_export_message(dumper, GF_OK, "Extracting H263 Video"); - strcat(szName, ".263"); + if (add_ext) + 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) ) { avccfg = gf_isom_avc_config_get(dumper->file, track, 1); - strcat(szName, ".h264"); + if (add_ext) + strcat(szName, ".h264"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AVC-H264 stream to h264"); } else if (m_type==GF_ISOM_MEDIA_FLASH) { gf_export_message(dumper, GF_OK, "Extracting Macromedia Flash Movie"); - strcat(szName, ".swf"); + if (add_ext) + strcat(szName, ".swf"); } else if (m_stype==GF_ISOM_SUBTYPE_AC3) { gf_export_message(dumper, GF_OK, "Extracting AC3 Audio"); - strcat(szName, ".ac3"); + if (add_ext) + strcat(szName, ".ac3"); } else { - strcat(szName, "."); - strcat(szName, gf_4cc_to_str(m_stype)); + if (add_ext) { + strcat(szName, "."); + strcat(szName, gf_4cc_to_str(m_stype)); + } udesc = gf_isom_get_generic_sample_description(dumper->file, track, 1); if (udesc) { dsi = udesc->extension_buf; udesc->extension_buf = NULL; @@ -810,24 +866,29 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) return GF_OK; } - if (is_ogg) return gf_dump_to_ogg(dumper, szName, track); + if (is_ogg) return gf_dump_to_ogg(dumper, is_stdout ? NULL : szName, track); if (is_vobsub) return gf_dump_to_vobsub(dumper, szName, track, dsi, dsi_size); if (qcp_type>1) { if (dumper->flags & GF_EXPORT_USE_QCP) { - strcat(szName, ".qcp"); + if (add_ext) + strcat(szName, ".qcp"); gf_export_message(dumper, GF_OK, "Extracting %s audio (QCP file)", (qcp_type==2) ? "SMV" : "EVRC"); } else if (qcp_type==2) { - strcat(szName, ".smv"); + if (add_ext) + strcat(szName, ".smv"); gf_export_message(dumper, GF_OK, "Extracting SMV audio"); } else { - strcat(szName, ".evc"); + if (add_ext) + strcat(szName, ".evc"); gf_export_message(dumper, GF_OK, "Extracting EVRC audio"); } } - if (dumper->out_name && (dumper->flags & GF_EXPORT_MERGE)) { + if (is_stdout) { + out = stdout; + } else if (dumper->out_name && (dumper->flags & GF_EXPORT_MERGE)) { out = gf_f64_open(dumper->out_name, "a+b"); if (out) gf_f64_seek(out, 0, SEEK_END); } else { @@ -1038,7 +1099,8 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) if (avccfg) gf_odf_avc_cfg_del(avccfg); gf_bs_del(bs); - fclose(out); + if (!is_stdout) + fclose(out); return e; #endif /*GPAC_DISABLE_AV_PARSERS*/ } @@ -1047,6 +1109,7 @@ GF_Err gf_media_export_native(GF_MediaExporter *dumper) static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper) { GF_Err e; + Bool is_stdout = 0; u32 max_size, tot_size, num_samples, i; s32 size; char *comp, *frame; @@ -1081,7 +1144,13 @@ static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper) } gf_export_message(dumper, GF_OK, "Extracting AVI video (format %s) to %s", comp, szOutFile); - fout = gf_f64_open(szOutFile, "wb"); + if (!strcmp(dumper->out_name, "std")) + is_stdout = 1; + else if (strrchr(dumper->out_name, '.')) { + strcpy(szOutFile, dumper->out_name); + } + + fout = is_stdout ? stdout : gf_f64_open(szOutFile, "wb"); max_size = 0; frame = NULL; @@ -1101,7 +1170,8 @@ static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper) gf_set_progress("AVI Extract", i+1, num_samples); } gf_free(frame); - fclose(fout); + if(!is_stdout) + fclose(fout); fout = NULL; goto exit; } @@ -1136,7 +1206,14 @@ static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper) } sprintf(szOutFile, "%s.%s", dumper->out_name, comp); gf_export_message(dumper, GF_OK, "Extracting AVI %s audio", comp); - fout = gf_f64_open(szOutFile, "wb"); + + if (!strcmp(dumper->out_name, "std")) { + is_stdout = 1; + } else if (strrchr(dumper->out_name, '.')) { + strcpy(szOutFile, dumper->out_name); + } + + fout = is_stdout ? stdout : gf_f64_open(szOutFile, "wb"); num_samples = 0; while (1) { Bool continuous; @@ -1150,7 +1227,7 @@ static GF_Err gf_media_export_avi_track(GF_MediaExporter *dumper) exit: - if (fout) fclose(fout); + if (fout && !is_stdout) fclose(fout); AVI_close(in); return e; } @@ -1424,7 +1501,7 @@ GF_Err gf_media_export_isom(GF_MediaExporter *dumper) { GF_ISOFile *outfile; GF_Err e; - Bool add_to_iod; + Bool add_to_iod, is_stdout; char szName[1000], *ext; u32 track; u8 mode; @@ -1441,13 +1518,17 @@ GF_Err gf_media_export_isom(GF_MediaExporter *dumper) dumper->flags |= GF_EXPORT_MERGE; return GF_OK; } - ext = (char *) gf_isom_get_filename(dumper->file); - if (ext) ext = strrchr(ext, '.'); - sprintf(szName, "%s%s", dumper->out_name, ext ? ext : ".mp4"); - + if (strrchr(dumper->out_name, '.')) { + strcpy(szName, dumper->out_name); + } else { + ext = (char *) gf_isom_get_filename(dumper->file); + if (ext) ext = strrchr(ext, '.'); + sprintf(szName, "%s%s", dumper->out_name, ext ? ext : ".mp4"); + } + is_stdout = (dumper->out_name && !strcmp(dumper->out_name, "std")) ? 1 : 0; add_to_iod = 1; mode = GF_ISOM_WRITE_EDIT; - if (dumper->flags & GF_EXPORT_MERGE) { + if (!is_stdout && (dumper->flags & GF_EXPORT_MERGE)) { FILE *t = gf_f64_open(szName, "rb"); if (t) { add_to_iod = 0; @@ -1455,7 +1536,7 @@ GF_Err gf_media_export_isom(GF_MediaExporter *dumper) fclose(t); } } - outfile = gf_isom_open(szName, mode, NULL); + outfile = gf_isom_open(is_stdout ? "std" : szName, mode, NULL); if (mode == GF_ISOM_WRITE_EDIT) { gf_isom_set_pl_indication(outfile, GF_ISOM_PL_AUDIO, 0xFF); @@ -1513,7 +1594,11 @@ GF_Err gf_media_export_avi(GF_MediaExporter *dumper) } if (dumper->flags & GF_EXPORT_PROBE_ONLY) return GF_OK; - sprintf(szName, "%s.avi", dumper->out_name); + if (strrchr(dumper->out_name, '.')) { + strcpy(szName, dumper->out_name); + } else { + sprintf(szName, "%s.avi", dumper->out_name); + } avi_out = AVI_open_output_file(szName); if (!avi_out) { gf_odf_desc_del((GF_Descriptor *)esd); @@ -1547,7 +1632,7 @@ GF_Err gf_media_export_avi(GF_MediaExporter *dumper) /*compute VfW delay*/ if (gf_isom_has_time_offset(dumper->file, track)) { - u32 max_CTSO; + s32 max_CTSO; u64 DTS; DTS = max_CTSO = 0; for (i=0; ivendor_code), sdesc->version, sdesc->revision); fprintf(nhml, "width=\"%d\" height=\"%d\" compressorName=\"%s\" temporalQuality=\"%d\" spatialQuality=\"%d\" horizontalResolution=\"%d\" verticalResolution=\"%d\" bitDepth=\"%d\" ", - sdesc->width, sdesc->height, sdesc->compressor_name, sdesc->temporal_quality, sdesc->spacial_quality, sdesc->h_res, sdesc->v_res, sdesc->depth); + sdesc->width, sdesc->height, sdesc->compressor_name, sdesc->temporal_quality, sdesc->spatial_quality, sdesc->h_res, sdesc->v_res, sdesc->depth); } else if (mtype==GF_ISOM_MEDIA_AUDIO) { fprintf(nhml, "codecVendor=\"%s\" codecVersion=\"%d\" codecRevision=\"%d\" ", gf_4cc_to_str(sdesc->vendor_code), sdesc->version, sdesc->revision); fprintf(nhml, "sampleRate=\"%d\" numChannels=\"%d\" bitsPerSample=\"%d\" ", sdesc->samplerate, sdesc->nb_channels, sdesc->bits_per_sample); @@ -1833,6 +1918,7 @@ GF_Err gf_media_export_saf(GF_MediaExporter *dumper) GF_SAFMuxer *mux; char *data; u32 size; + Bool is_stdout = 0; FILE *saf_f; SAFInfo safs[1024]; @@ -1895,9 +1981,11 @@ GF_Err gf_media_export_saf(GF_MediaExporter *dumper) } gf_export_message(dumper, GF_OK, "SAF: Multiplexing %d tracks", s_count); + if (dumper->out_name && !strcmp(dumper->out_name, "std")) + is_stdout = 1; strcpy(out_file, dumper->out_name); strcat(out_file, ".saf"); - saf_f = gf_f64_open(out_file, "wb"); + saf_f = is_stdout ? stdout : gf_f64_open(out_file, "wb"); samp_done = 0; while (samp_donetrackID); } - gf_m2ts_reset_parsers(ts); sprintf(szFile, "%s_pid%d", dumper->out_name ? dumper->out_name : "", stream->pid); switch (stream->stream_type) { @@ -2043,12 +2132,17 @@ GF_Err gf_media_export_ts_native(GF_MediaExporter *dumper) gf_export_message(dumper, GF_OK, "Extracting Unknown stream to raw"); break; } - dst = gf_f64_open(szFile, "wb"); + + if (dumper->out_name && !strcmp(dumper->out_name, "std")) + is_stdout=1; + + dst = is_stdout ? stdout : gf_f64_open(szFile, "wb"); if (!dst) { fclose(src); gf_m2ts_demux_del(ts); return gf_export_message(dumper, GF_IO_ERR, "Cannot open file %s for writing", szFile); } + gf_m2ts_reset_parsers(ts); gf_f64_seek(src, 0, SEEK_SET); fdone = 0; @@ -2064,7 +2158,9 @@ GF_Err gf_media_export_ts_native(GF_MediaExporter *dumper) if (dumper->flags & GF_EXPORT_DO_ABORT) break; } gf_set_progress("MPEG-2 TS Extract", fsize, fsize); - fclose(dst); + + if (!is_stdout) + fclose(dst); fclose(src); gf_m2ts_demux_del(ts); return GF_OK; diff --git a/src/media_tools/media_import.c b/src/media_tools/media_import.c index e80f708..30c6365 100644 --- a/src/media_tools/media_import.c +++ b/src/media_tools/media_import.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre, Romain Bouqueau, Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -170,8 +171,6 @@ static void get_video_timing(Double fps, u32 *timescale, u32 *dts_inc) } } - - static GF_Err gf_import_still_image(GF_MediaImporter *import, Bool mult_desc_allowed) { GF_BitStream *bs; @@ -1038,8 +1037,6 @@ static GF_Err gf_import_avi_video(GF_MediaImporter *import) char *comp, *frame; avi_t *in; - if (import->trackID>1) return GF_OK; - test = gf_f64_open(import->in_name, "rb"); if (!test) return gf_import_message(import, GF_URL_ERROR, "Opening %s failed", import->in_name); fclose(test); @@ -1069,7 +1066,10 @@ static GF_Err gf_import_avi_video(GF_MediaImporter *import) AVI_close(in); return GF_OK; } - + if (import->trackID>1) { + AVI_close(in); + return GF_OK; + } destroy_esd = 0; frame = NULL; AVI_seek_start(in); @@ -1399,11 +1399,10 @@ GF_Err gf_import_avi_audio(GF_MediaImporter *import) unsigned char temp[4]; avi_t *in; - if (import->flags & GF_IMPORT_PROBE_ONLY) return GF_OK; - /*video only, ignore*/ if (import->trackID==1) return GF_OK; + test = gf_f64_open(import->in_name, "rb"); if (!test) return gf_import_message(import, GF_URL_ERROR, "Opening file %s failed", import->in_name); fclose(test); @@ -1771,8 +1770,11 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import) goto exit; } /*if not first sample and same DTS as previous sample, force DTS++*/ - if (i && (samp->DTS==sampDTS)) { - samp->DTS++; + if (i && (samp->DTS<=sampDTS)) { + if (i+1 < num_samples) { + GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[ISOM import] 0-duration sample detected at DTS %d - adjusting\n", samp->DTS)); + } + samp->DTS = sampDTS + 1; } e = gf_isom_add_sample(import->dest, track, di, samp); } @@ -1781,7 +1783,14 @@ GF_Err gf_import_isomedia(GF_MediaImporter *import) gf_set_progress("Importing ISO File", i+1, num_samples); if (duration && (sampDTS > duration) ) break; if (import->flags & GF_IMPORT_DO_ABORT) break; - if (e) goto exit; + if (e) + goto exit; + } + + if (gf_isom_has_time_offset(import->orig, track_in)==2) { + e = gf_isom_set_composition_offset_mode(import->dest, track, 1); + if (e) + goto exit; } if (import->esd) { @@ -2652,7 +2661,7 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc) sdesc.vendor_code = GF_4CC(att->value[0], att->value[1], att->value[2], att->value[3]); } else if (!stricmp(att->name, "temporalQuality")) sdesc.temporal_quality = atoi(att->value); - else if (!stricmp(att->name, "spatialQuality")) sdesc.spacial_quality = atoi(att->value); + else if (!stricmp(att->name, "spatialQuality")) sdesc.spatial_quality = atoi(att->value); else if (!stricmp(att->name, "horizontalResolution")) sdesc.h_res = atoi(att->value); else if (!stricmp(att->name, "verticalResolution")) sdesc.v_res = atoi(att->value); else if (!stricmp(att->name, "bitDepth")) sdesc.depth = atoi(att->value); @@ -2677,6 +2686,9 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc) } } else if (!stricmp(att->name, "content_script_types")) dims.content_script_types = att->value; + else if (!stricmp(att->name, "mime_type")) dims.mime_type = att->value; + else if (!stricmp(att->name, "media_namespace")) dims.mime_type = att->value; + else if (!stricmp(att->name, "media_schema_location")) dims.xml_schema_loc = att->value; } if (sdesc.samplerate && !timescale) timescale = sdesc.samplerate; @@ -2780,7 +2792,16 @@ GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc) if (e) goto exit; gf_import_message(import, GF_OK, "3GPP DIMS import"); - } else { + } else if (mtype == GF_ISOM_MEDIA_SUBM) { + track = gf_isom_new_track(import->dest, tkID, mtype, timescale); + if (!track) { e = gf_isom_last_error(import->dest); goto exit; } + e = gf_isom_new_generic_subtitle_description(import->dest, track, + (char *)dims.contentEncoding, (char *)dims.xml_schema_loc, (char *)dims.mime_type, + (sdesc.codec_tag == GF_4CC( 'm', 'e', 't', 'x' ) ? 1 : 0), + (import->flags & GF_IMPORT_USE_DATAREF) ? szMedia : NULL, NULL, &di); + if (e) goto exit; + + } else { char szT[5]; sdesc.extension_buf = specInfo; sdesc.extension_buf_size = specInfoSize; @@ -3910,7 +3931,6 @@ restart_import: } switch (nal_type) { case GF_AVC_NALU_SVC_SUBSEQ_PARAM: - if (import->flags & GF_IMPORT_SVC_NONE) break; is_subseq = 1; case GF_AVC_NALU_SEQ_PARAM: idx = AVC_ReadSeqInfo(buffer+1/*skip NALU type*/, nal_size-1, &avc, is_subseq, NULL); @@ -3930,6 +3950,10 @@ restart_import: add_sps = 1; } dstcfg = svccfg; + if (import->flags & GF_IMPORT_SVC_NONE) { + add_sps = 0; + skip_nal = 1; + } } else { if ((avc.sps[idx].state & AVC_SPS_PARSED) && !(avc.sps[idx].state & AVC_SPS_DECLARED)) { avc.sps[idx].state |= AVC_SPS_DECLARED; @@ -3940,7 +3964,11 @@ restart_import: when concatenated bitstreams). Since we cannot put two SPS with the same idx in the decoder config, we keep them in the video bitstream*/ if (avc.sps[idx].state & AVC_SUBSPS_DECLARED) { - copy_size = nal_size; + if (import->flags & GF_IMPORT_SVC_NONE) { + copy_size = 0; + } else { + copy_size = nal_size; + } } if (add_sps) { @@ -3948,6 +3976,10 @@ restart_import: dstcfg->profile_compatibility = avc.sps[idx].prof_compat; dstcfg->AVCProfileIndication = avc.sps[idx].profile_idc; dstcfg->AVCLevelIndication = avc.sps[idx].level_idc; + dstcfg->chroma_format = avc.sps[idx].chroma_format; + dstcfg->luma_bit_depth = 8 + avc.sps[idx].luma_bit_depth_m8; + dstcfg->chroma_bit_depth = 8 + avc.sps[idx].chroma_bit_depth_m8; + slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot)); slc->size = nal_size; slc->id = idx; @@ -3956,8 +3988,8 @@ restart_import: gf_list_add(dstcfg->sequenceParameterSets, slc); /*disable frame rate scan, most bitstreams have wrong values there*/ if (detect_fps && avc.sps[idx].vui.timing_info_present_flag && avc.sps[idx].vui.fixed_frame_rate_flag - /*if detected FPS is greater than 120, assume wrong timing info*/ - && (avc.sps[idx].vui.time_scale <= 120*avc.sps[idx].vui.num_units_in_tick) + /*if detected FPS is greater than 1000, assume wrong timing info*/ + && (avc.sps[idx].vui.time_scale <= 1000*avc.sps[idx].vui.num_units_in_tick) ) { /*ISO/IEC 14496-10 n11084 Table E-6*/ /* not used : u8 DeltaTfiDivisorTable[] = {1,1,1,2,2,2,2,3,3,4,6}; */ @@ -4081,7 +4113,10 @@ restart_import: break; case GF_AVC_NALU_SVC_PREFIX_NALU: - if (import->flags & GF_IMPORT_SVC_NONE) break; + if (import->flags & GF_IMPORT_SVC_NONE) { + copy_size = 0; + break; + } assert(prev_nalu_prefix_size==0); copy_size = nal_size; break; @@ -4098,7 +4133,11 @@ restart_import: } } } - if (import->flags & GF_IMPORT_SVC_NONE) break; + if (import->flags & GF_IMPORT_SVC_NONE) { + skip_nal = 0; + copy_size = 0; + break; + } if (! skip_nal) { copy_size = nal_size; switch (avc.s_info.slice_type) { @@ -4110,6 +4149,28 @@ restart_import: break; case GF_AVC_NALU_SEQ_PARAM_EXT: + idx = AVC_ReadSeqParamSetExtId(buffer+1/*skip NALU type*/, nal_size-1); + if (idx<0) { + e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Error parsing Sequence Param Extension"); + goto exit; + } + + if (! (avc.sps[idx].state & AVC_SPS_EXT_DECLARED)) { + avc.sps[idx].state |= AVC_SPS_EXT_DECLARED; + + 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); + + if (!avccfg->sequenceParameterSetExtensions) + avccfg->sequenceParameterSetExtensions = gf_list_new(); + + gf_list_add(avccfg->sequenceParameterSetExtensions, slc); + } + break; + case GF_AVC_NALU_SLICE_AUX: default: @@ -4293,17 +4354,30 @@ restart_import: is_paff = 1; slice_is_ref = (avc.s_info.nal_unit_type==GF_AVC_NALU_IDR_SLICE); - if (slice_is_ref) nb_idr++; + 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 (avc.sei.recovery_point.valid) { + if (avc.sei.recovery_point.valid || (import->flags & GF_IMPORT_FORCE_SYNC)) { + Bool bIntraSlice = AVC_SliceIsIntra(&avc); + assert(avc.s_info.nal_unit_type!=GF_AVC_NALU_IDR_SLICE || bIntraSlice); + sei_recovery_frame_count = avc.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 (!avc.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")); + } + } avc.sei.recovery_point.valid = 0; - if ((import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) + if (bIntraSlice && (import->flags & GF_IMPORT_FORCE_SYNC) && (sei_recovery_frame_count==0)) slice_force_ref = 1; } sample_is_rap = AVC_SliceIsIDR(&avc); @@ -4371,7 +4445,7 @@ restart_import: } /*compute max delay (applicable when B slice are present)*/ - if (poc_diff && (s32)(cur_samp-(ref_frame-1)-last_poc/poc_diff)>(s32)max_total_delay) { + 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; } } @@ -4508,7 +4582,7 @@ restart_import: if (gf_list_count(avccfg->sequenceParameterSets) || !gf_list_count(svccfg->sequenceParameterSets) ) { gf_isom_avc_config_update(import->dest, track, 1, avccfg); if (gf_list_count(svccfg->sequenceParameterSets)) { - gf_isom_svc_config_update(import->dest, track, 1, svccfg, 1); + gf_isom_svc_config_update(import->dest, track, 1, svccfg, 1); } } else { gf_isom_svc_config_update(import->dest, track, 1, svccfg, 0); @@ -5503,7 +5577,7 @@ void m2ts_rewrite_avc_sample(GF_MediaImporter *import, GF_TSImport *tsimp) start = 0; bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_WRITE); while (1) { - if (!samp->data[start+sc_pos] && !samp->data[start+sc_pos+1] && !samp->data[start+sc_pos+2] && (samp->data[start+sc_pos+3]==1)) { + if (!samp->data[sc_pos] && !samp->data[sc_pos+1] && !samp->data[sc_pos+2] && (samp->data[sc_pos+3]==1)) { gf_bs_seek(bs, start); gf_bs_write_u32(bs, (u32) sc_pos-start-4); start = sc_pos; @@ -6249,7 +6323,7 @@ GF_Err gf_import_mpeg_ts(GF_MediaImporter *import) if (tsimp.track) { MP4T_RecomputeBitRate(import->dest, tsimp.track); /* creation of the edit lists */ - if (es->first_dts != es->program->first_dts) { + if ((es->first_dts != es->program->first_dts) && gf_isom_get_sample_count(import->dest, tsimp.track) ){ u32 media_ts, moov_ts, offset; u64 dur; media_ts = gf_isom_get_media_timescale(import->dest, tsimp.track); @@ -6606,12 +6680,14 @@ GF_Err gf_import_ac3(GF_MediaImporter *import) if (import->esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) import->esd->decoderConfig->decoderSpecificInfo); import->esd->decoderConfig->decoderSpecificInfo = NULL; - cfg.acmod = hdr.acmod; + cfg.is_ec3 = 0; + cfg.nb_streams = 1; cfg.brcode = hdr.brcode; - cfg.bsid = hdr.bsid; - cfg.bsmod = hdr.bsmod; - cfg.fscod = hdr.fscod; - cfg.lfon = hdr.lfon; + cfg.streams[0].acmod = hdr.acmod; + cfg.streams[0].bsid = hdr.bsid; + cfg.streams[0].bsmod = hdr.bsmod; + cfg.streams[0].fscod = hdr.fscod; + cfg.streams[0].lfon = hdr.lfon; gf_isom_ac3_config_new(import->dest, track, &cfg, (import->flags & GF_IMPORT_USE_DATAREF) ? import->in_name : NULL, NULL, &di); gf_isom_set_audio_info(import->dest, track, di, sr, nb_chan, 16); @@ -6667,6 +6743,252 @@ exit: } #endif +GF_EXPORT +GF_Err gf_media_import_chapters_file(GF_MediaImporter *import) +{ + int readen=0; + GF_Err e; + u32 state, offset; + u32 cur_chap; + u64 ts; + u32 i, h, m, s, ms, fr, fps; + char line[1024]; + char szTitle[1024]; + FILE *f = gf_f64_open(import->in_name, "rt"); + if (!f) return GF_URL_ERROR; + + readen = fread(line, 1, 4, f); + if (readen < 4){ + e = GF_URL_ERROR; + goto err_exit; + } + offset = 0; + if ((line[0]==(char)(0xFF)) && (line[1]==(char)(0xFE))) { + if (!line[2] && !line[3]){ + e = GF_NOT_SUPPORTED; + goto err_exit; + } + offset = 2; + } else if ((line[0]==(char)(0xFE)) && (line[1]==(char)(0xFF))) { + if (!line[2] && !line[3]){ + e = GF_NOT_SUPPORTED; + goto err_exit; + } + offset = 2; + } else if ((line[0]==(char)(0xEF)) && (line[1]==(char)(0xBB)) && (line[2]==(char)(0xBF))) { + /*we handle UTF8 as asci*/ + offset = 3; + } else { + offset = 0; + } + gf_f64_seek(f, offset, SEEK_SET); + + if (import->flags & GF_IMPORT_PROBE_ONLY) { + Bool is_chap_or_sub = 0; + import->nb_tracks = 0; + while (!is_chap_or_sub && (fgets(line, 1024, f) != NULL)) { + char *sep; + strlwr(line); + + if (strstr(line, "addchapter(")) is_chap_or_sub = 1; + else if (strstr(line, "-->")) is_chap_or_sub = 1; + else if ((sep = strstr(line, "chapter")) != NULL) { + sep+=7; + if (!strncmp(sep+1, "name", 4)) is_chap_or_sub = 1; + else if (!strncmp(sep+2, "name", 4)) is_chap_or_sub = 1; + else if (!strncmp(sep+3, "name", 4)) is_chap_or_sub = 1; + else if (strstr(line, "Zoom") || strstr(line, "zoom")) is_chap_or_sub = 1; + } + } + fclose(f); + if (is_chap_or_sub) { + import->nb_tracks = 1; + import->tk_info[0].media_type = GF_4CC('C','H','A','P'); + import->tk_info[0].type = GF_4CC('t','e','x','t'); + return GF_OK; + } + return GF_NOT_SUPPORTED; + } + + e = gf_isom_remove_chapter(import->dest, 0, 0); + if (e) goto err_exit; + + if (!import->video_fps) { + /*try to figure out the frame rate*/ + for (i=0; idest); i++) { + GF_ISOSample *samp; + u32 ts, inc; + if (gf_isom_get_media_type(import->dest, i+1) != GF_ISOM_MEDIA_VISUAL) continue; + if (gf_isom_get_sample_count(import->dest, i+1) < 20) continue; + samp = gf_isom_get_sample_info(import->dest, 1, 2, NULL, NULL); + inc = (u32) samp->DTS; + if (!inc) inc=1; + ts = gf_isom_get_media_timescale(import->dest, i+1); + import->video_fps = ts; + import->video_fps /= inc; + gf_isom_sample_del(&samp); + GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[Chapter import] Guessed video frame rate %g (%u:%u)\n", import->video_fps, ts, inc)); + break; + } + if (!import->video_fps) + import->video_fps = 25; + } + + cur_chap = 0; + ts = 0; + state = 0; + while (fgets(line, 1024, f) != NULL) { + char *title = NULL; + u32 off = 0; + char *sL; + while (1) { + u32 len = strlen(line); + if (!len) break; + switch (line[len-1]) { + case '\n': case '\t': case '\r': case ' ': + line[len-1] = 0; + continue; + } + break; + } + + while (line[off]==' ') off++; + if (!strlen(line+off)) continue; + sL = line+off; + + szTitle[0] = 0; + /*ZoomPlayer chapters*/ + if (!strnicmp(sL, "AddChapter(", 11)) { + u32 nb_fr; + sscanf(sL, "AddChapter(%u,%s)", &nb_fr, szTitle); + ts = nb_fr; + ts *= 1000; + ts = (u64) (((s64) ts ) / import->video_fps); + sL = strchr(sL, ','); strcpy(szTitle, sL+1); sL = strrchr(szTitle, ')'); if (sL) sL[0] = 0; + } else if (!strnicmp(sL, "AddChapterBySecond(", 19)) { + u32 nb_s; + sscanf(sL, "AddChapterBySecond(%u,%s)", &nb_s, szTitle); + ts = nb_s; + ts *= 1000; + sL = strchr(sL, ','); strcpy(szTitle, sL+1); sL = strrchr(szTitle, ')'); if (sL) sL[0] = 0; + } else if (!strnicmp(sL, "AddChapterByTime(", 17)) { + u32 h, m, s; + sscanf(sL, "AddChapterByTime(%u,%u,%u,%s)", &h, &m, &s, szTitle); + ts = 3600*h + 60*m + s; + ts *= 1000; + sL = strchr(sL, ','); + if (sL) sL = strchr(sL+1, ','); + if (sL) sL = strchr(sL+1, ','); + strcpy(szTitle, sL+1); sL = strrchr(szTitle, ')'); if (sL) sL[0] = 0; + } + /*regular or SMPTE time codes*/ + else if ((strlen(sL)>=8) && (sL[2]==':') && (sL[5]==':')) { + title = NULL; + if (strlen(sL)==8) { + sscanf(sL, "%02u:%02u:%02u", &h, &m, &s); + ts = (h*3600 + m*60+s)*1000; + } + else { + char szTS[20], *tok; + strncpy(szTS, sL, 18); + tok = strrchr(szTS, ' '); + if (tok) { + title = strchr(sL, ' ') + 1; + while (title[0]==' ') title++; + if (strlen(title)) strcpy(szTitle, title); + tok[0] = 0; + } + ts = 0; + h = m = s = ms = 0; + + if (sscanf(szTS, "%u:%u:%u;%u/%u", &h, &m, &s, &fr, &fps)==5) { + ts = (h*3600 + m*60+s)*1000 + 1000*fr/fps; + } else if (sscanf(szTS, "%u:%u:%u;%u", &h, &m, &s, &fr)==4) { + ts = (h*3600 + m*60+s); + ts = (s64) (((import->video_fps*((s64)ts) + fr) * 1000 ) / import->video_fps); + } else if (sscanf(szTS, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { + ts = (h*3600 + m*60+s)*1000+ms; + } else if (sscanf(szTS, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { + ts = (h*3600 + m*60+s)*1000+ms; + } else if (sscanf(szTS, "%u:%u:%u:%u", &h, &m, &s, &ms) == 4) { + ts = (h*3600 + m*60+s)*1000+ms; + } else if (sscanf(szTS, "%u:%u:%u", &h, &m, &s) == 3) { + ts = (h*3600 + m*60+s) * 1000; + } + } + } + /*CHAPTERX= and CHAPTERXNAME=*/ + else if (!strnicmp(sL, "CHAPTER", 7)) { + u32 idx; + char szTemp[20], *str; + strncpy(szTemp, sL, 19); + str = strrchr(szTemp, '='); + if (!str) continue; + str[0] = 0; + strlwr(szTemp); + idx = cur_chap; + str = strchr(sL, '='); + str++; + if (strstr(szTemp, "name")) { + sscanf(szTemp, "chapter%uname", &idx); + strcpy(szTitle, str); + if (idx!=cur_chap) { + cur_chap=idx; + state = 0; + } + state++; + } else { + sscanf(szTemp, "chapter%u", &idx); + if (idx!=cur_chap) { + cur_chap=idx; + state = 0; + } + state++; + + ts = 0; + h = m = s = ms = 0; + if (sscanf(str, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) { + ts = (h*3600 + m*60+s)*1000+ms; + } else if (sscanf(str, "%u:%u:%u:%u", &h, &m, &s, &ms) == 4) { + ts = (h*3600 + m*60+s)*1000+ms; + } else if (sscanf(str, "%u:%u:%u", &h, &m, &s) == 3) { + ts = (h*3600 + m*60+s) * 1000; + } + } + if (state==2) { + e = gf_isom_add_chapter(import->dest, 0, ts, szTitle); + if (e) goto err_exit; + state = 0; + } + continue; + } + else continue; + + if (strlen(szTitle)) { + e = gf_isom_add_chapter(import->dest, 0, ts, szTitle); + } else { + e = gf_isom_add_chapter(import->dest, 0, ts, NULL); + } + if (e) goto err_exit; + } + + +err_exit: + fclose(f); + return e; +} + +GF_EXPORT +GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, Double import_fps) +{ + GF_MediaImporter import; + memset(&import, 0, sizeof(GF_MediaImporter)); + import.dest = file; + import.in_name = chap_file; + import.video_fps = import_fps; + import.streamFormat = "CHAP"; + return gf_media_import(&import); +} GF_EXPORT GF_Err gf_media_import(GF_MediaImporter *importer) @@ -6790,8 +7112,8 @@ GF_Err gf_media_import(GF_MediaImporter *importer) if (!strnicmp(ext, ".saf", 4) || !strnicmp(ext, ".lsr", 4) || !stricmp(fmt, "SAF") ) return gf_import_saf(importer); /*text subtitles*/ - if (!strnicmp(ext, ".srt", 4) || !strnicmp(ext, ".sub", 4) || !strnicmp(ext, ".ttxt", 5) - || !stricmp(fmt, "SRT") || !stricmp(fmt, "SUB") || !stricmp(fmt, "TEXT") ) { + if (!strnicmp(ext, ".srt", 4) || !strnicmp(ext, ".sub", 4) || !strnicmp(ext, ".ttxt", 5) || !strnicmp(ext, ".vtt", 4) + || !stricmp(fmt, "SRT") || !stricmp(fmt, "SUB") || !stricmp(fmt, "TEXT") || !stricmp(fmt, "VTT")) { #ifndef GPAC_DISABLE_TTXT return gf_import_timed_text(importer); #else @@ -6809,6 +7131,9 @@ GF_Err gf_media_import(GF_MediaImporter *importer) if (!strnicmp(ext, ".dml", 4) || !stricmp(fmt, "DIMS") ) return gf_import_nhml_dims(importer, 1); + if (!strnicmp(ext, ".txt", 4) || !strnicmp(ext, ".chap", 5) || !stricmp(fmt, "CHAP") ) + return gf_media_import_chapters_file(importer); + /*try XML things*/ xml_type = gf_xml_get_root_type(importer->in_name, &e); if (xml_type) { @@ -6869,56 +7194,3 @@ GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level) #endif /*GPAC_DISABLE_MEDIA_IMPORT*/ -#ifndef GPAC_DISABLE_ISOM_WRITE -GF_EXPORT -GF_Err gf_media_change_par(GF_ISOFile *file, u32 track, s32 ar_num, s32 ar_den) -{ - u32 tk_w, tk_h, stype; - GF_Err e; - - e = gf_isom_get_visual_info(file, track, 1, &tk_w, &tk_h); - 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) ) { -#ifndef GPAC_DISABLE_AV_PARSERS - GF_AVCConfig *avcc = gf_isom_avc_config_get(file, track, 1); - AVC_ChangePAR(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; -#endif - } - else if (stype==GF_ISOM_SUBTYPE_MPEG4) { - GF_ESD *esd = gf_isom_get_esd(file, track, 1); - if (!esd || !esd->decoderConfig || (esd->decoderConfig->streamType!=4) ) { - if (esd) gf_odf_desc_del((GF_Descriptor *) esd); - return GF_NOT_SUPPORTED; - } -#ifndef GPAC_DISABLE_AV_PARSERS - if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) { - e = gf_m4v_rewrite_par(&esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength, ar_num, ar_den); - if (!e) e = gf_isom_change_mpeg4_description(file, track, 1, esd); - gf_odf_desc_del((GF_Descriptor *) esd); - if (e) return e; - } -#endif - } else { - return GF_BAD_PARAM; - } - - e = gf_isom_set_pixel_aspect_ratio(file, track, 1, ar_num, ar_den); - if (e) return e; - - if ((ar_den>=0) && (ar_num>=0)) { - if (ar_den) tk_w = tk_w * ar_num / ar_den; - else if (ar_num) tk_h = tk_h * ar_den / ar_num; - } - /*revert to full frame for track layout*/ - else { - e = gf_isom_get_visual_info(file, track, 1, &tk_w, &tk_h); - if (e) return e; - } - return gf_isom_set_track_layout_info(file, track, tk_w<<16, tk_h<<16, 0, 0, 0); -} -#endif /*GPAC_DISABLE_ISOM_WRITE*/ diff --git a/src/media_tools/mpd.c b/src/media_tools/mpd.c index 21c6c7a..67727ee 100644 --- a/src/media_tools/mpd.c +++ b/src/media_tools/mpd.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * -* Authors: Cyril Concolato - Jean Le Feuvre -* Copyright (c) Telecom ParisTech 2010- + * Authors: Jean Le Feuvre, Cyril COncolato + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / 3GPP/MPEG Media Presentation Description input module @@ -28,10 +28,15 @@ #include #include +#ifndef _WIN32_WCE +/*for mktime*/ +#include +#endif static Bool gf_mpd_parse_bool(char *attr) { if (!strcmp(attr, "true")) return 1; + if (!strcmp(attr, "1")) return 1; return 0; } @@ -40,6 +45,14 @@ static char *gf_mpd_parse_string(char *attr) return gf_strdup(attr); } +static Bool gf_mpd_valid_child(GF_MPD *mpd, GF_XMLNode *child) +{ + if (child->type != GF_XML_NODE_TYPE) return 0; + if (!mpd->xml_namespace && !child->ns) return 1; + if (mpd->xml_namespace && child->ns && !strcmp(mpd->xml_namespace, child->ns) ) return 1; + return 0; +} + static char *gf_mpd_parse_text_content(GF_XMLNode *child) { u32 child_index = 0; @@ -60,6 +73,13 @@ static u32 gf_mpd_parse_int(char *attr) return atoi(attr); } +static u64 gf_mpd_parse_long_int(char *attr) +{ + u64 longint; + sscanf(attr, LLU, &longint); + return longint; +} + static Double gf_mpd_parse_double(char *attr) { return atof(attr); @@ -75,8 +95,49 @@ static GF_MPD_Fractional *gf_mpd_parse_frac(char *attr) static u64 gf_mpd_parse_date(char *attr) { - fprintf(stdout, "error: mpd parse date not implemented\n"); +#ifdef _WIN32_WCE + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] Parsing MPD date (%s) is not supported on Windows CE\n", attr)); + return 0; +#else + Bool ok = 0; + Bool neg_time_zone = 0; + u32 year, month, day, h, m; + s32 oh, om; + Float s; + + h = m = 0; + s = 0; + oh = om = 0; + if (sscanf(attr, "%d-%d-%dT%d:%d:%gZ", &year, &month, &day, &h, &m, &s) == 6) + ok = 1; + else if (sscanf(attr, "%d-%d-%dT%d:%d:%g-%d:%d", &year, &month, &day, &h, &m, &s, &oh, &om) == 8) { + neg_time_zone = 1; + ok = 1; + } else if (sscanf(attr, "%d-%d-%dT%d:%d:%g+%d:%d", &year, &month, &day, &h, &m, &s, &oh, &om) == 8) { + ok = 1; + } + + if (ok) { + u64 res; + struct tm _t; + _t.tm_year = (year > 1900) ? year - 1900 : 0; + _t.tm_mon = month ? month - 1 : 0; + _t.tm_mday = day; + _t.tm_hour = h; + _t.tm_min = m; + _t.tm_sec = (u32) s; + res = mktime(&_t); + if (om || oh) { + s32 diff = (60*oh + om)*60; + if (neg_time_zone) diff = -diff; + res = res + diff; + } + return res; + } else { + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD] Failed to parse MPD date %s - format not supported\n", attr)); + } return 0; +#endif } static u32 gf_mpd_parse_duration(char *duration) { @@ -146,7 +207,7 @@ static GF_Err gf_mpd_parse_location(GF_MPD *mpd, GF_XMLNode *child) static GF_Err gf_mpd_parse_metrics(GF_MPD *mpd, GF_XMLNode *child) { - fprintf(stdout, "mpd metrics not implemented yet\n"); + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] Metrics not implemented yet\n")); return GF_OK; } @@ -238,7 +299,7 @@ static GF_MPD_URL *gf_mpd_parse_url(GF_XMLNode *root) return url; } -static void gf_mpd_parse_segment_base_generic(GF_MPD_SegmentBase *seg, GF_XMLNode *root) +static void gf_mpd_parse_segment_base_generic(GF_MPD *mpd, GF_MPD_SegmentBase *seg, GF_XMLNode *root) { GF_XMLAttribute *att; GF_XMLNode *child; @@ -249,20 +310,20 @@ static void gf_mpd_parse_segment_base_generic(GF_MPD_SegmentBase *seg, GF_XMLNod 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_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, "indexRangeExact")) seg->index_range_exact = gf_mpd_parse_bool(att->value); } i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "Initialization")) seg->initialization_segment = gf_mpd_parse_url(child); else if (!strcmp(child->name, "RepresentationIndex")) seg->representation_index = gf_mpd_parse_url(child); } } -static GF_MPD_SegmentTimeline *gf_mpd_parse_segment_timeline(GF_XMLNode *root) +static GF_MPD_SegmentTimeline *gf_mpd_parse_segment_timeline(GF_MPD *mpd, GF_XMLNode *root) { u32 i, j; GF_XMLAttribute *att; @@ -274,7 +335,7 @@ static GF_MPD_SegmentTimeline *gf_mpd_parse_segment_timeline(GF_XMLNode *root) i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "S")) { GF_MPD_SegmentTimelineEntry *segent; GF_SAFEALLOC(segent, GF_MPD_SegmentTimelineEntry); @@ -282,31 +343,34 @@ static GF_MPD_SegmentTimeline *gf_mpd_parse_segment_timeline(GF_XMLNode *root) j = 0; while ( (att = gf_list_enum(child->attributes, &j)) ) { - if (!strcmp(att->name, "t")) segent->start_time = gf_mpd_parse_int(att->value); - else if (!strcmp(att->name, "d")) segent->duration = gf_mpd_parse_int(att->value); - else if (!strcmp(att->name, "r")) segent->repeat_count = gf_mpd_parse_int(att->value); + if (!strcmp(att->name, "t")) + segent->start_time = gf_mpd_parse_long_int(att->value); + else if (!strcmp(att->name, "d")) + segent->duration = gf_mpd_parse_int(att->value); + else if (!strcmp(att->name, "r")) + segent->repeat_count = gf_mpd_parse_int(att->value); } } } return seg; } -static GF_MPD_SegmentBase *gf_mpd_parse_segment_base(GF_XMLNode *root) +static GF_MPD_SegmentBase *gf_mpd_parse_segment_base(GF_MPD *mpd, GF_XMLNode *root) { GF_MPD_SegmentBase *seg; GF_SAFEALLOC(seg, GF_MPD_SegmentBase); if (!seg) return NULL; - gf_mpd_parse_segment_base_generic(seg, root); + gf_mpd_parse_segment_base_generic(mpd, seg, root); return seg; } -void gf_mpd_parse_multiple_segment_base(GF_MPD_MultipleSegmentBase *seg, GF_XMLNode *root) +void gf_mpd_parse_multiple_segment_base(GF_MPD *mpd, GF_MPD_MultipleSegmentBase *seg, GF_XMLNode *root) { u32 i; GF_XMLAttribute *att; GF_XMLNode *child; - gf_mpd_parse_segment_base_generic((GF_MPD_SegmentBase*)seg, root); + gf_mpd_parse_segment_base_generic(mpd, (GF_MPD_SegmentBase*)seg, root); seg->start_number = (u32) -1; i = 0; @@ -317,8 +381,8 @@ void gf_mpd_parse_multiple_segment_base(GF_MPD_MultipleSegmentBase *seg, GF_XMLN i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; - if (!strcmp(child->name, "SegmentTimeline")) seg->segment_timeline = gf_mpd_parse_segment_timeline(child); + if (!gf_mpd_valid_child(mpd, child)) continue; + if (!strcmp(child->name, "SegmentTimeline")) seg->segment_timeline = gf_mpd_parse_segment_timeline(mpd, child); else if (!strcmp(child->name, "BitstreamSwitching")) seg->bitstream_switching_url = gf_mpd_parse_url(child); } } @@ -342,7 +406,7 @@ static void gf_mpd_parse_segment_url(GF_List *container, GF_XMLNode *root) } } -static GF_MPD_SegmentList *gf_mpd_parse_segment_list(GF_XMLNode *root) +static GF_MPD_SegmentList *gf_mpd_parse_segment_list(GF_MPD *mpd, GF_XMLNode *root) { u32 i; GF_MPD_SegmentList *seg; @@ -355,14 +419,14 @@ static GF_MPD_SegmentList *gf_mpd_parse_segment_list(GF_XMLNode *root) i = 0; while ( (att = gf_list_enum(root->attributes, &i)) ) { - if (strstr(att->name, "href") || strstr(att->name, "actuate")) { - } + if (strstr(att->name, "href")) seg->xlink_href = gf_mpd_parse_string(att->value); + else if (strstr(att->name, "actuate")) seg->xlink_actuate_on_load = !strcmp(att->value, "onLoad") ? 1 : 0; } - gf_mpd_parse_multiple_segment_base((GF_MPD_MultipleSegmentBase *)seg, root); + gf_mpd_parse_multiple_segment_base(mpd, (GF_MPD_MultipleSegmentBase *)seg, root); i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "SegmentURL")) gf_mpd_parse_segment_url(seg->segment_URLs, child); } if (!gf_list_count(seg->segment_URLs)) { @@ -372,7 +436,7 @@ static GF_MPD_SegmentList *gf_mpd_parse_segment_list(GF_XMLNode *root) return seg; } -static GF_MPD_SegmentTemplate *gf_mpd_parse_segment_template(GF_XMLNode *root) +static GF_MPD_SegmentTemplate *gf_mpd_parse_segment_template(GF_MPD *mpd, GF_XMLNode *root) { u32 i; GF_MPD_SegmentTemplate *seg; @@ -386,10 +450,13 @@ static GF_MPD_SegmentTemplate *gf_mpd_parse_segment_template(GF_XMLNode *root) if (!strcmp(att->name, "media")) seg->media = gf_mpd_parse_string(att->value); else if (!strcmp(att->name, "index")) seg->index = gf_mpd_parse_string(att->value); else if (!strcmp(att->name, "initialization") ) seg->initialization = gf_mpd_parse_string(att->value); - else if (!strcmp(att->name, "initialisation") ) seg->initialization = gf_mpd_parse_string(att->value); + else if (!stricmp(att->name, "initialisation") || !stricmp(att->name, "initialization") ) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] Wrong spelling: got %s but expected \"initialization\" \n", att->name )); + seg->initialization = gf_mpd_parse_string(att->value); + } else if (!strcmp(att->name, "bitstreamSwitching")) seg->bitstream_switching = gf_mpd_parse_string(att->value); } - gf_mpd_parse_multiple_segment_base((GF_MPD_MultipleSegmentBase *)seg, root); + gf_mpd_parse_multiple_segment_base(mpd, (GF_MPD_MultipleSegmentBase *)seg, root); return seg; } @@ -403,7 +470,7 @@ static GF_Err gf_mpd_parse_descriptor(GF_List *container, GF_XMLNode *root) return GF_OK; } -static void gf_mpd_parse_common_representation(GF_MPD_CommonAttributes *com, GF_XMLNode *root) +static void gf_mpd_parse_common_representation(GF_MPD *mpd, GF_MPD_CommonAttributes *com, GF_XMLNode *root) { GF_XMLAttribute *att; GF_XMLNode *child; @@ -437,7 +504,7 @@ static void gf_mpd_parse_common_representation(GF_MPD_CommonAttributes *com, GF_ i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "FramePacking")) { gf_mpd_parse_content_component(com->frame_packing, child); } @@ -456,7 +523,7 @@ static void gf_mpd_init_common_attributes(GF_MPD_CommonAttributes *com) com->content_protection = gf_list_new(); com->frame_packing = gf_list_new(); } -static GF_Err gf_mpd_parse_representation(GF_List *container, GF_XMLNode *root) +static GF_Err gf_mpd_parse_representation(GF_MPD *mpd, GF_List *container, GF_XMLNode *root) { u32 i; GF_MPD_Representation *rep; @@ -480,23 +547,23 @@ static GF_Err gf_mpd_parse_representation(GF_List *container, GF_XMLNode *root) else if (!strcmp(att->name, "dependencyId")) rep->dependency_id = gf_mpd_parse_string(att->value); else if (!strcmp(att->name, "mediaStreamStructureId")) rep->media_stream_structure_id = gf_mpd_parse_string(att->value); } - gf_mpd_parse_common_representation((GF_MPD_CommonAttributes*)rep, root); + gf_mpd_parse_common_representation(mpd, (GF_MPD_CommonAttributes*)rep, root); i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "BaseURL")) { e = gf_mpd_parse_base_url(rep->base_URLs, child); if (e) return e; } else if (!strcmp(child->name, "SegmentBase")) { - rep->segment_base = gf_mpd_parse_segment_base(child); + rep->segment_base = gf_mpd_parse_segment_base(mpd, child); } else if (!strcmp(child->name, "SegmentList")) { - rep->segment_list = gf_mpd_parse_segment_list(child); + rep->segment_list = gf_mpd_parse_segment_list(mpd, child); } else if (!strcmp(child->name, "SegmentTemplate")) { - rep->segment_template = gf_mpd_parse_segment_template(child); + rep->segment_template = gf_mpd_parse_segment_template(mpd, child); } else if (!strcmp(child->name, "SubRepresentation")) { /*TODO @@ -508,7 +575,7 @@ static GF_Err gf_mpd_parse_representation(GF_List *container, GF_XMLNode *root) return GF_OK; } -static GF_Err gf_mpd_parse_adaptation_set(GF_List *container, GF_XMLNode *root) +static GF_Err gf_mpd_parse_adaptation_set(GF_MPD *mpd, GF_List *container, GF_XMLNode *root) { u32 i; GF_MPD_AdaptationSet *set; @@ -534,8 +601,8 @@ static GF_Err gf_mpd_parse_adaptation_set(GF_List *container, GF_XMLNode *root) i = 0; while ( (att = gf_list_enum(root->attributes, &i)) ) { - if (strstr(att->name, "href") || strstr(att->name, "actuate")) { - } + if (strstr(att->name, "href")) set->xlink_href = gf_mpd_parse_string(att->value); + else if (strstr(att->name, "actuate")) set->xlink_actuate_on_load = !strcmp(att->value, "onLoad") ? 1 : 0; else if (!strcmp(att->name, "id")) set->id = gf_mpd_parse_int(att->value); else if (!strcmp(att->name, "group")) set->group = gf_mpd_parse_int(att->value); else if (!strcmp(att->name, "lang")) set->lang = gf_mpd_parse_string(att->value); @@ -557,11 +624,11 @@ static GF_Err gf_mpd_parse_adaptation_set(GF_List *container, GF_XMLNode *root) else set->subsegment_starts_with_sap = gf_mpd_parse_int(att->value); } } - gf_mpd_parse_common_representation((GF_MPD_CommonAttributes*)set, root); + gf_mpd_parse_common_representation(mpd, (GF_MPD_CommonAttributes*)set, root); i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "Accessibility")) { e = gf_mpd_parse_descriptor(set->accessibility, child); if (e) return e; @@ -587,16 +654,16 @@ static GF_Err gf_mpd_parse_adaptation_set(GF_List *container, GF_XMLNode *root) if (e) return e; } else if (!strcmp(child->name, "SegmentBase")) { - set->segment_base = gf_mpd_parse_segment_base(child); + set->segment_base = gf_mpd_parse_segment_base(mpd, child); } else if (!strcmp(child->name, "SegmentList")) { - set->segment_list = gf_mpd_parse_segment_list(child); + set->segment_list = gf_mpd_parse_segment_list(mpd, child); } else if (!strcmp(child->name, "SegmentTemplate")) { - set->segment_template = gf_mpd_parse_segment_template(child); + set->segment_template = gf_mpd_parse_segment_template(mpd, child); } else if (!strcmp(child->name, "Representation")) { - e = gf_mpd_parse_representation(set->representations, child); + e = gf_mpd_parse_representation(mpd, set->representations, child); if (e) return e; } } @@ -621,8 +688,8 @@ static GF_Err gf_mpd_parse_period(GF_MPD *mpd, GF_XMLNode *root) i = 0; while ( (att = gf_list_enum(root->attributes, &i)) ) { - if (strstr(att->name, "href") || strstr(att->name, "actuate")) { - } + if (strstr(att->name, "href")) period->xlink_href = gf_mpd_parse_string(att->value); + else if (strstr(att->name, "actuate")) period->xlink_actuate_on_load = !strcmp(att->value, "onLoad") ? 1 : 0; else if (!strcmp(att->name, "id")) period->ID = gf_mpd_parse_string(att->value); else if (!strcmp(att->name, "start")) period->start = gf_mpd_parse_duration(att->value); else if (!strcmp(att->name, "duration")) period->duration = gf_mpd_parse_duration(att->value); @@ -631,22 +698,22 @@ static GF_Err gf_mpd_parse_period(GF_MPD *mpd, GF_XMLNode *root) i = 0; while ( (child = gf_list_enum(root->content, &i))) { - if (child->type != GF_XML_NODE_TYPE) continue; + if (!gf_mpd_valid_child(mpd, child)) continue; if (!strcmp(child->name, "BaseURL")) { e = gf_mpd_parse_base_url(period->base_URLs, child); if (e) return e; } else if (!strcmp(child->name, "SegmentBase")) { - period->segment_base = gf_mpd_parse_segment_base(child); + period->segment_base = gf_mpd_parse_segment_base(mpd, child); } else if (!strcmp(child->name, "SegmentList")) { - period->segment_list = gf_mpd_parse_segment_list(child); + period->segment_list = gf_mpd_parse_segment_list(mpd, child); } else if (!strcmp(child->name, "SegmentTemplate")) { - period->segment_template = gf_mpd_parse_segment_template(child); + period->segment_template = gf_mpd_parse_segment_template(mpd, child); } else if (!strcmp(child->name, "AdaptationSet")) { - e = gf_mpd_parse_adaptation_set(period->adaptation_sets, child); + e = gf_mpd_parse_adaptation_set(mpd, period->adaptation_sets, child); if (e) return e; } else if (!strcmp(child->name, "SubSet")) { @@ -703,9 +770,9 @@ void gf_mpd_prog_info_free(void *_item) if (ptr->more_info_url) gf_free(ptr->more_info_url); gf_free(ptr); } -void gf_mpd_segment_url_free(void *_item) +void gf_mpd_segment_url_free(void *_ptr) { - GF_MPD_SegmentURL *ptr = (GF_MPD_SegmentURL*)_item; + GF_MPD_SegmentURL *ptr = (GF_MPD_SegmentURL *)_ptr; if (ptr->index) gf_free(ptr->index); if (ptr->index_range) gf_free(ptr->index_range); if (ptr->media) gf_free(ptr->media); @@ -734,6 +801,7 @@ void gf_mpd_segment_timeline_free(void *_item) void gf_mpd_segment_list_free(void *_item) { GF_MPD_SegmentList *ptr = (GF_MPD_SegmentList *)_item; + if (ptr->xlink_href) gf_free(ptr->xlink_href); if (ptr->initialization_segment) gf_mpd_url_free(ptr->initialization_segment); if (ptr->bitstream_switching_url) gf_mpd_url_free(ptr->bitstream_switching_url); if (ptr->representation_index) gf_mpd_url_free(ptr->representation_index); @@ -756,13 +824,13 @@ void gf_mpd_segment_template_free(void *_item) } void gf_mpd_descriptor_free(void *item) { - fprintf(stdout, "error: descriptor not implemented\n"); + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] descriptor not implemented\n")); gf_free(item); } void gf_mpd_content_component_free(void *item) { - fprintf(stdout, "error: content component not implemented\n"); + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] content component not implemented\n")); gf_free(item); } @@ -787,6 +855,8 @@ void gf_mpd_representation_free(void *_item) if (ptr->dependency_id) gf_free(ptr->dependency_id); if (ptr->media_stream_structure_id) gf_free(ptr->media_stream_structure_id); + if (ptr->playback.cached_init_segment_url) gf_free(ptr->playback.cached_init_segment_url); + gf_mpd_del_list(ptr->base_URLs, gf_mpd_base_url_free, 0); gf_mpd_del_list(ptr->sub_representations, NULL/*TODO*/, 0); if (ptr->segment_base) gf_mpd_segment_base_free(ptr->segment_base); @@ -802,6 +872,7 @@ void gf_mpd_adaptation_set_free(void *_item) if (ptr->lang) gf_free(ptr->lang); if (ptr->content_type) gf_free(ptr->content_type); if (ptr->par) gf_free(ptr->par); + if (ptr->xlink_href) gf_free(ptr->xlink_href); gf_mpd_del_list(ptr->accessibility, gf_mpd_descriptor_free, 0); gf_mpd_del_list(ptr->role, gf_mpd_descriptor_free, 0); gf_mpd_del_list(ptr->rating, gf_mpd_descriptor_free, 0); @@ -818,6 +889,7 @@ void gf_mpd_period_free(void *_item) { GF_MPD_Period *ptr = (GF_MPD_Period *)_item; if (ptr->ID) gf_free(ptr->ID); + if (ptr->xlink_href) gf_free(ptr->xlink_href); if (ptr->segment_base) gf_mpd_segment_base_free(ptr->segment_base); if (ptr->segment_list) gf_mpd_segment_list_free(ptr->segment_list); if (ptr->segment_template) gf_mpd_segment_template_free(ptr->segment_template); @@ -845,6 +917,7 @@ GF_EXPORT GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_base_url) { GF_Err e; + Bool ns_ok = 0; u32 att_index, child_index; GF_XMLAttribute *att; GF_XMLNode *child; @@ -859,9 +932,35 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_b mpd->metrics = gf_list_new(); /*setup some defaults*/ mpd->type = GF_MPD_TYPE_STATIC; + /*infinite by default*/ + mpd->time_shift_buffer_depth = (u32) -1; + mpd->xml_namespace = NULL; att_index = 0; child_index = gf_list_count(root->attributes); + for (att_index = 0 ; att_index < child_index; att_index++) { + att = gf_list_get(root->attributes, att_index); + if (!att) continue; + if (!strcmp(att->name, "xmlns")) { + if (!root->ns && (!strcmp(att->value, "urn:mpeg:dash:schema:mpd:2011") || !strcmp(att->value, "urn:mpeg:DASH:schema:MPD:2011")) ) { + ns_ok = 1; + break; + } + } + else if (!strncmp(att->name, "xmlns:", 6)) { + if (root->ns && !strcmp(att->name+6, root->ns) && (!strcmp(att->value, "urn:mpeg:dash:schema:mpd:2011") || !strcmp(att->value, "urn:mpeg:DASH:schema:MPD:2011")) ) { + ns_ok = 1; + mpd->xml_namespace = root->ns; + break; + } + } + } + + if (!ns_ok) { + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] Wrong namespace found for DASH MPD - cannot parse\n")); + } + + att_index = 0; for (att_index = 0 ; att_index < child_index; att_index++) { att = gf_list_get(root->attributes, att_index); if (!att) { @@ -895,15 +994,15 @@ GF_Err gf_mpd_init_from_dom(GF_XMLNode *root, GF_MPD *mpd, const char *default_b mpd->max_subsegment_duration = gf_mpd_parse_duration(att->value); } } - if (mpd->type == GF_MPD_TYPE_STATIC) - mpd->minimum_update_period = 0; + if (mpd->type == GF_MPD_TYPE_STATIC) + mpd->minimum_update_period = mpd->time_shift_buffer_depth = 0; child_index = 0; while (1) { child = gf_list_get(root->content, child_index); if (!child) { break; - } else if (child->type == GF_XML_NODE_TYPE) { + } else if (gf_mpd_valid_child(mpd, child) ) { if (!strcmp(child->name, "ProgramInformation")) { e = gf_mpd_parse_program_info(mpd, child); if (e) return e; @@ -945,7 +1044,7 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, e = parse_root_playlist(m3u8_file, &pl, base_url); if (e) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M3U8] Failed to parse root playlist '%s', error = %s\n", m3u8_file, gf_error_to_string(e))); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[M3U8] Failed to parse root playlist '%s', error = %s\n", m3u8_file, gf_error_to_string(e))); if (pl) variant_playlist_del(pl); pl = NULL; return e; @@ -967,7 +1066,7 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, u32 k; char *suburl; - if (!pe->url || !strstr(pe->url, ".m3u8")) + if (!pe->url ) continue; /*filter out duplicated entries (seen on M6 m3u8)*/ @@ -982,12 +1081,17 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, the_pe = pe; suburl = NULL; + + /*not HLS*/ + if ( !strstr(pe->url, ".m3u8")) + continue; + if (strcmp(base_url, pe->url)) suburl = gf_url_concatenate(base_url, pe->url); if (!suburl || !strcmp(base_url, suburl)) { if (suburl) gf_free(suburl); - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD Generator] Not downloading, programs are identical for %s...\n", pe->url)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD Generator] Not downloading, programs are identical for %s...\n", pe->url)); continue; } if (getter && getter->new_session && getter->del_session && getter->get_cache_name) { @@ -1015,8 +1119,8 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, #endif gf_free(suburl); } else { /* for use in MP4Box */ - if (strstr(suburl, "://") && !strstr(suburl, "://") ) { - e = gf_dm_wget(suburl, "tmp.m3u8"); + if (strstr(suburl, "://") ) { + e = gf_dm_wget(suburl, "tmp.m3u8", 0, 0); if (e==GF_OK) { e = parse_sub_playlist("tmp.m3u8", &pl, suburl, prog, pe); } @@ -1051,15 +1155,15 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, } if (is_end || ((the_pe->elementType == TYPE_PLAYLIST) && the_pe->element.playlist.is_ended)) { update_interval = 0; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD Generator] NO NEED to refresh playlist !\n")); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD Generator] NO NEED to refresh playlist !\n")); } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD Generator] Playlist will be refreshed every %g seconds, len=%d\n", update_interval, the_pe->durationInfo)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD Generator] Playlist will be refreshed every %g seconds, len=%d\n", update_interval, the_pe->durationInfo)); } assert( mpd_file ); fmpd = gf_f64_open(mpd_file, "wt"); if (!fmpd){ - GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[MPD Generator] Cannot write to temp file %s!\n", mpd_file)); + GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD Generator] Cannot write to temp file %s!\n", mpd_file)); variant_playlist_del(pl); return GF_IO_ERR; } @@ -1166,7 +1270,7 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, } } - fprintf(fmpd, " \n"); + fprintf(fmpd, " \n"); /*if we use templates, put the SegmentTemplate element at the adaptationSet level*/ if (use_template) { @@ -1196,7 +1300,7 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, tmp_file = strrchr(elt->url, '/'); if (!tmp_file) tmp_file = strrchr(elt->url, '\\'); if (tmp_file) { - e = gf_dm_wget(elt->url, tmp_file); + e = gf_dm_wget(elt->url, tmp_file, 0, 0); if (e==GF_OK) { import.in_name = tmp_file; e = gf_media_import(&import); @@ -1239,13 +1343,15 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, count2 = gf_list_count(prog->bitrates); for (j = 0; jbitrates, j); if (pe->elementType == TYPE_STREAM) { - fprintf(stdout, "NOT SUPPORTED: M3U8 Stream\n"); + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] NOT SUPPORTED: M3U8 Stream\n")); } else if (pe->elementType != TYPE_PLAYLIST) { - fprintf(stdout, "NOT SUPPORTED: M3U8 unknown type\n"); + GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[MPD] NOT SUPPORTED: M3U8 unknown type\n")); } count3 = gf_list_count(pe->element.playlist.elements); @@ -1259,10 +1365,23 @@ 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; } + if (pe->bandwidth && pe->codecs && pe->width && pe->height) { + import_file = 0; + } + + /*get rid of level 0 aac*/ + elt = gf_list_get(pe->element.playlist.elements, 0); + if (elt && strstr(elt->url, ".aac")) + is_aac = 1; - width = height = samplerate = num_channels = 0; + if (is_aac) + fprintf(fmpd, ""); continue; } @@ -1398,6 +1520,9 @@ GF_Err gf_m3u8_to_mpd(const char *m3u8_file, const char *base_url, fprintf(fmpd, " \n"); fprintf(fmpd, " \n"); gf_free(base_url); + + if (is_aac) + fprintf(fmpd, " -->\n"); } } diff --git a/src/media_tools/mpeg2_ps.c b/src/media_tools/mpeg2_ps.c index 686c74a..3d2db20 100644 --- a/src/media_tools/mpeg2_ps.c +++ b/src/media_tools/mpeg2_ps.c @@ -497,7 +497,7 @@ static void copy_bytes_to_pes_buffer (mpeg2ps_stream_t *sptr, to_move); sptr->pes_buffer_size = to_move; sptr->pes_buffer_on = 0; - //printf("moving %d bytes\n", to_move); + //fprintf(stderr, "moving %d bytes\n", to_move); if (to_move + pes_len > sptr->pes_buffer_size_max) { sptr->pes_buffer = (u8 *)gf_realloc(sptr->pes_buffer, to_move + pes_len + 2048); @@ -507,7 +507,7 @@ static void copy_bytes_to_pes_buffer (mpeg2ps_stream_t *sptr, file_read_bytes(sptr->m_fd, sptr->pes_buffer + sptr->pes_buffer_size, pes_len); sptr->pes_buffer_size += pes_len; #if 0 - printf("copying %u bytes - on %u size %u\n", + fprintf(stderr, "copying %u bytes - on %u size %u\n", pes_len, sptr->pes_buffer_on, sptr->pes_buffer_size); #endif } @@ -556,7 +556,7 @@ static Bool read_to_next_pes_header (FILE *fd, *stream_id = hdr & 0xff; *pes_len = convert16(local + 4); #if 0 - printf("loc: "X64" %x len %u\n", file_location(fd) - 6, + fprintf(stderr, "loc: "X64" %x len %u\n", file_location(fd) - 6, local[3], *pes_len); #endif @@ -613,7 +613,7 @@ static Bool read_pes_header_data (FILE *fd, } ts->have_pts = 1; ts->pts = ts->dts = read_pts(local); - //printf("mpeg1 pts "U64"\n", ts->pts); + //fprintf(stderr, "mpeg1 pts "U64"\n", ts->pts); *have_ts = 1; pes_len -= 4; } else if ((*local & 0xf0) == 0x30) { @@ -798,7 +798,7 @@ mpeg2ps_stream_find_mpeg_video_frame (mpeg2ps_stream_t *sptr) sptr->next_pes_ts.have_pts = sptr->next_pes_ts.have_dts = 0; } #if 0 - printf("header %x at %d\n", scode, sptr->pes_buffer_on); + fprintf(stderr, "header %x at %d\n", scode, sptr->pes_buffer_on); #endif if (scode == MPEG12_PICTURE_START_CODE) { @@ -823,7 +823,7 @@ mpeg2ps_stream_find_mpeg_video_frame (mpeg2ps_stream_t *sptr) sptr->pict_header_offset += sptr->pes_buffer_on; } else { #if 0 - printf("2header %x at %d\n", scode, start); + fprintf(stderr, "2header %x at %d\n", scode, start); #endif start += offset; @@ -884,7 +884,7 @@ static Bool mpeg2ps_stream_find_ac3_frame (mpeg2ps_stream_t *sptr) } while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) { #if 0 - printf("don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, + fprintf(stderr, "don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, sptr->pes_buffer_size, sptr->pes_buffer_size - sptr->pes_buffer_on, sptr->frame_len); @@ -937,7 +937,7 @@ static Bool mpeg2ps_stream_find_mp3_frame (mpeg2ps_stream_t *sptr) } while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) { #if 0 - printf("don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, + fprintf(stderr, "don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, sptr->pes_buffer_size, sptr->pes_buffer_size - sptr->pes_buffer_on, sptr->frame_len); @@ -1334,7 +1334,7 @@ static void mpeg2ps_scan_file (mpeg2ps_t *ps) * Now, we go to close to the end, and try to find the last * dts that we can */ - // printf("to end "X64"\n", end - orig_check); + // fprintf(stderr, "to end "X64"\n", end - orig_check); file_seek_to(ps->fd, ps->end_loc - orig_check); while (read_to_next_pes_header(ps->fd, &stream_id, &pes_len)) { @@ -1370,10 +1370,10 @@ static void mpeg2ps_scan_file (mpeg2ps_t *ps) sptr->end_dts_loc = loc; } #if 0 - printf("loc "X64" stream %x %x", loc, stream_id, substream); - if (ts.have_pts) printf(" pts "U64, ts.pts); - if (ts.have_dts) printf(" dts "U64, ts.dts); - printf("\n"); + fprintf(stderr, "loc "X64" stream %x %x", loc, stream_id, substream); + if (ts.have_pts) fprintf(stderr, " pts "U64, ts.pts); + if (ts.have_dts) fprintf(stderr, " dts "U64, ts.dts); + fprintf(stderr, "\n"); #endif file_skip_bytes(ps->fd, pes_left); } diff --git a/src/media_tools/mpegts.c b/src/media_tools/mpegts.c index 9cc877b..2a7b2c2 100644 --- a/src/media_tools/mpegts.c +++ b/src/media_tools/mpegts.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Walid B.H - Jean Le Feuvre - * Copyright (c)2006-200X ENST - All rights reserved + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * * This file is part of GPAC / MPEG2-TS sub-project * @@ -27,10 +27,9 @@ #ifndef GPAC_DISABLE_MPEG2TS +#include #include #include -#include -#include #include #ifdef GPAC_CONFIG_LINUX @@ -39,11 +38,11 @@ //#define FORCE_DISABLE_MPEG4SL_OVER_MPEG2TS -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE #include #endif -#ifndef GPAC_DISABLE_DSMCC +#ifdef GPAC_ENABLE_DSMCC #include #endif @@ -113,6 +112,7 @@ static u32 gf_m2ts_reframe_reset(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool sam static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool same_pts, unsigned char *data, u32 data_len) { Bool au_start_in_pes=0; + Bool prev_is_au_delim=0; Bool force_new_au=0; Bool start_code_found = 0; Bool short_start_code = 0; @@ -205,20 +205,29 @@ static u32 gf_m2ts_reframe_avc_h264(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, Bool #endif /*check AU start type*/ if (nal_type==GF_AVC_NALU_ACCESS_UNIT) { - 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)); + 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_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); + else { + pck.flags = 0; + ts->on_event(ts, GF_M2TS_EVT_PES_PCK, &pck); + prev_is_au_delim=0; + } data += sc_pos; data_len -= sc_pos; @@ -793,9 +802,12 @@ static void gf_m2ts_reset_sections(GF_List *sections) } } -static void gf_m2ts_section_filter_del(GF_M2TS_SectionFilter *sf) +static void gf_m2ts_section_filter_reset(GF_M2TS_SectionFilter *sf) { - if (sf->section) gf_free(sf->section); + if (sf->section) { + gf_free(sf->section); + sf->section = NULL; + } while (sf->table) { GF_M2TS_Table *t = sf->table; sf->table = t->next; @@ -803,6 +815,12 @@ static void gf_m2ts_section_filter_del(GF_M2TS_SectionFilter *sf) gf_list_del(t->sections); gf_free(t); } + sf->cc = -1; + sf->length = sf->received = 0; +} +static void gf_m2ts_section_filter_del(GF_M2TS_SectionFilter *sf) +{ + gf_m2ts_section_filter_reset(sf); gf_free(sf); } @@ -814,7 +832,7 @@ void gf_m2ts_es_del(GF_M2TS_ES *es) GF_M2TS_SECTION_ES *ses = (GF_M2TS_SECTION_ES *)es; if (ses->sec) gf_m2ts_section_filter_del(ses->sec); -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE if (es->flags & GF_M2TS_ES_IS_MPE) gf_dvb_mpe_section_del(es); #endif @@ -844,7 +862,7 @@ static void gf_m2ts_section_complete(GF_M2TS_Demuxer *ts, GF_M2TS_SectionFilter { if (!sec->process_section) { if ((ts->on_event && (sec->section[0]==GF_M2TS_TABLE_ID_AIT)) ) { -#ifndef GPAC_DISABLE_DSMCC +#ifdef GPAC_ENABLE_DSMCC GF_M2TS_SL_PCK pck; pck.data_len = sec->length; pck.data = sec->section; @@ -855,7 +873,7 @@ static void gf_m2ts_section_complete(GF_M2TS_Demuxer *ts, GF_M2TS_SectionFilter } else if ((ts->on_event && (sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_ENCAPSULATED_DATA || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_UN_MESSAGE || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_DOWNLOAD_DATA_MESSAGE || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_STREAM_DESCRIPTION || sec->section[0]==GF_M2TS_TABLE_ID_DSM_CC_PRIVATE)) ) { -#ifndef GPAC_DISABLE_DSMCC +#ifdef GPAC_ENABLE_DSMCC GF_M2TS_SL_PCK pck; pck.data_len = sec->length; pck.data = sec->section; @@ -864,7 +882,7 @@ static void gf_m2ts_section_complete(GF_M2TS_Demuxer *ts, GF_M2TS_SectionFilter //ts->on_event(ts, GF_M2TS_EVT_DSMCC_FOUND, &pck); #endif } -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE else if (ts->on_mpe_event && ((ses && (ses->flags & GF_M2TS_EVT_DVB_MPE)) || (sec->section[0]==GF_M2TS_TABLE_ID_INT)) ) { GF_M2TS_SL_PCK pck; pck.data_len = sec->length; @@ -1520,11 +1538,13 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF case GF_M2TS_SUBTITLE_DVB: GF_SAFEALLOC(pes, GF_M2TS_PES); pes->cc = -1; + pes->flags = GF_M2TS_ES_IS_PES; es = (GF_M2TS_ES *)pes; break; case GF_M2TS_PRIVATE_DATA: GF_SAFEALLOC(pes, GF_M2TS_PES); pes->cc = -1; + pes->flags = GF_M2TS_ES_IS_PES; es = (GF_M2TS_ES *)pes; break; /* Sections */ @@ -1567,7 +1587,7 @@ static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, GF case GF_M2TS_MPE_SECTIONS: GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("stream type MPE found : pid = %d \n", pid)); -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE es = gf_dvb_mpe_section_new(); if (es->flags & GF_M2TS_ES_IS_SECTION) { /* NULL means: trigger the call to on_event with DVB_GENERAL type and the raw section as payload */ @@ -1837,7 +1857,7 @@ static void gf_m2ts_process_cat(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ses, GF if (ts->on_event) ts->on_event(ts, evt_type, NULL); } -static GFINLINE u64 gf_m2ts_get_pts(unsigned char *data) +u64 gf_m2ts_get_pts(unsigned char *data) { u64 pts; u32 val; @@ -1849,7 +1869,7 @@ static GFINLINE u64 gf_m2ts_get_pts(unsigned char *data) return pts; } -static void gf_m2ts_pes_header(GF_M2TS_PES *pes, unsigned char *data, u32 data_size, GF_M2TS_PESHeader *pesh) +void gf_m2ts_pes_header(GF_M2TS_PES *pes, unsigned char *data, u32 data_size, GF_M2TS_PESHeader *pesh) { u32 has_pts, has_dts; u32 len_check; @@ -1892,6 +1912,8 @@ static void gf_m2ts_pes_header(GF_M2TS_PES *pes, unsigned char *data, u32 data_s pesh->DTS = gf_m2ts_get_pts(data); data+=5; len_check += 5; + } else { + pesh->DTS = pesh->PTS; } if (len_check < pesh->hdr_data_len) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d Skipping %d bytes in pes header\n", pes->pid, pesh->hdr_data_len - len_check)); @@ -1900,7 +1922,7 @@ static void gf_m2ts_pes_header(GF_M2TS_PES *pes, unsigned char *data, u32 data_s } } -static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Header *hdr) +static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes) { GF_M2TS_PESHeader pesh; @@ -1920,7 +1942,7 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea gf_m2ts_pes_header(pes, pes->data+3, pes->data_len-3, &pesh); /*send PES timing*/ - { + if (ts->notify_pes_timing) { GF_M2TS_PES_PCK pck; memset(&pck, 0, sizeof(GF_M2TS_PES_PCK)); pck.PTS = pesh.PTS; @@ -1947,13 +1969,13 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea #endif pes->PTS = pesh.PTS; - if (!pesh.DTS) pesh.DTS = pesh.PTS; - #ifndef GPAC_DISABLE_LOG - if (pesh.DTS==pes->DTS) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - same DTS "LLU" for two consecutive PES packets \n", pes->pid, pes->DTS) ); - } if (pesh.DTSDTS) { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - DTS "LLU" less than previous DTS "LLU"\n", pes->pid, pesh.DTS, pes->DTS) ); + { + if (pes->DTS && (pesh.DTS==pes->DTS)) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - same DTS "LLU" for two consecutive PES packets \n", pes->pid, pes->DTS) ); + } if (pesh.DTSDTS) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d - DTS "LLU" less than previous DTS "LLU"\n", pes->pid, pesh.DTS, pes->DTS) ); + } } #endif pes->DTS = pesh.DTS; @@ -2004,10 +2026,10 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea } } } else { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: unknown stream ID %08X\n", pes->pid, stream_id)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: unknown stream ID %08X\n", pes->pid, stream_id)); } - } else { - GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Bad PES Header, discarding packet (maybe stream is encrypted ?)\n", hdr->pid)); + } else if (pes->data) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Bad PES Header, discarding packet (maybe stream is encrypted ?)\n", pes->pid)); } if (pes->data) gf_free(pes->data); pes->data = NULL; @@ -2019,14 +2041,17 @@ static void gf_m2ts_flush_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Hea static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Header *hdr, unsigned char *data, u32 data_size, GF_M2TS_AdaptationField *paf) { u8 expect_cc; - Bool disc; + Bool disc=0; Bool flush_pes = 0; - /*duplicated packet, NOT A DISCONTINUITY, discard the packet*/ - if (hdr->continuity_counter==pes->cc) return; - - expect_cc = (pes->cc<0) ? hdr->continuity_counter : (pes->cc + 1) & 0xf; - disc = (expect_cc == hdr->continuity_counter) ? 0 : 1; + /*duplicated packet, NOT A DISCONTINUITY, we should discard the packet - however we may encounter this configuration in DASH at segment boundaries. + If payload start is set, ignore duplication*/ + if (hdr->continuity_counter==pes->cc) { + if (!hdr->payload_start || (hdr->adaptation_field!=3) ) return; + } else { + expect_cc = (pes->cc<0) ? hdr->continuity_counter : (pes->cc + 1) & 0xf; + if (expect_cc != hdr->continuity_counter) disc = 1; + } pes->cc = hdr->continuity_counter; if (disc) { @@ -2035,15 +2060,21 @@ static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_H disc = 0; } if (disc) { - GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Packet discontinuity (%d expected - got %d- - trashing PES packet\n", pes->pid, expect_cc, hdr->continuity_counter)); - if (pes->data) { - gf_free(pes->data); - pes->data = NULL; + if (hdr->payload_start) { + if (pes->data) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Packet discontinuity (%d expected - got %d) - may have lost end of previous PES\n", pes->pid, expect_cc, hdr->continuity_counter)); + } + } else { + if (pes->data) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] PES %d: Packet discontinuity (%d expected - got %d) - trashing PES packet\n", pes->pid, expect_cc, hdr->continuity_counter)); + gf_free(pes->data); + pes->data = NULL; + } + pes->data_len = 0; + pes->pes_len = 0; + pes->cc = -1; + return; } - pes->data_len = 0; - pes->pes_len = 0; - pes->cc = -1; - return; } } @@ -2056,7 +2087,7 @@ static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_H pes->before_last_pcr_value_pck_number = pes->program->before_last_pcr_value_pck_number; pes->last_pcr_value = pes->program->last_pcr_value; pes->last_pcr_value_pck_number = pes->program->last_pcr_value_pck_number; - } else if (pes->pes_len && (pes->data_len + data_size == pes->pes_len + 6)) { + } else if (pes->pes_len && (pes->data_len + data_size == pes->pes_len + 6)) { /* 6 = startcode+stream_id+length*/ /*reassemble pes*/ if (pes->data) pes->data = (char*)gf_realloc(pes->data, pes->data_len+data_size); @@ -2070,7 +2101,7 @@ static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_H /*PES first fragment: flush previous packet*/ if (flush_pes && pes->data) { - gf_m2ts_flush_pes(ts, pes, hdr); + gf_m2ts_flush_pes(ts, pes); if (!data_size) return; } /*we need to wait for first packet of PES*/ @@ -2081,7 +2112,7 @@ static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_H /*reassemble*/ if (pes->data){ pes->data = (char*)gf_realloc(pes->data, pes->data_len+data_size); - //printf("[MPEG-2 TS] REALLOC \n"); + //fprintf(stderr, "[MPEG-2 TS] REALLOC \n"); }else{ pes->data = (char*)gf_malloc(data_size); } @@ -2094,7 +2125,7 @@ static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_H GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] PID %d: Got PES packet len %d\n", pes->pid, pes->pes_len)); if (pes->pes_len + 6 == pes->data_len) { - gf_m2ts_flush_pes(ts, pes, hdr); + gf_m2ts_flush_pes(ts, pes); } } } @@ -2157,7 +2188,7 @@ static void gf_m2ts_process_packet(GF_M2TS_Demuxer *ts, unsigned char *data) //#if DEBUG_TS_PACKET GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] Packet PID %d\n", hdr.pid)); //#endif - //printf("[MPEG-2 TS] Packet PID %d\n", hdr.pid); + paf = NULL; payload_size = 184; pos = 4; @@ -2245,6 +2276,7 @@ static void gf_m2ts_process_packet(GF_M2TS_Demuxer *ts, unsigned char *data) es->program->before_last_pcr_value_pck_number = es->program->last_pcr_value_pck_number; es->program->last_pcr_value_pck_number = ts->pck_number; es->program->last_pcr_value = paf->PCR_base * 300 + paf->PCR_ext; + if (!es->program->last_pcr_value) es->program->last_pcr_value = 1; pck.PTS = es->program->last_pcr_value; pck.stream = (GF_M2TS_PES *)es; if (paf->discontinuity_indicator) pck.flags = GF_M2TS_PES_PCK_DISCONTINUITY; @@ -2362,18 +2394,7 @@ void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *ts) if (es->flags & GF_M2TS_ES_IS_SECTION) { GF_M2TS_SECTION_ES *ses = (GF_M2TS_SECTION_ES *)es; - ses->sec->cc = -1; - ses->sec->length = 0; - ses->sec->received = 0; - gf_free(ses->sec->section); - ses->sec->section = NULL; - while (ses->sec->table) { - GF_M2TS_Table *t = ses->sec->table; - ses->sec->table = t->next; - gf_m2ts_reset_sections(t->sections); - gf_list_del(t->sections); - gf_free(t); - } + gf_m2ts_section_filter_reset(ses->sec); } else { GF_M2TS_PES *pes = (GF_M2TS_PES *)es; if (!pes || (pes->pid==pes->program->pmt_pid)) continue; @@ -2390,24 +2411,24 @@ void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *ts) if (pes->buf) gf_free(pes->buf); pes->buf = NULL; pes->buf_len = 0; + pes->before_last_pcr_value = pes->before_last_pcr_value_pck_number = 0; + pes->last_pcr_value = pes->last_pcr_value_pck_number = 0; + if (pes->program->pcr_pid==pes->pid) { + pes->program->last_pcr_value = pes->program->last_pcr_value_pck_number = 0; + pes->program->before_last_pcr_value = pes->program->before_last_pcr_value_pck_number = 0; + } } // gf_free(es); // ts->ess[i] = NULL; } -/* - if (ts->pat) { - ts->pat->cc = -1; - ts->pat->length = 0; - ts->pat->received = 0; - gf_free(ts->pat->section); - while (ts->pat->table) { - GF_M2TS_Table *t = ts->pat->table; - ts->pat->table = t->next; - if (t->data) gf_free(t->data); - gf_free(t); - } - } -*/ + + gf_m2ts_section_filter_reset(ts->cat); + gf_m2ts_section_filter_reset(ts->pat); + gf_m2ts_section_filter_reset(ts->sdt); + gf_m2ts_section_filter_reset(ts->nit); + gf_m2ts_section_filter_reset(ts->eit); + gf_m2ts_section_filter_reset(ts->tdt_tot); + } static void gf_m2ts_process_section_discard(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *es, GF_List *sections, u8 table_id, u16 ex_table_id, u8 version_number, u8 last_section_number, u32 status) @@ -2492,7 +2513,7 @@ GF_M2TS_Demuxer *gf_m2ts_demux_new() ts->eit = gf_m2ts_section_filter_new(NULL/*gf_m2ts_process_eit*/, 1); ts->tdt_tot = gf_m2ts_section_filter_new(gf_m2ts_process_tdt_tot, 1); -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE gf_dvb_mpe_init(ts); #endif @@ -2564,12 +2585,12 @@ void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts) if (ts->tdt_tot) gf_list_del(ts->SDTs); -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE gf_dvb_mpe_shutdown(ts); #endif if(gf_list_count(ts->dsmcc_controler)){ -#ifndef GPAC_DISABLE_DSMCC +#ifdef GPAC_ENABLE_DSMCC GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord = (GF_M2TS_DSMCC_OVERLORD*)gf_list_get(ts->dsmcc_controler,0); gf_cleanup_dir(dsmcc_overlord->root_dir); gf_rmdir(dsmcc_overlord->root_dir); @@ -2581,7 +2602,7 @@ void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts) } while(gf_list_count(ts->ChannelAppList)){ -#ifndef GPAC_DISABLE_DSMCC +#ifdef GPAC_ENABLE_DSMCC GF_M2TS_CHANNEL_APPLICATION_INFO* ChanAppInfo = (GF_M2TS_CHANNEL_APPLICATION_INFO*)gf_list_get(ts->ChannelAppList,0); gf_m2ts_delete_channel_application_info(ChanAppInfo); gf_list_rem(ts->ChannelAppList,0); @@ -2589,12 +2610,22 @@ void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts) } gf_list_del(ts->ChannelAppList); + if (ts->requested_progs) { + assert(!gf_list_count(ts->requested_progs)); + gf_list_del(ts->requested_progs); + } + + if (ts->requested_pids) { + assert(!gf_list_count(ts->requested_pids)); + gf_list_del(ts->requested_pids); + } + gf_free(ts); } void gf_m2ts_print_info(GF_M2TS_Demuxer *ts) { -#ifndef GPAC_DISABLE_MPE +#ifdef GPAC_ENABLE_MPE gf_m2ts_print_mpe_info(ts); #endif } @@ -2712,7 +2743,18 @@ restart_file: gf_sleep(3000); } } - if (feof(ts->file)) GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TSDemux] EOS reached\n")); + if (feof(ts->file)) { + u32 i; + for (i=0; iess[i]) { + if (ts->ess[i]->flags & GF_M2TS_ES_IS_PES) { + gf_m2ts_flush_pes(ts, (GF_M2TS_PES *) ts->ess[i]); + ts->on_event(ts, GF_M2TS_EVT_EOS, (GF_M2TS_PES *) ts->ess[i]); + } + } + } + GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[M2TSDemux] EOS reached\n")); + } next_segment_setup: if (ts->run_state && ts->query_next) { @@ -3109,6 +3151,134 @@ GF_Err TSDemux_DemuxPlay(GF_M2TS_Demuxer *ts){ } +Bool gf_m2ts_probe_file(const char *fileName) +{ + char buf[188]; + u32 count = 10; + FILE *t = gf_f64_open(fileName, "rb"); + while (t && count) { + u32 read = fread(buf, 1, 188, t); + if (!read) { + count = 0; + break; + } + if (buf[0] != 0x47) + break; + if (read<188) + count = 0; + else count--; + } + if (t) fclose(t); + return count ? 0 : 1; +} + +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[2] &= 0x1; + ptr[2] |= (unsigned char)((TS&0x0003f8000)>>14); + ptr[3] = (unsigned char)((TS&0x000007f80)>>7); + ptr[4] &= 0x1; + ptr[4] |= (unsigned char)((TS&0x00000007f)<<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); +} + +#define ADJUST_TIMESTAMP(_TS) \ + if (_TS < (u64) -ts_shift) _TS = pcr_mod + _TS + ts_shift; \ + else _TS = _TS + ts_shift; \ + while (_TS > pcr_mod) _TS -= pcr_mod; \ + + +GF_Err gf_m2ts_restamp(char *buffer, u32 size, s64 ts_shift, u8 *is_pes) +{ + u32 done = 0; + u64 pcr_mod; +// if (!ts_shift) return GF_OK; + + pcr_mod = 0x80000000; + pcr_mod*=4; + while (done + 188 <= size) { + char *pesh; + u8 *pck; + u64 pcr_base=0, pcr_ext=0; + u16 pid; + u8 adaptation_field, adaptation_field_length; + + pck = buffer+done; + if (pck[0]!=0x47) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS Restamp] Invalid sync byte %X\n", pck[0])); + return GF_NON_COMPLIANT_BITSTREAM; + } + pid = ((pck[1] & 0x1f) <<8 ) + pck[2]; + + adaptation_field_length = 0; + adaptation_field = (pck[3] >> 4) & 0x3; + if ((adaptation_field==2) || (adaptation_field==3)) { + adaptation_field_length = pck[4]; + if ( pck[5]&0x10 /*PCR_flag*/) { + pcr_base = (((u64)pck[6])<<25) + (pck[7]<<17) + (pck[8]<<9) + (pck[9]<<1) + (pck[10]>>7); + pcr_ext = ((pck[10]&1)<<8) + pck[11]; + + ADJUST_TIMESTAMP(pcr_base); + + pck[6] = (unsigned char)(0xff&(pcr_base>>25)); + pck[7] = (unsigned char)(0xff&(pcr_base>>17)); + pck[8] = (unsigned char)(0xff&(pcr_base>>9)); + pck[9] = (unsigned char)(0xff&(pcr_base>>1)); + pck[10] = (unsigned char)(((0x1&pcr_base)<<7) | 0x7e | ((0x100&pcr_ext)>>8)); + if (pcr_ext != ((pck[10]&1)<<8) + pck[11]) { + GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[M2TS Restamp] Sanity check failed for PCR restamping\n")); + return GF_IO_ERR; + } + pck[11] = (unsigned char)(0xff&pcr_ext); + } + } + 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]; + + if ((pesh[0]==0x00) && (pesh[1]==0x00) && (pesh[2]==0x01)) { + Bool has_pts, has_dts; + if ((pesh[6]&0xc0)!=0x80) { + done+=188; + continue; + } + has_pts = (pesh[7]&0x80); + has_dts = has_pts ? (pesh[7]&0x40) : 0; + + if (has_pts) { + u64 PTS; + if (((pesh[9]&0xe0)>>4)!=0x2) { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TS Restamp] PID %4d: Wrong PES header, PTS decoding: '0010' expected\n", pid)); + done+=188; + continue; + } + + PTS = gf_m2ts_get_pts(pesh + 9); + ADJUST_TIMESTAMP(PTS); + rewrite_pts_dts(pesh+9, PTS); + } + + if (has_dts) { + u64 DTS = gf_m2ts_get_pts(pesh + 14); + ADJUST_TIMESTAMP(DTS); + rewrite_pts_dts(pesh+14, DTS); + } + } else { + GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[M2TS Restamp] PID %4d: Wrong PES not beginning with start code\n", pid)); + } + done+=188; + } + return GF_OK; +} #endif /*GPAC_DISABLE_MPEG2TS*/ diff --git a/src/media_tools/reedsolomon.c b/src/media_tools/reedsolomon.c index c0b9c6b..d6f3f5f 100644 --- a/src/media_tools/reedsolomon.c +++ b/src/media_tools/reedsolomon.c @@ -16,6 +16,9 @@ #include #include +#ifdef GPAC_ENABLE_MPE + + /* This is one of 14 irreducible polynomials * of degree 8 and cycle length 255. (Ch 5, pp. 275, Magnetic Recording) * The high order 1 bit is implicit */ @@ -438,10 +441,10 @@ correct_errors_erasures (unsigned char codeword[], print_parity (void) { int i; - printf("Parity Bytes: "); + fprintf(stderr, "Parity Bytes: "); for (i = 0; i < NPAR; i++) - printf("[%d]:%x, ",i,pBytes[i]); - printf("\n"); + fprintf(stderr, "[%d]:%x, ",i,pBytes[i]); + fprintf(stderr, "\n"); } @@ -449,10 +452,10 @@ correct_errors_erasures (unsigned char codeword[], print_syndrome (void) { int i; - printf("Syndrome Bytes: "); + fprintf(stderr, "Syndrome Bytes: "); for (i = 0; i < NPAR; i++) - printf("[%d]:%x, ",i,synBytes[i]); - printf("\n"); + fprintf(stderr, "[%d]:%x, ",i,synBytes[i]); + fprintf(stderr, "\n"); } /* Append the parity bytes onto the end of the message */ @@ -507,7 +510,7 @@ correct_errors_erasures (unsigned char codeword[], int i; for (i = 0; i < 3; i++) { - printf(" inv log S[%d]/S[%d] = %d\n", i, i+1, + fprintf(stderr, " inv log S[%d]/S[%d] = %d\n", i, i+1, glog[gmult(synBytes[i], ginv(synBytes[i+1]))]); } } @@ -567,3 +570,5 @@ correct_errors_erasures (unsigned char codeword[], build_codeword(msg, nbytes, dst); } + + #endif //GPAC_ENABLE_MPE diff --git a/src/media_tools/saf.c b/src/media_tools/saf.c index 79e777a..2f7024c 100644 --- a/src/media_tools/saf.c +++ b/src/media_tools/saf.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / LASeR codec sub-project diff --git a/src/media_tools/text_import.c b/src/media_tools/text_import.c index 4abc7e8..8b4e181 100644 --- a/src/media_tools/text_import.c +++ b/src/media_tools/text_import.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media Tools sub-project @@ -40,6 +41,7 @@ enum GF_TEXT_IMPORT_SUB, GF_TEXT_IMPORT_TTXT, GF_TEXT_IMPORT_TEXML, + GF_TEXT_IMPORT_WEBVTT, }; #define REM_TRAIL_MARKS(__str, __sep) while (1) { \ @@ -117,8 +119,10 @@ static GF_Err gf_text_guess_format(char *filename, u32 *fmt) if (strstr(szLine, "x-quicktime-tx3g") || strstr(szLine, "text3GTrack")) *fmt = GF_TEXT_IMPORT_TEXML; else if (strstr(szLine, "TextStream")) *fmt = GF_TEXT_IMPORT_TTXT; } + else if (strstr(szLine, "WEBVTT") ) + *fmt = GF_TEXT_IMPORT_WEBVTT; else if (strstr(szLine, " --> ") ) - *fmt = GF_TEXT_IMPORT_SRT; + *fmt = GF_TEXT_IMPORT_SRT; /* might want to change the default to WebVTT */ fclose(test); return GF_OK; @@ -129,9 +133,16 @@ static GF_Err gf_text_guess_format(char *filename, u32 *fmt) #define TTXT_DEFAULT_HEIGHT 60 #define TTXT_DEFAULT_FONT_SIZE 18 -static void gf_text_get_video_size(GF_ISOFile *dest, u32 *width, u32 *height) +static void gf_text_get_video_size(GF_MediaImporter *import, u32 *width, u32 *height) { u32 w, h, f_w, f_h, i; + GF_ISOFile *dest = import->dest; + + if (import->text_track_width && import->text_track_height) { + (*width) = import->text_track_width; + (*height) = import->text_track_height; + return; + } f_w = f_h = 0; for (i=0; idest, &w, &h); + gf_text_get_video_size(import, &w, &h); /*have to work with default - use max size (if only one video, this means the text region is the entire display, and with bottom alignment things should be fine...*/ @@ -355,9 +366,10 @@ static GF_Err gf_text_import_srt(GF_MediaImporter *import) sd->default_pos.top = sd->default_pos.left = sd->default_pos.right = sd->default_pos.bottom = 0; } else { if ((sd->default_pos.bottom==sd->default_pos.top) || (sd->default_pos.right==sd->default_pos.left)) { - sd->default_pos.top = sd->default_pos.left = 0; - sd->default_pos.right = import->twidth ? import->twidth : w; - sd->default_pos.bottom = import->theight ? import->theight : h; + sd->default_pos.left = import->text_x; + sd->default_pos.top = import->text_y; + sd->default_pos.right = (import->text_width ? import->text_width : w) + sd->default_pos.left; + sd->default_pos.bottom = (import->text_height ? import->text_height : h) + sd->default_pos.top; } } @@ -388,7 +400,6 @@ static GF_Err gf_text_import_srt(GF_MediaImporter *import) if (sOK) REM_TRAIL_MARKS(szLine, "\r\n\t ") if (!sOK || !strlen(szLine)) { - state = 0; rec.style_flags = 0; rec.startCharOffset = rec.endCharOffset = 0; if (txt_line) { @@ -396,20 +407,24 @@ static GF_Err gf_text_import_srt(GF_MediaImporter *import) GF_TextSample * empty_samp = gf_isom_new_text_sample(); s = gf_isom_text_to_sample(empty_samp); gf_isom_delete_text_sample(empty_samp); - s->DTS = (u64) ((timescale*prev_end)/1000); + if (state<=2) { + s->DTS = (u64) ((timescale*prev_end)/1000); + s->IsRAP = 1; + gf_isom_add_sample(import->dest, track, 1, s); + nb_samp++; + } + gf_isom_sample_del(&s); + } + + s = gf_isom_text_to_sample(samp); + if (state<=2) { + s->DTS = (u64) ((timescale*start)/1000); s->IsRAP = 1; gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); nb_samp++; + prev_end = end; } - - s = gf_isom_text_to_sample(samp); - s->DTS = (u64) ((timescale*start)/1000); - s->IsRAP = 1; - gf_isom_add_sample(import->dest, track, 1, s); - gf_isom_sample_del(&s); - nb_samp++; - prev_end = end; txt_line = 0; char_len = 0; set_start_char = set_end_char = 0; @@ -420,6 +435,7 @@ static GF_Err gf_text_import_srt(GF_MediaImporter *import) gf_set_progress("Importing SRT", gf_f64_tell(srt_in), file_size); if (duration && (end >= duration)) break; } + state = 0; if (!sOK) break; continue; } @@ -436,12 +452,15 @@ static GF_Err gf_text_import_srt(GF_MediaImporter *import) break; case 1: if (sscanf(szLine, "%u:%u:%u,%u --> %u:%u:%u,%u", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems) != 8) { - e = gf_import_message(import, GF_CORRUPTED_DATA, "Error scanning SRT frame %d timing", curLine); - goto exit; + sh = eh = 0; + if (sscanf(szLine, "%u:%u,%u --> %u:%u,%u", &sm, &ss, &sms, &em, &es, &ems) != 6) { + e = gf_import_message(import, GF_CORRUPTED_DATA, "Error scanning SRT frame %d timing", curLine); + goto exit; + } } start = (3600*sh + 60*sm + ss)*1000 + sms; if (startin_name, "rt"); + gf_f64_seek(vtt_in, 0, SEEK_END); + file_size = gf_f64_tell(vtt_in); + gf_f64_seek(vtt_in, 0, SEEK_SET); + + unicode_type = gf_text_get_utf_type(vtt_in); + if (unicode_type<0) { + fclose(vtt_in); + return gf_import_message(import, GF_NOT_SUPPORTED, "Unsupported WebVTT UTF encoding"); + } + + cfg = NULL; + 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 = 1000; + } + timescale = import->esd->slConfig->timestampResolution; + if (!timescale) timescale = 1000; + + /*explicit text config*/ + if (import->esd->decoderConfig && import->esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_GEN_SUB_CFG_TAG) { + cfg = (GF_GenericSubtitleConfig *) import->esd->decoderConfig->decoderSpecificInfo; + import->esd->decoderConfig->decoderSpecificInfo = NULL; + } + ID = import->esd->ESID; + OCR_ES_ID = import->esd->OCRESID; + } else { + timescale = 1000; + OCR_ES_ID = ID = 0; + } + + if (cfg && cfg->timescale) timescale = cfg->timescale; + track = gf_isom_new_track(import->dest, ID, GF_ISOM_MEDIA_SUBM, timescale); + if (!track) { + fclose(vtt_in); + return gf_import_message(import, gf_isom_last_error(import->dest), "Error creating WebVTT track"); + } + 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); + + if (OCR_ES_ID) gf_isom_set_track_reference(import->dest, track, GF_ISOM_REF_OCR, OCR_ES_ID); + + /*setup track*/ + if (cfg) { + /*set track info*/ + gf_isom_set_track_layout_info(import->dest, track, cfg->text_width<<16, cfg->text_height<<16, 0, 0, cfg->layer); + + /*and set sample descriptions*/ + count = gf_list_count(cfg->sample_descriptions); + for (i=0; isample_descriptions, i); + gf_isom_new_generic_subtitle_description(import->dest, track, content_encoding, xml_schema_loc, mime_ns, is_xml, NULL, NULL, &state); + } + gf_import_message(import, GF_OK, "WebVTT import - text track %d x %d", cfg->text_width, cfg->text_height); + gf_odf_desc_del((GF_Descriptor *)cfg); + } else { + u32 w; + u32 h; + + gf_text_get_video_size(import, &w, &h); + gf_isom_set_track_layout_info(import->dest, track, w<<16, h<<16, 0, 0, 0); + + gf_isom_new_generic_subtitle_description(import->dest, track, content_encoding, xml_schema_loc, mime_ns, is_xml, NULL, NULL, &state); + + gf_import_message(import, GF_OK, "WebVTT import"); + } + gf_text_import_set_language(import, track); + duration = (u32) (((Double) import->duration)*timescale/1000.0); + + e = GF_OK; + state = 0; + end = 0; + prev_end = 0; + txt_line = 0; + start = 0; + nb_samp = 0; + curCue = 0; + samp = gf_isom_new_generic_subtitle_sample(); + + sOK = gf_text_get_utf8_line(szLine, 2048, vtt_in, unicode_type); + len = strlen(szLine); + if (len < 6 || strnicmp(szLine, "WEBVTT", 6)) { + e = gf_import_message(import, GF_CORRUPTED_DATA, "Bad WebVTT formatting - expecting WEBVTT file signature", szLine); + goto exit; + } else if (len > 6) { + /* ignore additional text on the same line as WEBVTT file signature */ + } + gf_isom_generic_subtitle_sample_add_text(samp, szLine, len); + txt_line ++; + gf_isom_generic_subtitle_sample_add_text(samp, "\n", 1); + txt_line ++; + + first_samp = 1; + while (1) { + sOK = gf_text_get_utf8_line(szLine, 2048, vtt_in, unicode_type); + if (sOK) REM_TRAIL_MARKS(szLine, "\r\n\t ") + if (!sOK || !strlen(szLine)) { + state = 0; + if (txt_line) { + if (prev_end && (start > prev_end)) { + GF_GenericSubtitleSample * empty_samp = gf_isom_new_generic_subtitle_sample(); + s = gf_isom_generic_subtitle_to_sample(empty_samp); + gf_isom_delete_generic_subtitle_sample(empty_samp); + s->DTS = (u64) ((timescale*prev_end)/1000); + s->IsRAP = 1; + e = gf_isom_add_sample(import->dest, track, 1, s); + gf_isom_sample_del(&s); + nb_samp++; + } + + s = gf_isom_generic_subtitle_to_sample(samp); + s->DTS = (u64) ((timescale*start)/1000); + s->IsRAP = 1; + e = gf_isom_add_sample(import->dest, track, 1, s); + gf_isom_sample_del(&s); + nb_samp++; + txt_line = 0; + prev_end = end; + gf_isom_generic_subtitle_reset(samp); + + //gf_import_progress(import, nb_samp, nb_samp+1); + gf_set_progress("Importing WebVTT", gf_f64_tell(vtt_in), file_size); + if (duration && (end >= duration)) break; + } + if (!sOK) break; + continue; + } + + switch (state) { + case 0: + if (!strstr(szLine, "-->")) { + /*cue id = szLine */ + state = 1; + gf_isom_generic_subtitle_sample_add_text(samp, szLine, strlen(szLine)); + txt_line ++; + gf_isom_generic_subtitle_sample_add_text(samp, "\n", 1); + txt_line ++; + break; + } + + case 1: + /* TODO: fix the parsing of time stamps to be compliant */ + if (sscanf(szLine, "%u:%u:%u.%u --> %u:%u:%u.%u %s", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems, szSettings) < 8) { + e = gf_import_message(import, GF_CORRUPTED_DATA, "Error scanning WebVTT cue timing for cue %d", curCue); + goto exit; + } else { + /* ignore cue settings */ + } + curCue++; + start = (3600*sh + 60*sm + ss)*1000 + sms; + end = (3600*eh + 60*em + es)*1000 + ems; + /*make stream start at 0 by inserting a fake AU*/ + if (first_samp && (start>0)) { + s = gf_isom_generic_subtitle_to_sample(samp); + s->DTS = 0; + gf_isom_add_sample(import->dest, track, 1, s); + gf_isom_sample_del(&s); + nb_samp++; + } + gf_isom_generic_subtitle_sample_add_text(samp, szLine, strlen(szLine)); + txt_line ++; + gf_isom_generic_subtitle_sample_add_text(samp, "\n", 1); + txt_line ++; + state = 2; + break; + + default: /*state = 2 */ + /*reset only when text is present*/ + first_samp = 0; + + ptr = (char *) szLine; + len = gf_utf8_mbstowcs(uniLine, 5000, (const char **) &ptr); + if (len == (u32) -1) { + e = gf_import_message(import, GF_CORRUPTED_DATA, "Invalid UTF data in cue %d", curCue); + goto exit; + } + gf_isom_generic_subtitle_sample_add_text(samp, szLine, len); + txt_line ++; + gf_isom_generic_subtitle_sample_add_text(samp, "\n", 1); + txt_line ++; + break; + } + if (duration && (start >= duration)) break; + } + + gf_isom_delete_generic_subtitle_sample(samp); + /*do not add any empty sample at the end since it modifies track duration and is not needed - it is the player job + to figure out when to stop displaying the last text sample + However update the last sample duration*/ + gf_isom_set_last_sample_duration(import->dest, track, (u32) (end-start) ); + gf_set_progress("Importing WebVTT", nb_samp, nb_samp); + +exit: + if (e) gf_isom_remove_track(import->dest, track); + fclose(vtt_in); + return e; +} + static GF_Err gf_text_import_sub(GF_MediaImporter *import) { FILE *sub_in; @@ -678,7 +945,7 @@ static GF_Err gf_text_import_sub(GF_MediaImporter *import) } else { u32 w, h; GF_TextSampleDescriptor *sd; - gf_text_get_video_size(import->dest, &w, &h); + gf_text_get_video_size(import, &w, &h); /*have to work with default - use max size (if only one video, this means the text region is the entire display, and with bottom alignment things should be fine...*/ @@ -700,9 +967,10 @@ static GF_Err gf_text_import_sub(GF_MediaImporter *import) sd->default_pos.top = sd->default_pos.left = sd->default_pos.right = sd->default_pos.bottom = 0; } else { if ((sd->default_pos.bottom==sd->default_pos.top) || (sd->default_pos.right==sd->default_pos.left)) { - sd->default_pos.top = sd->default_pos.left = 0; - sd->default_pos.right = import->twidth ? import->twidth : w; - sd->default_pos.bottom = import->theight ? import->theight : h; + sd->default_pos.left = import->text_x; + sd->default_pos.top = import->text_y; + sd->default_pos.right = (import->text_width ? import->text_width : w) + sd->default_pos.left; + sd->default_pos.bottom = (import->text_height ? import->text_height : h) + sd->default_pos.top; } } @@ -1702,6 +1970,7 @@ GF_Err gf_import_timed_text(GF_MediaImporter *import) case GF_TEXT_IMPORT_SUB: return gf_text_import_sub(import); case GF_TEXT_IMPORT_TTXT: return gf_text_import_ttxt(import); case GF_TEXT_IMPORT_TEXML: return gf_text_import_texml(import); + case GF_TEXT_IMPORT_WEBVTT: return gf_text_import_webvtt(import); default: return GF_BAD_PARAM; } } diff --git a/src/odf/desc_private.c b/src/odf/desc_private.c index cb3059b..df63d5e 100644 --- a/src/odf/desc_private.c +++ b/src/odf/desc_private.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/descriptors.c b/src/odf/descriptors.c index 780aef6..ea42ff4 100644 --- a/src/odf/descriptors.c +++ b/src/odf/descriptors.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project @@ -508,6 +509,16 @@ void gf_odf_avc_cfg_del(GF_AVCConfig *cfg) gf_free(sl); } gf_list_del(cfg->pictureParameterSets); + + if (cfg->sequenceParameterSetExtensions) { + while (gf_list_count(cfg->sequenceParameterSetExtensions)) { + GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(cfg->sequenceParameterSetExtensions, 0); + gf_list_rem(cfg->sequenceParameterSetExtensions, 0); + if (sl->data) gf_free(sl->data); + gf_free(sl); + } + gf_list_del(cfg->pictureParameterSets); + } gf_free(cfg); } @@ -537,7 +548,27 @@ GF_Err gf_odf_avc_cfg_write(GF_AVCConfig *cfg, char **outData, u32 *outSize) gf_bs_write_int(bs, sl->size, 16); gf_bs_write_data(bs, sl->data, sl->size); } - + switch (cfg->AVCProfileIndication) { + case 100: + case 110: + case 122: + case 144: + gf_bs_write_int(bs, 0xFF, 6); + gf_bs_write_int(bs, cfg->chroma_format, 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); + + count = cfg->sequenceParameterSetExtensions ? gf_list_count(cfg->sequenceParameterSetExtensions) : 0; + gf_bs_write_u8(bs, count); + for (i=0; isequenceParameterSetExtensions, i); + gf_bs_write_u16(bs, sl->size); + gf_bs_write_data(bs, sl->data, sl->size); + } + break; + } *outSize = 0; *outData = NULL; gf_bs_get_content(bs, outData, outSize); @@ -574,6 +605,33 @@ GF_AVCConfig *gf_odf_avc_cfg_read(char *dsi, u32 dsi_size) gf_bs_read_data(bs, sl->data, sl->size); gf_list_add(avcc->pictureParameterSets, sl); } + switch (avcc->AVCProfileIndication) { + case 100: + case 110: + case 122: + case 144: + gf_bs_read_int(bs, 6); + avcc->chroma_format = gf_bs_read_int(bs, 2); + gf_bs_read_int(bs, 5); + avcc->luma_bit_depth = 8 + gf_bs_read_int(bs, 3); + gf_bs_read_int(bs, 5); + avcc->chroma_bit_depth = 8 + gf_bs_read_int(bs, 3); + + count = gf_bs_read_int(bs, 8); + if (count) { + avcc->sequenceParameterSetExtensions = gf_list_new(); + for (i=0; isize = gf_bs_read_u16(bs); + sl->data = (char *)gf_malloc(sizeof(char) * sl->size); + gf_bs_read_data(bs, sl->data, sl->size); + gf_list_add(avcc->sequenceParameterSetExtensions, sl); + } + } + break; + } + + gf_bs_del(bs); return avcc; } diff --git a/src/odf/ipmpx_code.c b/src/odf/ipmpx_code.c index 145799b..db5b139 100644 --- a/src/odf/ipmpx_code.c +++ b/src/odf/ipmpx_code.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/ipmpx_dump.c b/src/odf/ipmpx_dump.c index 3c708fd..8755ba9 100644 --- a/src/odf/ipmpx_dump.c +++ b/src/odf/ipmpx_dump.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/ipmpx_parse.c b/src/odf/ipmpx_parse.c index 9e8e6ce..2e4bafe 100644 --- a/src/odf/ipmpx_parse.c +++ b/src/odf/ipmpx_parse.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/oci_codec.c b/src/odf/oci_codec.c index b84f7a2..5b6cd35 100644 --- a/src/odf/oci_codec.c +++ b/src/odf/oci_codec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/odf_code.c b/src/odf/odf_code.c index 059079b..8707162 100644 --- a/src/odf/odf_code.c +++ b/src/odf/odf_code.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/odf_codec.c b/src/odf/odf_codec.c index 1fec14e..cbf816a 100644 --- a/src/odf/odf_codec.c +++ b/src/odf/odf_codec.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/odf_command.c b/src/odf/odf_command.c index a24d02b..2c34bd6 100644 --- a/src/odf/odf_command.c +++ b/src/odf/odf_command.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/odf_dump.c b/src/odf/odf_dump.c index 12057c6..1445b88 100644 --- a/src/odf/odf_dump.c +++ b/src/odf/odf_dump.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project @@ -53,10 +54,12 @@ GF_Err gf_odf_dump_com(void *p, FILE *trace, u32 indent, Bool XMTDump) return gf_odf_dump_esd_update((GF_ESDUpdate *)com, trace, indent, XMTDump); case GF_ODF_ESD_REMOVE_TAG: return gf_odf_dump_esd_remove((GF_ESDRemove *)com, trace, indent, XMTDump); +#ifndef GPAC_MINIMAL_ODF case GF_ODF_IPMP_UPDATE_TAG: return gf_odf_dump_ipmp_update((GF_IPMPUpdate *)com, trace, indent, XMTDump); case GF_ODF_IPMP_REMOVE_TAG: return gf_odf_dump_ipmp_remove((GF_IPMPRemove *)com, trace, indent, XMTDump); +#endif default: return gf_odf_dump_base_command((GF_BaseODCom *) com, trace, indent, XMTDump); } @@ -109,6 +112,17 @@ GF_Err gf_odf_dump_desc(void *ptr, FILE *trace, u32 indent, Bool XMTDump) return gf_odf_dump_dcd((GF_DecoderConfig *)desc, trace, indent, XMTDump); case GF_ODF_SLC_TAG: return gf_odf_dump_slc((GF_SLConfig *)desc, trace, indent, XMTDump); + case GF_ODF_ESD_INC_TAG: + return gf_odf_dump_esd_inc((GF_ES_ID_Inc *)desc, trace, indent, XMTDump); + case GF_ODF_ESD_REF_TAG: + return gf_odf_dump_esd_ref((GF_ES_ID_Ref *)desc, trace, indent, XMTDump); + case GF_ODF_ISOM_IOD_TAG: + return gf_odf_dump_isom_iod((GF_IsomInitialObjectDescriptor *)desc, trace, indent, XMTDump); + case GF_ODF_ISOM_OD_TAG: + return gf_odf_dump_isom_od((GF_IsomObjectDescriptor *)desc, trace, indent, XMTDump); + case GF_ODF_OD_TAG: + return gf_odf_dump_od((GF_ObjectDescriptor *)desc, trace, indent, XMTDump); +#ifndef GPAC_MINIMAL_ODF case GF_ODF_CC_TAG: return gf_odf_dump_cc((GF_CCDescriptor *)desc, trace, indent, XMTDump); case GF_ODF_CC_DATE_TAG: @@ -117,10 +131,6 @@ GF_Err gf_odf_dump_desc(void *ptr, FILE *trace, u32 indent, Bool XMTDump) return gf_odf_dump_cc_name((GF_CC_Name *)desc, trace, indent, XMTDump); case GF_ODF_CI_TAG: return gf_odf_dump_ci((GF_CIDesc *)desc, trace, indent, XMTDump); - case GF_ODF_ESD_INC_TAG: - return gf_odf_dump_esd_inc((GF_ES_ID_Inc *)desc, trace, indent, XMTDump); - case GF_ODF_ESD_REF_TAG: - return gf_odf_dump_esd_ref((GF_ES_ID_Ref *)desc, trace, indent, XMTDump); case GF_ODF_TEXT_TAG: return gf_odf_dump_exp_text((GF_ExpandedTextual *)desc, trace, indent, XMTDump); case GF_ODF_EXT_PL_TAG: @@ -136,12 +146,6 @@ GF_Err gf_odf_dump_desc(void *ptr, FILE *trace, u32 indent, Bool XMTDump) return gf_odf_dump_kw((GF_KeyWord *)desc, trace, indent, XMTDump); case GF_ODF_LANG_TAG: return gf_odf_dump_lang((GF_Language *)desc, trace, indent, XMTDump); - case GF_ODF_ISOM_IOD_TAG: - return gf_odf_dump_isom_iod((GF_IsomInitialObjectDescriptor *)desc, trace, indent, XMTDump); - case GF_ODF_ISOM_OD_TAG: - return gf_odf_dump_isom_od((GF_IsomObjectDescriptor *)desc, trace, indent, XMTDump); - case GF_ODF_OD_TAG: - return gf_odf_dump_od((GF_ObjectDescriptor *)desc, trace, indent, XMTDump); case GF_ODF_OCI_DATE_TAG: return gf_odf_dump_oci_date((GF_OCI_Data *)desc, trace, indent, XMTDump); case GF_ODF_OCI_NAME_TAG: @@ -164,6 +168,11 @@ GF_Err gf_odf_dump_desc(void *ptr, FILE *trace, u32 indent, Bool XMTDump) return gf_odf_dump_segment((GF_Segment *)desc, trace, indent, XMTDump); case GF_ODF_MEDIATIME_TAG: return gf_odf_dump_mediatime((GF_MediaTime *)desc, trace, indent, XMTDump); + case GF_ODF_IPMP_TL_TAG: + return gf_odf_dump_ipmp_tool_list((GF_IPMP_ToolList*)desc, trace, indent, XMTDump); + case GF_ODF_IPMP_TOOL_TAG: + return gf_odf_dump_ipmp_tool((GF_IPMP_Tool*)desc, trace, indent, XMTDump); +#endif //GPAC_MINIMAL_ODF case GF_ODF_TEXT_CFG_TAG: return gf_odf_dump_txtcfg((GF_TextConfig *)desc, trace, indent, XMTDump); case GF_ODF_MUXINFO_TAG: @@ -174,10 +183,6 @@ GF_Err gf_odf_dump_desc(void *ptr, FILE *trace, u32 indent, Bool XMTDump) return gf_odf_dump_laser_cfg((GF_LASERConfig *)desc, trace, indent, XMTDump); case GF_ODF_UI_CFG_TAG: return gf_odf_dump_ui_cfg((GF_UIConfig *)desc, trace, indent, XMTDump); - case GF_ODF_IPMP_TL_TAG: - return gf_odf_dump_ipmp_tool_list((GF_IPMP_ToolList*)desc, trace, indent, XMTDump); - case GF_ODF_IPMP_TOOL_TAG: - return gf_odf_dump_ipmp_tool((GF_IPMP_Tool*)desc, trace, indent, XMTDump); case GF_ODF_AUX_VIDEO_DATA: return gf_odf_dump_aux_vid((GF_AuxVideoDescriptor *)desc, trace, indent, XMTDump); default: @@ -297,6 +302,7 @@ static void DumpIntHex(FILE *trace, const char *attName, u32 val, u32 indent, B EndAttribute(trace, indent, XMTDump); } +#ifndef GPAC_MINIMAL_ODF static void DumpFloat(FILE *trace, const char *attName, Float val, u32 indent, Bool XMTDump) { StartAttribute(trace, attName, indent, XMTDump); @@ -310,6 +316,23 @@ static void DumpDouble(FILE *trace, const char *attName, Double val, u32 indent, fprintf(trace, "%g", val); EndAttribute(trace, indent, XMTDump); } +static void DumpBin128(FILE *trace, const char *name, char *data, u32 indent, Bool XMTDump) +{ + u32 i; + if (!name ||!data) return; + StartAttribute(trace, name, indent, XMTDump); + fprintf(trace, "0x"); + i=0; + while (!data[i] && (i<16)) i++; + if (i==16) { + fprintf(trace, "00"); + } else { + for (; i<16; i++) fprintf(trace, "%02X", (unsigned char) data[i]); + } + EndAttribute(trace, indent, XMTDump); +} + +#endif static void DumpBool(FILE *trace, const char *attName, u32 val, u32 indent, Bool XMTDump) { @@ -342,22 +365,6 @@ static void DumpData(FILE *trace, const char *name, char *data, u64 dataLength, } EndAttribute(trace, indent, XMTDump); } -static void DumpBin128(FILE *trace, const char *name, char *data, u32 indent, Bool XMTDump) -{ - u32 i; - if (!name ||!data) return; - StartAttribute(trace, name, indent, XMTDump); - fprintf(trace, "0x"); - i=0; - while (!data[i] && (i<16)) i++; - if (i==16) { - fprintf(trace, "00"); - } else { - for (; i<16; i++) fprintf(trace, "%02X", (unsigned char) data[i]); - } - EndAttribute(trace, indent, XMTDump); -} - GF_Err DumpDescList(GF_List *list, FILE *trace, u32 indent, const char *ListName, Bool XMTDump, Bool no_skip_empty) { @@ -1027,6 +1034,58 @@ GF_Err gf_odf_dump_slc(GF_SLConfig *sl, FILE *trace, u32 indent, Bool XMTDump) return GF_OK; } +GF_Err gf_odf_dump_default(GF_DefaultDescriptor *dd, FILE *trace, u32 indent, Bool XMTDump) +{ + if (dd->tag == GF_ODF_DSI_TAG) { + StartDescDump(trace, "DecoderSpecificInfo", indent, XMTDump); + indent++; + if (XMTDump) { + DumpString(trace, "type", "auto", indent, XMTDump); + DumpData(trace, "src", dd->data, dd->dataLength, indent, XMTDump); + } else { + DumpData(trace, "info", dd->data, dd->dataLength, indent, XMTDump); + } + indent--; + if (XMTDump) { + EndSubElement(trace, indent, 1); + } else { + EndDescDump(trace, "", indent, 0); + } + } else { + StartDescDump(trace, "DefaultDescriptor", indent, XMTDump); + indent++; + DumpData(trace, "data", dd->data, dd->dataLength, indent, XMTDump); + indent--; + EndSubElement(trace, indent, XMTDump); + } + return GF_OK; +} + +GF_Err gf_odf_dump_esd_inc(GF_ES_ID_Inc *esd_inc, FILE *trace, u32 indent, Bool XMTDump) +{ + StartDescDump(trace, "ES_ID_Inc", indent, XMTDump); + indent++; + DumpInt(trace, "trackID", esd_inc->trackID, indent, XMTDump); + indent--; + EndAttributes(trace, indent, XMTDump); + EndDescDump(trace, "ES_ID_Inc", indent, XMTDump); + return GF_OK; +} + +GF_Err gf_odf_dump_esd_ref(GF_ES_ID_Ref *esd_ref, FILE *trace, u32 indent, Bool XMTDump) +{ + StartDescDump(trace, "ES_ID_Ref", indent, XMTDump); + indent++; + DumpInt(trace, "trackRef", esd_ref->trackRef, indent, XMTDump); + indent--; + EndAttributes(trace, indent, XMTDump); + EndDescDump(trace, "ES_ID_Ref", indent, XMTDump); + return GF_OK; +} + + +#ifndef GPAC_MINIMAL_ODF + GF_Err gf_odf_dump_cc(GF_CCDescriptor *ccd, FILE *trace, u32 indent, Bool XMTDump) { StartDescDump(trace, "ContentClassificationDescriptor", indent, XMTDump); @@ -1091,54 +1150,6 @@ GF_Err gf_odf_dump_ci(GF_CIDesc *cid, FILE *trace, u32 indent, Bool XMTDump) return GF_OK; } -GF_Err gf_odf_dump_default(GF_DefaultDescriptor *dd, FILE *trace, u32 indent, Bool XMTDump) -{ - if (dd->tag == GF_ODF_DSI_TAG) { - StartDescDump(trace, "DecoderSpecificInfo", indent, XMTDump); - indent++; - if (XMTDump) { - DumpString(trace, "type", "auto", indent, XMTDump); - DumpData(trace, "src", dd->data, dd->dataLength, indent, XMTDump); - } else { - DumpData(trace, "info", dd->data, dd->dataLength, indent, XMTDump); - } - indent--; - if (XMTDump) { - EndSubElement(trace, indent, 1); - } else { - EndDescDump(trace, "", indent, 0); - } - } else { - StartDescDump(trace, "DefaultDescriptor", indent, XMTDump); - indent++; - DumpData(trace, "data", dd->data, dd->dataLength, indent, XMTDump); - indent--; - EndSubElement(trace, indent, XMTDump); - } - return GF_OK; -} - -GF_Err gf_odf_dump_esd_inc(GF_ES_ID_Inc *esd_inc, FILE *trace, u32 indent, Bool XMTDump) -{ - StartDescDump(trace, "ES_ID_Inc", indent, XMTDump); - indent++; - DumpInt(trace, "trackID", esd_inc->trackID, indent, XMTDump); - indent--; - EndAttributes(trace, indent, XMTDump); - EndDescDump(trace, "ES_ID_Inc", indent, XMTDump); - return GF_OK; -} - -GF_Err gf_odf_dump_esd_ref(GF_ES_ID_Ref *esd_ref, FILE *trace, u32 indent, Bool XMTDump) -{ - StartDescDump(trace, "ES_ID_Ref", indent, XMTDump); - indent++; - DumpInt(trace, "trackRef", esd_ref->trackRef, indent, XMTDump); - indent--; - EndAttributes(trace, indent, XMTDump); - EndDescDump(trace, "ES_ID_Ref", indent, XMTDump); - return GF_OK; -} GF_Err gf_odf_dump_exp_text(GF_ExpandedTextual *etd, FILE *trace, u32 indent, Bool XMTDump) { @@ -1288,6 +1299,7 @@ GF_Err gf_odf_dump_lang(GF_Language *ld, FILE *trace, u32 indent, Bool XMTDump) if (!XMTDump) EndDescDump(trace, "LanguageDescriptor", indent, XMTDump); return GF_OK; } +#endif// GPAC_MINIMAL_ODF GF_Err gf_odf_dump_aux_vid(GF_AuxVideoDescriptor *ld, FILE *trace, u32 indent, Bool XMTDump) { @@ -1464,6 +1476,7 @@ GF_Err gf_odf_dump_isom_od(GF_IsomObjectDescriptor *od, FILE *trace, u32 indent, return GF_OK; } +#ifndef GPAC_MINIMAL_ODF GF_Err gf_odf_dump_oci_date(GF_OCI_Data *ocd, FILE *trace, u32 indent, Bool XMTDump) { StartDescDump(trace, "OCICreationDateDescriptor", indent, XMTDump); @@ -1668,6 +1681,7 @@ GF_Err gf_odf_dump_mediatime(GF_MediaTime *mt, FILE *trace, u32 indent, Bool XMT return GF_OK; } +#endif //GPAC_MINIMAL_ODF GF_Err gf_odf_dump_muxinfo(GF_MuxInfo *mi, FILE *trace, u32 indent, Bool XMTDump) { @@ -1719,6 +1733,7 @@ GF_Err gf_odf_dump_muxinfo(GF_MuxInfo *mi, FILE *trace, u32 indent, Bool XMTDump return GF_OK; } +#ifndef GPAC_MINIMAL_ODF GF_Err gf_odf_dump_ipmp_tool_list(GF_IPMP_ToolList *tl, FILE *trace, u32 indent, Bool XMTDump) { StartDescDump(trace, "IPMP_ToolListDescriptor", indent, XMTDump); @@ -1748,6 +1763,7 @@ GF_Err gf_odf_dump_ipmp_tool(GF_IPMP_Tool*t, FILE *trace, u32 indent, Bool XMTDu EndDescDump(trace, "IPMP_Tool", indent, XMTDump); return GF_OK; } +#endif //GPAC_MINIMAL_ODF GF_Err gf_odf_dump_od_update(GF_ODUpdate *com, FILE *trace, u32 indent, Bool XMTDump) @@ -1846,6 +1862,7 @@ GF_Err gf_odf_dump_esd_remove(GF_ESDRemove *com, FILE *trace, u32 indent, Bool X return GF_OK; } +#ifndef GPAC_MINIMAL_ODF GF_Err gf_odf_dump_ipmp_update(GF_IPMPUpdate *com, FILE *trace, u32 indent, Bool XMTDump) { if (XMTDump) { @@ -1878,6 +1895,7 @@ GF_Err gf_odf_dump_ipmp_remove(GF_IPMPRemove *com, FILE *trace, u32 indent, Bool EndSubElement(trace, indent, XMTDump); return GF_OK; } +#endif //GPAC_MINIMAL_ODF GF_Err gf_odf_dump_base_command(GF_BaseODCom *com, FILE *trace, u32 indent, Bool XMTDump) { diff --git a/src/odf/odf_parse.c b/src/odf/odf_parse.c index ab93f3e..3fa81e3 100644 --- a/src/odf/odf_parse.c +++ b/src/odf/odf_parse.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/qos.c b/src/odf/qos.c index f20702a..a7a8fd7 100644 --- a/src/odf/qos.c +++ b/src/odf/qos.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/odf/slc.c b/src/odf/slc.c index b0bd1e6..462df90 100644 --- a/src/odf/slc.c +++ b/src/odf/slc.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project diff --git a/src/scene_manager/encode_isom.c b/src/scene_manager/encode_isom.c index 021b4e5..6b37b2a 100644 --- a/src/scene_manager/encode_isom.c +++ b/src/scene_manager/encode_isom.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project @@ -268,6 +269,10 @@ static GF_Err gf_sm_import_stream(GF_SceneManager *ctx, GF_ISOFile *mp4, GF_ESD e = gf_media_import(&import); if (e) return e; + if (src->OCRESID) { + gf_isom_set_track_reference(mp4, gf_isom_get_track_by_id(mp4, import.final_trackID), GF_ISOM_REF_OCR, src->OCRESID); + } + i=0; while ((d = gf_list_enum(src->extensionDescriptors, &i))) { if (d->tag == GF_ODF_AUX_VIDEO_DATA) { diff --git a/src/scene_manager/loader_bt.c b/src/scene_manager/loader_bt.c index 78b908c..5ceeb21 100644 --- a/src/scene_manager/loader_bt.c +++ b/src/scene_manager/loader_bt.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project @@ -31,74 +32,6 @@ #include /*for key codes...*/ #include -#include -#include - - -void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName) -{ - u32 data_size = 0; - char *data = NULL; - char *buffer; - M_BitWrapper *bw = (M_BitWrapper *)node; - - if (!bw->buffer.buffer) return; - buffer = bw->buffer.buffer; - if (!strnicmp(buffer, "file://", 7)) { - char *url = gf_url_concatenate(fileName, buffer+7); - if (url) { - FILE *f = fopen(url, "rb"); - if (f) { - fseek(f, 0, SEEK_END); - data_size = ftell(f); - fseek(f, 0, SEEK_SET); - data = gf_malloc(sizeof(char)*data_size); - if (data) { - size_t s = fread(data, 1, data_size, f); - assert(s == data_size); - } - fclose(f); - } - gf_free(url); - } - } else { - Bool base_64 = 0; - if (!strnicmp(buffer, "data:application/octet-string", 29)) { - char *sep = strchr(bw->buffer.buffer, ','); - base_64 = strstr(bw->buffer.buffer, ";base64") ? 1 : 0; - if (sep) buffer = sep+1; - } - - if (base_64) { - data_size = 2*strlen(buffer); - data = (char*)gf_malloc(sizeof(char)*data_size); - if (data) - data_size = gf_base64_decode(buffer, strlen(buffer), data, data_size); - } else { - u32 i, c; - char s[3]; - data_size = strlen(buffer) / 3; - data = (char*)gf_malloc(sizeof(char) * data_size); - if (data) { - s[2] = 0; - for (i=0; ibuffer.buffer); - bw->buffer.buffer = NULL; - bw->buffer_len = 0; - if (data) { - bw->buffer.buffer = data; - bw->buffer_len = data_size; - } - -} #ifndef GPAC_DISABLE_LOADER_BT @@ -108,6 +41,7 @@ void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName) /*since 0.2.2, we use zlib for bt reading to handle wrl.gz files*/ #include +void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName); void load_bt_done(GF_SceneLoader *load); diff --git a/src/scene_manager/loader_isom.c b/src/scene_manager/loader_isom.c index 20eee00..5a11a5b 100644 --- a/src/scene_manager/loader_isom.c +++ b/src/scene_manager/loader_isom.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scene_manager/loader_qt.c b/src/scene_manager/loader_qt.c index b84ac02..15270ff 100644 --- a/src/scene_manager/loader_qt.c +++ b/src/scene_manager/loader_qt.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scene_manager/loader_svg.c b/src/scene_manager/loader_svg.c index cedbab8..872deca 100644 --- a/src/scene_manager/loader_svg.c +++ b/src/scene_manager/loader_svg.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre, Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scene_manager/loader_xmt.c b/src/scene_manager/loader_xmt.c index 86c336b..a617c83 100644 --- a/src/scene_manager/loader_xmt.c +++ b/src/scene_manager/loader_xmt.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project @@ -30,10 +31,9 @@ #include #include -void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName); - #ifndef GPAC_DISABLE_LOADER_XMT +void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName); /*for QP types*/ #include "../bifs/quant.h" diff --git a/src/scene_manager/scene_dump.c b/src/scene_manager/scene_dump.c index b60a27a..f828007 100644 --- a/src/scene_manager/scene_dump.c +++ b/src/scene_manager/scene_dump.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scene_manager/scene_engine.c b/src/scene_manager/scene_engine.c index 0221033..e2254fb 100644 --- a/src/scene_manager/scene_engine.c +++ b/src/scene_manager/scene_engine.c @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * - * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre, Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / ISO Media File Format sub-project diff --git a/src/scene_manager/scene_manager.c b/src/scene_manager/scene_manager.c index 9cc2752..819f045 100644 --- a/src/scene_manager/scene_manager.c +++ b/src/scene_manager/scene_manager.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project @@ -28,6 +29,7 @@ #include #include #include +#include GF_EXPORT @@ -731,3 +733,73 @@ GF_Err gf_sm_load_suspend(GF_SceneLoader *load, Bool suspend) if (load->suspend) return load->suspend(load, suspend); return GF_OK; } + +#if !defined(GPAC_DISABLE_LOADER_BT) || !defined(GPAC_DISABLE_LOADER_XMT) +#include +void gf_sm_update_bitwrapper_buffer(GF_Node *node, const char *fileName) +{ + u32 data_size = 0; + char *data = NULL; + char *buffer; + M_BitWrapper *bw = (M_BitWrapper *)node; + + if (!bw->buffer.buffer) return; + buffer = bw->buffer.buffer; + if (!strnicmp(buffer, "file://", 7)) { + char *url = gf_url_concatenate(fileName, buffer+7); + if (url) { + FILE *f = fopen(url, "rb"); + if (f) { + fseek(f, 0, SEEK_END); + data_size = ftell(f); + fseek(f, 0, SEEK_SET); + data = gf_malloc(sizeof(char)*data_size); + if (data) { + size_t s = fread(data, 1, data_size, f); + assert(s == data_size); + } + fclose(f); + } + gf_free(url); + } + } else { + Bool base_64 = 0; + if (!strnicmp(buffer, "data:application/octet-string", 29)) { + char *sep = strchr(bw->buffer.buffer, ','); + base_64 = strstr(bw->buffer.buffer, ";base64") ? 1 : 0; + if (sep) buffer = sep+1; + } + + if (base_64) { + data_size = 2*strlen(buffer); + data = (char*)gf_malloc(sizeof(char)*data_size); + if (data) + data_size = gf_base64_decode(buffer, strlen(buffer), data, data_size); + } else { + u32 i, c; + char s[3]; + data_size = strlen(buffer) / 3; + data = (char*)gf_malloc(sizeof(char) * data_size); + if (data) { + s[2] = 0; + for (i=0; ibuffer.buffer); + bw->buffer.buffer = NULL; + bw->buffer_len = 0; + if (data) { + bw->buffer.buffer = data; + bw->buffer_len = data_size; + } + +} +#endif //!defined(GPAC_DISABLE_LOADER_BT) || !defined(GPAC_DISABLE_LOADER_XMT) + + diff --git a/src/scene_manager/scene_stats.c b/src/scene_manager/scene_stats.c index cb73599..a36ae00 100644 --- a/src/scene_manager/scene_stats.c +++ b/src/scene_manager/scene_stats.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scene_manager/swf_bifs.c b/src/scene_manager/swf_bifs.c index da983b8..38e2874 100644 --- a/src/scene_manager/swf_bifs.c +++ b/src/scene_manager/swf_bifs.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scene_manager/swf_parse.c b/src/scene_manager/swf_parse.c index 8bebbb7..1b5b39b 100644 --- a/src/scene_manager/swf_parse.c +++ b/src/scene_manager/swf_parse.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project @@ -32,15 +33,6 @@ #ifndef GPAC_DISABLE_SWF_IMPORT -/*display list item (one per layer only)*/ -typedef struct -{ - GF_Matrix2D mat; - GF_ColorMatrix cmat; - u32 depth; - u32 char_id; -} DispShape; - enum { SWF_END = 0, @@ -2090,6 +2082,7 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version) fclose(file); if (version==3) { +#ifndef GPAC_DISABLE_AV_PARSERS char *dst, *raw; u8 oti; u32 osize, w, h, j, pf; @@ -2135,6 +2128,7 @@ static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version) fclose(file); gf_free(raw); +#endif //GPAC_DISABLE_AV_PARSERS } gf_free(buf); @@ -2482,7 +2476,11 @@ GF_Err gf_sm_load_init_swf(GF_SceneLoader *load) read->no_as = 1; } - e = swf_to_bifs_init(read); + if (!(load->swf_import_flags & GF_SM_SWF_USE_SVG)) { + e = swf_to_bifs_init(read); + } else { + e = swf_to_svg_init(read); + } if (e) goto exit; /*parse all tags*/ diff --git a/src/scene_manager/swf_svg.c b/src/scene_manager/swf_svg.c new file mode 100644 index 0000000..1001a4e --- /dev/null +++ b/src/scene_manager/swf_svg.c @@ -0,0 +1,1182 @@ +/* + * GPAC - Multimedia Framework C SDK + * + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved + * + * This file is part of GPAC / Scene Management sub-project + * + * GPAC is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GPAC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include + +#ifndef GPAC_DISABLE_VRML + +#ifndef GPAC_DISABLE_SWF_IMPORT + +#define SWF_TEXT_SCALE (1/1024.0f) + +typedef struct +{ + u32 btn_id; + u32 sprite_up_id; +} s2sBtnRec; + +static void swf_svg_print_color(SWFReader *read, u32 ARGB) +{ + SFColor val; + val.red = INT2FIX((ARGB>>16)&0xFF) / 255*100; + val.green = INT2FIX((ARGB>>8)&0xFF) / 255*100; + val.blue = INT2FIX((ARGB)&0xFF) / 255*100; + fprintf(read->svg_output, "rgb(%f%%,%f%%,%f%%)", FIX2FLT(val.red), FIX2FLT(val.green), FIX2FLT(val.blue)); +} + +static void swf_svg_print_alpha(SWFReader *read, u32 ARGB) +{ + Fixed alpha; + alpha = INT2FIX((ARGB>>24)&0xFF)/255; + fprintf(read->svg_output, "%f", FIX2FLT(alpha)); +} + +static void swg_svg_print_shape_record_to_fill_stroke(SWFReader *read, SWFShapeRec *srec, Bool is_fill) +{ + /*get regular appearance reuse*/ + if (is_fill) { + switch (srec->type) { + /*solid/alpha fill*/ + case 0x00: + fprintf(read->svg_output, "fill=\""); + swf_svg_print_color(read, srec->solid_col); + fprintf(read->svg_output, "\" "); + fprintf(read->svg_output, "fill-opacity=\""); + swf_svg_print_alpha(read, srec->solid_col); + fprintf(read->svg_output, "\" "); + break; + case 0x10: + case 0x12: + //if (read->flags & GF_SM_SWF_NO_GRADIENT) { + // u32 col = srec->grad_col[srec->nbGrad/2]; + // col |= 0xFF000000; + // n->appearance = s2b_get_appearance(read, (GF_Node *) n, col, 0, 0); + //} else { + // n->appearance = s2b_get_gradient(read, (GF_Node *) n, shape, srec); + //} + //break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + //n->appearance = s2b_get_bitmap(read, (GF_Node *) n, shape, srec); + //break; + default: + swf_report(read, GF_NOT_SUPPORTED, "fill_style %x not supported", srec->type); + break; + } + } else { + fprintf(read->svg_output, "fill=\"none\" "); + fprintf(read->svg_output, "stroke=\""); + swf_svg_print_color(read, srec->solid_col); + fprintf(read->svg_output, "\" "); + fprintf(read->svg_output, "stroke-opacity=\""); + swf_svg_print_alpha(read, srec->solid_col); + fprintf(read->svg_output, "\" "); + fprintf(read->svg_output, "stroke-width=\"%f\" ", FIX2FLT(srec->width)); + } +} + +static void swf_svg_print_shape_record_to_path_d(SWFReader *read, SWFShapeRec *srec) +{ + u32 pt_idx; + u32 i; + + pt_idx = 0; + for (i=0; ipath->nbType; i++) { + switch (srec->path->types[i]) { + /*moveTo*/ + case 0: + fprintf(read->svg_output, "M%f,%f", FIX2FLT(srec->path->pts[pt_idx].x), FIX2FLT(srec->path->pts[pt_idx].y)); + pt_idx++; + break; + /*lineTo*/ + case 1: + fprintf(read->svg_output, "L%f,%f", FIX2FLT(srec->path->pts[pt_idx].x), FIX2FLT(srec->path->pts[pt_idx].y)); + pt_idx++; + break; + /*curveTo*/ + case 2: + fprintf(read->svg_output, "Q%f,%f", FIX2FLT(srec->path->pts[pt_idx].x), FIX2FLT(srec->path->pts[pt_idx].y)); + pt_idx++; + fprintf(read->svg_output, ",%f,%f", FIX2FLT(srec->path->pts[pt_idx].x), FIX2FLT(srec->path->pts[pt_idx].y)); + pt_idx++; + break; + } + } +} + +static void swf_svg_print_matrix(SWFReader *read, GF_Matrix2D *mat) +{ + if (!gf_mx2d_is_identity(*mat)) + { + GF_Point2D scale; + GF_Point2D translate; + Fixed rotate; + if( gf_mx2d_decompose(mat, &scale, &rotate, &translate)) + { + fprintf(read->svg_output, "transform=\""); + if (translate.x != 0 || translate.y != 0) + { + fprintf(read->svg_output, "translate(%f, %f) ", translate.x, translate.y); + } + if (rotate != 0) + { + fprintf(read->svg_output, "rotate(%f) ", rotate); + } + if (scale.x != FIX_ONE || scale.y != FIX_ONE) + { + fprintf(read->svg_output, "scale(%f, %f) ", scale.x, scale.y); + } + fprintf(read->svg_output, "\" "); + } + else + { + fprintf(read->svg_output, "transform=\"matrix(%f,%f,%f,%f,%f,%f)\" ", mat->m[0], mat->m[3], mat->m[1], mat->m[4], mat->m[2], mat->m[5]); + } + } +} + +/*translates Flash to SVG shapes*/ +static GF_Err swf_svg_define_shape(SWFReader *read, SWFShape *shape, SWFFont *parent_font, Bool last_sub_shape) +{ + u32 i; + SWFShapeRec *srec; + + if (parent_font && (read->flags & GF_SM_SWF_NO_FONT)) + { + return GF_OK; + } + + if (!read->cur_shape) + { + fprintf(read->svg_output, "\n"); + if (!parent_font) + { + fprintf(read->svg_output, "\n", shape->ID); + } + else + { + char szGlyphId[256]; + sprintf(szGlyphId, "Font%d_Glyph%d", parent_font->fontID, gf_list_count(parent_font->glyphs)); + fprintf(read->svg_output, "\n", szGlyphId); + gf_list_add(parent_font->glyphs, szGlyphId); + } + } + read->cur_shape = (GF_Node *)"shape"; + + i=0; + while ((srec = (SWFShapeRec*)gf_list_enum(shape->fill_left, &i))) { + fprintf(read->svg_output, "svg_output, "\" "); + swg_svg_print_shape_record_to_fill_stroke(read, srec, 1); + fprintf(read->svg_output, "/>\n"); + } + i=0; + while ((srec = (SWFShapeRec*)gf_list_enum(shape->lines, &i))) { + fprintf(read->svg_output, "svg_output, "\" "); + swg_svg_print_shape_record_to_fill_stroke(read, srec, 0); + fprintf(read->svg_output, "/>\n"); + } + + if (last_sub_shape) + { + read->cur_shape = NULL; + fprintf(read->svg_output, "\n"); + fprintf(read->svg_output, "\n"); + } + return GF_OK; +} + +static GF_Err swf_svg_define_text(SWFReader *read, SWFText *text) +{ + Bool use_text; + u32 i; + u32 j; + SWFGlyphRec *gr; + SWFFont *ft; + + use_text = (read->flags & GF_SM_SWF_NO_FONT) ? 1 : 0; + + fprintf(read->svg_output, "\n"); + fprintf(read->svg_output, "ID); + swf_svg_print_matrix(read, &text->mat); + fprintf(read->svg_output, ">\n"); + + i=0; + while ((gr = (SWFGlyphRec*)gf_list_enum(text->text, &i))) + { + ft = NULL; + if (use_text) { + ft = swf_find_font(read, gr->fontID); + if (!ft->glyph_codes) { + use_text = 0; + swf_report(read, GF_BAD_PARAM, "Font glyphs are not defined, cannot reference extern font - Forcing glyph embedding"); + } + } + if (use_text) { + /*restore back the font height in pixels (it's currently in SWF glyph design units)*/ + fprintf(read->svg_output, "svg_output, "x=\"%f \" ", FIX2FLT(gr->orig_x)); + fprintf(read->svg_output, "y=\"%f \" ", FIX2FLT(gr->orig_y)); + fprintf(read->svg_output, "font-size=\"%d\" ", (u32)(gr->fontSize * SWF_TWIP_SCALE)); + if (ft->fontName) + { + fprintf(read->svg_output, "font-family=\"%s\" ", ft->fontName); + } + if (ft->is_italic) + { + fprintf(read->svg_output, "font-style=\"italic\" "); + } + if (ft->is_bold) + { + fprintf(read->svg_output, "font-weight=\"bold\" "); + } + fprintf(read->svg_output, ">"); + /*convert to UTF-8*/ + { + u16 *str_w; + u16 *widestr; + char *str; + + str_w = (u16*)gf_malloc(sizeof(u16) * (gr->nbGlyphs+1)); + for (j=0; jnbGlyphs; j++) + { + str_w[j] = ft->glyph_codes[gr->indexes[j]]; + } + str_w[j] = 0; + str = (char*)gf_malloc(sizeof(char) * (gr->nbGlyphs+2)); + widestr = str_w; + j = gf_utf8_wcstombs(str, sizeof(u8) * (gr->nbGlyphs+1), (const unsigned short **) &widestr); + if (j != (u32) -1) { + str[j] = 0; + fprintf(read->svg_output, "%s", str); + } + } + fprintf(read->svg_output, "\n"); + } + else + { + /*convert glyphs*/ + Fixed dx; + fprintf(read->svg_output, "svg_output, "translate(%f, %f)\" >\n", FIX2FLT(gr->orig_x), FIX2FLT(gr->orig_y)); + + dx = 0; + for (j=0; jnbGlyphs; j++) + { + fprintf(read->svg_output, "\n", gr->fontID, gr->indexes[j], FLT2FIX(gf_divfix(dx, FLT2FIX(gr->fontSize * SWF_TEXT_SCALE)))); + dx += gr->dx[j]; + } + fprintf(read->svg_output, "\n"); + } + } + fprintf(read->svg_output, "\n"); + fprintf(read->svg_output, "\n"); + return GF_OK; +} + +static GF_Err swf_svg_define_edit_text(SWFReader *read, SWFEditText *text) +{ + //char styles[1024]; + //char *ptr; + //Bool use_layout; + //M_Layout *layout = NULL; + //M_Shape *txt; + //M_Text *t; + //M_FontStyle *f; + //M_Transform2D *tr; + + //tr = (M_Transform2D *) s2s_new_node(read, TAG_MPEG4_Transform2D); + //tr->scale.y = -FIX_ONE; + + //use_layout = 0; + //if (text->align==3) use_layout = 1; + //else if (text->multiline) use_layout = 1; + + //if (use_layout) { + // layout = (M_Layout *) s2s_new_node(read, TAG_MPEG4_Layout); + // tr->translation.x = read->width/2; + // tr->translation.y = read->height/2; + //} + + //t = (M_Text *) s2s_new_node(read, TAG_MPEG4_Text); + //f = (M_FontStyle *) s2s_new_node(read, TAG_MPEG4_FontStyle); + //t->fontStyle = (GF_Node *) f; + //gf_node_register(t->fontStyle, (GF_Node *) t); + + ///*restore back the font height in pixels (it's currently in SWF glyph design units)*/ + //f->size = text->font_height; + //f->spacing = text->font_height + text->leading; + + //gf_sg_vrml_mf_reset(&f->justify, GF_SG_VRML_MFSTRING); + //gf_sg_vrml_mf_append(&f->justify, GF_SG_VRML_MFSTRING, (void**)&ptr); + //switch (text->align) { + //case 0: + // ((SFString*)ptr)->buffer = gf_strdup("BEGIN"); + // break; + //case 1: + // ((SFString*)ptr)->buffer = gf_strdup("END"); + // break; + //case 3: + // ((SFString*)ptr)->buffer = gf_strdup("JUSTIFY"); + // break; + //default: + // ((SFString*)ptr)->buffer = gf_strdup("MIDDLE"); + // break; + //} + + //strcpy(styles, ""); + //if (!text->read_only) strcat(styles, "EDITABLE"); + //if (text->password) strcat(styles, "PASSWORD"); + // + //if (f->style.buffer) gf_free(f->style.buffer); + //f->style.buffer = gf_strdup(styles); + + //if (text->init_value) { + // gf_sg_vrml_mf_reset(&t->string, GF_SG_VRML_MFSTRING); + // gf_sg_vrml_mf_append(&t->string, GF_SG_VRML_MFSTRING, (void**)&ptr); + + // if (text->html) { + // GF_SAXParser *xml; + // SWFFlatText flat; + // flat.final = 0; + // flat.len = 0; + // xml = gf_xml_sax_new(swf_nstart, swf_nend, swf_ntext, &flat); + // gf_xml_sax_init(xml, NULL); + // gf_xml_sax_parse(xml, text->init_value); + // gf_xml_sax_del(xml); + + // if (flat.final) { + // ((SFString*)ptr)->buffer = gf_strdup(flat.final); + // gf_free(flat.final); + // } + // } else { + // ((SFString*)ptr)->buffer = gf_strdup(text->init_value); + // } + //} + + + //txt = (M_Shape *) s2s_new_node(read, TAG_MPEG4_Shape); + //txt->appearance = s2s_get_appearance(read, (GF_Node *) txt, text->color, 0, 0); + //txt->geometry = (GF_Node *) t; + //gf_node_register(txt->geometry, (GF_Node *) txt); + + //if (layout) { + // gf_sg_vrml_mf_reset(&layout->justify, GF_SG_VRML_MFSTRING); + // gf_sg_vrml_mf_append(&layout->justify, GF_SG_VRML_MFSTRING, NULL); + // switch (text->align) { + // case 0: + // layout->justify.vals[0] = gf_strdup("BEGIN"); + // break; + // case 1: + // layout->justify.vals[0] = gf_strdup("END"); + // break; + // case 3: + // layout->justify.vals[0] = gf_strdup("JUSTIFY"); + // break; + // default: + // layout->justify.vals[0] = gf_strdup("MIDDLE"); + // break; + // } + // if (text->multiline || text->word_wrap) layout->wrap = 1; + + // gf_node_insert_child((GF_Node *) layout, (GF_Node *)txt, -1); + // gf_node_register((GF_Node *) txt, (GF_Node *) layout); + + // gf_node_insert_child((GF_Node *) tr, (GF_Node *)layout, -1); + // gf_node_register((GF_Node *) layout, (GF_Node *) tr); + //} else { + // gf_node_insert_child((GF_Node *) tr, (GF_Node *)txt, -1); + // gf_node_register((GF_Node *) txt, (GF_Node *) tr); + //} + //if (tr) { + // char szDEF[1024]; + // u32 ID; + // sprintf(szDEF, "Text%d", text->ID); + // read->load->ctx->max_node_id++; + // ID = read->load->ctx->max_node_id; + // gf_node_set_id((GF_Node*)tr, ID, szDEF); + // s2s_insert_symbol(read, (GF_Node*)tr); + //} + return GF_OK; +} + +#if 0 +/*called upon end of sprite or clip*/ +static void swf_svg_end_of_clip(SWFReader *read) +{ + //char szDEF[1024]; + //u32 i; + //GF_AUContext *au; + //GF_Command *com; + //GF_CommandField *f; + //GF_Node *empty; + // + //return; + + //empty = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0"); + + //au = gf_list_get(read->bifs_es->AUs, 0); + //for (i=0; imax_depth; i++) { + // /*and write command*/ + // com = gf_sg_command_new(read->load->scene_graph, GF_SG_INDEXED_REPLACE); + // sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id); + // com->node = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); + + // gf_node_register(com->node, NULL); + // f = gf_sg_command_field_new(com); + // f->field_ptr = &f->new_node; + // f->fieldType = GF_SG_VRML_SFNODE; + // f->pos = i; + // f->fieldIndex = 2; /*children index*/ + // f->new_node = empty; + // gf_node_register(f->new_node, com->node); + + // gf_list_insert(au->commands, com, i); + //} +} +#endif + +static Bool swf_svg_allocate_depth(SWFReader *read, u32 depth) +{ + //char szDEF[100]; + //GF_Node *disp, *empty; + //if (read->max_depth > depth) return 1; + + //sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id); + //disp = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); + + //empty = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0"); + //while (read->max_depth<=depth) { + // gf_node_insert_child(disp, empty, -1); + // gf_node_register(empty, disp); + // read->max_depth++; + //} + return 0; +} + +static GF_Err swf_svg_define_sprite(SWFReader *read, u32 nb_frames) +{ + //GF_Err e; + //GF_ObjectDescriptor *od; + //GF_ESD *esd; + //u32 ID; + //GF_Node *n, *par; + //GF_FieldInfo info; + //char szDEF[100]; + //GF_StreamContext *prev_sc; + //GF_AUContext *prev_au; + + ///*init OD*/ + //e = swf_init_od(read, 0); + //if (e) return e; + + ///*create animationStream object*/ + //od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); + //if (!od) return GF_OUT_OF_MEM; + + //od->objectDescriptorID = swf_get_od_id(read); + //esd = (GF_ESD *) gf_odf_desc_esd_new(0); + //if (!esd) return GF_OUT_OF_MEM; + //esd->ESID = swf_get_es_id(read); + ///*sprite runs on its own timeline*/ + //esd->OCRESID = esd->ESID; + ///*always depends on main scene*/ + //esd->dependsOnESID = 1; + //esd->decoderConfig->streamType = GF_STREAM_SCENE; + //esd->decoderConfig->objectTypeIndication = 1; + //esd->slConfig->timestampResolution = read->bifs_es->timeScale; + //gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); + //esd->decoderConfig->decoderSpecificInfo = NULL; + //gf_list_add(od->ESDescriptors, esd); + + ///*by default insert OD at begining*/ + //e = swf_insert_od(read, 0, od); + //if (e) { + // gf_odf_desc_del((GF_Descriptor *) od); + // return e; + //} + + ///*create AS for sprite - all AS are created in initial scene replace*/ + //n = s2s_new_node(read, TAG_MPEG4_AnimationStream); + //gf_node_insert_child(read->root, n, 0); + //gf_node_register(n, read->root); + ///*assign URL*/ + //gf_node_get_field_by_name(n, "url", &info); + //gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); + //((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; + //((M_AnimationStream *)n)->startTime = 0; + + //n = s2s_new_node(read, TAG_MPEG4_MediaControl); + //sprintf(szDEF, "CLIP%d_CTRL", read->current_sprite_id); + //read->load->ctx->max_node_id++; + //ID = read->load->ctx->max_node_id; + //gf_node_set_id(n, ID, szDEF); + + //gf_node_insert_child(read->root, n, 0); + //gf_node_register(n, read->root); + ///*assign URL*/ + //gf_node_get_field_by_name(n, "url", &info); + //gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); + //((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; + ///*inactive by default (until inserted)*/ + //((M_MediaControl *)n)->mediaSpeed = 0; + //((M_MediaControl *)n)->loop = 1; + + ///*create sprite grouping node*/ + //n = s2s_new_node(read, TAG_MPEG4_Group); + //sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id); + + //read->load->ctx->max_node_id++; + //ID = read->load->ctx->max_node_id; + //gf_node_set_id(n, ID, szDEF); + //par = gf_sg_find_node_by_name(read->load->scene_graph, "DICTIONARY"); + //assert(par); + //gf_node_list_add_child(&((M_Switch *)par)->choice, n); + //gf_node_register(n, par); + //par = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0"); + //gf_node_insert_child(n, par, -1); + //gf_node_register(par, n); + + ///*store BIFS context*/ + //prev_sc = read->bifs_es; + //prev_au = read->bifs_au; + ///*create new BIFS stream*/ + //read->bifs_es = gf_sm_stream_new(read->load->ctx, esd->ESID, GF_STREAM_SCENE, 1); + //read->bifs_es->timeScale = prev_sc->timeScale; + //read->bifs_es->imp_exp_time = prev_sc->imp_exp_time + prev_au->timing; + + ///*create first AU*/ + //read->bifs_au = gf_sm_stream_au_new(read->bifs_es, 0, 0, 1); + + //e = swf_parse_sprite(read); + //if (e) return e; + + //swf_svg_end_of_clip(read); + + ///*restore BIFS context*/ + //read->bifs_es = prev_sc; + //read->bifs_au = prev_au; + + return GF_OK; +} + +static GF_Err swf_svg_setup_sound(SWFReader *read, SWFSound *snd, Bool soundstream_first_block) +{ +// GF_Err e; +// GF_ObjectDescriptor *od; +// GF_ESD *esd; +// GF_MuxInfo *mux; +// GF_Node *n, *par; +// GF_FieldInfo info; +// u32 ID; +// char szDEF[100]; +// +// /*soundstream header, only declare the associated MediaControl node for later actions*/ +// if (!snd->ID && !soundstream_first_block) { +// n = s2s_new_node(read, TAG_MPEG4_MediaControl); +// sprintf(szDEF, "CLIP%d_SND", read->current_sprite_id); +// read->load->ctx->max_node_id++; +// ID = read->load->ctx->max_node_id; +// gf_node_set_id(n, ID, szDEF); +// +// gf_node_insert_child(read->root, n, 0); +// gf_node_register(n, read->root); +// return GF_OK; +// } +// +// e = swf_init_od(read, 0); +// if (e) return e; +// +// /*create audio object*/ +// od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); +// if (!od) return GF_OUT_OF_MEM; +// od->objectDescriptorID = swf_get_od_id(read); +// esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG); +// if (!esd) return GF_OUT_OF_MEM; +// esd->ESID = swf_get_es_id(read); +// if (snd->ID) { +// /*sound runs on its own timeline*/ +// esd->OCRESID = esd->ESID; +// } else { +// /*soundstream runs on movie/sprite timeline*/ +// esd->OCRESID = read->bifs_es->ESID; +// esd->OCRESID = esd->ESID; +// } +// gf_list_add(od->ESDescriptors, esd); +// +// /*setup mux info*/ +// mux = (GF_MuxInfo*)gf_odf_desc_new(GF_ODF_MUXINFO_TAG); +// mux->file_name = gf_strdup(snd->szFileName); +//// mux->startTime = snd->frame_delay_ms; +// mux->startTime = 0; +// /*MP3 in, destroy file once done*/ +// if (snd->format==2) mux->delete_file = 1; +// gf_list_add(esd->extensionDescriptors, mux); +// +// +// /*by default insert OD at begining*/ +// e = swf_insert_od(read, 0, od); +// if (e) { +// gf_odf_desc_del((GF_Descriptor *) od); +// return e; +// } +// /*create sound & audio clip*/ +// n = s2s_new_node(read, TAG_MPEG4_Sound2D); +// gf_node_insert_child(read->root, n, 0); +// gf_node_register(n, read->root); +// par = n; +// n = s2s_new_node(read, TAG_MPEG4_AudioClip); +// ((M_Sound2D *)par)->source = n; +// gf_node_register(n, par); +// /*assign URL*/ +// gf_node_get_field_by_name(n, "url", &info); +// gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); +// ((MFURL *)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; +// +// ((M_AudioClip*)n)->startTime = -1.0; +// +// /*regular sound: set an ID to do play/stop*/ +// if (snd->ID) { +// sprintf(szDEF, "Sound%d", snd->ID); +// read->load->ctx->max_node_id++; +// ID = read->load->ctx->max_node_id; +// gf_node_set_id(n, ID, szDEF); +// } +// /*soundStream - add a MediaControl*/ +// else { +// /*if sprite always have the media active but controled by its mediaControl*/ +// if (read->current_sprite_id) { +// ((M_AudioClip*)n)->startTime = 0; +// } +// /*otherwise start the media at the first soundstream block*/ +// else { +// ((M_AudioClip*)n)->startTime = snd->frame_delay_ms/1000.0; +// ((M_AudioClip*)n)->startTime = 0; +// } +// +// sprintf(szDEF, "CLIP%d_SND", read->current_sprite_id); +// n = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); +// +// /*assign URL*/ +// gf_node_get_field_by_name(n, "url", &info); +// gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); +// ((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; +// ((M_MediaControl *)n)->loop = 0; +// +// /*inactive by default (until inserted)*/ +// if (read->current_sprite_id) { +// ((M_MediaControl *)n)->mediaSpeed = 0; +// } else { +// ((M_MediaControl *)n)->mediaSpeed = FIX_ONE; +// } +// } + return GF_OK; +} + +static GF_Err swf_svg_setup_image(SWFReader *read, u32 ID, char *fileName) +{ + + //GF_Err e; + //GF_ObjectDescriptor *od; + //GF_ESD *esd; + //GF_MuxInfo *mux; + //GF_Node *n, *par; + //GF_FieldInfo info; + //char szDEF[100]; + // + //e = swf_init_od(read, 0); + //if (e) return e; + + ///*create visual object*/ + //od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); + //if (!od) return GF_OUT_OF_MEM; + //od->objectDescriptorID = swf_get_od_id(read); + //esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG); + //if (!esd) return GF_OUT_OF_MEM; + //esd->ESID = swf_get_es_id(read); + //esd->OCRESID = esd->ESID; + //gf_list_add(od->ESDescriptors, esd); + + ///*setup mux info*/ + //mux = (GF_MuxInfo*)gf_odf_desc_new(GF_ODF_MUXINFO_TAG); + + //mux->file_name = gf_strdup(fileName); + ///*destroy file once done*/ + ////mux->delete_file = 1; + //gf_list_add(esd->extensionDescriptors, mux); + + + ///*by default insert OD at begining*/ + //e = swf_insert_od(read, 0, od); + //if (e) { + // gf_odf_desc_del((GF_Descriptor *) od); + // return e; + //} + ///*create appearance clip*/ + //par = s2s_new_node(read, TAG_MPEG4_Shape); + //s2s_insert_symbol(read, par); + //n = s2s_new_node(read, TAG_MPEG4_Appearance); + //((M_Shape *)par)->appearance = n; + //gf_node_register(n, par); + + //par = n; + //n = s2s_new_node(read, TAG_MPEG4_ImageTexture); + //((M_Appearance *)par)->texture = n; + //gf_node_register(n, par); + + //sprintf(szDEF, "Bitmap%d", ID); + //read->load->ctx->max_node_id++; + //ID = read->load->ctx->max_node_id; + //gf_node_set_id(n, ID, szDEF); + + ///*assign URL*/ + //gf_node_get_field_by_name(n, "url", &info); + //gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); + //((MFURL *)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; + + return GF_OK; +} + +static GF_Err swf_svg_set_backcol(SWFReader *read, u32 xrgb) +{ + //SFColor rgb; + //GF_Node *bck = gf_sg_find_node_by_name(read->load->scene_graph, "BACKGROUND"); + + //rgb.red = INT2FIX((xrgb>>16) & 0xFF) / 255; + //rgb.green = INT2FIX((xrgb>>8) & 0xFF) / 255; + //rgb.blue = INT2FIX((xrgb) & 0xFF) / 255; + //s2s_set_field(read, read->bifs_au->commands, bck, "backColor", -1, GF_SG_VRML_SFCOLOR, &rgb, 0); + return GF_OK; +} + +static GF_Err swf_svg_start_sound(SWFReader *read, SWFSound *snd, Bool stop) +{ + //GF_Node *sound2D; + //SFTime t = 0; + //char szDEF[100]; + + //sprintf(szDEF, "Sound%d", snd->ID); + //sound2D = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); + ///*check flags*/ + //if (sound2D) + // s2s_set_field(read, read->bifs_au->commands, sound2D, stop ? "stopTime" : "startTime", -1, GF_SG_VRML_SFTIME, &t, 0); + + return GF_OK; +} + +static GF_Err swf_svg_place_obj(SWFReader *read, u32 depth, u32 ID, u32 prev_id, u32 type, GF_Matrix2D *mat, GF_ColorMatrix *cmat, GF_Matrix2D *prev_mat, GF_ColorMatrix *prev_cmat) +{ + //fprintf(read->svg_output, "svg_output, "/>\n"); + + //GF_Command *com; + //GF_CommandField *f; + //GF_Node *obj, *par; + //char szDEF[100]; + //Bool is_sprite; + + //obj = s2s_get_node(read, ID); + //is_sprite = 0; + //if (!obj) { + // sprintf(szDEF, "CLIP%d_DL", ID); + // obj = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); + // if (obj) is_sprite = 1; + //} + //if (!obj) return GF_BAD_PARAM; + + ///*then add cmat/mat and node*/ + //par = s2s_wrap_node(read, obj, mat, cmat); + + ///*and write command*/ + //com = gf_sg_command_new(read->load->scene_graph, GF_SG_INDEXED_REPLACE); + //sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id); + //com->node = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); + //gf_node_register(com->node, NULL); + //f = gf_sg_command_field_new(com); + //f->field_ptr = &f->new_node; + //f->fieldType = GF_SG_VRML_SFNODE; + //f->pos = depth; + //f->fieldIndex = 2; /*children index*/ + //f->new_node = par; + //gf_node_register(f->new_node, com->node); + //gf_list_add(read->bifs_au->commands, com); + + //if (ID==prev_id) return GF_OK; + + //strcpy(szDEF, gf_node_get_name(obj)); + ///*when inserting a button, trigger a pause*/ + //if (!strnicmp(szDEF, "Button", 6)) { + // u32 i, count; + // s2s_control_sprite(read, read->bifs_au->commands, read->current_sprite_id, 1, 0, 0, 1); + + // count = gf_list_count(read->buttons); + // for (i=0; ibuttons, i); + // if (btnrec->btn_id==ID) { + // s2s_control_sprite(read, read->bifs_au->commands, btnrec->sprite_up_id, 0, 0, 0, 1); + // } + // } + //} + ///*starts anim*/ + //else if (is_sprite) { + // s2s_control_sprite(read, read->bifs_au->commands, ID, 0, 1, 0, 0); + // if (prev_id) { + // s2s_control_sprite(read, read->bifs_au->commands, prev_id, 1, 0, 0, 0); + // } + //} + return GF_OK; +} + +static GF_Err swf_svg_remove_obj(SWFReader *read, u32 depth, u32 ID) +{ + return GF_OK; +} + +static GF_Err swf_svg_show_frame(SWFReader *read) +{ + u32 i; + u32 len; + GF_List *sdl = gf_list_new(); // sorted display list + + /* sorting the display list */ + while (gf_list_count(read->display_list)) + { + Bool inserted = 0; + DispShape *s; + + s = (DispShape *)gf_list_get(read->display_list, 0); + gf_list_rem(read->display_list, 0); + + for (i = 0; i < gf_list_count(sdl); i++) + { + DispShape *s2 = (DispShape *)gf_list_get(sdl, i); + if (s->depth < s2->depth) + { + gf_list_insert(sdl, s, i); + inserted = 1; + break; + } + } + if (!inserted) + { + gf_list_add(sdl, s); + } + } + gf_list_del(read->display_list); + read->display_list = sdl; + + /* dumping the display list */ + len = gf_list_count(read->display_list); + for (i=0; idisplay_list, i); + fprintf(read->svg_output, "char_id, s->depth); + swf_svg_print_matrix(read, &s->mat); + fprintf(read->svg_output, "/>\n"); + } + fprintf(read->svg_output, "\n"); + + fprintf(read->svg_output, "\n",read->current_frame+1); + fprintf(read->svg_output, "\n", + 1.0*(read->current_frame+1)/read->frame_rate, 1.0*(read->current_frame+2)/read->frame_rate, + (((read->current_frame+1) <= (read->frame_count-1)) ? "remove" : "freeze")); + return GF_OK; +} + +static void swf_svg_finalize(SWFReader *read) +{ + //u32 i, count; + + //swf_svg_end_of_clip(read); + + //while (gf_list_count(read->buttons)) { + // s2sBtnRec *btnrec = gf_list_get(read->buttons, 0); + // gf_list_rem(read->buttons, 0); + // gf_free(btnrec); + //} + + //count = gf_list_count(read->fonts); + //for (i=0;ifonts, i); + // while (gf_list_count(ft->glyphs)) { + // GF_Node *gl = (GF_Node *)gf_list_get(ft->glyphs, 0); + // gf_list_rem(ft->glyphs, 0); + // gf_node_unregister(gl, NULL); + // } + //} + fprintf(read->svg_output, "\n"); + fprintf(read->svg_output, "\n"); + fclose(read->svg_output); +} + +static GF_Err swf_svg_define_button(SWFReader *read, SWF_Button *btn) +{ + //char szName[1024]; + //M_Switch *button; + //SWF_ButtonRecord *br; + //GF_Node *btn_root, *n, *btn_ts; + //u32 i, ID, pos; + + //if (!btn) { + // read->btn = NULL; + // read->btn_over = read->btn_not_over = read->btn_active = read->btn_not_active = NULL; + // return GF_OK; + //} + + //read->btn = btn; + + //btn_root = s2s_new_node(read, TAG_MPEG4_Transform2D); + //sprintf(szName, "Button%d", btn->ID); + //read->load->ctx->max_node_id++; + //ID = read->load->ctx->max_node_id; + //gf_node_set_id((GF_Node *)btn_root, ID, szName); + + //n = s2s_button_add_child(read, btn_root, TAG_MPEG4_ColorTransform, NULL, -1); + //((M_ColorTransform*)n)->maa = ((M_ColorTransform*)n)->mab = ((M_ColorTransform*)n)->mar = ((M_ColorTransform*)n)->mag = ((M_ColorTransform*)n)->ta = 0; + + ///*locate hit buttons and add them to the color transform*/ + //for (i=0; icount; i++) { + // GF_Node *character; + // br = &btn->buttons[i]; + // if (!br->hitTest) continue; + // character = s2s_get_node(read, br->character_id); + // if (!character) { + // sprintf(szName, "CLIP%d_DL", br->character_id); + // character = gf_sg_find_node_by_name(read->load->scene_graph, szName); + // } + // if (character) { + // gf_node_list_add_child(&((GF_ParentNode*)n)->children, character); + // gf_node_register(character, (GF_Node *)n); + // } + //} + ///*add touch sensor to the color transform*/ + //sprintf(szName, "BTN%d_TS", read->btn->ID); + //btn_ts = s2s_button_add_child(read, n, TAG_MPEG4_TouchSensor, szName, -1); + + //s2s_insert_symbol(read, (GF_Node *)btn_root); + + ///*isActive handler*/ + //sprintf(szName, "BTN%d_CA", read->btn->ID); + //n = s2s_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1); + //read->btn_active = ((M_Conditional*)n)->buffer.commandList; + //s2s_button_add_route(read, btn_ts, 4, n, 0); + + ///*!isActive handler*/ + //sprintf(szName, "BTN%d_CNA", read->btn->ID); + //n = s2s_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1); + //read->btn_not_active = ((M_Conditional*)n)->buffer.commandList; + //s2s_button_add_route(read, btn_ts, 4, n, 1); + + ///*isOver handler*/ + //sprintf(szName, "BTN%d_CO", read->btn->ID); + //n = s2s_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1); + //read->btn_over = ((M_Conditional*)n)->buffer.commandList; + //s2s_button_add_route(read, btn_ts, 5, n, 0); + + ///*!isOver handler*/ + //sprintf(szName, "BTN%d_CNO", read->btn->ID); + //n = s2s_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1); + //read->btn_not_over = ((M_Conditional*)n)->buffer.commandList; + //s2s_button_add_route(read, btn_ts, 5, n, 1); + + ///*by default show first character*/ + //pos = 0; + //for (i=0; icount; i++) { + // GF_Node *sprite_ctrl = NULL; + // GF_Node *character; + // br = &btn->buttons[i]; + // if (!br->up && !br->down && !br->over) continue; + + // character = s2s_get_node(read, br->character_id); + + // if (!character) { + // sprintf(szName, "CLIP%d_DL", br->character_id); + // character = gf_sg_find_node_by_name(read->load->scene_graph, szName); + // if (character) { + // sprintf(szName, "CLIP%d_CTRL", br->character_id); + // sprite_ctrl = gf_sg_find_node_by_name(read->load->scene_graph, szName); + // } + // } + // if (character) { + // SFInt32 choice = 0; + // GF_Node *n = s2s_wrap_node(read, character, &br->mx, &br->cmx); + + // sprintf(szName, "BTN%d_R%d", btn->ID, i+1); + // button = (M_Switch *) s2s_button_add_child(read, btn_root, TAG_MPEG4_Switch, szName, pos); + // pos++; + + // gf_node_list_add_child(&button->choice, n); + // gf_node_register(n, (GF_Node *)button); + // /*initial state*/ + // if (br->up) { + // button->whichChoice = 0; + // /*register this button for sprite start upon place_obj*/ + // if (sprite_ctrl) { + // s2sBtnRec *btnrec; + // if (!read->buttons) read->buttons = gf_list_new(); + // btnrec = gf_malloc(sizeof(s2sBtnRec)); + // btnrec->btn_id = btn->ID; + // btnrec->sprite_up_id = br->character_id; + // gf_list_add(read->buttons, btnrec); + // } + + // } else { + // button->whichChoice = -1; + // } + + // choice = br->up ? 0 : -1; + // s2s_set_field(read, read->btn_not_over, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0); + // /*start or stop sprite if button is up or not*/ + // if (sprite_ctrl) { + // s2s_control_sprite(read, read->btn_not_over, br->character_id, choice, 1, 0, 0); + // } + + // choice = br->down ? 0 : -1; + // s2s_set_field(read, read->btn_active, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0); + // if (sprite_ctrl && !br->over) { + // s2s_control_sprite(read, read->btn_active, br->character_id, choice, 1, 0, 0); + // } + + // choice = br->over ? 0 : -1; + // s2s_set_field(read, read->btn_not_active, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0); + // s2s_set_field(read, read->btn_over, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0); + // if (sprite_ctrl) { + // s2s_control_sprite(read, read->btn_over, br->character_id, choice, 1, 0, 0); + // if (!br->down) + // s2s_control_sprite(read, read->btn_not_active, br->character_id, choice, 1, 0, 0); + // } + // } + //} + + return GF_OK; +} + +Bool swf_svg_action(SWFReader *read, SWFAction *act) +{ +// GF_List *dst; +// MFURL url; +// SFURL sfurl; +// Bool bval; +// GF_Node *n; +// Double time; +// +// dst = read->bifs_au->commands; +// if (read->btn) { +// if (act->button_mask & GF_SWF_COND_OVERUP_TO_OVERDOWN) dst = read->btn_active; +// else if (act->button_mask & GF_SWF_COND_IDLE_TO_OVERUP) dst = read->btn_over; +// else if (act->button_mask & GF_SWF_COND_OVERUP_TO_IDLE) dst = read->btn_not_over; +// else dst = read->btn_not_active; +// } +// +// switch (act->type) { +// case GF_SWF_AS3_WAIT_FOR_FRAME: +// /*while correct, this is not optimal, we set the wait-frame upon GOTO frame*/ +//// read->wait_frame = act->frame_number; +// break; +// case GF_SWF_AS3_GOTO_FRAME: +// if (act->frame_number>read->current_frame) +// read->wait_frame = act->frame_number; +// +// time = act->frame_number ? act->frame_number +1: 0; +// time /= read->frame_rate; +// s2s_control_sprite(read, dst, read->current_sprite_id, 0, 1, time, 0); +// break; +// case GF_SWF_AS3_GET_URL: +// n = gf_sg_find_node_by_name(read->load->scene_graph, "MOVIE_URL"); +// sfurl.OD_ID = 0; sfurl.url = act->url; +// url.count = 1; url.vals = &sfurl; +// s2s_set_field(read, dst, n, "url", -1, GF_SG_VRML_MFURL, &url, 0); +// s2s_set_field(read, dst, n, "parameter", -1, GF_SG_VRML_MFSTRING, &url, 0); +// bval = 1; +// s2s_set_field(read, dst, n, "activate", -1, GF_SG_VRML_SFBOOL, &bval, 0); +// break; +// case GF_SWF_AS3_PLAY: +// s2s_control_sprite(read, dst, read->current_sprite_id, 0, 1, -1, 0); +// break; +// case GF_SWF_AS3_STOP: +// s2s_control_sprite(read, dst, read->current_sprite_id, 1, 0, 0, 0); +// break; +// default: +// return 0; +// } +// + return 1; +} + +GF_Err swf_to_svg_init(SWFReader *read) +{ + char szFileName[GF_MAX_PATH]; + sprintf(szFileName, "%s.svg", read->load->fileName); + /*init callbacks*/ + read->svg_output = gf_f64_open(szFileName, "wt"); + fprintf(read->svg_output, "\n"); + fprintf(read->svg_output, "svg_output, "xmlns:xlink=\"http://www.w3.org/1999/xlink\" "); + fprintf(read->svg_output, "width=\"100%%\" "); + fprintf(read->svg_output, "height=\"100%%\" "); + fprintf(read->svg_output, "viewBox=\"0 0 %d %d\" ", FIX2INT(read->width), FIX2INT(read->height)); + fprintf(read->svg_output, "viewport-fill=\"rgb(255,255,255)\" "); + fprintf(read->svg_output, ">\n"); + fprintf(read->svg_output, "\n",read->current_frame); + fprintf(read->svg_output, "\n", + 1.0*(read->current_frame)/read->frame_rate, 1.0*(read->current_frame+1)/read->frame_rate); + read->show_frame = swf_svg_show_frame; + read->allocate_depth = swf_svg_allocate_depth; + read->place_obj = swf_svg_place_obj; + read->remove_obj = swf_svg_remove_obj; + read->define_shape = swf_svg_define_shape; + read->define_sprite = swf_svg_define_sprite; + read->set_backcol = swf_svg_set_backcol; + read->define_button = swf_svg_define_button; + read->define_text = swf_svg_define_text; + read->define_edit_text = swf_svg_define_edit_text; + read->setup_sound = swf_svg_setup_sound; + read->start_sound = swf_svg_start_sound; + read->setup_image = swf_svg_setup_image; + read->action = swf_svg_action; + read->finalize = swf_svg_finalize; + return GF_OK; +} + +#endif /*GPAC_DISABLE_SWF_IMPORT*/ + +#else +GF_Err swf_to_svg_init(SWFReader *read) +{ + return GF_NOT_SUPPORTED; +} + +#endif /*GPAC_DISABLE_VRML*/ diff --git a/src/scene_manager/text_to_bifs.c b/src/scene_manager/text_to_bifs.c index 1e70c4e..6bc75c9 100644 --- a/src/scene_manager/text_to_bifs.c +++ b/src/scene_manager/text_to_bifs.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scenegraph/base_scenegraph.c b/src/scenegraph/base_scenegraph.c index 05187c4..e93409f 100644 --- a/src/scenegraph/base_scenegraph.c +++ b/src/scenegraph/base_scenegraph.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -291,7 +292,10 @@ void gf_sg_reset(GF_SceneGraph *sg) { GF_SceneGraph *par; GF_List *gc; - u32 type, count; +#ifndef GPAC_DISABLE_SVG + u32 type; +#endif + u32 count; NodeIDedItem *reg_node; if (!sg) return; @@ -390,8 +394,9 @@ restart: This will take care of nodes referencing themselves*/ { GF_ParentList *nlist = node->sgprivate->parents; +#ifndef GPAC_DISABLE_SVG type = (node->sgprivate->tag>GF_NODE_RANGE_LAST_VRML) ? 1 : 0; - +#endif while (nlist) { GF_ParentList *next = nlist->next; #if 0 @@ -865,7 +870,9 @@ static void ReplaceIRINode(GF_Node *FromNode, GF_Node *old_node, GF_Node *newNod /*get all parents of the node and replace, the instance of the node and finally destroy the node*/ GF_Err gf_node_replace(GF_Node *node, GF_Node *new_node, Bool updateOrderedGroup) { +#ifndef GPAC_DISABLE_SVG u32 type; +#endif #ifndef GPAC_DISABLE_VRML Bool replace_proto; #endif @@ -878,8 +885,8 @@ GF_Err gf_node_replace(GF_Node *node, GF_Node *new_node, Bool updateOrderedGroup if (node == (GF_Node*)pSG->pOwningProto) pSG = pSG->parent_scene; #endif - type = (node->sgprivate->tag>GF_NODE_RANGE_LAST_VRML) ? 1 : 0; #ifndef GPAC_DISABLE_SVG + type = (node->sgprivate->tag>GF_NODE_RANGE_LAST_VRML) ? 1 : 0; if (type) { Replace_IRI(pSG, node, new_node); } diff --git a/src/scenegraph/commands.c b/src/scenegraph/commands.c index 6d06516..2005268 100644 --- a/src/scenegraph/commands.c +++ b/src/scenegraph/commands.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -144,6 +145,7 @@ static void SG_CheckFieldChange(GF_Node *node, GF_FieldInfo *field) gf_node_changed(node, field); } +#ifndef GPAC_DISABLE_SVG static void gf_node_unregister_children_deactivate(GF_Node *container, GF_ChildNodeItem *child) { GF_ChildNodeItem *cur; @@ -155,6 +157,7 @@ static void gf_node_unregister_children_deactivate(GF_Node *container, GF_ChildN gf_free(cur); } } +#endif GF_EXPORT diff --git a/src/scenegraph/dom_events.c b/src/scenegraph/dom_events.c index 4739de2..0aa1c35 100644 --- a/src/scenegraph/dom_events.c +++ b/src/scenegraph/dom_events.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004 + * Authors: Jean Le Feuvre, Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / DOM 3 Events sub-project diff --git a/src/scenegraph/dom_smjs.c b/src/scenegraph/dom_smjs.c index 878cd63..7b1cc04 100644 --- a/src/scenegraph/dom_smjs.c +++ b/src/scenegraph/dom_smjs.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2007-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2007-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -106,23 +106,17 @@ char *js_get_utf8(JSContext *c, jsval val) typedef struct { u32 nb_inst; - JSClass domDocumentClass; - JSClass domNodeClass; - JSClass domElementClass; - JSClass domTextClass; - JSClass domNodeListClass; - JSClass domEventClass; + GF_JSClass domDocumentClass; + GF_JSClass domNodeClass; + GF_JSClass domElementClass; + GF_JSClass domTextClass; + GF_JSClass domNodeListClass; + GF_JSClass domEventClass; - JSClass xmlHTTPRequestClass; - JSClass DCCIClass; + GF_JSClass xmlHTTPRequestClass; + GF_JSClass DCCIClass; - JSClass storageClass; - - JSObject *dom_node_proto; - JSObject *dom_document_proto; - JSObject *dom_element_proto; - JSObject *dom_event_proto; - JSObject *storage_proto; + GF_JSClass storageClass; void *(*get_element_class)(GF_Node *n); void *(*get_document_class)(GF_SceneGraph *n); @@ -222,7 +216,7 @@ GF_SceneGraph *dom_get_doc(JSContext *c, JSObject *obj) static jsval dom_document_construct(JSContext *c, GF_SceneGraph *sg) { - JSClass *jsclass; + GF_JSClass *jsclass; JSObject *new_obj; if (sg->document) return OBJECT_TO_JSVAL(sg->document); @@ -232,17 +226,17 @@ static jsval dom_document_construct(JSContext *c, GF_SceneGraph *sg) jsclass = NULL; if (dom_rt->get_document_class) - jsclass = (JSClass *) dom_rt->get_document_class(sg); + jsclass = (GF_JSClass *) dom_rt->get_document_class(sg); if (!jsclass) jsclass = &dom_rt->domDocumentClass; - new_obj = JS_NewObject(c, jsclass, 0, 0); + new_obj = JS_NewObject(c, & jsclass->_class, 0, 0); SMJS_SET_PRIVATE(c, new_obj, sg); sg->document = new_obj; return OBJECT_TO_JSVAL(new_obj); } -static jsval dom_base_node_construct(JSContext *c, JSClass *_class, GF_Node *n) +static jsval dom_base_node_construct(JSContext *c, GF_JSClass *_class, GF_Node *n) { Bool set_rooted; GF_SceneGraph *sg; @@ -271,7 +265,7 @@ static jsval dom_base_node_construct(JSContext *c, JSClass *_class, GF_Node *n) n->sgprivate->scenegraph->reference_count ++; gf_node_register(n, NULL); - new_obj = JS_NewObject(c, _class, 0, 0); + new_obj = JS_NewObject(c, & _class->_class, 0, 0); SMJS_SET_PRIVATE(c, new_obj, n); if (!n->sgprivate->interact) GF_SAFEALLOC(n->sgprivate->interact, struct _node_interactive_ext); @@ -294,13 +288,13 @@ static jsval dom_base_node_construct(JSContext *c, JSClass *_class, GF_Node *n) } static jsval dom_node_construct(JSContext *c, GF_Node *n) { - JSClass *__class = NULL; + GF_JSClass *__class = NULL; if (!n) return JSVAL_NULL; if (n->sgprivate->scenegraph->dcci_doc) __class = &dom_rt->DCCIClass; else if (dom_rt->get_element_class) - __class = (JSClass *) dom_rt->get_element_class(n); + __class = (GF_JSClass *) dom_rt->get_element_class(n); if (!__class ) __class = &dom_rt->domElementClass; @@ -310,13 +304,13 @@ static jsval dom_node_construct(JSContext *c, GF_Node *n) } jsval dom_element_construct(JSContext *c, GF_Node *n) { - JSClass *__class = NULL; + GF_JSClass *__class = NULL; if (!n) return JSVAL_NULL; if (n->sgprivate->scenegraph->dcci_doc) __class = &dom_rt->DCCIClass; else if (dom_rt->get_element_class) - __class = (JSClass *) dom_rt->get_element_class(n); + __class = (GF_JSClass *) dom_rt->get_element_class(n); if (!__class) __class = &dom_rt->domElementClass; @@ -408,15 +402,15 @@ static jsval dom_nodelist_construct(JSContext *c, GF_ParentNode *n) n->sgprivate->scenegraph->reference_count++; gf_node_register((GF_Node*)n, NULL); - new_obj = JS_NewObject(c, &dom_rt->domNodeListClass, 0, 0); + new_obj = JS_NewObject(c, &dom_rt->domNodeListClass._class, 0, 0); SMJS_SET_PRIVATE(c, new_obj, nl); return OBJECT_TO_JSVAL(new_obj); } -static void dom_nodelist_finalize(JSContext *c, JSObject *obj) -{ +static DECL_FINALIZE(dom_nodelist_finalize) + DOMNodeList *nl; - if (!JS_InstanceOf(c, obj, &dom_rt->domNodeListClass, NULL) ) + if (!GF_JS_InstanceOf(c, obj, &dom_rt->domNodeListClass, NULL) ) return; nl = (DOMNodeList *) SMJS_GET_PRIVATE(c, obj); @@ -444,7 +438,7 @@ static JSBool SMJS_FUNCTION(dom_nodelist_item) DOMNodeList *nl; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &dom_rt->domNodeListClass, NULL) ) + if (!GF_JS_InstanceOf(c, obj, &dom_rt->domNodeListClass, NULL) ) return JS_TRUE; if ((argc!=1) || !JSVAL_IS_INT(argv[0])) return JS_TRUE; @@ -461,10 +455,10 @@ static JSBool SMJS_FUNCTION(dom_nodelist_item) return JS_TRUE; } -static JSBool dom_nodelist_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( dom_nodelist_getProperty) + DOMNodeList *nl; - if (!JS_InstanceOf(c, obj, &dom_rt->domNodeListClass, NULL) + if (!GF_JS_InstanceOf(c, obj, &dom_rt->domNodeListClass, NULL) ) return JS_TRUE; @@ -478,8 +472,10 @@ static JSBool dom_nodelist_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GE } return JS_TRUE; } -static JSBool dom_nodelist_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( dom_nodelist_setProperty) + + /*avoids gcc warning*/ + if (!obj) obj=NULL; if (!SMJS_ID_IS_INT(id)) return JS_TRUE; /*no write prop*/ return JS_TRUE; @@ -761,8 +757,8 @@ JSBool SMJS_FUNCTION(dom_event_remove_listener) } /*dom3 node*/ -static void dom_node_finalize(JSContext *c, JSObject *obj) -{ +static DECL_FINALIZE( dom_node_finalize) + GF_Node *n = (GF_Node *) SMJS_GET_PRIVATE(c, obj); /*the JS proto of the svgClass or a destroyed object*/ if (!n) return; @@ -1103,8 +1099,8 @@ static u32 get_namespace_code_by_prefix(GF_Node *node, char *prefix) } #endif /*GPAC_UNUSED_FUNC*/ -static JSBool dom_node_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( dom_node_getProperty) + u32 tag; GF_Node *n; GF_SceneGraph *sg = NULL; @@ -1302,8 +1298,8 @@ void dom_node_set_textContent(GF_Node *n, char *text) gf_node_changed(n, &info); } -static JSBool dom_node_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( dom_node_setProperty) + u32 tag; GF_Node *n; @@ -1349,8 +1345,8 @@ static JSBool dom_node_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER /*don't attempt to do anything with the scenegraph, it may be destroyed fortunately a sg cannot be created like that...*/ -void dom_document_finalize(JSContext *c, JSObject *obj) -{ +DECL_FINALIZE(dom_document_finalize) + GF_SceneGraph *sg = dom_get_doc(c, obj); sg = (GF_SceneGraph*) SMJS_GET_PRIVATE(c, obj); @@ -1369,8 +1365,8 @@ void dom_document_finalize(JSContext *c, JSObject *obj) } } -static JSBool dom_document_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( dom_document_getProperty ) + u32 prop_id; GF_SceneGraph *sg = dom_get_doc(c, obj); if (!sg) return JS_TRUE; @@ -1409,8 +1405,8 @@ static JSBool dom_document_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GE return JS_TRUE; } -static JSBool dom_document_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET(dom_document_setProperty) + u32 prop_id; GF_SceneGraph *sg = dom_get_doc(c, obj); if (!sg) return JS_TRUE; @@ -1545,7 +1541,7 @@ static JSBool SMJS_FUNCTION(xml_document_elements_by_tag) GF_SAFEALLOC(nl, DOMNodeList); if (name && !strcmp(name, "*")) name = NULL; xml_doc_gather_nodes((GF_ParentNode*)sg->RootNode, name, nl); - new_obj = JS_NewObject(c, &dom_rt->domNodeListClass, 0, 0); + new_obj = JS_NewObject(c, &dom_rt->domNodeListClass._class, 0, 0); SMJS_SET_PRIVATE(c, new_obj, nl); SMJS_SET_RVAL( OBJECT_TO_JSVAL(new_obj)); SMJS_FREE(c, name); @@ -1583,13 +1579,13 @@ static JSBool SMJS_FUNCTION(xml_document_element_by_id) } /*dom3 element*/ -void dom_element_finalize(JSContext *c, JSObject *obj) -{ +DECL_FINALIZE( dom_element_finalize) + dom_node_finalize(c, obj); } -static JSBool dom_element_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( dom_element_getProperty) + u32 prop_id; GF_Node *n = dom_get_node(c, obj); if (!n) return JS_TRUE; @@ -2050,7 +2046,7 @@ static JSBool SMJS_FUNCTION(xml_element_elements_by_tag) name = NULL; } xml_doc_gather_nodes((GF_ParentNode*)n, name, nl); - new_obj = JS_NewObject(c, &dom_rt->domNodeListClass, 0, 0); + new_obj = JS_NewObject(c, &dom_rt->domNodeListClass._class, 0, 0); SMJS_SET_PRIVATE(c, new_obj, nl); SMJS_SET_RVAL( OBJECT_TO_JSVAL(new_obj) ); @@ -2098,8 +2094,8 @@ static JSBool SMJS_FUNCTION(xml_element_set_id) /*dom3 character/text/comment*/ -static JSBool dom_text_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( dom_text_getProperty) + u32 prop_id; GF_DOMText *txt = (GF_DOMText*)dom_get_node(c, obj); if (!txt || (txt->sgprivate->tag != TAG_DOMText)) return JS_TRUE; @@ -2124,8 +2120,8 @@ static JSBool dom_text_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER } return JS_TRUE; } -static JSBool dom_text_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( dom_text_setProperty) + u32 prop_id; GF_DOMText *txt = (GF_DOMText*)dom_get_node(c, obj); if (!txt || (txt->sgprivate->tag != TAG_DOMText)) return JS_TRUE; @@ -2172,8 +2168,8 @@ static JSBool SMJS_FUNCTION(event_prevent_default) return JS_TRUE; } -static JSBool event_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( event_getProperty) + JSString *s; GF_DOM_Event *evt = SMJS_GET_PRIVATE(c, obj); if (evt==NULL) return JS_TRUE; @@ -2527,10 +2523,10 @@ static void xml_http_reset(XMLHTTPContext *ctx) ctx->html_status = 0; } -static void xml_http_finalize(JSContext *c, JSObject *obj) -{ +static DECL_FINALIZE( xml_http_finalize) + XMLHTTPContext *ctx; - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (ctx) { if (ctx->onreadystatechange) gf_js_remove_root(c, &(ctx->onreadystatechange), GF_JSGC_VAL); @@ -2541,9 +2537,9 @@ static void xml_http_finalize(JSContext *c, JSObject *obj) static JSBool SMJS_FUNCTION(xml_http_constructor) { XMLHTTPContext *p; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&dom_rt->xmlHTTPRequestClass) - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; GF_SAFEALLOC(p, XMLHTTPContext); p->c = c; p->_this = obj; @@ -2587,7 +2583,7 @@ static JSBool SMJS_FUNCTION(xml_http_open) SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -2656,7 +2652,7 @@ static JSBool SMJS_FUNCTION(xml_http_set_header) SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -2895,7 +2891,7 @@ static JSBool SMJS_FUNCTION(xml_http_send) SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -2910,7 +2906,7 @@ static JSBool SMJS_FUNCTION(xml_http_send) if (argc) { if (JSVAL_IS_NULL(argv[0])) { } else if (JSVAL_IS_OBJECT(argv[0])) { -// if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &documentClass, NULL) ) return JS_TRUE; +// if (!GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &documentClass, NULL) ) return JS_TRUE; /*NOT SUPPORTED YET, we must serialize the sg*/ return JS_TRUE; @@ -2999,7 +2995,7 @@ static JSBool SMJS_FUNCTION(xml_http_abort) XMLHTTPContext *ctx; SMJS_OBJ - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -3018,7 +3014,7 @@ static JSBool SMJS_FUNCTION(xml_http_get_all_headers) XMLHTTPContext *ctx; SMJS_OBJ - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -3052,7 +3048,7 @@ static JSBool SMJS_FUNCTION(xml_http_get_header) XMLHTTPContext *ctx; SMJS_OBJ SMJS_ARGS - if (!argc || !JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!argc || !GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -3081,11 +3077,11 @@ static JSBool SMJS_FUNCTION(xml_http_get_header) return JS_TRUE; } -static JSBool xml_http_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( xml_http_getProperty) + JSString *s; XMLHTTPContext *ctx; - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -3137,14 +3133,13 @@ static JSBool xml_http_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER return JS_TRUE; } } - return JS_PropertyStub(c, obj, id, vp); - return JS_TRUE; + return SMJS_CALL_PROP_STUB(); } -static JSBool xml_http_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( xml_http_setProperty) + XMLHTTPContext *ctx; - if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_TRUE; ctx = (XMLHTTPContext *)SMJS_GET_PRIVATE(c, obj); if (!ctx) return JS_TRUE; @@ -3179,14 +3174,14 @@ static JSBool xml_http_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER } -static JSBool dcci_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(dcci_getProperty) + GF_DOMFullAttribute *att; GF_ChildNodeItem *child; GF_DOMFullNode *n; char *value; JSString *s; - if (!JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; n = (GF_DOMFullNode*) dom_get_node(c, obj); if (!n) return JS_TRUE; @@ -3265,17 +3260,18 @@ static JSBool dcci_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js return JS_TRUE; } } - return JS_PropertyStub(c, obj, id, vp); + return SMJS_CALL_PROP_STUB(); } -static JSBool dcci_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( dcci_setProperty) + GF_ChildNodeItem *child; GF_DOMFullNode *n; + GF_DOMFullAttribute*att; GF_DOM_Event evt; char *str; - jsval readonly=JSVAL_NULL; - if (!JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; + Bool readonly; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; n = (GF_DOMFullNode*) dom_get_node(c, obj); if (!n) return JS_TRUE; @@ -3286,12 +3282,16 @@ static JSBool dcci_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, js switch (SMJS_ID_TO_INT(id)) { /*value*/ case 0: -#if (JS_VERSION>=185) - dcci_getProperty(c, obj, (jsint) (3), &readonly); -#else - dcci_getProperty(c, obj, INT_TO_JSVAL(3), &readonly); -#endif - if (JSVAL_TO_BOOLEAN(readonly) == JS_TRUE) break; + readonly = 0; + att = (GF_DOMFullAttribute*) n->attributes; + while (att) { + if (att->name && !strcmp(att->name, "readOnly") && att->data && !strcmp(att->data, "true")) { + readonly = 1; + break; + } + att = (GF_DOMFullAttribute*) att->next; + } + if (readonly) break; child = n->children; while (child) { if (child->node && (child->node->sgprivate->tag==TAG_DOMText)) { @@ -3362,7 +3362,7 @@ static JSBool SMJS_FUNCTION(dcci_has_property) char *ns, *name; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; n = (GF_DOMFullNode*) dom_get_node(c, obj); if (!n) return JS_TRUE; if (argc!=3) return JS_TRUE; @@ -3419,7 +3419,7 @@ static JSBool SMJS_FUNCTION(dcci_search_property) SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->DCCIClass, NULL) ) return JS_TRUE; n = (GF_DOMFullNode*) dom_get_node(c, obj); if (!n) return JS_TRUE; if (argc!=4) return JS_TRUE; @@ -3432,7 +3432,7 @@ static JSBool SMJS_FUNCTION(dcci_search_property) GF_SAFEALLOC(nl, DOMNodeList); dcci_prop_collect(nl, n, ns, name, deep, 1); - new_obj = JS_NewObject(c, &dom_rt->domNodeListClass, 0, 0); + new_obj = JS_NewObject(c, &dom_rt->domNodeListClass._class, 0, 0); SMJS_SET_PRIVATE(c, new_obj, nl); SMJS_SET_RVAL( OBJECT_TO_JSVAL(new_obj) ); SMJS_FREE(c, ns); @@ -3440,33 +3440,39 @@ static JSBool SMJS_FUNCTION(dcci_search_property) return JS_TRUE; } -static JSBool storage_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &dom_rt->storageClass, NULL) ) return JS_TRUE; +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; return JS_TRUE; } -static JSBool storage_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &dom_rt->storageClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_SET( storage_setProperty) + + /*avoids gcc warning*/ + if (!id) id=0; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->storageClass, NULL) ) return JS_TRUE; return JS_TRUE; } static JSBool SMJS_FUNCTION(storage_constructor) { - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&dom_rt->storageClass) - if (!JS_InstanceOf(c, obj, &dom_rt->storageClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &dom_rt->storageClass, NULL) ) return JS_TRUE; return JS_TRUE; } -static void storage_finalize(JSContext *c, JSObject *obj) -{ +static DECL_FINALIZE( storage_finalize) + + /*avoids GCC warning*/ + if (!c) c=NULL; } void dom_js_define_storage(JSContext *c, JSObject *parent_obj, const char *name) { - JS_DefineObject(c, parent_obj, name, &dom_rt->storageClass, 0, 0 ); + JS_DefineObject(c, parent_obj, name, &dom_rt->storageClass._class, 0, 0 ); } void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) @@ -3544,17 +3550,17 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) {0, 0, 0, 0, 0} }; - dom_rt->dom_node_proto = JS_InitClass(c, global, 0, &dom_rt->domNodeClass, 0, 0, nodeProps, nodeFuncs, 0, 0); - if (!dom_rt->dom_node_proto) { + GF_JS_InitClass(c, global, 0, &dom_rt->domNodeClass, 0, 0, nodeProps, nodeFuncs, 0, 0); + if (!dom_rt->domNodeClass._proto) { GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[DOMCore] Not enough memory to initialize JS node class\n")); return; } GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] node class initialized\n")); - JS_DefineProperty(c, dom_rt->dom_node_proto, "ELEMENT_NODE", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_node_proto, "TEXT_NODE", INT_TO_JSVAL(3), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_node_proto, "CDATA_SECTION_NODE", INT_TO_JSVAL(4), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_node_proto, "DOCUMENT_NODE", INT_TO_JSVAL(9), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domNodeClass._proto, "ELEMENT_NODE", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domNodeClass._proto, "TEXT_NODE", INT_TO_JSVAL(3), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domNodeClass._proto, "CDATA_SECTION_NODE", INT_TO_JSVAL(4), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domNodeClass._proto, "DOCUMENT_NODE", INT_TO_JSVAL(9), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); } { @@ -3597,7 +3603,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) {0, 0, 0, 0, 0}, }; - dom_rt->dom_document_proto = JS_InitClass(c, global, dom_rt->dom_node_proto, &dom_rt->domDocumentClass, 0, 0, documentProps, documentFuncs, 0, 0); + GF_JS_InitClass(c, global, dom_rt->domNodeClass._proto, &dom_rt->domDocumentClass, 0, 0, documentProps, documentFuncs, 0, 0); GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] document class initialized\n")); } @@ -3631,7 +3637,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) {"schemaTypeInfo", 2, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0}, {0, 0, 0, 0, 0}, }; - dom_rt->dom_element_proto = JS_InitClass(c, global, dom_rt->dom_node_proto, &dom_rt->domElementClass, 0, 0, elementProps, elementFuncs, 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")); } @@ -3657,7 +3663,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) {"wholeText", 4, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0}, {0, 0, 0, 0, 0}, }; - JS_InitClass(c, global, dom_rt->dom_node_proto, &dom_rt->domTextClass, 0, 0, textProps, textFuncs, 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")); } @@ -3728,17 +3734,17 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) {0, 0, 0, 0, 0}, }; - dom_rt->dom_event_proto = JS_InitClass(c, global, 0, &dom_rt->domEventClass, 0, 0, eventProps, eventFuncs, 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")); - JS_DefineProperty(c, dom_rt->dom_event_proto, "CAPTURING_PHASE", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_event_proto, "AT_TARGET", INT_TO_JSVAL(2), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_event_proto, "BUBBLING_PHASE", INT_TO_JSVAL(3), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "CAPTURING_PHASE", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "AT_TARGET", INT_TO_JSVAL(2), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "BUBBLING_PHASE", INT_TO_JSVAL(3), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_event_proto, "DOM_KEY_LOCATION_STANDARD ", INT_TO_JSVAL(0), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_event_proto, "DOM_KEY_LOCATION_LEFT", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_event_proto, "DOM_KEY_LOCATION_RIGHT", INT_TO_JSVAL(2), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(c, dom_rt->dom_event_proto, "DOM_KEY_LOCATION_NUMPAD", INT_TO_JSVAL(3), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "DOM_KEY_LOCATION_STANDARD ", INT_TO_JSVAL(0), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "DOM_KEY_LOCATION_LEFT", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "DOM_KEY_LOCATION_RIGHT", INT_TO_JSVAL(2), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(c, dom_rt->domEventClass._proto, "DOM_KEY_LOCATION_NUMPAD", INT_TO_JSVAL(3), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); } @@ -3751,7 +3757,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) {"length", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(c, global, 0, &dom_rt->domNodeListClass, 0, 0, nodeListProps, nodeListFuncs, 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")); } @@ -3775,7 +3781,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) /*todo - addEventListener and removeEventListener*/ SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(c, global, 0, &dom_rt->xmlHTTPRequestClass, xml_http_constructor, 0, xmlHTTPRequestClassProps, xmlHTTPRequestClassFuncs, 0, 0); + GF_JS_InitClass(c, global, 0, &dom_rt->xmlHTTPRequestClass, xml_http_constructor, 0, xmlHTTPRequestClassProps, xmlHTTPRequestClassFuncs, 0, 0); GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] XMLHttpRequest class initialized\n")); } @@ -3786,7 +3792,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) JSFunctionSpec storageClassFuncs[] = { SMJS_FUNCTION_SPEC(0, 0, 0) }; - dom_rt->storage_proto = JS_InitClass(c, global, 0, &dom_rt->storageClass, storage_constructor, 0, storageClassProps, storageClassFuncs, 0, 0); + GF_JS_InitClass(c, global, 0, &dom_rt->storageClass, storage_constructor, 0, storageClassProps, storageClassFuncs, 0, 0); GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[DOMCore] Storage class initialized\n")); } @@ -3819,7 +3825,7 @@ void dom_js_load(GF_SceneGraph *scene, JSContext *c, JSObject *global) SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(c, global, dom_rt->dom_element_proto, &dom_rt->DCCIClass, 0, 0, DCCIClassProps, DCCIClassFuncs, 0, 0); + GF_JS_InitClass(c, global, dom_rt->domElementClass._proto, &dom_rt->DCCIClass, 0, 0, DCCIClassProps, DCCIClassFuncs, 0, 0); dcci_root = dom_base_node_construct(c, &dom_rt->DCCIClass, dcci->RootNode); JS_DefineProperty(c, global, "DCCIRoot", dcci_root, 0, 0, JSPROP_READONLY | JSPROP_PERMANENT ); @@ -3876,7 +3882,11 @@ void dom_js_pre_destroy(JSContext *c, GF_SceneGraph *sg, GF_Node *n) } } if (sg->document) { +#ifdef USE_FFDEV_15 + dom_document_finalize(NULL, sg->document); +#else dom_document_finalize(c, sg->document); +#endif } } @@ -3893,7 +3903,7 @@ void dom_js_unload() static void dom_js_define_document_ex(JSContext *c, JSObject *global, GF_SceneGraph *doc, const char *name) { - JSClass *__class; + GF_JSClass *__class; JSObject *obj; if (!doc || !doc->RootNode) return; @@ -3905,7 +3915,7 @@ static void dom_js_define_document_ex(JSContext *c, JSObject *global, GF_SceneGr __class = dom_rt->get_document_class(doc); if (!__class) __class = &dom_rt->domDocumentClass; - obj = JS_DefineObject(c, global, name, __class, 0, 0 ); + obj = JS_DefineObject(c, global, name, & __class->_class, 0, 0 ); gf_node_register(doc->RootNode, NULL); SMJS_SET_PRIVATE(c, obj, doc); doc->document = obj; @@ -3918,19 +3928,19 @@ void dom_js_define_document(JSContext *c, JSObject *global, GF_SceneGraph *doc) JSObject *dom_js_define_event(JSContext *c, JSObject *global) { - JSObject *obj = JS_DefineObject(c, global, "evt", &dom_rt->domEventClass, 0, 0 ); + JSObject *obj = JS_DefineObject(c, global, "evt", &dom_rt->domEventClass._class, 0, 0 ); //JS_AliasProperty(c, global, "evt", "event"); return obj; } JSObject *gf_dom_new_event(JSContext *c) { - return JS_NewObject(c, &dom_rt->domEventClass, 0, 0); + return JS_NewObject(c, &dom_rt->domEventClass._class, 0, 0); } -JSObject *dom_js_get_node_proto(JSContext *c) { return dom_rt->dom_node_proto; } -JSObject *dom_js_get_element_proto(JSContext *c) { return dom_rt->dom_element_proto; } -JSObject *dom_js_get_document_proto(JSContext *c) { return dom_rt->dom_document_proto; } -JSObject *dom_js_get_event_proto(JSContext *c) { return dom_rt->dom_event_proto; } +JSObject *dom_js_get_node_proto(JSContext *c) { return dom_rt->domNodeClass._proto; } +JSObject *dom_js_get_element_proto(JSContext *c) { return dom_rt->domElementClass._proto; } +JSObject *dom_js_get_document_proto(JSContext *c) { return dom_rt->domDocumentClass._proto; } +JSObject *dom_js_get_event_proto(JSContext *c) { return dom_rt->domEventClass._proto; } void dom_set_class_selector(JSContext *c, void *(*get_element_class)(GF_Node *n), void *(*get_document_class)(GF_SceneGraph *n) ) { diff --git a/src/scenegraph/mpeg4_animators.c b/src/scenegraph/mpeg4_animators.c index 5e708c3..20156ac 100644 --- a/src/scenegraph/mpeg4_animators.c +++ b/src/scenegraph/mpeg4_animators.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/mpeg4_nodes.c b/src/scenegraph/mpeg4_nodes.c index f020ce1..3c2d2bc 100644 --- a/src/scenegraph/mpeg4_nodes.c +++ b/src/scenegraph/mpeg4_nodes.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/mpeg4_valuator.c b/src/scenegraph/mpeg4_valuator.c index 2c9cb69..dcda43d 100644 --- a/src/scenegraph/mpeg4_valuator.c +++ b/src/scenegraph/mpeg4_valuator.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/smil_anim.c b/src/scenegraph/smil_anim.c index c16f05b..3a93fa5 100644 --- a/src/scenegraph/smil_anim.c +++ b/src/scenegraph/smil_anim.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c)2004-200X ENST - All rights reserved + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * * This file is part of GPAC / SVG Scene Graph sub-project * diff --git a/src/scenegraph/smil_timing.c b/src/scenegraph/smil_timing.c index aa525d9..d95063d 100644 --- a/src/scenegraph/smil_timing.c +++ b/src/scenegraph/smil_timing.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c)2004-200X ENST - All rights reserved + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2004-2012 * * This file is part of GPAC / SVG Scene Graph sub-project * diff --git a/src/scenegraph/svg_attributes.c b/src/scenegraph/svg_attributes.c index e09a072..bdc7d09 100644 --- a/src/scenegraph/svg_attributes.c +++ b/src/scenegraph/svg_attributes.c @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * - * Authors: Cyril Concolato - Jean le Feuvre - Jean-Claude Moissinac - * Copyright (c) 2005-200X ENST + * Authors: Cyril Concolato, Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Loader module diff --git a/src/scenegraph/svg_properties.c b/src/scenegraph/svg_properties.c index 56a5f6f..870359d 100644 --- a/src/scenegraph/svg_properties.c +++ b/src/scenegraph/svg_properties.c @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * - * Authors: Cyril Concolato - Jean le Feuvre - Jean-Claude Moissinac - * Copyright (c) 2005-200X ENST + * Authors: Cyril Concolato, Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Loader module diff --git a/src/scenegraph/svg_smjs.c b/src/scenegraph/svg_smjs.c index 63ab3a5..1f3d7c7 100644 --- a/src/scenegraph/svg_smjs.c +++ b/src/scenegraph/svg_smjs.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -46,8 +46,13 @@ static Bool svg_script_execute_handler(GF_Node *node, GF_DOM_Event *event, GF_No jsval dom_element_construct(JSContext *c, GF_Node *n); +#ifdef USE_FFDEV_15 +void dom_element_finalize(JSFreeOp *fop, JSObject *obj); +void dom_document_finalize(JSFreeOp *fop, JSObject *obj); +#else void dom_element_finalize(JSContext *c, JSObject *obj); void dom_document_finalize(JSContext *c, JSObject *obj); +#endif GF_Node *dom_get_element(JSContext *c, JSObject *obj); GF_SceneGraph *dom_get_doc(JSContext *c, JSObject *obj); @@ -83,15 +88,15 @@ typedef struct { u32 nb_inst; /*SVG uDOM classes*/ - JSClass svgElement; - JSClass svgDocument; - JSClass globalClass; - JSClass connectionClass; - JSClass rgbClass; - JSClass rectClass; - JSClass pointClass; - JSClass pathClass; - JSClass matrixClass; + GF_JSClass svgElement; + GF_JSClass svgDocument; + GF_JSClass globalClass; + GF_JSClass connectionClass; + GF_JSClass rgbClass; + GF_JSClass rectClass; + GF_JSClass pointClass; + GF_JSClass pathClass; + GF_JSClass matrixClass; } GF_SVGuDOM; static GF_SVGuDOM *svg_rt = NULL; @@ -138,7 +143,7 @@ static JSBool SMJS_FUNCTION(svg_nav_to_location) GF_SceneGraph *sg; SMJS_OBJ SMJS_ARGS - if ((argc!=1) || !JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL)) return JS_TRUE; + if ((argc!=1) || !GF_JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL)) return JS_TRUE; sg = SMJS_GET_PRIVATE(c, obj); par.uri.url = SMJS_CHARS(c, argv[0]); par.uri.nb_params = 0; @@ -182,7 +187,7 @@ static JSBool SMJS_FUNCTION(svg_echo) GF_SceneGraph *sg; SMJS_OBJ SMJS_ARGS - if ((argc!=1) || !JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL)) return JS_TRUE; + if ((argc!=1) || !GF_JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL)) return JS_TRUE; sg = SMJS_GET_PRIVATE(c, obj); if (!sg) return JS_TRUE; @@ -221,10 +226,10 @@ static void svg_define_udom_exception(JSContext *c, JSObject *global) JS_DefineProperty(c, obj, "NAV_UP_LEFT", INT_TO_JSVAL(11), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); } -static JSBool global_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( global_getProperty) + GF_SceneGraph *sg; - if (!JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL) ) + if (!GF_JS_InstanceOf(c, obj, &svg_rt->globalClass, NULL) ) return JS_TRUE; sg = SMJS_GET_PRIVATE(c, obj); @@ -293,8 +298,8 @@ static GF_Node *get_corresponding_use(GF_Node *n) /*otherwise recursively get up the tree*/ return get_corresponding_use(gf_node_get_parent(n, 0)); } -static JSBool svg_doc_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( svg_doc_getProperty) + u32 prop_id; GF_SceneGraph *sg = dom_get_doc(c, obj); if (!sg) return JS_TRUE; @@ -309,8 +314,8 @@ static JSBool svg_doc_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, return JS_TRUE; } -static JSBool svg_element_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(svg_element_getProperty) + u32 prop_id; GF_JSAPIParam par; JSString *s; @@ -348,7 +353,7 @@ static JSBool svg_element_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GET case 7:/*currentTranslate*/ if (n->sgprivate->tag!=TAG_SVG_svg) return JS_TRUE; if (ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_GET_TRANSLATE, (GF_Node *)n, &par)) { - JSObject *r = JS_NewObject(c, &svg_rt->pointClass, 0, 0); + JSObject *r = JS_NewObject(c, &svg_rt->pointClass._class, 0, 0); pointCI *rc = gf_malloc(sizeof(pointCI)); rc->x = FIX2FLT(par.pt.x); rc->y = FIX2FLT(par.pt.y); @@ -361,7 +366,7 @@ static JSBool svg_element_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GET case 8:/*viewport*/ if (n->sgprivate->tag!=TAG_SVG_svg) return JS_TRUE; if (ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_GET_VIEWPORT, (GF_Node *)n, &par)) { - JSObject *r = JS_NewObject(c, &svg_rt->rectClass, 0, 0); + JSObject *r = JS_NewObject(c, &svg_rt->rectClass._class, 0, 0); rectCI *rc = gf_malloc(sizeof(rectCI)); rc->x = FIX2FLT(par.rc.x); rc->y = FIX2FLT(par.rc.y); @@ -407,8 +412,8 @@ static JSBool svg_element_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GET return JS_TRUE; } -static JSBool svg_element_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( svg_element_setProperty) + GF_JSAPIParam par; jsdouble d; u32 prop_id; @@ -837,7 +842,7 @@ JSBool SMJS_FUNCTION(svg_udom_get_matrix_trait) if (info.fieldType==SVG_Transform_datatype) { GF_Matrix2D *mx = gf_malloc(sizeof(GF_Matrix2D)); - mO = JS_NewObject(c, &svg_rt->matrixClass, 0, 0); + mO = JS_NewObject(c, &svg_rt->matrixClass._class, 0, 0); gf_mx2d_init(*mx); gf_mx2d_copy(*mx, ((SVG_Transform*)info.far_ptr)->mat); @@ -869,7 +874,7 @@ JSBool SMJS_FUNCTION(svg_udom_get_rect_trait) if (info.fieldType==SVG_ViewBox_datatype) { rectCI *rc; SVG_ViewBox *v = (SVG_ViewBox *)info.far_ptr; - newObj = JS_NewObject(c, &svg_rt->rectClass, 0, 0); + newObj = JS_NewObject(c, &svg_rt->rectClass._class, 0, 0); GF_SAFEALLOC(rc, rectCI); rc->x = FIX2FLT(v->x); rc->y = FIX2FLT(v->y); @@ -931,7 +936,7 @@ JSBool SMJS_FUNCTION(svg_udom_get_rgb_color_trait) SVG_Color *col = (SVG_Color *)info.far_ptr; if (col->type == SVG_COLOR_CURRENTCOLOR) return JS_TRUE; if (col->type == SVG_COLOR_INHERIT) return JS_TRUE; - newObj = JS_NewObject(c, &svg_rt->rgbClass, 0, 0); + newObj = JS_NewObject(c, &svg_rt->rgbClass._class, 0, 0); GF_SAFEALLOC(rgb, rgbCI); rgb->r = (u8) (255*FIX2FLT(col->red)) ; rgb->g = (u8) (255*FIX2FLT(col->green)) ; @@ -945,7 +950,7 @@ JSBool SMJS_FUNCTION(svg_udom_get_rgb_color_trait) { SVG_Paint *paint = (SVG_Paint *)info.far_ptr; if (1 || paint->type==SVG_PAINT_COLOR) { - newObj = JS_NewObject(c, &svg_rt->rgbClass, 0, 0); + newObj = JS_NewObject(c, &svg_rt->rgbClass._class, 0, 0); GF_SAFEALLOC(rgb, rgbCI); rgb->r = (u8) (255*FIX2FLT(paint->color.red) ); rgb->g = (u8) (255*FIX2FLT(paint->color.green) ); @@ -1088,7 +1093,7 @@ JSBool SMJS_FUNCTION(svg_udom_set_matrix_trait) if (JSVAL_IS_NULL(argv[1]) || !JSVAL_IS_OBJECT(argv[1])) return JS_TRUE; mO = JSVAL_TO_OBJECT(argv[1]); - if (!JS_InstanceOf(c, mO, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, mO, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx = SMJS_GET_PRIVATE(c, mO); if (!mx) return JS_TRUE; @@ -1121,7 +1126,7 @@ JSBool SMJS_FUNCTION(svg_udom_set_rect_trait) if (JSVAL_IS_NULL(argv[1]) || !JSVAL_IS_OBJECT(argv[1])) return JS_TRUE; rO = JSVAL_TO_OBJECT(argv[1]); - if (!JS_InstanceOf(c, rO, &svg_rt->rectClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, rO, &svg_rt->rectClass, NULL) ) return JS_TRUE; rc = SMJS_GET_PRIVATE(c, rO); if (!rc) return JS_TRUE; @@ -1157,7 +1162,7 @@ JSBool SMJS_FUNCTION(svg_udom_set_path_trait) if (!JSVAL_IS_STRING(argv[0])) return JS_TRUE; if (JSVAL_IS_NULL(argv[1]) || !JSVAL_IS_OBJECT(argv[1])) return JS_TRUE; pO = JSVAL_TO_OBJECT(argv[1]); - if (!JS_InstanceOf(c, pO, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, pO, &svg_rt->pathClass, NULL) ) return JS_TRUE; path = SMJS_GET_PRIVATE(c, pO); if (!path) return JS_TRUE; @@ -1224,7 +1229,7 @@ JSBool SMJS_FUNCTION(svg_udom_set_rgb_color_trait) if (!JSVAL_IS_OBJECT(argv[1])) return JS_TRUE; colO = JSVAL_TO_OBJECT(argv[1]); if (!colO) return JS_TRUE; - if (!JS_InstanceOf(c, colO, &svg_rt->rgbClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, colO, &svg_rt->rgbClass, NULL) ) return JS_TRUE; rgb = SMJS_GET_PRIVATE(c, colO); if (!rgb) return JS_TRUE; @@ -1270,7 +1275,7 @@ static JSBool SMJS_FUNCTION_EXT(svg_get_bbox, Bool get_screen) par.bbox.is_set = 0; if (ScriptAction(n->sgprivate->scenegraph, get_screen ? GF_JSAPI_OP_GET_SCREEN_BBOX : GF_JSAPI_OP_GET_LOCAL_BBOX, (GF_Node *)n, &par) ) { if (par.bbox.is_set) { - JSObject *rO = JS_NewObject(c, &svg_rt->rectClass, 0, 0); + JSObject *rO = JS_NewObject(c, &svg_rt->rectClass._class, 0, 0); rectCI *rc = gf_malloc(sizeof(rectCI)); rc->sg = NULL; rc->x = FIX2FLT(par.bbox.min_edge.x); @@ -1304,7 +1309,7 @@ JSBool SMJS_FUNCTION(svg_udom_get_screen_ctm) if (!n || argc) return JS_TRUE; if (ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_GET_TRANSFORM, (GF_Node *)n, &par)) { - JSObject *mO = JS_NewObject(c, &svg_rt->matrixClass, 0, 0); + JSObject *mO = JS_NewObject(c, &svg_rt->matrixClass._class, 0, 0); GF_Matrix2D *mx = gf_malloc(sizeof(GF_Matrix2D)); gf_mx2d_from_mx(mx, &par.mx); SMJS_SET_PRIVATE(c, mO, mx); @@ -1338,7 +1343,7 @@ JSBool SMJS_FUNCTION(svg_udom_create_matrix_components) mx->m[2] = FLT2FIX(v); JS_ValueToNumber(c, argv[5], &v); mx->m[5] = FLT2FIX(v); - mat = JS_NewObject(c, &svg_rt->matrixClass, 0, 0); + mat = JS_NewObject(c, &svg_rt->matrixClass._class, 0, 0); SMJS_SET_PRIVATE(c, mat, mx); SMJS_SET_RVAL( OBJECT_TO_JSVAL(mat) ); return JS_TRUE; @@ -1352,7 +1357,7 @@ JSBool SMJS_FUNCTION(svg_udom_create_rect) if (!n || argc) return JS_TRUE; GF_SAFEALLOC(rc, rectCI); - r = JS_NewObject(c, &svg_rt->rectClass, 0, 0); + r = JS_NewObject(c, &svg_rt->rectClass._class, 0, 0); SMJS_SET_PRIVATE(c, r, rc); SMJS_SET_RVAL( OBJECT_TO_JSVAL(r) ); return JS_TRUE; @@ -1366,7 +1371,7 @@ JSBool SMJS_FUNCTION(svg_udom_create_point) if (!n || argc) return JS_TRUE; GF_SAFEALLOC(pt, pointCI); - r = JS_NewObject(c, &svg_rt->pointClass, 0, 0); + r = JS_NewObject(c, &svg_rt->pointClass._class, 0, 0); SMJS_SET_PRIVATE(c, r, pt); SMJS_SET_RVAL( OBJECT_TO_JSVAL(r) ); return JS_TRUE; @@ -1380,7 +1385,7 @@ JSBool SMJS_FUNCTION(svg_udom_create_path) if (!n || argc) return JS_TRUE; GF_SAFEALLOC(path, pathCI); - p = JS_NewObject(c, &svg_rt->pathClass, 0, 0); + p = JS_NewObject(c, &svg_rt->pathClass._class, 0, 0); SMJS_SET_PRIVATE(c, p, path); SMJS_SET_RVAL( OBJECT_TO_JSVAL(p) ); return JS_TRUE; @@ -1399,7 +1404,7 @@ JSBool SMJS_FUNCTION(svg_udom_create_color) col->r = JSVAL_TO_INT(argv[0]); col->g = JSVAL_TO_INT(argv[1]); col->b = JSVAL_TO_INT(argv[2]); - p = JS_NewObject(c, &svg_rt->rgbClass, 0, 0); + p = JS_NewObject(c, &svg_rt->rgbClass._class, 0, 0); SMJS_SET_PRIVATE(c, p, col); SMJS_SET_RVAL( OBJECT_TO_JSVAL(p) ); return JS_TRUE; @@ -1536,15 +1541,17 @@ static JSFunctionSpec connectionFuncs[] = { }; #endif /*GPAC_UNUSED_FUNC*/ -static void baseCI_finalize(JSContext *c, JSObject *obj) -{ +static DECL_FINALIZE( baseCI_finalize) + + /*avoids GCC warning*/ void *data = SMJS_GET_PRIVATE(c, obj); + if (!c) c=NULL; if (data) gf_free(data); } -static JSBool rgb_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->rgbClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_GET(rgb_getProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->rgbClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { rgbCI *col = SMJS_GET_PRIVATE(c, obj); if (!col) return JS_TRUE; @@ -1558,9 +1565,9 @@ static JSBool rgb_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsv } return JS_TRUE; } -static JSBool rgb_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->rgbClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_SET( rgb_setProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->rgbClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { rgbCI *col = SMJS_GET_PRIVATE(c, obj); if (!col) return JS_TRUE; @@ -1575,9 +1582,9 @@ static JSBool rgb_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsv } -static JSBool rect_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->rectClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_GET(rect_getProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->rectClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { rectCI *rc = SMJS_GET_PRIVATE(c, obj); if (!rc) return JS_TRUE; @@ -1599,9 +1606,9 @@ static JSBool rect_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js } return JS_TRUE; } -static JSBool rect_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->rectClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_SET( rect_setProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->rectClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { jsdouble d; rectCI *rc = SMJS_GET_PRIVATE(c, obj); @@ -1618,9 +1625,9 @@ static JSBool rect_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, js return JS_TRUE; } -static JSBool point_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->pointClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_GET( point_getProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pointClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { pointCI *pt = SMJS_GET_PRIVATE(c, obj); if (!pt) return JS_TRUE; @@ -1638,9 +1645,9 @@ static JSBool point_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, j } return JS_TRUE; } -static JSBool point_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->pointClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_SET( point_setProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pointClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { jsdouble d; pointCI *pt = SMJS_GET_PRIVATE(c, obj); @@ -1683,7 +1690,7 @@ static JSObject *svg_new_path_object(JSContext *c, SVG_PathData *d) p->pts[i].y = FIX2FLT(pt->y); } } - obj = JS_NewObject(c, &svg_rt->pathClass, 0, 0); + obj = JS_NewObject(c, &svg_rt->pathClass._class, 0, 0); SMJS_SET_PRIVATE(c, obj, p); return obj; #endif @@ -1710,9 +1717,9 @@ static void pathCI_finalize(JSContext *c, JSObject *obj) } } -static JSBool path_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; +static SMJS_FUNC_PROP_GET( path_getProperty) + + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; if (SMJS_ID_IS_INT(id)) { pathCI *p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; @@ -1729,7 +1736,7 @@ static JSBool SMJS_FUNCTION(svg_path_get_segment) u32 idx; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if ((argc!=1) || !JSVAL_IS_INT(argv[0])) return JS_TRUE; @@ -1756,7 +1763,7 @@ static JSBool SMJS_FUNCTION(svg_path_get_segment_param) SMJS_OBJ SMJS_ARGS u32 i, idx, param_idx, pt_idx; - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if ((argc!=2) || !JSVAL_IS_INT(argv[0]) || !JSVAL_IS_INT(argv[1])) return JS_TRUE; @@ -1845,7 +1852,7 @@ static JSBool SMJS_FUNCTION(svg_path_move_to) u32 nb_pts; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if ((argc!=2) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1])) return JS_TRUE; @@ -1866,7 +1873,7 @@ static JSBool SMJS_FUNCTION(svg_path_line_to) u32 nb_pts; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if ((argc!=2) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1])) return JS_TRUE; @@ -1888,7 +1895,7 @@ static JSBool SMJS_FUNCTION(svg_path_quad_to) u32 nb_pts; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if ((argc!=4) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1]) || !JSVAL_IS_NUMBER(argv[2]) || !JSVAL_IS_NUMBER(argv[3])) return JS_TRUE; @@ -1911,7 +1918,7 @@ static JSBool SMJS_FUNCTION(svg_path_curve_to) u32 nb_pts; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if ((argc!=6) || !JSVAL_IS_NUMBER(argv[0]) || !JSVAL_IS_NUMBER(argv[1]) || !JSVAL_IS_NUMBER(argv[2]) || !JSVAL_IS_NUMBER(argv[3]) || !JSVAL_IS_NUMBER(argv[4]) || !JSVAL_IS_NUMBER(argv[5])) return JS_TRUE; @@ -1934,7 +1941,7 @@ static JSBool SMJS_FUNCTION(svg_path_close) { pathCI *p; SMJS_OBJ - if (!JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->pathClass, NULL) ) return JS_TRUE; p = SMJS_GET_PRIVATE(c, obj); if (!p) return JS_TRUE; if (argc) return JS_TRUE; @@ -1944,10 +1951,10 @@ static JSBool SMJS_FUNCTION(svg_path_close) return JS_TRUE; } -static JSBool matrix_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( matrix_getProperty) + GF_Matrix2D *mx; - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx = SMJS_GET_PRIVATE(c, obj); if (!SMJS_ID_IS_INT(id)) return JS_TRUE; @@ -1963,11 +1970,11 @@ static JSBool matrix_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, } return JS_TRUE; } -static JSBool matrix_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( matrix_setProperty) + jsdouble d; GF_Matrix2D *mx; - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx = SMJS_GET_PRIVATE(c, obj); if (!SMJS_ID_IS_INT(id)) return JS_TRUE; @@ -1988,7 +1995,7 @@ static JSBool SMJS_FUNCTION(svg_mx2d_get_component) GF_Matrix2D *mx; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx = SMJS_GET_PRIVATE(c, obj); if (!mx || (argc!=1)) return JS_TRUE; if (!JSVAL_IS_INT(argv[0])) return JS_TRUE; @@ -2009,12 +2016,12 @@ static JSBool SMJS_FUNCTION(svg_mx2d_multiply) GF_Matrix2D *mx1, *mx2; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx1 = SMJS_GET_PRIVATE(c, obj); if (!mx1 || (argc!=1)) return JS_TRUE; if (!JSVAL_IS_OBJECT(argv[0])) return JS_TRUE; mat = JSVAL_TO_OBJECT(argv[0]); - if (!JS_InstanceOf(c, mat, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, mat, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx2 = SMJS_GET_PRIVATE(c, mat); if (!mx2) return JS_TRUE; gf_mx2d_add_matrix(mx1, mx2); @@ -2026,7 +2033,7 @@ static JSBool SMJS_FUNCTION(svg_mx2d_inverse) { GF_Matrix2D *mx1; SMJS_OBJ - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx1 = SMJS_GET_PRIVATE(c, obj); if (!mx1) return JS_TRUE; gf_mx2d_inverse(mx1); @@ -2040,7 +2047,7 @@ static JSBool SMJS_FUNCTION(svg_mx2d_translate) GF_Matrix2D *mx1, mx2; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx1 = SMJS_GET_PRIVATE(c, obj); if (!mx1 || (argc!=2)) return JS_TRUE; JS_ValueToNumber(c, argv[0], &x); @@ -2060,7 +2067,7 @@ static JSBool SMJS_FUNCTION(svg_mx2d_scale) GF_Matrix2D *mx1, mx2; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx1 = SMJS_GET_PRIVATE(c, obj); if (!mx1 || (argc!=1)) return JS_TRUE; JS_ValueToNumber(c, argv[0], &scale); @@ -2077,7 +2084,7 @@ static JSBool SMJS_FUNCTION(svg_mx2d_rotate) GF_Matrix2D *mx1, mx2; SMJS_OBJ SMJS_ARGS - if (!JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; + if (!GF_JS_InstanceOf(c, obj, &svg_rt->matrixClass, NULL) ) return JS_TRUE; mx1 = SMJS_GET_PRIVATE(c, obj); if (!mx1 || (argc!=1)) return JS_TRUE; JS_ValueToNumber(c, argv[0], &angle); @@ -2090,7 +2097,7 @@ static JSBool SMJS_FUNCTION(svg_mx2d_rotate) jsval svg_udom_new_rect(JSContext *c, Fixed x, Fixed y, Fixed width, Fixed height) { - JSObject *r = JS_NewObject(c, &svg_rt->rectClass, 0, 0); + JSObject *r = JS_NewObject(c, &svg_rt->rectClass._class, 0, 0); rectCI *rc = gf_malloc(sizeof(rectCI)); rc->x = FIX2FLT(x); rc->y = FIX2FLT(y); @@ -2103,7 +2110,7 @@ jsval svg_udom_new_rect(JSContext *c, Fixed x, Fixed y, Fixed width, Fixed heigh jsval svg_udom_new_point(JSContext *c, Fixed x, Fixed y) { - JSObject *p = JS_NewObject(c, &svg_rt->pointClass, 0, 0); + JSObject *p = JS_NewObject(c, &svg_rt->pointClass._class, 0, 0); pointCI *pt = gf_malloc(sizeof(pointCI)); pt->x = FIX2FLT(x); pt->y = FIX2FLT(y); @@ -2131,7 +2138,6 @@ void *svg_get_document_class(GF_SceneGraph *sg) static void svg_init_js_api(GF_SceneGraph *scene) { - JSObject *proto; JS_SetContextPrivate(scene->svg_js->js_ctx, scene); JS_SetErrorReporter(scene->svg_js->js_ctx, svg_script_error); @@ -2179,7 +2185,7 @@ static void svg_init_js_api(GF_SceneGraph *scene) {0, 0, 0, 0, 0} }; JSObject *doc_proto = dom_js_get_document_proto(scene->svg_js->js_ctx); - JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, doc_proto, &svg_rt->svgDocument, 0, 0, svgDocumentProps, 0, 0, 0); + GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, doc_proto, &svg_rt->svgDocument, 0, 0, svgDocumentProps, 0, 0, 0); } /*SVGElement class*/ @@ -2259,7 +2265,7 @@ static void svg_init_js_api(GF_SceneGraph *scene) {0, 0, 0, 0, 0} }; JSObject *elt_proto = dom_js_get_element_proto(scene->svg_js->js_ctx); - JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, elt_proto, &svg_rt->svgElement, 0, 0, svgElementProps, svgElementFuncs, 0, 0); + GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, elt_proto, &svg_rt->svgElement, 0, 0, svgElementProps, svgElementFuncs, 0, 0); } @@ -2271,7 +2277,7 @@ static void svg_init_js_api(GF_SceneGraph *scene) {"blue", 2, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->rgbClass, 0, 0, rgbClassProps, 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*/ { @@ -2282,7 +2288,7 @@ static void svg_init_js_api(GF_SceneGraph *scene) {"height", 3, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->rectClass, 0, 0, rectClassProps, 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*/ { @@ -2291,7 +2297,7 @@ static void svg_init_js_api(GF_SceneGraph *scene) {"y", 1, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->pointClass, 0, 0, pointClassProps, 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); } /*SVGMatrix class*/ { @@ -2313,7 +2319,7 @@ static void svg_init_js_api(GF_SceneGraph *scene) {"f", 5, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->matrixClass, 0, 0, matrixClassProps, matrixClassFuncs, 0, 0); + GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &svg_rt->matrixClass, 0, 0, matrixClassProps, matrixClassFuncs, 0, 0); } /*SVGPath class*/ { @@ -2331,12 +2337,12 @@ static void svg_init_js_api(GF_SceneGraph *scene) {"numberOfSegments", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0}, {0, 0, 0, 0, 0} }; - proto = 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, proto, "MOVE_TO", INT_TO_JSVAL(77), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(scene->svg_js->js_ctx, proto, "LINE_TO", INT_TO_JSVAL(76), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(scene->svg_js->js_ctx, proto, "CURVE_TO", INT_TO_JSVAL(67), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(scene->svg_js->js_ctx, proto, "QUAD_TO", INT_TO_JSVAL(81), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); - JS_DefineProperty(scene->svg_js->js_ctx, proto, "CLOSE", INT_TO_JSVAL(90), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + 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); + JS_DefineProperty(scene->svg_js->js_ctx, svg_rt->pathClass._proto, "LINE_TO", INT_TO_JSVAL(76), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(scene->svg_js->js_ctx, svg_rt->pathClass._proto, "CURVE_TO", INT_TO_JSVAL(67), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(scene->svg_js->js_ctx, svg_rt->pathClass._proto, "QUAD_TO", INT_TO_JSVAL(81), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); + JS_DefineProperty(scene->svg_js->js_ctx, svg_rt->pathClass._proto, "CLOSE", INT_TO_JSVAL(90), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT); } /*we have our own constructors*/ @@ -2620,7 +2626,7 @@ void JSScript_LoadSVG(GF_Node *node) #ifdef DUMP_DEF_AND_ROOT void dump_root(const char *name, void *rp, void *data) { - if (name[0]=='_') fprintf(stdout, "\t%s\n", name); + if (name[0]=='_') fprintf(stderr, "\t%s\n", name); } #endif @@ -2739,14 +2745,14 @@ static Bool svg_script_execute_handler(GF_Node *node, GF_DOM_Event *event, GF_No #ifdef DUMP_DEF_AND_ROOT if ((event->type==GF_EVENT_CLICK) || (event->type==GF_EVENT_MOUSEOVER)) { NodeIDedItem *reg_node; - fprintf(stdout, "Node registry\n"); + fprintf(stderr, "Node registry\n"); reg_node = node->sgprivate->scenegraph->id_node; while (reg_node) { - fprintf(stdout, "\t%s\n", reg_node->NodeName); + fprintf(stderr, "\t%s\n", reg_node->NodeName); reg_node = reg_node->next; } - fprintf(stdout, "\n\nNamed roots:\n"); + fprintf(stderr, "\n\nNamed roots:\n"); JS_DumpNamedRoots(JS_GetRuntime(svg_js->js_ctx), dump_root, NULL); } #endif diff --git a/src/scenegraph/svg_types.c b/src/scenegraph/svg_types.c index 556a268..bfdcbdf 100644 --- a/src/scenegraph/svg_types.c +++ b/src/scenegraph/svg_types.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2004 + * Authors: Cyril Concolato, Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2004-2012 * All rights reserved * * This file is part of GPAC / SVG Scene Graph sub-project diff --git a/src/scenegraph/vrml_interpolators.c b/src/scenegraph/vrml_interpolators.c index 6bea733..e39ad3f 100644 --- a/src/scenegraph/vrml_interpolators.c +++ b/src/scenegraph/vrml_interpolators.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/vrml_proto.c b/src/scenegraph/vrml_proto.c index c8eabaf..355c842 100644 --- a/src/scenegraph/vrml_proto.c +++ b/src/scenegraph/vrml_proto.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -352,7 +353,9 @@ GF_Node *gf_vrml_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *clon GF_Node *node, *child; GF_ChildNodeItem *list, *last; GF_Route *r1, *r2; +#ifndef GPAC_DISABLE_BIFS void BIFS_SetupConditionalClone(GF_Node *node, GF_Node *orig); +#endif GF_ProtoInstance *proto; GF_Proto *proto_node; GF_FieldInfo field_orig, field; @@ -457,9 +460,13 @@ GF_Node *gf_vrml_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *clon } } +#ifndef GPAC_DISABLE_BIFS /*init node before creating ISed routes so the eventIn handler are in place*/ - if (node->sgprivate->tag == TAG_MPEG4_Conditional) BIFS_SetupConditionalClone(node, orig); - else if (node->sgprivate->tag != TAG_ProtoNode) gf_node_init(node); + if (node->sgprivate->tag == TAG_MPEG4_Conditional) + BIFS_SetupConditionalClone(node, orig); + else +#endif + if (node->sgprivate->tag != TAG_ProtoNode) gf_node_init(node); if (!inScene->pOwningProto) return node; proto = inScene->pOwningProto; @@ -876,7 +883,7 @@ GF_Err gf_sg_proto_field_set_ised(GF_Proto *proto, u32 protoFieldIndex, GF_Node } else if ((gf_sg_vrml_get_sf_type(field.fieldType)==GF_SG_VRML_SFURL) && (gf_sg_vrml_get_sf_type(nodeField.fieldType) == GF_SG_VRML_SFSTRING)) { e = GF_OK; } else { -// printf("error in IS - node field %s.%s - inType %s - outType %s\n", gf_node_get_class_name(node) , nodeField.name, gf_sg_vrml_get_field_type_by_name(field.fieldType), gf_sg_vrml_get_field_type_by_name(nodeField.fieldType)); + GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[VRML] error in IS - node field %s.%s - inType %s - outType %s\n", gf_node_get_class_name(node) , nodeField.name, gf_sg_vrml_get_field_type_by_name(field.fieldType), gf_sg_vrml_get_field_type_by_name(nodeField.fieldType))); return GF_SG_INVALID_PROTO; } } @@ -956,7 +963,7 @@ GF_Err gf_sg_proto_instance_set_ised(GF_Node *protoinst, u32 protoFieldIndex, GF } else if ((gf_sg_vrml_get_sf_type(field.fieldType)==GF_SG_VRML_SFURL) && (gf_sg_vrml_get_sf_type(nodeField.fieldType) == GF_SG_VRML_SFSTRING)) { e = GF_OK; } else { -// printf("error in IS - node field %s.%s - inType %s - outType %s\n", gf_node_get_class_name(node) , nodeField.name, gf_sg_vrml_get_field_type_by_name(field.fieldType), gf_sg_vrml_get_field_type_by_name(nodeField.fieldType)); + GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[VRML] error in IS - node field %s.%s - inType %s - outType %s\n", gf_node_get_class_name(node) , nodeField.name, gf_sg_vrml_get_field_type_by_name(field.fieldType), gf_sg_vrml_get_field_type_by_name(nodeField.fieldType))); return GF_SG_INVALID_PROTO; } } diff --git a/src/scenegraph/vrml_route.c b/src/scenegraph/vrml_route.c index 17b4a5f..5ad5502 100644 --- a/src/scenegraph/vrml_route.c +++ b/src/scenegraph/vrml_route.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/vrml_script.c b/src/scenegraph/vrml_script.c index d51f74f..2fdc4e7 100644 --- a/src/scenegraph/vrml_script.c +++ b/src/scenegraph/vrml_script.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/vrml_smjs.c b/src/scenegraph/vrml_smjs.c index 0ec8310..45a6262 100644 --- a/src/scenegraph/vrml_smjs.c +++ b/src/scenegraph/vrml_smjs.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project @@ -34,8 +35,6 @@ #include - - /*fixes for JS > 1.8.0rc1 where GC routines have changed*/ GF_EXPORT Bool gf_js_add_root(JSContext *cx, void *rp, u32 type) @@ -85,38 +84,19 @@ Bool gf_js_add_named_root(JSContext *cx, void *rp, u32 type, const char *name) #endif } -GF_EXPORT -Bool gf_js_remove_root(JSContext *cx, void *rp, u32 type) + +JSObject *gf_sg_js_global_object(JSContext *cx, GF_JSClass *__class) { #if (JS_VERSION>=185) - JSBool ret; - switch (type) { - case GF_JSGC_STRING: - ret = JS_RemoveStringRoot(cx, rp); - break; - case GF_JSGC_OBJECT: - ret = JS_RemoveObjectRoot(cx, rp); - break; - case GF_JSGC_VAL: - ret = JS_RemoveValueRoot(cx, rp); - break; - default: - ret = JS_RemoveGCThingRoot(cx, rp); - break; - } - return (ret == JS_TRUE) ? 1 : 0; + __class->_class.flags |= JSCLASS_GLOBAL_FLAGS; +#ifdef USE_FFDEV_16 + return JS_NewGlobalObject(cx, &__class->_class, NULL); #else - return (JS_RemoveRoot(cx, rp)==JS_TRUE) ? 1 : 0; + return JS_NewCompartmentAndGlobalObject(cx, &__class->_class, NULL); #endif -} -JSObject *gf_sg_js_global_object(JSContext *cx, JSClass *__class) -{ -#if (JS_VERSION>=185) - __class->flags |= JSCLASS_GLOBAL_FLAGS; - return JS_NewCompartmentAndGlobalObject(cx, __class, NULL); #else - return JS_NewObject(cx, __class, 0, 0 ); + return JS_NewObject(cx, &__class->_class, 0, 0 ); #endif } @@ -188,28 +168,28 @@ typedef struct JSContext *ctx; GF_Mutex *mx; - JSClass SFNodeClass; + GF_JSClass SFNodeClass; #ifndef GPAC_DISABLE_VRML - JSClass globalClass; - JSClass browserClass; - JSClass SFVec2fClass; - JSClass SFVec3fClass; - JSClass SFRotationClass; - JSClass SFColorClass; - JSClass SFImageClass; - JSClass MFInt32Class; - JSClass MFBoolClass; - JSClass MFFloatClass; - JSClass MFTimeClass; - JSClass MFVec2fClass; - JSClass MFVec3fClass; - JSClass MFRotationClass; - JSClass MFColorClass; - JSClass MFStringClass; - JSClass MFUrlClass; - JSClass MFNodeClass; - JSClass AnyClass; + GF_JSClass globalClass; + GF_JSClass browserClass; + GF_JSClass SFVec2fClass; + GF_JSClass SFVec3fClass; + GF_JSClass SFRotationClass; + GF_JSClass SFColorClass; + GF_JSClass SFImageClass; + GF_JSClass MFInt32Class; + GF_JSClass MFBoolClass; + GF_JSClass MFFloatClass; + GF_JSClass MFTimeClass; + GF_JSClass MFVec2fClass; + GF_JSClass MFVec3fClass; + GF_JSClass MFRotationClass; + GF_JSClass MFColorClass; + GF_JSClass MFStringClass; + GF_JSClass MFUrlClass; + GF_JSClass MFNodeClass; + GF_JSClass AnyClass; #endif /*extensions are loaded for the lifetime of the runtime NOT of the context - this avoids nasty @@ -219,6 +199,41 @@ typedef struct static GF_JSRuntime *js_rt = NULL; +GF_EXPORT +Bool gf_js_remove_root(JSContext *cx, void *rp, u32 type) +{ +#if (JS_VERSION>=185) + switch (type) { + case GF_JSGC_STRING: +#ifdef USE_FFDEV_15 + if (!cx) JS_RemoveStringRootRT(js_rt->js_runtime, rp); + else +#endif + JS_RemoveStringRoot(cx, rp); + break; + case GF_JSGC_OBJECT: +#ifdef USE_FFDEV_15 + if (!cx) JS_RemoveObjectRootRT(js_rt->js_runtime, rp); + else +#endif + JS_RemoveObjectRoot(cx, rp); + break; + case GF_JSGC_VAL: +#ifdef USE_FFDEV_15 + if (!cx) JS_RemoveValueRootRT(js_rt->js_runtime, rp); + else +#endif + JS_RemoveValueRoot(cx, rp); + break; + default: + if (cx) JS_RemoveGCThingRoot(cx, rp); + break; + } + return 1; +#else + return (JS_RemoveRoot(cx, rp)==JS_TRUE) ? 1 : 0; +#endif +} void gf_sg_load_script_extensions(GF_SceneGraph *sg, JSContext *c, JSObject *obj, Bool unload) { @@ -371,7 +386,11 @@ void gf_sg_ecmascript_del(JSContext *ctx) GF_EXPORT #if (JS_VERSION>=185) +#ifdef USE_FFDEV_15 +JSBool gf_sg_js_has_instance(JSContext *c, JSHandleObject obj,const jsval *val, JSBool *vp) +#else JSBool gf_sg_js_has_instance(JSContext *c, JSObject *obj,const jsval *val, JSBool *vp) +#endif #else JSBool gf_sg_js_has_instance(JSContext *c, JSObject *obj, jsval val, JSBool *vp) #endif @@ -414,7 +433,11 @@ Bool JSScriptFromFile(GF_Node *node, const char *opt_file, Bool no_complain); void gf_sg_js_call_gc(JSContext *c) { gf_sg_lock_javascript(c, 1); +#ifdef USE_FFDEV_14 + JS_GC(js_rt->js_runtime); +#else JS_GC(c); +#endif gf_sg_lock_javascript(c, 0); } @@ -590,7 +613,7 @@ static JSObject *node_get_binding(GF_ScriptPriv *priv, GF_Node *node, Bool is_co node->sgprivate->flags |= GF_NODE_HAS_BINDING; gf_node_register(node, NULL); - obj = JS_NewObject(priv->js_ctx, &js_rt->SFNodeClass, 0, 0); + obj = JS_NewObject(priv->js_ctx, &js_rt->SFNodeClass._class, 0, 0); SMJS_SET_PRIVATE(priv->js_ctx, obj, field); field->obj = obj; @@ -791,7 +814,7 @@ static JSBool SMJS_FUNCTION(addRoute) SMJS_ARGS if (argc!=4) return JS_FALSE; - if (!JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (!JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); @@ -816,7 +839,7 @@ static JSBool SMJS_FUNCTION(addRoute) if (!JSVAL_IS_OBJECT(argv[2])) return JS_FALSE; /*regular route*/ - if (JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[2]), &js_rt->SFNodeClass, NULL) && JSVAL_IS_STRING(argv[3]) ) { + if (GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[2]), &js_rt->SFNodeClass, NULL) && JSVAL_IS_STRING(argv[3]) ) { GF_Route *r; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[2])); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); @@ -898,7 +921,7 @@ static JSBool SMJS_FUNCTION(deleteRoute) SMJS_ARGS if (argc!=4) return JS_FALSE; - if (!JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (!JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; if (JSVAL_IS_STRING(argv[1]) && JSVAL_IS_NULL(argv[2]) && JSVAL_IS_NULL(argv[3])) { ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])); @@ -915,7 +938,7 @@ static JSBool SMJS_FUNCTION(deleteRoute) return JS_TRUE; } - if (!JSVAL_IS_OBJECT(argv[2]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[2]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (!JSVAL_IS_OBJECT(argv[2]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[2]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; if (!JSVAL_IS_STRING(argv[1]) || !JSVAL_IS_STRING(argv[3])) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])); @@ -1170,8 +1193,8 @@ void Script_FieldChanged(JSContext *c, GF_Node *parent, GF_JSField *parent_owner } } -JSBool gf_sg_script_eventout_set_prop(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *val) -{ +SMJS_FUNC_PROP_SET( gf_sg_script_eventout_set_prop) + u32 i; char *eventName; GF_ScriptPriv *script; @@ -1184,6 +1207,8 @@ JSBool gf_sg_script_eventout_set_prop(JSContext *c, JSObject *obj, SMJS_PROP_SET if (! SMJS_ID_IS_STRING(id)) return JS_FALSE; str = SMJS_ID_TO_STRING(id); if (!str) return JS_FALSE; + /*avoids gcc warning*/ + if (!obj) obj=NULL; script = JS_GetScriptStack(c); if (!script) return JS_FALSE; @@ -1194,7 +1219,7 @@ JSBool gf_sg_script_eventout_set_prop(JSContext *c, JSObject *obj, SMJS_PROP_SET while ((sf = gf_list_enum(script->fields, &i))) { if (!stricmp(sf->name, eventName)) { gf_node_get_field(n, sf->ALL_index, &info); - gf_sg_script_to_node_field(c, *val, &info, n, NULL); + gf_sg_script_to_node_field(c, *vp, &info, n, NULL); sf->activate_event_out = 1; SMJS_FREE(c, eventName); return JS_TRUE; @@ -1370,7 +1395,7 @@ static JSBool SMJS_FUNCTION(SFNodeConstructor) GF_ScriptPriv *priv = JS_GetScriptStack(c); M_Script *sc = JS_GetScript(c); SMJS_ARGS - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->SFNodeClass) tag = 0; if (!argc) { field = NewJSField(c); @@ -1381,7 +1406,7 @@ static JSBool SMJS_FUNCTION(SFNodeConstructor) SMJS_SET_RVAL( OBJECT_TO_JSVAL(obj) ); return JS_TRUE; } - if (!JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (!GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; ID = 0; node_name = SMJS_CHARS(c, argv[0]); @@ -1443,11 +1468,13 @@ locate_proto: return JS_TRUE; } -static void node_finalize_ex(JSContext *c, JSObject *obj, Bool is_js_call) +static void node_finalize_ex(JSContext *c, JSObject * obj, Bool is_js_call) { GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); +#ifndef USE_FFDEV_15 JS_ObjectDestroyed(c, obj, ptr, is_js_call); +#endif if (ptr) { JS_GetScript(ptr->js_ctx ? ptr->js_ctx : c); @@ -1463,13 +1490,14 @@ static void node_finalize_ex(JSContext *c, JSObject *obj, Bool is_js_call) gf_free(ptr); } } -static void node_finalize(JSContext *c, JSObject *obj) -{ + +static DECL_FINALIZE(node_finalize) + node_finalize_ex(c, obj, 1); } -static JSBool node_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(node_getProperty) + GF_Node *n; u32 index; JSString *str; @@ -1477,7 +1505,7 @@ static JSBool node_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js GF_JSField *ptr; GF_ScriptPriv *priv; - if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (! GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); n = * ((GF_Node **)ptr->field.far_ptr); @@ -1507,7 +1535,7 @@ static JSBool node_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js GF_JSAPIParam par; par.bbox.is_set = 0; if (ScriptAction(c, n->sgprivate->scenegraph, GF_JSAPI_OP_GET_LOCAL_BBOX, (GF_Node *)n, &par) ) { - JSObject *_obj = JS_NewObject(priv->js_ctx, &js_rt->AnyClass, 0, 0); + JSObject *_obj = JS_NewObject(priv->js_ctx, &js_rt->AnyClass._class, 0, 0); Float x, y, w, h; x = y = w = h = 0; if (par.bbox.is_set) { @@ -1532,14 +1560,15 @@ static JSBool node_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, js return JS_FALSE; } -static JSBool node_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( node_setProperty) + GF_Node *n; GF_FieldInfo info; u32 index; char *fieldname; GF_JSField *ptr; - if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + + if (! GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); /*this is the prototype*/ @@ -1595,7 +1624,7 @@ static JSBool SMJS_FUNCTION(node_toString) GF_JSField *f; const char *name; SMJS_OBJ - if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (! GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; f = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (!f) return JS_FALSE; @@ -1623,7 +1652,7 @@ static JSBool SMJS_FUNCTION(node_getTime) GF_Node *n; GF_JSField *f; SMJS_OBJ - if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (! GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; f = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (!f) return JS_FALSE; @@ -1634,8 +1663,8 @@ static JSBool SMJS_FUNCTION(node_getTime) } /* Generic field destructor */ -static void field_finalize(JSContext *c, JSObject *obj) -{ +static DECL_FINALIZE(field_finalize) + GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); JS_ObjectDestroyed(c, obj, ptr, 1); if (!ptr) return; @@ -1672,10 +1701,10 @@ static JSBool SMJS_FUNCTION(SFImageConstructor) u32 w, h, nbComp; MFInt32 *pixels; SMJS_ARGS - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->SFImageClass) if (argc<4) return 0; if (!JSVAL_IS_INT(argv[0]) || !JSVAL_IS_INT(argv[1]) || !JSVAL_IS_INT(argv[2])) return JS_FALSE; - if (!JSVAL_IS_OBJECT(argv[3]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[3]), &js_rt->MFInt32Class, NULL)) return JS_FALSE; + if (!JSVAL_IS_OBJECT(argv[3]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[3]), &js_rt->MFInt32Class, NULL)) return JS_FALSE; w = JSVAL_TO_INT(argv[0]); h = JSVAL_TO_INT(argv[1]); nbComp = JSVAL_TO_INT(argv[2]); @@ -1684,8 +1713,8 @@ static JSBool SMJS_FUNCTION(SFImageConstructor) return JS_TRUE; } -static JSBool image_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(image_getProperty) + GF_ScriptPriv *priv = JS_GetScriptStack(c); GF_JSField *val = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); SFImage *sfi; @@ -1714,8 +1743,8 @@ static JSBool image_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, j return JS_TRUE; } -static JSBool image_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( image_setProperty) + u32 ival; Bool changed = 0; GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); @@ -1752,7 +1781,7 @@ static JSBool image_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, j { MFInt32 *pixels; u32 len, i; - if (!JSVAL_IS_OBJECT(*vp) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(*vp), &js_rt->MFInt32Class, NULL)) return JS_FALSE; + if (!JSVAL_IS_OBJECT(*vp) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(*vp), &js_rt->MFInt32Class, NULL)) return JS_FALSE; pixels = (MFInt32 *) ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp)))->field.far_ptr; if (sfi->pixels) gf_free(sfi->pixels); len = sfi->width*sfi->height*sfi->numComponents; @@ -1788,14 +1817,14 @@ static JSBool SMJS_FUNCTION(SFVec2fConstructor) { jsdouble x = 0.0, y = 0.0; SMJS_ARGS - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->SFVec2fClass) if (argc > 0) JS_ValueToNumber(c, argv[0], &x); if (argc > 1) JS_ValueToNumber(c, argv[1], &y); SFVec2f_Create(c, obj, FLT2FIX( x), FLT2FIX( y)); return JS_TRUE; } -static JSBool vec2f_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(vec2f_getProperty) + GF_JSField *val = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (SMJS_ID_IS_INT(id)) { @@ -1808,8 +1837,8 @@ static JSBool vec2f_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, j return JS_TRUE; } -static JSBool vec2f_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET(vec2f_setProperty) + jsdouble d; Fixed v; Bool changed = 0; @@ -1849,12 +1878,12 @@ static JSBool SMJS_FUNCTION(vec2f_add) JSObject *pNew; SMJS_ARGS SMJS_OBJ - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec2fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec2fClass, NULL)) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; v2 = ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec2fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec2fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec2f_Create(c, pNew, v1->x + v2->x, v1->y + v2->y); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -1865,12 +1894,12 @@ static JSBool SMJS_FUNCTION(vec2f_subtract) JSObject *pNew; SMJS_ARGS SMJS_OBJ - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec2fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec2fClass, NULL)) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; v2 = ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec2fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec2fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec2f_Create(c, pNew, v1->x - v2->x, v1->y - v2->y); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -1881,7 +1910,7 @@ static JSBool SMJS_FUNCTION(vec2f_negate) JSObject *pNew; SMJS_OBJ v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec2fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec2fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec2f_Create(c, pNew, -v1->x , -v1->y ); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -1896,7 +1925,7 @@ static JSBool SMJS_FUNCTION(vec2f_multiply) SMJS_OBJ if (argc<=0) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec2fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec2fClass._class, 0, SMJS_GET_PARENT(c, obj)); JS_ValueToNumber(c, argv[0], &d ); v = FLT2FIX( d); SFVec2f_Create(c, pNew, gf_mulfix(v1->x , v), gf_mulfix(v1->y, v) ); @@ -1913,7 +1942,7 @@ static JSBool SMJS_FUNCTION(vec2f_divide) SMJS_OBJ if (argc<=0) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec2fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec2fClass._class, 0, SMJS_GET_PARENT(c, obj)); JS_ValueToNumber(c, argv[0], &d ); v = FLT2FIX(d); SFVec2f_Create(c, pNew, gf_divfix(v1->x, v), gf_divfix(v1->y, v)); @@ -1938,7 +1967,7 @@ static JSBool SMJS_FUNCTION(vec2f_normalize) SMJS_OBJ v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; res = gf_v2d_len(v1); - pNew = JS_NewObject(c, &js_rt->SFVec2fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec2fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec2f_Create(c, pNew, gf_divfix(v1->x, res), gf_divfix(v1->y, res) ); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -1948,7 +1977,7 @@ static JSBool SMJS_FUNCTION(vec2f_dot) SFVec2f *v1, *v2; SMJS_OBJ SMJS_ARGS - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec2fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec2fClass, NULL)) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; @@ -1977,15 +2006,15 @@ static JSBool SMJS_FUNCTION(SFVec3fConstructor) { SMJS_ARGS jsdouble x = 0.0, y = 0.0, z = 0.0; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->SFVec3fClass) if (argc > 0) JS_ValueToNumber(c, argv[0], &x); if (argc > 1) JS_ValueToNumber(c, argv[1], &y); if (argc > 2) JS_ValueToNumber(c, argv[2], &z); SFVec3f_Create(c, obj, FLT2FIX( x), FLT2FIX( y), FLT2FIX( z)); return JS_TRUE; } -static JSBool vec3f_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(vec3f_getProperty) + GF_JSField *val = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (SMJS_ID_IS_INT(id)) { switch (SMJS_ID_TO_INT(id)) { @@ -1997,8 +2026,8 @@ static JSBool vec3f_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, j } return JS_TRUE; } -static JSBool vec3f_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( vec3f_setProperty ) + jsdouble d; Fixed v; Bool changed = 0; @@ -2040,12 +2069,12 @@ static JSBool SMJS_FUNCTION(vec3f_add) JSObject *pNew; SMJS_ARGS SMJS_OBJ - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; v2 = ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec3f_Create(c, pNew, v1->x + v2->x, v1->y + v2->y, v1->z + v2->z); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2056,12 +2085,12 @@ static JSBool SMJS_FUNCTION(vec3f_subtract) JSObject *pNew; SMJS_ARGS SMJS_OBJ - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; v2 = ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec3f_Create(c, pNew, v1->x - v2->x, v1->y - v2->y, v1->z - v2->z); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2072,7 +2101,7 @@ static JSBool SMJS_FUNCTION(vec3f_negate) JSObject *pNew; SMJS_OBJ v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec3f_Create(c, pNew, -v1->x , -v1->y , -v1->z ); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2088,7 +2117,7 @@ static JSBool SMJS_FUNCTION(vec3f_multiply) if (argc<=0) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); JS_ValueToNumber(c, argv[0], &d ); v = FLT2FIX(d); SFVec3f_Create(c, pNew, gf_mulfix(v1->x, v), gf_mulfix(v1->y, v), gf_mulfix(v1->z, v) ); @@ -2105,7 +2134,7 @@ static JSBool SMJS_FUNCTION(vec3f_divide) SMJS_ARGS if (argc<=0) return JS_FALSE; v1 = ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); JS_ValueToNumber(c, argv[0], &d ); v = FLT2FIX(d); SFVec3f_Create(c, pNew, gf_divfix(v1->x, v), gf_divfix(v1->y, v), gf_divfix(v1->z, v)); @@ -2129,7 +2158,7 @@ static JSBool SMJS_FUNCTION(vec3f_normalize) SMJS_OBJ v1 = * (SFVec3f *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; gf_vec_norm(&v1); - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec3f_Create(c, pNew, v1.x, v1.y, v1.z); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2139,7 +2168,7 @@ static JSBool SMJS_FUNCTION(vec3f_dot) SFVec3f v1, v2; SMJS_OBJ SMJS_ARGS - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) return JS_FALSE; v1 = *(SFVec3f *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; @@ -2153,12 +2182,12 @@ static JSBool SMJS_FUNCTION(vec3f_cross) JSObject *pNew; SMJS_ARGS SMJS_OBJ - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) return JS_FALSE; v1 = * (SFVec3f *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; v2 = * (SFVec3f *) ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); v3 = gf_vec_cross(v1, v2); SFVec3f_Create(c, pNew, v3.x, v3.y, v3.z); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); @@ -2190,7 +2219,7 @@ static JSBool SMJS_FUNCTION(SFRotationConstructor) Fixed l1, l2, dot; SMJS_ARGS jsdouble x = 0.0, y = 0.0, z = 0.0, a = 0.0; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->SFRotationClass) if (argc == 0) { SFRotation_Create(c, obj, FLT2FIX(x), FLT2FIX(y), FIX_ONE, FLT2FIX(a) ); @@ -2207,7 +2236,7 @@ static JSBool SMJS_FUNCTION(SFRotationConstructor) if (argc!=2) return JS_FALSE; if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE; an_obj = JSVAL_TO_OBJECT(argv[0]); - if (! JS_InstanceOf(c, an_obj, &js_rt->SFVec3fClass, NULL)) return JS_FALSE; + if (! GF_JS_InstanceOf(c, an_obj, &js_rt->SFVec3fClass, NULL)) return JS_FALSE; v1 = * (SFVec3f *) ((GF_JSField *) SMJS_GET_PRIVATE(c, an_obj))->field.far_ptr; if (JSVAL_IS_DOUBLE(argv[1])) { JS_ValueToNumber(c, argv[1], &a); @@ -2217,7 +2246,7 @@ static JSBool SMJS_FUNCTION(SFRotationConstructor) if (!JSVAL_IS_OBJECT(argv[1])) return JS_FALSE; an_obj = JSVAL_TO_OBJECT(argv[1]); - if (!JS_InstanceOf(c, an_obj, &js_rt->SFVec3fClass, NULL)) return JS_FALSE; + if (!GF_JS_InstanceOf(c, an_obj, &js_rt->SFVec3fClass, NULL)) return JS_FALSE; v2 = * (SFVec3f *) ((GF_JSField *) SMJS_GET_PRIVATE(c, an_obj))->field.far_ptr; l1 = gf_vec_len(v1); l2 = gf_vec_len(v2); @@ -2230,8 +2259,8 @@ static JSBool SMJS_FUNCTION(SFRotationConstructor) return JS_TRUE; } -static JSBool rot_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET(rot_getProperty) + GF_JSField *val = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (SMJS_ID_IS_INT(id)) { switch (SMJS_ID_TO_INT(id)) { @@ -2244,8 +2273,8 @@ static JSBool rot_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsv } return JS_TRUE; } -static JSBool rot_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET( rot_setProperty ) + jsdouble d; Fixed v; Bool changed = 0; @@ -2292,7 +2321,7 @@ static JSBool SMJS_FUNCTION(rot_getAxis) JSObject *pNew; SMJS_OBJ r = * (SFRotation *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec3f_Create(c, pNew, r.x, r.y, r.z); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2303,7 +2332,7 @@ static JSBool SMJS_FUNCTION(rot_inverse) JSObject *pNew; SMJS_OBJ r = * (SFRotation *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; - pNew = JS_NewObject(c, &js_rt->SFRotationClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFRotationClass._class, 0, SMJS_GET_PARENT(c, obj)); SFRotation_Create(c, pNew, r.x, r.y, r.z, r.q-GF_PI); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2317,7 +2346,7 @@ static JSBool SMJS_FUNCTION(rot_multiply) SMJS_OBJ SMJS_ARGS - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFRotationClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFRotationClass, NULL)) return JS_FALSE; r1 = * (SFRotation *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; @@ -2327,7 +2356,7 @@ static JSBool SMJS_FUNCTION(rot_multiply) q1 = gf_quat_multiply(&q1, &q2); r1 = gf_quat_to_rotation(&q1); - pNew = JS_NewObject(c, &js_rt->SFRotationClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFRotationClass._class, 0, SMJS_GET_PARENT(c, obj)); SFRotation_Create(c, pNew, r1.x, r1.y, r1.z, r1.q); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2342,7 +2371,7 @@ static JSBool SMJS_FUNCTION(rot_multVec) SMJS_ARGS if (argc<=0) return JS_FALSE; - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) return JS_FALSE; r = *(SFRotation *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; @@ -2350,7 +2379,7 @@ static JSBool SMJS_FUNCTION(rot_multVec) gf_mx_init(mx); gf_mx_add_rotation(&mx, r.q, r.x, r.y, r.z); gf_mx_apply_vec(&mx, &v); - pNew = JS_NewObject(c, &js_rt->SFVec3fClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFVec3fClass._class, 0, SMJS_GET_PARENT(c, obj)); SFVec3f_Create(c, pNew, v.x, v.y, v.z); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2364,7 +2393,7 @@ static JSBool SMJS_FUNCTION(rot_setAxis) SMJS_ARGS if (argc<=0) return JS_FALSE; - if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) + if (argc<=0 || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFVec3fClass, NULL)) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); @@ -2388,7 +2417,7 @@ static JSBool SMJS_FUNCTION(rot_slerp) SMJS_OBJ if (argc<=1) return JS_FALSE; - if (!JSVAL_IS_DOUBLE(argv[1]) || !JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFRotationClass, NULL)) return JS_FALSE; + if (!JSVAL_IS_DOUBLE(argv[1]) || !JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFRotationClass, NULL)) return JS_FALSE; v1 = *(SFRotation *) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; v2 = *(SFRotation *) ((GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0])))->field.far_ptr; @@ -2397,7 +2426,7 @@ static JSBool SMJS_FUNCTION(rot_slerp) q2 = gf_quat_from_rotation(v2); q1 = gf_quat_slerp(q1, q2, FLT2FIX( d)); res = gf_quat_to_rotation(&q1); - pNew = JS_NewObject(c, &js_rt->SFRotationClass, 0, SMJS_GET_PARENT(c, obj)); + pNew = JS_NewObject(c, &js_rt->SFRotationClass._class, 0, SMJS_GET_PARENT(c, obj)); SFRotation_Create(c, pNew, res.x, res.y, res.z, res.q); SMJS_SET_RVAL( OBJECT_TO_JSVAL(pNew) ); return JS_TRUE; @@ -2422,15 +2451,15 @@ static JSBool SMJS_FUNCTION(SFColorConstructor) { SMJS_ARGS jsdouble r = 0.0, g = 0.0, b = 0.0; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->SFColorClass) if (argc > 0) JS_ValueToNumber(c, argv[0], &r); if (argc > 1) JS_ValueToNumber(c, argv[1], &g); if (argc > 2) JS_ValueToNumber(c, argv[2], &b); SFColor_Create(c, obj, FLT2FIX( r), FLT2FIX( g), FLT2FIX( b)); return JS_TRUE; } -static JSBool color_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_GET( color_getProperty ) + GF_JSField *val = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (SMJS_ID_IS_INT(id)) { switch (SMJS_ID_TO_INT(id)) { @@ -2443,8 +2472,8 @@ static JSBool color_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, j return JS_TRUE; } -static JSBool color_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp) -{ +static SMJS_FUNC_PROP_SET(color_setProperty) + jsdouble d; Fixed v; Bool changed = 0; @@ -2529,10 +2558,10 @@ static void setup_js_array(JSContext *c, JSObject *obj, GF_JSField *ptr, uintN a gf_list_add(priv->js_cache, obj); } -#define MFARRAY_CONSTRUCTOR(_fieldType) \ +#define MFARRAY_CONSTRUCTOR(__classp, _fieldType) \ GF_JSField *ptr; \ SMJS_ARGS \ - SMJS_OBJ_CONSTRUCTOR \ + SMJS_OBJ_CONSTRUCTOR(__classp) \ ptr = NewJSField(c); \ ptr->field.fieldType = _fieldType; \ setup_js_array(c, obj, ptr, (jsint) argc, argv); \ @@ -2542,31 +2571,31 @@ static void setup_js_array(JSContext *c, JSObject *obj, GF_JSField *ptr, uintN a static JSBool SMJS_FUNCTION(MFBoolConstructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFBOOL); + MFARRAY_CONSTRUCTOR(&js_rt->MFBoolClass, GF_SG_VRML_MFBOOL); } static JSBool SMJS_FUNCTION(MFInt32Constructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFINT32); + MFARRAY_CONSTRUCTOR(&js_rt->MFInt32Class, GF_SG_VRML_MFINT32); } static JSBool SMJS_FUNCTION(MFFloatConstructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFFLOAT); + MFARRAY_CONSTRUCTOR(&js_rt->MFFloatClass, GF_SG_VRML_MFFLOAT); } static JSBool SMJS_FUNCTION(MFTimeConstructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFTIME); + MFARRAY_CONSTRUCTOR(&js_rt->MFTimeClass, GF_SG_VRML_MFTIME); } static JSBool SMJS_FUNCTION(MFStringConstructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFSTRING); + MFARRAY_CONSTRUCTOR(&js_rt->MFStringClass, GF_SG_VRML_MFSTRING); } static JSBool SMJS_FUNCTION(MFURLConstructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFURL); + MFARRAY_CONSTRUCTOR(&js_rt->MFUrlClass, GF_SG_VRML_MFURL); } static JSBool SMJS_FUNCTION(MFNodeConstructor) { - MFARRAY_CONSTRUCTOR(GF_SG_VRML_MFNODE); + MFARRAY_CONSTRUCTOR(&js_rt->MFNodeClass, GF_SG_VRML_MFNODE); } @@ -2574,7 +2603,9 @@ static void array_finalize_ex(JSContext *c, JSObject *obj, Bool is_js_call) { GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); +#ifndef USE_FFDEV_15 JS_ObjectDestroyed(c, obj, ptr, 1); +#endif if (!ptr) return; @@ -2593,13 +2624,14 @@ static void array_finalize_ex(JSContext *c, JSObject *obj, Bool is_js_call) } gf_free(ptr); } -static void array_finalize(JSContext *c, JSObject *obj) -{ + +static DECL_FINALIZE(array_finalize) + array_finalize_ex(c, obj, 1); } -JSBool array_getElement(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *rval) -{ +static SMJS_FUNC_PROP_GET( array_getElement ) + u32 i; GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (SMJS_ID_IS_INT(id)) { @@ -2607,9 +2639,9 @@ JSBool array_getElement(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *rv if (ptr->field.fieldType==GF_SG_VRML_MFNODE) { GF_Node *node = gf_node_list_get_child(*(GF_ChildNodeItem **)ptr->field.far_ptr, i); JSObject *anobj = node ? node_get_binding(JS_GetScriptStack(c), node, 0) : NULL; - if (anobj) *rval = OBJECT_TO_JSVAL(anobj); + if (anobj) *vp = OBJECT_TO_JSVAL(anobj); } else { - JS_GetElement(c, ptr->js_list, (jsint) i, rval); + JS_GetElement(c, ptr->js_list, (jsint) i, vp); } } return JS_TRUE; @@ -2617,14 +2649,14 @@ JSBool array_getElement(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *rv //this could be overloaded for each MF type... -JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rval) -{ +static SMJS_FUNC_PROP_SET(array_setElement) + u32 ind; jsuint len; jsdouble d; GF_JSField *from; JSBool ret; - JSClass *the_sf_class = NULL; + GF_JSClass *the_sf_class = NULL; JSString *str; char *str_val; void *sf_slot; @@ -2695,22 +2727,22 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv /*assign object*/ if (ptr->field.fieldType==GF_SG_VRML_MFNODE) { - if (JSVAL_IS_VOID(*rval) || JSVAL_IS_NULL(*rval) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(*rval), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (JSVAL_IS_VOID(*vp) || JSVAL_IS_NULL(*vp) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(*vp), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; } else if (the_sf_class) { - if (JSVAL_IS_VOID(*rval)) return JS_FALSE; - if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(*rval), the_sf_class, NULL) ) return JS_FALSE; + if (JSVAL_IS_VOID(*vp)) return JS_FALSE; + if (!GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(*vp), the_sf_class, NULL) ) return JS_FALSE; } else if (ptr->field.fieldType==GF_SG_VRML_MFBOOL) { - if (!JSVAL_IS_BOOLEAN(*rval)) return JS_FALSE; + if (!JSVAL_IS_BOOLEAN(*vp)) return JS_FALSE; } else if (ptr->field.fieldType==GF_SG_VRML_MFINT32) { - if (!JSVAL_IS_INT(*rval)) return JS_FALSE; + if (!JSVAL_IS_INT(*vp)) return JS_FALSE; } else if (ptr->field.fieldType==GF_SG_VRML_MFFLOAT) { - if (!JSVAL_IS_NUMBER(*rval)) return JS_FALSE; + if (!JSVAL_IS_NUMBER(*vp)) return JS_FALSE; } else if (ptr->field.fieldType==GF_SG_VRML_MFTIME) { - if (!JSVAL_IS_NUMBER(*rval)) return JS_FALSE; + if (!JSVAL_IS_NUMBER(*vp)) return JS_FALSE; } else if (ptr->field.fieldType==GF_SG_VRML_MFSTRING) { - if (!JSVAL_IS_STRING(*rval)) return JS_FALSE; + if (!JSVAL_IS_STRING(*vp)) return JS_FALSE; } else if (ptr->field.fieldType==GF_SG_VRML_MFURL) { - if (!JSVAL_IS_STRING(*rval)) return JS_FALSE; + if (!JSVAL_IS_STRING(*vp)) return JS_FALSE; } @@ -2721,14 +2753,14 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv if (!ptr->owner) return JS_TRUE; /*get new node*/ - from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*rval)); + from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp)); new_n = *(GF_Node**)from->field.far_ptr; #if 0 anobj = node_get_binding(JS_GetScriptStack(c), from->node, 0); /*add it to the new object if needed*/ - ret = JS_SetElement(c, ptr->js_list, ind, rval); + ret = JS_SetElement(c, ptr->js_list, ind, vp); #endif /*get and delete previous node if any, but unregister later*/ @@ -2749,7 +2781,7 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv return JS_TRUE; } - ret = JS_SetElement(c, ptr->js_list, ind, rval); + ret = JS_SetElement(c, ptr->js_list, ind, vp); if (ret==JS_FALSE) return JS_FALSE; if (!ptr->owner) return JS_TRUE; @@ -2757,17 +2789,17 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv /*rewrite MF slot*/ switch (ptr->field.fieldType) { case GF_SG_VRML_MFBOOL: - ((MFBool *)ptr->field.far_ptr)->vals[ind] = (Bool) JSVAL_TO_BOOLEAN(*rval); + ((MFBool *)ptr->field.far_ptr)->vals[ind] = (Bool) JSVAL_TO_BOOLEAN(*vp); break; case GF_SG_VRML_MFINT32: - ((MFInt32 *)ptr->field.far_ptr)->vals[ind] = (s32) JSVAL_TO_INT(*rval); + ((MFInt32 *)ptr->field.far_ptr)->vals[ind] = (s32) JSVAL_TO_INT(*vp); break; case GF_SG_VRML_MFFLOAT: - JS_ValueToNumber(c, *rval, &d); + JS_ValueToNumber(c, *vp, &d); ((MFFloat *)ptr->field.far_ptr)->vals[ind] = FLT2FIX(d); break; case GF_SG_VRML_MFTIME: - JS_ValueToNumber(c, *rval, &d); + JS_ValueToNumber(c, *vp, &d); ((MFTime *)ptr->field.far_ptr)->vals[ind] = d; break; case GF_SG_VRML_MFSTRING: @@ -2775,7 +2807,7 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv gf_free(((MFString *)ptr->field.far_ptr)->vals[ind]); ((MFString *)ptr->field.far_ptr)->vals[ind] = NULL; } - str = JSVAL_IS_STRING(*rval) ? JSVAL_TO_STRING(*rval) : JS_ValueToString(c, *rval); + str = JSVAL_IS_STRING(*vp) ? JSVAL_TO_STRING(*vp) : JS_ValueToString(c, *vp); str_val = SMJS_CHARS_FROM_STRING(c, str); ((MFString *)ptr->field.far_ptr)->vals[ind] = gf_strdup(str_val); SMJS_FREE(c, str_val); @@ -2786,7 +2818,7 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv gf_free(((MFURL *)ptr->field.far_ptr)->vals[ind].url); ((MFURL *)ptr->field.far_ptr)->vals[ind].url = NULL; } - str = JSVAL_IS_STRING(*rval) ? JSVAL_TO_STRING(*rval) : JS_ValueToString(c, *rval); + str = JSVAL_IS_STRING(*vp) ? JSVAL_TO_STRING(*vp) : JS_ValueToString(c, *vp); str_val = SMJS_CHARS_FROM_STRING(c, str); ((MFURL *)ptr->field.far_ptr)->vals[ind].url = gf_strdup(str_val); ((MFURL *)ptr->field.far_ptr)->vals[ind].OD_ID = 0; @@ -2794,19 +2826,19 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv break; case GF_SG_VRML_MFVEC2F: - from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*rval)); + from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp)); gf_sg_vrml_field_copy(& ((MFVec2f *)ptr->field.far_ptr)->vals[ind], from->field.far_ptr, from->field.fieldType); break; case GF_SG_VRML_MFVEC3F: - from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*rval)); + from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp)); gf_sg_vrml_field_copy(& ((MFVec3f *)ptr->field.far_ptr)->vals[ind], from->field.far_ptr, from->field.fieldType); break; case GF_SG_VRML_MFROTATION: - from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*rval)); + from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp)); gf_sg_vrml_field_copy(& ((MFRotation *)ptr->field.far_ptr)->vals[ind], from->field.far_ptr, from->field.fieldType); break; case GF_SG_VRML_MFCOLOR: - from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*rval)); + from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp)); gf_sg_vrml_field_copy(& ((MFColor *)ptr->field.far_ptr)->vals[ind], from->field.far_ptr, from->field.fieldType); break; } @@ -2815,14 +2847,16 @@ JSBool array_setElement(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *rv return JS_TRUE; } -JSBool array_setLength(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *val) -{ +static SMJS_FUNC_PROP_SET( array_setLength) + u32 len, i, sftype; JSBool ret; - JSClass *the_sf_class; + GF_JSClass *the_sf_class; GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); - if (!JSVAL_IS_INT(*val) || JSVAL_TO_INT(*val) < 0) return JS_FALSE; - len = JSVAL_TO_INT(*val); + if (!JSVAL_IS_INT(*vp) || JSVAL_TO_INT(*vp) < 0) return JS_FALSE; + /*avoids gcc warning*/ + if (!id) id=0; + len = JSVAL_TO_INT(*vp); if (!len) { @@ -2864,8 +2898,9 @@ JSBool array_setLength(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *val if (n) gf_node_unregister(n, ptr->owner); c--; } - if (len>c) - fprintf(stdout, "NOT SUPPORTED!!!\n"); + if (len>c) { + GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[VRML] MFARRAY EXPANSION NOT SUPPORTED!!!\n")); + } } return JS_TRUE; } @@ -2895,11 +2930,13 @@ JSBool array_setLength(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *val return JS_TRUE; } -JSBool array_getLength(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *val) -{ +static SMJS_FUNC_PROP_GET( array_getLength) + JSBool ret; jsuint len; GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); + /*avoids gcc warning*/ + if (!id) id=0; if (ptr->field.fieldType==GF_SG_VRML_MFNODE) { len = gf_node_list_get_count(*(GF_ChildNodeItem **)ptr->field.far_ptr); @@ -2907,7 +2944,7 @@ JSBool array_getLength(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *val } else { ret = JS_GetArrayLength(c, ptr->js_list, &len); } - *val = INT_TO_JSVAL(len); + *vp = INT_TO_JSVAL(len); return ret; } @@ -2920,14 +2957,14 @@ static JSBool SMJS_FUNCTION(MFVec2fConstructor) u32 i; SMJS_ARGS GF_JSField *ptr = NewJSField(c); - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->MFVec2fClass) setup_js_array(c, obj, ptr, 0, 0); JS_SetArrayLength(c, ptr->js_list, argc); SMJS_SET_PRIVATE(c, obj, ptr); for (i=0; iSFVec2fClass, NULL) ) { + if (!JSVAL_IS_OBJECT(argv[i]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[i]), &js_rt->SFVec2fClass, NULL) ) { item = SMJS_CONSTRUCT_OBJECT(c, &js_rt->SFVec2fClass, obj); val = OBJECT_TO_JSVAL(item); JS_SetElement(c, ptr->js_list, i, &val); @@ -2947,7 +2984,7 @@ static JSBool SMJS_FUNCTION(MFVec3fConstructor) u32 i; SMJS_ARGS GF_JSField *ptr; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->MFVec3fClass) ptr = NewJSField(c); ptr->field.fieldType = GF_SG_VRML_MFVEC3F; @@ -2956,7 +2993,7 @@ static JSBool SMJS_FUNCTION(MFVec3fConstructor) SMJS_SET_PRIVATE(c, obj, ptr); for (i=0; iSFVec3fClass, NULL) ) { + if (!JSVAL_IS_OBJECT(argv[i]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[i]), &js_rt->SFVec3fClass, NULL) ) { item = SMJS_CONSTRUCT_OBJECT(c, &js_rt->SFVec3fClass, obj); val = OBJECT_TO_JSVAL(item); JS_SetElement(c, ptr->js_list, i, &val); @@ -2976,7 +3013,7 @@ static JSBool SMJS_FUNCTION(MFRotationConstructor) u32 i; SMJS_ARGS GF_JSField *ptr; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->MFRotationClass) ptr = NewJSField(c); ptr->field.fieldType = GF_SG_VRML_MFROTATION; @@ -2985,7 +3022,7 @@ static JSBool SMJS_FUNCTION(MFRotationConstructor) SMJS_SET_PRIVATE(c, obj, ptr); for (i=0; iSFRotationClass, NULL) ) { + if (!JSVAL_IS_OBJECT(argv[i]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[i]), &js_rt->SFRotationClass, NULL) ) { item = SMJS_CONSTRUCT_OBJECT(c, &js_rt->SFVec3fClass, obj); val = OBJECT_TO_JSVAL(item); JS_SetElement(c, ptr->js_list, i, &val); @@ -3005,7 +3042,7 @@ static JSBool SMJS_FUNCTION(MFColorConstructor) u32 i; SMJS_ARGS GF_JSField *ptr; - SMJS_OBJ_CONSTRUCTOR + SMJS_OBJ_CONSTRUCTOR(&js_rt->MFColorClass) ptr = NewJSField(c); ptr->field.fieldType = GF_SG_VRML_MFCOLOR; @@ -3014,7 +3051,7 @@ static JSBool SMJS_FUNCTION(MFColorConstructor) SMJS_SET_PRIVATE(c, obj, ptr); for (i=0; iSFColorClass, NULL) ) { + if (!JSVAL_IS_OBJECT(argv[i]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[i]), &js_rt->SFColorClass, NULL) ) { item = SMJS_CONSTRUCT_OBJECT(c, &js_rt->SFColorClass, obj); val = OBJECT_TO_JSVAL(item); JS_SetElement(c, ptr->js_list, i, &val); @@ -3037,7 +3074,7 @@ JSBool SMJS_FUNCTION(vrml_event_add_listener) GF_Node *node; GF_JSField *ptr; SMJS_OBJ - if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (! GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); node = * ((GF_Node **)ptr->field.far_ptr); @@ -3049,7 +3086,7 @@ JSBool SMJS_FUNCTION(vrml_event_remove_listener) GF_Node *node; GF_JSField *ptr; SMJS_OBJ - if (! JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; + if (! GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) return JS_FALSE; ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); node = * ((GF_Node **)ptr->field.far_ptr); @@ -3066,19 +3103,34 @@ static JSBool SMJS_FUNCTION(vrml_dom3_not_implemented) void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) { - /*GCC port: classes are declared within code since JS_PropertyStub and co are exported symbols - from JS runtime lib, so with non-constant addresses*/ JS_SETUP_CLASS(js_rt->globalClass, "global", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub); + JS_SETUP_CLASS(js_rt->AnyClass, "AnyClass", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub); JS_SETUP_CLASS(js_rt->browserClass , "Browser", 0, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub); +#if 1 JS_SETUP_CLASS(js_rt->SFNodeClass, "SFNode", JSCLASS_HAS_PRIVATE, node_getProperty, node_setProperty, node_finalize); +#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; +#endif JS_SETUP_CLASS(js_rt->SFVec2fClass , "SFVec2f", JSCLASS_HAS_PRIVATE, vec2f_getProperty, vec2f_setProperty, field_finalize); @@ -3151,7 +3203,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) JS_DefineProperty(sc->js_ctx, sc->js_obj, "NULL", JSVAL_NULL, 0, 0, JSPROP_READONLY | JSPROP_PERMANENT ); JS_DefineProperty(sc->js_ctx, sc->js_obj, "_this", PRIVATE_TO_JSVAL(script), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT ); - sc->js_browser = JS_DefineObject(sc->js_ctx, sc->js_obj, "Browser", &js_rt->browserClass, 0, 0 ); + sc->js_browser = JS_DefineObject(sc->js_ctx, sc->js_obj, "Browser", &js_rt->browserClass._class, 0, 0 ); JS_DefineProperty(sc->js_ctx, sc->js_browser, "_this", PRIVATE_TO_JSVAL(script), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT ); { JSFunctionSpec browserFunctions[] = { @@ -3195,7 +3247,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) {"__dummy", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFNodeClass, SFNodeConstructor, 1, SFNodeProps, SFNodeMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFNodeClass, SFNodeConstructor, 1, SFNodeProps, SFNodeMethods, 0, 0); } { JSPropertySpec SFVec2fProps[] = { @@ -3215,7 +3267,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) SMJS_FUNCTION_SPEC("toString", field_toString, 0), SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFVec2fClass, SFVec2fConstructor, 0, SFVec2fProps, SFVec2fMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFVec2fClass, SFVec2fConstructor, 0, SFVec2fProps, SFVec2fMethods, 0, 0); } { JSPropertySpec SFVec3fProps[] = { @@ -3237,7 +3289,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) SMJS_FUNCTION_SPEC("toString", field_toString, 0), SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFVec3fClass, SFVec3fConstructor, 0, SFVec3fProps, SFVec3fMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFVec3fClass, SFVec3fConstructor, 0, SFVec3fProps, SFVec3fMethods, 0, 0); } { JSPropertySpec SFRotationProps[] = { @@ -3257,7 +3309,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) SMJS_FUNCTION_SPEC("toString", field_toString, 0), SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFRotationClass, SFRotationConstructor, 0, SFRotationProps, SFRotationMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFRotationClass, SFRotationConstructor, 0, SFRotationProps, SFRotationMethods, 0, 0); } { JSPropertySpec SFColorProps[] = { @@ -3272,7 +3324,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) SMJS_FUNCTION_SPEC("toString", field_toString, 0), SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFColorClass, SFColorConstructor, 0, SFColorProps, SFColorMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFColorClass, SFColorConstructor, 0, SFColorProps, SFColorMethods, 0, 0); } { JSPropertySpec SFImageProps[] = { @@ -3282,7 +3334,7 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) {"array", 3, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0}, {0, 0, 0, 0, 0} }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFImageClass, SFImageConstructor, 0, SFImageProps, 0, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->SFImageClass, SFImageConstructor, 0, SFImageProps, 0, 0, 0); } { @@ -3296,23 +3348,23 @@ void gf_sg_script_init_sm_api(GF_ScriptPriv *sc, GF_Node *script) SMJS_FUNCTION_SPEC(0, 0, 0) }; - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFInt32Class, MFInt32Constructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFBoolClass, MFBoolConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFFloatClass, MFFloatConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFTimeClass, MFTimeConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFStringClass, MFStringConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFUrlClass, MFURLConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFVec2fClass, MFVec2fConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFVec3fClass, MFVec3fConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFRotationClass, MFRotationConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFColorClass, MFColorConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFNodeClass, MFNodeConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFInt32Class, MFInt32Constructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFBoolClass, MFBoolConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFFloatClass, MFFloatConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFTimeClass, MFTimeConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFStringClass, MFStringConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFUrlClass, MFURLConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFVec2fClass, MFVec2fConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFVec3fClass, MFVec3fConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFRotationClass, MFRotationConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFColorClass, MFColorConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &js_rt->MFNodeClass, MFNodeConstructor, 0, MFArrayProp, MFArrayMethods, 0, 0); } /* cant get any doc specifying if these are supposed to be supported in MPEG4Script... - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &SFVec4fClass, SFVec4fConstructor, 0, SFVec4fProps, SFVec4fMethods, 0, 0); - JS_InitClass(sc->js_ctx, sc->js_obj, 0, &MFVec4fClass, MFVec4fCons, 0, MFArrayProp, 0, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &SFVec4fClass, SFVec4fConstructor, 0, SFVec4fProps, SFVec4fMethods, 0, 0); + GF_JS_InitClass(sc->js_ctx, sc->js_obj, 0, &MFVec4fClass, MFVec4fCons, 0, MFArrayProp, 0, 0, 0); */ } @@ -3435,7 +3487,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF switch (field->fieldType) { case GF_SG_VRML_SFVEC2F: { - if (JS_InstanceOf(c, obj, &js_rt->SFVec2fClass, NULL) ) { + if (GF_JS_InstanceOf(c, obj, &js_rt->SFVec2fClass, NULL) ) { p = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); gf_sg_vrml_field_copy(field->far_ptr, p->field.far_ptr, GF_SG_VRML_SFVEC2F); Script_FieldChanged(c, owner, parent, field); @@ -3444,7 +3496,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF } case GF_SG_VRML_SFVEC3F: { - if (JS_InstanceOf(c, obj, &js_rt->SFVec3fClass, NULL) ) { + if (GF_JS_InstanceOf(c, obj, &js_rt->SFVec3fClass, NULL) ) { p = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); gf_sg_vrml_field_copy(field->far_ptr, p->field.far_ptr, GF_SG_VRML_SFVEC3F); Script_FieldChanged(c, owner, parent, field); @@ -3453,7 +3505,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF } case GF_SG_VRML_SFROTATION: { - if ( JS_InstanceOf(c, obj, &js_rt->SFRotationClass, NULL) ) { + if ( GF_JS_InstanceOf(c, obj, &js_rt->SFRotationClass, NULL) ) { p = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); gf_sg_vrml_field_copy(field->far_ptr, p->field.far_ptr, GF_SG_VRML_SFROTATION); Script_FieldChanged(c, owner, parent, field); @@ -3462,7 +3514,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF } case GF_SG_VRML_SFCOLOR: { - if (JS_InstanceOf(c, obj, &js_rt->SFColorClass, NULL) ) { + if (GF_JS_InstanceOf(c, obj, &js_rt->SFColorClass, NULL) ) { p = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); gf_sg_vrml_field_copy(field->far_ptr, p->field.far_ptr, GF_SG_VRML_SFCOLOR); Script_FieldChanged(c, owner, parent, field); @@ -3479,7 +3531,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF if (JSVAL_IS_NULL(val)) { Script_FieldChanged(c, owner, parent, field); - } else if (JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) { + } else if (GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) { GF_Node *n = * (GF_Node**) ((GF_JSField *) SMJS_GET_PRIVATE(c, obj))->field.far_ptr; * ((GF_Node **)field->far_ptr) = n; gf_node_register(n, owner); @@ -3489,7 +3541,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF } case GF_SG_VRML_SFIMAGE: { - if ( JS_InstanceOf(c, obj, &js_rt->SFImageClass, NULL) ) { + if ( GF_JS_InstanceOf(c, obj, &js_rt->SFImageClass, NULL) ) { p = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); gf_sg_vrml_field_copy(field->far_ptr, p->field.far_ptr, GF_SG_VRML_SFIMAGE); Script_FieldChanged(c, owner, parent, field); @@ -3501,19 +3553,19 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF } //from here we handle only MF fields - if ( !JS_InstanceOf(c, obj, &js_rt->MFBoolClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFInt32Class, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFFloatClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFTimeClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFStringClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFUrlClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFVec2fClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFVec3fClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFRotationClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFColorClass, NULL) - && !JS_InstanceOf(c, obj, &js_rt->MFNodeClass, NULL) + if ( !GF_JS_InstanceOf(c, obj, &js_rt->MFBoolClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFInt32Class, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFFloatClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFTimeClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFStringClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFUrlClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFVec2fClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFVec3fClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFRotationClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFColorClass, NULL) + && !GF_JS_InstanceOf(c, obj, &js_rt->MFNodeClass, NULL) /* - && !JS_InstanceOf(c, obj, &MFVec4fClass, NULL) + && !GF_JS_InstanceOf(c, obj, &MFVec4fClass, NULL) */ ) return; @@ -3522,7 +3574,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF JS_GetArrayLength(c, p->js_list, &len); /*special handling for MF node, reset list first*/ - if (JS_InstanceOf(c, obj, &js_rt->MFNodeClass, NULL)) { + if (GF_JS_InstanceOf(c, obj, &js_rt->MFNodeClass, NULL)) { GF_Node *child; GF_ChildNodeItem *last = NULL; gf_node_unregister_children(owner, * (GF_ChildNodeItem **) field->far_ptr); @@ -3534,7 +3586,7 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF if (JSVAL_IS_NULL(item)) break; if (!JSVAL_IS_OBJECT(item)) break; node_obj = JSVAL_TO_OBJECT(item); - if ( !JS_InstanceOf(c, node_obj, &js_rt->SFNodeClass, NULL)) break; + if ( !GF_JS_InstanceOf(c, node_obj, &js_rt->SFNodeClass, NULL)) break; from = (GF_JSField *) SMJS_GET_PRIVATE(c, node_obj); child = * ((GF_Node**)from->field.far_ptr); @@ -3610,25 +3662,25 @@ void gf_sg_script_to_node_field(JSContext *c, jsval val, GF_FieldInfo *field, GF break; case GF_SG_VRML_MFVEC2F: - if ( JSVAL_IS_OBJECT(item) && JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFVec2fClass, NULL) ) { + if ( JSVAL_IS_OBJECT(item) && GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFVec2fClass, NULL) ) { from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(item)); gf_sg_vrml_field_copy(& ((MFVec2f*)field->far_ptr)->vals[i], from->field.far_ptr, GF_SG_VRML_SFVEC2F); } break; case GF_SG_VRML_MFVEC3F: - if ( JSVAL_IS_OBJECT(item) && JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFVec3fClass, NULL) ) { + if ( JSVAL_IS_OBJECT(item) && GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFVec3fClass, NULL) ) { from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(item)); gf_sg_vrml_field_copy(& ((MFVec3f*)field->far_ptr)->vals[i], from->field.far_ptr, GF_SG_VRML_SFVEC3F); } break; case GF_SG_VRML_MFROTATION: - if ( JSVAL_IS_OBJECT(item) && JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFRotationClass, NULL) ) { + if ( JSVAL_IS_OBJECT(item) && GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFRotationClass, NULL) ) { from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(item)); gf_sg_vrml_field_copy(& ((MFRotation*)field->far_ptr)->vals[i], from->field.far_ptr, GF_SG_VRML_SFROTATION); } break; case GF_SG_VRML_MFCOLOR: - if ( JSVAL_IS_OBJECT(item) && JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFColorClass, NULL) ) { + if ( JSVAL_IS_OBJECT(item) && GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(item), &js_rt->SFColorClass, NULL) ) { from = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(item)); gf_sg_vrml_field_copy(& ((MFColor*)field->far_ptr)->vals[i], from->field.far_ptr, GF_SG_VRML_SFCOLOR); } @@ -3745,7 +3797,7 @@ static void gf_sg_script_update_cached_object(GF_ScriptPriv *priv, JSObject *obj too costly to handle in script*/ if (gf_node_list_get_count(f)==count) return; - fprintf(stdout, "rewriting MFNode cache\n"); + fprintf(stderr, "rewriting MFNode cache\n"); while (f) { slot = NULL; /*first look in the original array*/ @@ -3870,23 +3922,23 @@ jsval gf_sg_script_to_smjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_No switch (field->fieldType) { case GF_SG_VRML_SFVEC2F: SETUP_FIELD - obj = JS_NewObject(priv->js_ctx, &js_rt->SFVec2fClass, 0, priv->js_obj); + obj = JS_NewObject(priv->js_ctx, &js_rt->SFVec2fClass._class, 0, priv->js_obj); break; case GF_SG_VRML_SFVEC3F: SETUP_FIELD - obj = JS_NewObject(priv->js_ctx, &js_rt->SFVec3fClass, 0, priv->js_obj); + obj = JS_NewObject(priv->js_ctx, &js_rt->SFVec3fClass._class, 0, priv->js_obj); break; case GF_SG_VRML_SFROTATION: SETUP_FIELD - obj = JS_NewObject(priv->js_ctx, &js_rt->SFRotationClass, 0, priv->js_obj); + obj = JS_NewObject(priv->js_ctx, &js_rt->SFRotationClass._class, 0, priv->js_obj); break; case GF_SG_VRML_SFCOLOR: SETUP_FIELD - obj = JS_NewObject(priv->js_ctx, &js_rt->SFColorClass, 0, priv->js_obj); + obj = JS_NewObject(priv->js_ctx, &js_rt->SFColorClass._class, 0, priv->js_obj); break; case GF_SG_VRML_SFIMAGE: SETUP_FIELD - obj = JS_NewObject(priv->js_ctx, &js_rt->SFImageClass, 0, priv->js_obj); + obj = JS_NewObject(priv->js_ctx, &js_rt->SFImageClass._class, 0, priv->js_obj); break; case GF_SG_VRML_SFNODE: if (! *(GF_Node**) field->far_ptr) @@ -3982,7 +4034,7 @@ jsval gf_sg_script_to_smjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_No obj = SMJS_CONSTRUCT_OBJECT(priv->js_ctx, &js_rt->MFVec2fClass, priv->js_obj); SETUP_MF_FIELD for (i=0; icount; i++) { - JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFVec2fClass, 0, obj); + JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFVec2fClass._class, 0, obj); newVal = OBJECT_TO_JSVAL(pf); slot = SFVec2f_Create(priv->js_ctx, pf, f->vals[i].x, f->vals[i].y); slot->owner = parent; @@ -3996,7 +4048,7 @@ jsval gf_sg_script_to_smjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_No obj = SMJS_CONSTRUCT_OBJECT(priv->js_ctx, &js_rt->MFVec3fClass, priv->js_obj); SETUP_MF_FIELD for (i=0; icount; i++) { - JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFVec3fClass, 0, obj); + JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFVec3fClass._class, 0, obj); newVal = OBJECT_TO_JSVAL(pf); slot = SFVec3f_Create(priv->js_ctx, pf, f->vals[i].x, f->vals[i].y, f->vals[i].z); slot->owner = parent; @@ -4010,7 +4062,7 @@ jsval gf_sg_script_to_smjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_No obj = SMJS_CONSTRUCT_OBJECT(priv->js_ctx, &js_rt->MFRotationClass, priv->js_obj); SETUP_MF_FIELD for (i=0; icount; i++) { - JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFRotationClass, 0, obj); + JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFRotationClass._class, 0, obj); newVal = OBJECT_TO_JSVAL(pf); slot = SFRotation_Create(priv->js_ctx, pf, f->vals[i].x, f->vals[i].y, f->vals[i].z, f->vals[i].q); slot->owner = parent; @@ -4024,7 +4076,7 @@ jsval gf_sg_script_to_smjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_No obj = SMJS_CONSTRUCT_OBJECT(priv->js_ctx, &js_rt->MFColorClass, priv->js_obj); SETUP_MF_FIELD for (i=0; icount; i++) { - JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFColorClass, 0, obj); + JSObject *pf = JS_NewObject(priv->js_ctx, &js_rt->SFColorClass._class, 0, obj); newVal = OBJECT_TO_JSVAL(pf); slot = SFColor_Create(priv->js_ctx, pf, f->vals[i].red, f->vals[i].green, f->vals[i].blue); slot->owner = parent; @@ -4507,6 +4559,7 @@ static void JSScript_LoadVRML(GF_Node *node) GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[VRML JS] Evaluating script %s\n", str)); +#if 1 ret = JS_EvaluateScript(priv->js_ctx, priv->js_obj, str, strlen(str), 0, 0, &rval); if (ret==JS_TRUE) { /*call initialize if present*/ @@ -4515,6 +4568,7 @@ static void JSScript_LoadVRML(GF_Node *node) gf_js_vrml_flush_event_out(node, priv); } +#endif gf_sg_lock_javascript(priv->js_ctx, 0); @@ -4762,7 +4816,7 @@ GF_EXPORT GF_Node *gf_sg_js_get_node(JSContext *c, JSObject *obj) { #ifndef GPAC_DISABLE_VRML - if (js_rt && JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) { + if (js_rt && GF_JS_InstanceOf(c, obj, &js_rt->SFNodeClass, NULL) ) { GF_JSField *ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, obj); if (ptr->field.fieldType==GF_SG_VRML_SFNODE) return * ((GF_Node **)ptr->field.far_ptr); } diff --git a/src/scenegraph/vrml_tools.c b/src/scenegraph/vrml_tools.c index 7459f26..03f72bc 100644 --- a/src/scenegraph/vrml_tools.c +++ b/src/scenegraph/vrml_tools.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project diff --git a/src/scenegraph/x3d_nodes.c b/src/scenegraph/x3d_nodes.c index c7e36e2..3ee64df 100644 --- a/src/scenegraph/x3d_nodes.c +++ b/src/scenegraph/x3d_nodes.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / X3D Scene Graph sub-project diff --git a/src/scenegraph/xbl_process.c b/src/scenegraph/xbl_process.c index 0af4aa2..b5863ed 100644 --- a/src/scenegraph/xbl_process.c +++ b/src/scenegraph/xbl_process.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Cyril Concolato 2008 - + * Authors: Cyril Concolato + * Copyright (c) Telecom ParisTech 2008-2012 * All rights reserved * * This file is part of GPAC / Scene Management sub-project diff --git a/src/scenegraph/xml_ns.c b/src/scenegraph/xml_ns.c index 2e72377..4b3fdd2 100644 --- a/src/scenegraph/xml_ns.c +++ b/src/scenegraph/xml_ns.c @@ -1,8 +1,9 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Cyril Concolato - Jean Le Feuvre - * Copyright (c)2008-200X ENST - All rights reserved + * Authors: Jean Le Feuvre - Cyril Concolato + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved * * This file is part of GPAC / SVG Scene Graph sub-project * diff --git a/src/terminal/channel.c b/src/terminal/channel.c index 7c833ed..be98760 100644 --- a/src/terminal/channel.c +++ b/src/terminal/channel.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -642,7 +643,7 @@ static void gf_es_check_timing(GF_Channel *ch) if (!ch->clock->clock_init) { if (!ch->clock->use_ocr) { gf_clock_set_time(ch->clock, ch->CTS); - GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: Forcing clock initialization at STB %d - AU DTS %d\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), ch->DTS)); + GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: Forcing clock initialization at STB %d - AU DTS %d CTS %d\n", ch->esd->ESID, gf_term_get_time(ch->odm->term), ch->DTS, ch->CTS)); ch->IsClockInit = 1; } } @@ -1101,7 +1102,10 @@ void gf_es_receive_sl_packet(GF_ClientService *serv, GF_Channel *ch, char *paylo if (ch->AULength == OldLength + payload_size) EndAU = 1; if (EndAU) ch->NextIsAUStart = 1; - if (EndAU && !ch->IsClockInit) gf_es_check_timing(ch); + if (EndAU && !ch->IsClockInit && !ch->skip_time_check_for_pending) { + ch->skip_time_check_for_pending = 0; + gf_es_check_timing(ch); + } /* we need to skip all the packets of the current AU in the carousel scenario */ if (ch->skip_carousel_au == 1) return; @@ -1205,6 +1209,8 @@ void gf_es_on_eos(GF_Channel *ch) /*flush buffer*/ ch_buffer_off(ch); + if (ch->len) + Channel_DispatchAU(ch, 0); gf_odm_on_eos(ch->odm, ch); } diff --git a/src/terminal/clock.c b/src/terminal/clock.c index 8883847..b559596 100644 --- a/src/terminal/clock.c +++ b/src/terminal/clock.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file scene part of GPAC / Media terminal sub-project diff --git a/src/terminal/decoder.c b/src/terminal/decoder.c index 6fd214a..f18a433 100644 --- a/src/terminal/decoder.c +++ b/src/terminal/decoder.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -60,6 +61,8 @@ GF_Codec *gf_codec_new(GF_ObjectManager *odm, GF_ESD *base_layer, s32 PL, GF_Err if (tmp->type==GF_STREAM_PRIVATE_MEDIA) tmp->type = GF_STREAM_VISUAL; + tmp->Priority = base_layer->streamPriority ? base_layer->streamPriority : 1; + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[Codec] Found decoder %s for stream type %s\n", tmp->decio ? tmp->decio->module_name : "RAW", gf_esd_get_textual_description(base_layer) )); return tmp; } @@ -241,7 +244,6 @@ GF_Err gf_codec_add_channel(GF_Codec *codec, GF_Channel *ch) Also assign codec priority here*/ if (!ch->esd->dependsOnESID || !codec->ck) { codec->ck = ch->clock; - codec->Priority = ch->esd->streamPriority; /*insert base layer first - note we are sure this is a stream of the same type as the codec (other streams - OCI, MPEG7, MPEGJ - are not added that way)*/ return gf_list_insert(codec->inChannels, ch, 0); @@ -383,7 +385,7 @@ check_unit: cap.cap.valueInt = 0; sdec->GetCapabilities(codec->decio, &cap); if (!cap.cap.valueInt) { - gf_term_stop_codec(codec); + gf_term_stop_codec(codec, 0); if ((codec->type==GF_STREAM_OD) && (codec->nb_dec_frames==1)) { /*this is just by safety, since seeking is only allowed when a single clock is present in the scene*/ @@ -510,7 +512,7 @@ static GF_Err PrivateScene_Process(GF_Codec *codec, u32 TimeAvailable) if (codec->Muted) return GF_OK; if (codec->Status == GF_ESM_CODEC_EOS) { - gf_term_stop_codec(codec); + gf_term_stop_codec(codec, 0); return GF_OK; } @@ -670,12 +672,14 @@ static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable) e = mdec->ProcessData(mdec, NULL, 0, 0, CU->data, &unit_size, 0, 0); if (e==GF_OK) e = UnlockCompositionUnit(codec, CU, unit_size); } - gf_term_stop_codec(codec); + gf_term_stop_codec(codec, 0); if (codec->CB) gf_cm_set_eos(codec->CB); } /*if no data, and channel not buffering, ABORT CB buffer (data timeout or EOS not detectable)*/ else if (ch && !ch->BufferOn) gf_cm_abort_buffering(codec->CB); + + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] ODM%d: No data in decoding buffer\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID)); return GF_OK; } @@ -687,6 +691,15 @@ static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable) gf_es_drop_au(ch); return GF_BAD_PARAM; } + /*we are still flushing our CB - keep the current pending AU and wait for CB resize*/ + if (codec->force_cb_resize) { + if (codec->CB->UnitCount>1) { + return GF_OK; + } + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[%s] ODM%d: Resizing output buffer %d -> %d\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, codec->CB->UnitSize, codec->force_cb_resize)); + ResizeCompositionBuffer(codec, codec->force_cb_resize); + codec->force_cb_resize=0; + } /*image codecs*/ if (codec->CB->Capacity == 1) { @@ -770,7 +783,6 @@ static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable) /*when using temporal scalability make sure we can decode*/ if (ch->esd->dependsOnESID && (codec->last_unit_dts > AU->DTS)){ -// printf("SCALABLE STREAM DEAD!!\n"); goto drop; } @@ -781,8 +793,10 @@ static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable) AU->CTS = codec->last_unit_cts + ch->ts_offset + (u32) (codec->cur_video_frames * 1000 / codec->fps); } } - if ( LockCompositionUnit(codec, AU->CTS, &CU, &unit_size) == GF_OUT_OF_MEM) + if ( LockCompositionUnit(codec, AU->CTS, &CU, &unit_size) == GF_OUT_OF_MEM) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] Exit decode loop because no more space in composition buffer\n", codec->decio->module_name )); return GF_OK; + } scalable_retry: @@ -794,20 +808,30 @@ scalable_retry: else e = mdec->ProcessData(mdec, AU->data, AU->dataLength, ch->esd->ESID, CU->data, &unit_size, AU->PaddingBits, mmlevel); now = gf_term_get_time(codec->odm->term) - now; - if (codec->Status == GF_ESM_CODEC_STOP) return GF_OK; - + if (codec->Status == GF_ESM_CODEC_STOP) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] Exit decode loop because codec has been stopped\n", codec->decio->module_name)); + return GF_OK; + } /*input is too small, resize composition memory*/ switch (e) { case GF_BUFFER_TOO_SMALL: /*release but no dispatch*/ UnlockCompositionUnit(codec, CU, 0); + + /*if we have pending media do wait! - this shoud be fixed by avoiding to destroy the CB ... */ + if (codec->CB->UnitCount>1) { + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[%s] ODM%d: Resize output buffer requested\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID)); + codec->force_cb_resize = unit_size; + return GF_OK; + } + GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[%s] ODM%d: Resizing output buffer %d -> %d\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, codec->CB->UnitSize, unit_size)); ResizeCompositionBuffer(codec, unit_size); continue; /*this happens a lot when using non-MPEG-4 streams (ex: ffmpeg demuxer)*/ case GF_PACKED_FRAMES: /*in seek don't dispatch any output*/ - if (mmlevel == GF_CODEC_LEVEL_SEEK) + if (mmlevel >= GF_CODEC_LEVEL_DROP) unit_size = 0; e = UnlockCompositionUnit(codec, CU, unit_size); @@ -885,6 +909,7 @@ drop: if (e) { UnlockCompositionUnit(codec, CU, unit_size); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] Exit decode loop because error %s\n", codec->decio->module_name, gf_error_to_string(e) )); return e; } @@ -896,22 +921,25 @@ drop: } /*in seek don't dispatch any output*/ - if (mmlevel == GF_CODEC_LEVEL_SEEK) + if (mmlevel >= GF_CODEC_LEVEL_DROP) unit_size = 0; UnlockCompositionUnit(codec, CU, unit_size); - if (!ch || !AU) return GF_OK; - + if (!ch || !AU) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] Exit decode loop because no more input data\n", codec->decio->module_name)); + return GF_OK; + } /*escape from decoding loop only if above critical limit - this is to avoid starvation on audio*/ if (!ch->esd->dependsOnESID && (codec->CB->UnitCount > codec->CB->Min)) { now = gf_term_get_time(codec->odm->term); if (now - entryTime >= TimeAvailable) { + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] Exit decode loop because time is up: %d vs %d available\n", codec->decio->module_name, now - entryTime, TimeAvailable)); return GF_OK; } } Decoder_GetNextAU(codec, &ch, &AU); if (!ch || !AU) return GF_OK; - } + } return GF_OK; } @@ -976,7 +1004,7 @@ GF_Err gf_codec_process_ocr(GF_Codec *codec, u32 TimeAvailable) if (!AU || !ch) { /*if the codec is in EOS state, move to STOP*/ if (codec->Status == GF_ESM_CODEC_EOS) { - gf_term_stop_codec(codec); + gf_term_stop_codec(codec, 0); #ifndef GPAC_DISABLE_VRML /*if a mediacontrol is ruling this OCR*/ if (codec->odm->media_ctrl && codec->odm->media_ctrl->control->loop) mediacontrol_restart(codec->odm); diff --git a/src/terminal/input_sensor.c b/src/terminal/input_sensor.c index a79f127..7c60f57 100644 --- a/src/terminal/input_sensor.c +++ b/src/terminal/input_sensor.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/input_sensor.h b/src/terminal/input_sensor.h index 949719d..7333654 100644 --- a/src/terminal/input_sensor.h +++ b/src/terminal/input_sensor.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/media_control.c b/src/terminal/media_control.c index d7284e7..1df75e8 100644 --- a/src/terminal/media_control.c +++ b/src/terminal/media_control.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -223,6 +224,7 @@ void MC_GetRange(MediaControlStack *ctrl, Double *start_range, Double *end_range u32 i; Double duration; GF_Segment *last_seg, *prev_seg; + if (gf_list_count(ctrl->seg)) { GF_Segment *desc = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg); if (!desc) { @@ -292,7 +294,7 @@ void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy) need_restart = (stack->changed==2) ? 1 : 0; shall_restart = (stack->control->mediaStartTime>=0) ? 1 : 0; - + /*check url target*/ if (stack->stream) { if (MC_URLChanged(&stack->url, &stack->control->url)) { @@ -314,6 +316,7 @@ void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy) /*remove from prev*/ if (prev && prev->odm && (prev != stack->stream)) gf_odm_remove_mediacontrol(prev->odm, stack); /*register with new*/ + /*if we assigned the media control to an exiting object - force the state of the object*/ gf_odm_set_mediacontrol((GF_ObjectManager *) stack->stream->odm, stack); while (gf_list_count(stack->seg)) gf_list_rem(stack->seg, 0); @@ -389,7 +392,7 @@ void RenderMediaControl(GF_Node *node, void *rs, Bool is_destroy) stack->is_init = 1; /*the object has already been started, and media start time is not 0, restart*/ if (stack->stream->num_open) { - if (stack->media_start > 0) { + if ( (stack->media_start > 0) || (gf_list_count(stack->seg)>0 ) ) { mediacontrol_restart(odm); } else if (stack->media_speed == 0) { mediacontrol_pause(odm); @@ -535,7 +538,12 @@ void gf_odm_remove_mediacontrol(GF_ObjectManager *odm, MediaControlStack *ctrl) { gf_list_del_item(odm->mc_stack, ctrl); /*removed. Note the spec doesn't say what to do in this case...*/ - if (odm->media_ctrl == ctrl) gf_odm_set_mediacontrol(odm, NULL); + if (odm->media_ctrl == ctrl) { + /*we're about to release the media control from this object - if paused, force a resume (as if no MC was set)*/ + if (ctrl->paused) + mediacontrol_resume(odm); + gf_odm_set_mediacontrol(odm, NULL); + } } Bool gf_odm_switch_mediacontrol(GF_ObjectManager *odm, MediaControlStack *ctrl) diff --git a/src/terminal/media_control.h b/src/terminal/media_control.h index 0f8ef6d..a991e1f 100644 --- a/src/terminal/media_control.h +++ b/src/terminal/media_control.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/media_manager.c b/src/terminal/media_manager.c index 86d7538..21d782d 100644 --- a/src/terminal/media_manager.c +++ b/src/terminal/media_manager.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -137,6 +138,8 @@ void gf_term_add_codec(GF_Terminal *term, GF_Codec *codec) GF_SAFEALLOC(cd, CodecEntry); cd->dec = codec; + if (!cd->dec->Priority) + cd->dec->Priority = 1; cap.CapCode = GF_CODEC_WANTS_THREAD; cap.cap.valueInt = 0; @@ -309,9 +312,9 @@ static u32 MM_SimulationStep_Decoder(GF_Terminal *term) /*avoid signaling errors too often...*/ #ifndef GPAC_DISABLE_LOG if (e) { - GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM%d] Decoding Error %s\n", ce->dec->odm->OD->objectDescriptorID, gf_error_to_string(e) )); + GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODM%d] Decoding Error %s\n", ce->dec->odm->OD->objectDescriptorID, gf_error_to_string(e) )); } else { - GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[%s] Decode time slice %d ms out of %d ms\n", ce->dec->decio ? ce->dec->decio->module_name : "RAW", time_taken, time_left )); + GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[%s] Decode time slice %d ms out of %d ms\n", ce->dec->decio ? ce->dec->decio->module_name : "RAW", time_taken, time_left )); } #endif if (ce->flags & GF_MM_CE_DISCRADED) { @@ -415,7 +418,7 @@ u32 RunSingleDec(void *ptr) /*NOTE: when starting/stoping a decoder we only lock the decoder mutex, NOT the media manager. This avoids deadlocking in case a system codec waits for the scene graph and the compositor requests a stop/start on a media*/ -void gf_term_start_codec(GF_Codec *codec) +void gf_term_start_codec(GF_Codec *codec, Bool is_resume) { GF_CodecCapability cap; CodecEntry *ce; @@ -429,13 +432,15 @@ void gf_term_start_codec(GF_Codec *codec) /*clean decoder memory and wait for RAP*/ if (codec->CB) gf_cm_reset(codec->CB); - cap.CapCode = GF_CODEC_WAIT_RAP; - gf_codec_set_capability(codec, cap); - - if (codec->decio && (codec->decio->InterfaceType == GF_SCENE_DECODER_INTERFACE)) { - cap.CapCode = GF_CODEC_SHOW_SCENE; - cap.cap.valueInt = 1; + if (!is_resume) { + cap.CapCode = GF_CODEC_WAIT_RAP; gf_codec_set_capability(codec, cap); + + if (codec->decio && (codec->decio->InterfaceType == GF_SCENE_DECODER_INTERFACE)) { + cap.CapCode = GF_CODEC_SHOW_SCENE; + cap.cap.valueInt = 1; + gf_codec_set_capability(codec, cap); + } } gf_codec_set_status(codec, GF_ESM_CODEC_PLAY); @@ -455,7 +460,7 @@ void gf_term_start_codec(GF_Codec *codec) gf_mx_v(ce->mx); } -void gf_term_stop_codec(GF_Codec *codec) +void gf_term_stop_codec(GF_Codec *codec, Bool is_pause) { GF_CodecCapability cap; Bool locked = 0; @@ -477,15 +482,17 @@ void gf_term_stop_codec(GF_Codec *codec) locked = gf_mx_try_lock(term->mm_mx); } - cap.CapCode = GF_CODEC_ABORT; - cap.cap.valueInt = 0; - gf_codec_set_capability(codec, cap); - - if (codec->decio && codec->odm->mo && (codec->odm->mo->flags & GF_MO_DISPLAY_REMOVE) ) { - cap.CapCode = GF_CODEC_SHOW_SCENE; + if (!is_pause) { + cap.CapCode = GF_CODEC_ABORT; cap.cap.valueInt = 0; gf_codec_set_capability(codec, cap); - codec->odm->mo->flags &= ~GF_MO_DISPLAY_REMOVE; + + if (codec->decio && codec->odm->mo && (codec->odm->mo->flags & GF_MO_DISPLAY_REMOVE) ) { + cap.CapCode = GF_CODEC_SHOW_SCENE; + cap.cap.valueInt = 0; + gf_codec_set_capability(codec, cap); + codec->odm->mo->flags &= ~GF_MO_DISPLAY_REMOVE; + } } /*set status directly and don't touch CB state*/ diff --git a/src/terminal/media_memory.c b/src/terminal/media_memory.c index 9a538b5..3903b15 100644 --- a/src/terminal/media_memory.c +++ b/src/terminal/media_memory.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/media_memory.h b/src/terminal/media_memory.h index 5a2d5e3..508e249 100644 --- a/src/terminal/media_memory.h +++ b/src/terminal/media_memory.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/media_object.c b/src/terminal/media_object.c index 1c08338..189dc0b 100644 --- a/src/terminal/media_object.c +++ b/src/terminal/media_object.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -828,7 +829,7 @@ Bool gf_mo_url_changed(GF_MediaObject *mo, MFURL *url) /*special case for 3GPP text: if not playing and user node changed, force removing it*/ if (ret && mo->odm && !mo->num_open && (mo->type == GF_MEDIA_OBJECT_TEXT)) { mo->flags |= GF_MO_DISPLAY_REMOVE; - gf_term_stop_codec(mo->odm->codec); + gf_term_stop_codec(mo->odm->codec, 0); } return ret; } @@ -868,7 +869,7 @@ void gf_mo_set_speed(GF_MediaObject *mo, Fixed speed) ctrl = gf_odm_get_mediacontrol(mo->odm); if (ctrl) return; #endif - if (mo->odm->net_service && (mo->odm->net_service->owner->flags & GF_ODM_INHERIT_TIMELINE)) + if (mo->odm->net_service && mo->odm->net_service->owner && (mo->odm->net_service->owner->flags & GF_ODM_INHERIT_TIMELINE)) return; gf_odm_set_speed(mo->odm, speed); } diff --git a/src/terminal/media_sensor.c b/src/terminal/media_sensor.c index 4988b47..40935ff 100644 --- a/src/terminal/media_sensor.c +++ b/src/terminal/media_sensor.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -115,6 +116,24 @@ void MS_Modified(GF_Node *node) gf_term_invalidate_compositor(st->parent->root_od->term); } + +static void media_sensor_activate(MediaSensorStack *media_sens, GF_Segment *desc) +{ + media_sens->sensor->isActive = 1; + gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); + /*set info*/ + gf_sg_vrml_mf_reset(& media_sens->sensor->info, GF_SG_VRML_MFSTRING); + gf_sg_vrml_mf_alloc(& media_sens->sensor->info, GF_SG_VRML_MFSTRING, 1); + media_sens->sensor->info.vals[0] = desc->SegmentName ? gf_strdup(desc->SegmentName) : NULL; + gf_node_event_out((GF_Node *) media_sens->sensor, 5/*"info"*/); + /*set duration*/ + media_sens->sensor->mediaDuration = desc->Duration; + gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/); + /*set seg start time*/ + media_sens->sensor->streamObjectStartTime = desc->startTime; + gf_node_event_out((GF_Node *) media_sens->sensor, 2/*"streamObjectStartTime"*/); +} + void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos) { GF_Segment *desc; @@ -152,6 +171,8 @@ void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos) if (!is_eos && !media_sens->sensor->isActive) { media_sens->sensor->isActive = 1; + gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); + gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); if (odm->subscene) { media_sens->sensor->mediaDuration = (Double) (s64)odm->subscene->duration; @@ -195,7 +216,7 @@ void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos) GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g - segment %s\n", odm->OD->objectDescriptorID, time, desc->SegmentName)); } - break; + continue; } if (desc->startTime + desc->Duration < time) continue; if (desc->startTime + desc->Duration == time) { @@ -208,22 +229,11 @@ void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos) } if (!media_sens->sensor->isActive) { - media_sens->sensor->isActive = 1; - gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); - /*set info*/ - gf_sg_vrml_mf_reset(& media_sens->sensor->info, GF_SG_VRML_MFSTRING); - gf_sg_vrml_mf_alloc(& media_sens->sensor->info, GF_SG_VRML_MFSTRING, 1); - media_sens->sensor->info.vals[0] = desc->SegmentName ? gf_strdup(desc->SegmentName) : NULL; - gf_node_event_out((GF_Node *) media_sens->sensor, 5/*"info"*/); - /*set duration*/ - media_sens->sensor->mediaDuration = desc->Duration; - gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/); - /*set seg start time*/ - media_sens->sensor->streamObjectStartTime = desc->startTime; - gf_node_event_out((GF_Node *) media_sens->sensor, 2/*"streamObjectStartTime"*/); + media_sensor_activate(media_sens, desc); GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Activating media sensor time %g - segment %s\n", odm->OD->objectDescriptorID, time, desc->SegmentName)); } + /*set media time - relative to segment start time*/ time -= desc->startTime; if (media_sens->sensor->mediaCurrentTime != time) { diff --git a/src/terminal/mpeg4_inline.c b/src/terminal/mpeg4_inline.c index 6a2b556..d7c0572 100644 --- a/src/terminal/mpeg4_inline.c +++ b/src/terminal/mpeg4_inline.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -328,14 +329,15 @@ static void gf_inline_traverse(GF_Node *n, void *rs, Bool is_destroy) } -static Bool gf_inline_is_hardcoded_proto(MFURL *url, GF_Config *cfg) +static Bool gf_inline_is_hardcoded_proto(GF_Terminal *term, MFURL *url) { u32 i; - const char *sOpt = gf_cfg_get_key(cfg, "Systems", "hardcoded_protos"); for (i=0; icount; i++) { if (!url->vals[i].url) continue; if (strstr(url->vals[i].url, "urn:inet:gpac:builtin")) return 1; - if (sOpt && strstr(sOpt, url->vals[i].url)) return 1; + + if (gf_sc_uri_is_hardcoded_proto(term->compositor, url->vals[i].url)) + return 1; } return 0; } @@ -347,7 +349,7 @@ GF_SceneGraph *gf_inline_get_proto_lib(void *_is, MFURL *lib_url) GF_Scene *scene = (GF_Scene *) _is; if (!scene || !lib_url->count) return NULL; - if (gf_inline_is_hardcoded_proto(lib_url, scene->root_od->term->user->config)) return GF_SG_INTERNAL_PROTO; + if (gf_inline_is_hardcoded_proto(scene->root_od->term, lib_url)) return GF_SG_INTERNAL_PROTO; i=0; while ((pl = (GF_ProtoLink*)gf_list_enum(scene->extern_protos, &i))) { @@ -395,7 +397,7 @@ GF_SceneGraph *gf_inline_get_proto_lib(void *_is, MFURL *lib_url) if (!lib_url || !lib_url->count) return NULL; /*internal, don't waste ressources*/ - if (gf_inline_is_hardcoded_proto(lib_url, scene->root_od->term->user->config)) return NULL; + if (gf_inline_is_hardcoded_proto(scene->root_od->term, lib_url)) return NULL; i=0; while ((pl = (GF_ProtoLink*)gf_list_enum(scene->extern_protos, &i)) ) { diff --git a/src/terminal/network_service.c b/src/terminal/network_service.c index 10bc92c..3b56074 100644 --- a/src/terminal/network_service.c +++ b/src/terminal/network_service.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -218,7 +219,7 @@ static void term_on_disconnect(void *user_priv, GF_ClientService *service, LPNET if (service->subservice_disconnect) { if (service->owner && service->subservice_disconnect==1) { GF_Scene *scene = service->owner->subscene ? service->owner->subscene : service->owner->parentscene; - /*destrou all media*/ + /*destroy all media*/ gf_scene_disconnect(scene, 1); } return; @@ -501,7 +502,7 @@ static void term_on_command(void *user_priv, GF_ClientService *service, GF_Netwo } } gf_mx_v(term->mm_mx); -// fprintf(stdout, "Buffer occupancy %d\n", com->buffer.occupancy); +// fprintf(stderr, "Buffer occupancy %d\n", com->buffer.occupancy); if (com->buffer.occupancy==(u32) -1) com->buffer.occupancy = 0; return; } @@ -730,7 +731,7 @@ static GF_InputService *gf_term_can_handle_service(GF_Terminal *term, const char if (sPlug) sPlug = strrchr(sPlug, '"'); if (sPlug) { sPlug += 2; - GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("%s:%d FOUND matching module %s\n", __FILE__, __LINE__, sPlug)); + GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("%s:%d FOUND matching module %s\n", __FILE__, __LINE__, sPlug)); ifce = (GF_InputService *) gf_modules_load_interface_by_name(term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); if (force_module && ifce && !strstr(ifce->module_name, force_module)) { gf_modules_close_interface((GF_BaseInterface *) ifce); @@ -1123,7 +1124,8 @@ void gf_term_download_update_stats(GF_DownloadSession * sess) GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size)); gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec); - if ( (serv->download_rebuffer || serv->auto_rebuffer) && serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) { + /*JLF fix this*/ + if (0&& (serv->download_rebuffer || serv->auto_rebuffer) && serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) { GF_Clock *ck = gf_odm_get_media_clock(serv->owner); Double download_percent, playback_percent, adj_percent; download_percent = 100 * bytes_done; diff --git a/src/terminal/object_browser.c b/src/terminal/object_browser.c index a034b2c..e5772a6 100644 --- a/src/terminal/object_browser.c +++ b/src/terminal/object_browser.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/object_manager.c b/src/terminal/object_manager.c index c0467ed..da429aa 100644 --- a/src/terminal/object_manager.c +++ b/src/terminal/object_manager.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -282,7 +283,7 @@ void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove) void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url) { u32 od_type; - char *ext; + char *ext, *redirect_url; char *sub_url = (char *) service_sub_url; GF_Descriptor *desc; @@ -334,6 +335,7 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url } } + redirect_url = NULL; switch (desc->tag) { case GF_ODF_IOD_TAG: { @@ -349,6 +351,8 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url odm->Visual_PL = the_iod->visual_profileAndLevel; odm->flags |= GF_ODM_HAS_PROFILES; if (the_iod->inlineProfileFlag) odm->flags |= GF_ODM_INLINE_PROFILES; + redirect_url = the_iod->URLString; + odm->OD->URLString = NULL; gf_odf_desc_del((GF_Descriptor *) the_iod->IPMPToolList); gf_free(the_iod); } @@ -356,6 +360,8 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url case GF_ODF_OD_TAG: odm->Audio_PL = odm->Graphics_PL = odm->OD_PL = odm->Scene_PL = odm->Visual_PL = (u8) -1; odm->OD = (GF_ObjectDescriptor *)desc; + redirect_url = odm->OD->URLString; + odm->OD->URLString = NULL; break; default: gf_term_message(odm->term, odm->net_service->url, "MPEG4 Service Setup Failure", GF_ODF_INVALID_DESCRIPTOR); @@ -364,10 +370,17 @@ void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url gf_odm_setup_object(odm, odm->net_service); + if (redirect_url && !strnicmp(redirect_url, "views://", 8)) { + + gf_scene_generate_views(odm->subscene ? odm->subscene : odm->parentscene , (char *) redirect_url + 8, (char*)odm->parentscene ? odm->parentscene->root_od->net_service->url : NULL); + } /*it may happen that this object was inserted in a dynamic scene from a service through a URL redirect. In which case, the scene regeneration might not have been completed since the redirection was not done yet - force a scene regenerate*/ - if (odm->parentscene && odm->parentscene->is_dynamic_scene) + else if (odm->parentscene && odm->parentscene->is_dynamic_scene) gf_scene_regenerate(odm->parentscene); + + + gf_free(redirect_url); return; err_exit: @@ -377,6 +390,8 @@ err_exit: evt.connect.is_connected = 0; gf_term_send_event(odm->term, &evt); } + if (redirect_url) + gf_free(redirect_url); } @@ -591,6 +606,7 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv) if (odm->OD->URLString) { GF_ClientService *parent = odm->net_service; char *url = odm->OD->URLString; + char *parent_url = NULL; odm->OD->URLString = NULL; /*store original OD ID */ if (!odm->current_time) odm->current_time = odm->OD->objectDescriptorID; @@ -608,7 +624,11 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv) odm->subscene = gf_scene_new(odm->parentscene); odm->subscene->root_od = odm; } - gf_term_post_connect_object(odm->term, odm, url, parent ? parent->url : NULL); + parent_url = parent ? parent->url : NULL; + if (parent_url && !strnicmp(parent_url, "views://", 8)) + parent_url = NULL; + + gf_term_post_connect_object(odm->term, odm, url, parent_url); gf_free(url); gf_term_lock_net(odm->term, 0); return; @@ -744,7 +764,7 @@ void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv) } if (force_play) { odm->flags |= GF_ODM_INITIAL_BROADCAST_PLAY; - GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Inserted from broadcast - forcing play\n", odm->OD->objectDescriptorID)); + GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Inserted from broadcast or input service - forcing play\n", odm->OD->objectDescriptorID)); gf_odm_start(odm, 2); } } @@ -1187,7 +1207,7 @@ GF_Err gf_odm_post_es_setup(GF_Channel *ch, GF_Codec *dec, GF_Err had_err) com.play.start_range /= 1000; com.play.end_range = -1.0; gf_term_service_command(ch->service, &com); - if (dec && (dec->Status!=GF_ESM_CODEC_PLAY)) gf_term_start_codec(dec); + if (dec && (dec->Status!=GF_ESM_CODEC_PLAY)) gf_term_start_codec(dec, 0); gf_term_lock_net(ch->odm->term, 0); } return GF_OK; @@ -1354,6 +1374,7 @@ void gf_odm_play(GF_ObjectManager *odm) u32 nb_failure; u64 range_end; Bool skip_od_st; + Bool media_control_paused = 0; GF_NetworkCommand com; #ifndef GPAC_DISABLE_VRML MediaControlStack *ctrl; @@ -1449,6 +1470,8 @@ void gf_odm_play(GF_ObjectManager *odm) if ((ch->esd->ESID!=ch->clock->clockID) && (ck_time>com.play.start_range) && (com.play.end_range>com.play.start_range) && (ck_timepaused) media_control_paused = 1; + gf_clock_set_speed(ch->clock, ctrl->control->mediaSpeed); /*if requested seek time AND media control, adjust start range to current play time*/ if (odm->media_start_time) { @@ -1504,20 +1527,23 @@ void gf_odm_play(GF_ObjectManager *odm) /*start codecs last (otherwise we end up pulling data from channels not yet connected->pbs when seeking)*/ if (odm->codec) { - gf_term_start_codec(odm->codec); + gf_term_start_codec(odm->codec, 0); } else if (odm->subscene) { - if (odm->subscene->scene_codec) gf_term_start_codec(odm->subscene->scene_codec); - if (!skip_od_st && odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec); + if (odm->subscene->scene_codec) gf_term_start_codec(odm->subscene->scene_codec, 0); + if (!skip_od_st && odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec, 0); if (odm->flags & GF_ODM_REGENERATE_SCENE) { odm->flags &= ~GF_ODM_REGENERATE_SCENE; gf_scene_regenerate(odm->subscene); } } - if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec); + if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec, 0); #ifndef GPAC_MINIMAL_ODF - if (odm->oci_codec) gf_term_start_codec(odm->oci_codec); + if (odm->oci_codec) gf_term_start_codec(odm->oci_codec, 0); #endif + + if (media_control_paused) + gf_odm_pause(odm); } Bool gf_odm_owns_clock(GF_ObjectManager *odm, GF_Clock *ck) @@ -1578,7 +1604,7 @@ void gf_odm_stop(GF_ObjectManager *odm, Bool force_close) while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { gf_es_stop(ch); } - gf_term_stop_codec(odm->codec); + gf_term_stop_codec(odm->codec, 0); /*and wait until frame has been consumed by the renderer we don't use semaphore wait as the raw channel may already be pending on the semaphore*/ while (odm->codec->CB->UnitCount) { @@ -1597,21 +1623,21 @@ void gf_odm_stop(GF_ObjectManager *odm, Bool force_close) if (force_close && odm->mo) odm->mo->flags |= GF_MO_DISPLAY_REMOVE; /*stop codecs*/ if (odm->codec) { - gf_term_stop_codec(odm->codec); + gf_term_stop_codec(odm->codec, 0); } else if (odm->subscene) { u32 i=0; GF_ObjectManager *sub_odm; - if (odm->subscene->scene_codec) gf_term_stop_codec(odm->subscene->scene_codec); - if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec); + if (odm->subscene->scene_codec) gf_term_stop_codec(odm->subscene->scene_codec, 0); + if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec, 0); /*stops all resources of the subscene as well*/ while ((sub_odm=(GF_ObjectManager *)gf_list_enum(odm->subscene->resources, &i))) { gf_odm_stop(sub_odm, force_close); } } - if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec); + if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec, 0); #ifndef GPAC_MINIMAL_ODF - if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec); + if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec, 0); #endif // gf_term_lock_net(odm->term, 1); @@ -1780,18 +1806,18 @@ void gf_odm_pause(GF_ObjectManager *odm) /*stop codecs, and update status for media codecs*/ if (odm->codec) { - gf_term_stop_codec(odm->codec); + gf_term_stop_codec(odm->codec, 1); gf_codec_set_status(odm->codec, GF_ESM_CODEC_PAUSE); } else if (odm->subscene) { if (odm->subscene->scene_codec) { gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_PAUSE); - gf_term_stop_codec(odm->subscene->scene_codec); + gf_term_stop_codec(odm->subscene->scene_codec, 1); } - if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec); + if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec, 1); } - if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec); + if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec, 1); #ifndef GPAC_MINIMAL_ODF - if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec); + if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec, 1); #endif com.command_type = GF_NET_CHAN_PAUSE; @@ -1800,6 +1826,7 @@ void gf_odm_pause(GF_ObjectManager *odm) gf_clock_pause(ch->clock); com.base.on_channel = ch; gf_term_service_command(ch->service, &com); + GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] CH%d: At OTB %d requesting PAUSE (clock init %d)\n", odm->OD->objectDescriptorID, ch->esd->ESID, gf_clock_time(ch->clock), ch->clock->clock_init )); } #ifndef GPAC_DISABLE_VRML @@ -1822,6 +1849,7 @@ void gf_odm_resume(GF_ObjectManager *odm) GF_Channel *ch; #ifndef GPAC_DISABLE_VRML MediaSensorStack *media_sens; + MediaControlStack *ctrl; #endif if (odm->flags & GF_ODM_NO_TIME_CTRL) return; @@ -1829,26 +1857,33 @@ void gf_odm_resume(GF_ObjectManager *odm) /*start codecs, and update status for media codecs*/ if (odm->codec) { - gf_term_start_codec(odm->codec); + gf_term_start_codec(odm->codec, 1); gf_codec_set_status(odm->codec, GF_ESM_CODEC_PLAY); } else if (odm->subscene) { if (odm->subscene->scene_codec) { gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_PLAY); - gf_term_start_codec(odm->subscene->scene_codec); + gf_term_start_codec(odm->subscene->scene_codec, 1); } - if (odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec); + if (odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec, 1); } - if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec); + if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec, 1); #ifndef GPAC_MINIMAL_ODF - if (odm->oci_codec) gf_term_start_codec(odm->oci_codec); + if (odm->oci_codec) gf_term_start_codec(odm->oci_codec, 1); #endif + ctrl = gf_odm_get_mediacontrol(odm); com.command_type = GF_NET_CHAN_RESUME; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ){ gf_clock_resume(ch->clock); com.base.on_channel = ch; gf_term_service_command(ch->service, &com); + GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] CH%d: At OTB %d requesting RESUME (clock init %d)\n", odm->OD->objectDescriptorID, ch->esd->ESID, gf_clock_time(ch->clock), ch->clock->clock_init )); + + /*override speed with MC*/ + if (ctrl) { + gf_clock_set_speed(ch->clock, ctrl->control->mediaSpeed); + } } #ifndef GPAC_DISABLE_VRML diff --git a/src/terminal/scene.c b/src/terminal/scene.c index ef8e6b3..64cfe1f 100644 --- a/src/terminal/scene.c +++ b/src/terminal/scene.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -270,6 +271,7 @@ void gf_scene_disconnect(GF_Scene *scene, Bool for_shutdown) if (dec && dec->ReleaseScene) dec->ReleaseScene(dec); gf_sg_reset(scene->graph); scene->graph_attached = 0; + scene->simulation_time = 0; /*reset statc ressource flag since we destroyed scene objects*/ @@ -1545,9 +1547,10 @@ GF_SceneGraph *gf_scene_enum_extra_scene(GF_SceneGraph *sg, u32 *i) #define USE_TEXTURES 0 -void gf_scene_generate_views(GF_Scene *scene, char *url) +void gf_scene_generate_views(GF_Scene *scene, char *url, char *parent_path) { char *url_search; + Bool use_old_syntax = 1; GF_Node *n1, *switcher; #if USE_TEXTURES GF_Node *n2; @@ -1568,16 +1571,24 @@ void gf_scene_generate_views(GF_Scene *scene, char *url) gf_node_list_add_child( &((GF_ParentNode *)n1)->children, switcher); ((M_Switch*)switcher)->whichChoice = -2; + if (strstr(url, "::")) use_old_syntax = 0; + url_search = url; while (1) { - char *sep = strchr(url_search, ':'); - /*if :// or :\ is found, skip it*/ - if (sep && ( ((sep[1] == '/') && (sep[2] == '/')) || (sep[1] == '\\') ) ) { - url_search = sep+1; - continue; + char *sep; + + if (use_old_syntax) { + sep = strchr(url_search, ':'); + /*if :// or :\ is found, skip it*/ + if (sep && ( ((sep[1] == '/') && (sep[2] == '/')) || (sep[1] == '\\') ) ) { + url_search = sep+1; + continue; + } + } else { + sep = strstr(url_search, "::"); } - if (sep) sep[0] = 0; + #if USE_TEXTURES /*create a shape and bitmap node*/ n2 = is_create_node(scene->graph, TAG_MPEG4_Shape, NULL); @@ -1600,7 +1611,7 @@ void gf_scene_generate_views(GF_Scene *scene, char *url) gf_sg_vrml_mf_reset(&mt->url, GF_SG_VRML_MFURL); gf_sg_vrml_mf_append(&mt->url, GF_SG_VRML_MFURL, NULL); - mt->url.vals[0].url = gf_strdup(url); + mt->url.vals[0].url = gf_url_concatenate(parent_path, url); #else inl = (M_Inline *) is_create_node(scene->graph, TAG_MPEG4_Inline, NULL); gf_node_list_add_child( &((M_Switch *)switcher)->choice, (GF_Node *)inl); @@ -1608,12 +1619,16 @@ void gf_scene_generate_views(GF_Scene *scene, char *url) gf_sg_vrml_mf_reset(&inl->url, GF_SG_VRML_MFURL); gf_sg_vrml_mf_append(&inl->url, GF_SG_VRML_MFURL, NULL); - inl->url.vals[0].url = gf_strdup(url); + inl->url.vals[0].url = gf_url_concatenate(parent_path, url); #endif if (!sep) break; sep[0] = ':'; - url = sep+1; + if (use_old_syntax) { + url = sep+1; + } else { + url = sep+2; + } url_search = url; } diff --git a/src/terminal/svg_external.c b/src/terminal/svg_external.c index 3c89af8..9fa8b06 100644 --- a/src/terminal/svg_external.c +++ b/src/terminal/svg_external.c @@ -2,7 +2,7 @@ * GPAC - Multimedia Framework C SDK * * Authors: Cyril Concolato - Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / SVG Rendering sub-project diff --git a/src/terminal/term_node_init.c b/src/terminal/term_node_init.c index 7f4556f..75502bc 100644 --- a/src/terminal/term_node_init.c +++ b/src/terminal/term_node_init.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index b68b308..062010a 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / Media terminal sub-project @@ -465,9 +466,10 @@ static void gf_term_connect_from_time_ex(GF_Terminal * term, const char *URL, u6 if (!strnicmp(URL, "views://", 8)) { odm->OD = (GF_ObjectDescriptor *)gf_odf_desc_new(GF_ODF_OD_TAG); - gf_scene_generate_views(term->root_scene, (char *) URL+8); + gf_scene_generate_views(term->root_scene, (char *) URL+8, (char*)parent_path); return; } + /*connect - we don't have any parentID */ gf_term_connect_object(term, odm, (char *) URL, (char*)parent_path); } diff --git a/src/utils/alloc.c b/src/utils/alloc.c index 83bf5cf..616ef2b 100644 --- a/src/utils/alloc.c +++ b/src/utils/alloc.c @@ -3,7 +3,6 @@ * * Authors: Romain Bouqueau - Jean Le Feuvre * Copyright (c) Telecom ParisTech 2010-20XX - * * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -299,37 +298,44 @@ static void *(*gf_mem_realloc_proto)(void *ptr, size_t size, char *filename, int static void (*gf_mem_free_proto)(void *ptr, char *filename, int line) = gf_mem_free_basic; static char *(*gf_mem_strdup_proto)(const char *str, char *filename, int line) = gf_mem_strdup_basic; -SYMBOL_EXPORT CDECL -void *gf_mem_malloc(size_t size, char *filename, int line) +#ifndef MY_GF_EXPORT +#if defined(__GNUC__) && __GNUC__ >= 4 +#define GF_EXPORT __attribute__((visibility("default"))) +#else +/*use def files for windows or let compiler decide*/ +#define MY_GF_EXPORT +#endif +#endif + +MY_GF_EXPORT void *gf_mem_malloc(size_t size, char *filename, int line) { return gf_mem_malloc_proto(size, filename, line); } -SYMBOL_EXPORT CDECL -void *gf_mem_calloc(size_t num, size_t size_of, char *filename, int line) +MY_GF_EXPORT void *gf_mem_calloc(size_t num, size_t size_of, char *filename, int line) { return gf_mem_calloc_proto(num, size_of, filename, line); } -SYMBOL_EXPORT CDECL +MY_GF_EXPORT void *gf_mem_realloc(void *ptr, size_t size, char *filename, int line) { return gf_mem_realloc_proto(ptr, size, filename, line); } -SYMBOL_EXPORT CDECL +MY_GF_EXPORT void gf_mem_free(void *ptr, char *filename, int line) { gf_mem_free_proto(ptr, filename, line); } -SYMBOL_EXPORT CDECL +MY_GF_EXPORT char *gf_mem_strdup(const char *str, char *filename, int line) { return gf_mem_strdup_proto(str, filename, line); } -CDECL +MY_GF_EXPORT void gf_mem_enable_tracker() { gf_mem_malloc_proto = gf_mem_malloc_tracker; diff --git a/src/utils/base_encoding.c b/src/utils/base_encoding.c index 3f8907c..cb92a1b 100644 --- a/src/utils/base_encoding.c +++ b/src/utils/base_encoding.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -132,11 +133,6 @@ u32 gf_base64_decode(char *in_buf, u32 inSize, char *out, u32 outSize) return j; } - -/* - * Copyright (c) ENST 2004 - Philippe de Cuetos - */ - static const char base_16[] = "0123456789abcdef"; GF_EXPORT @@ -269,4 +265,4 @@ GF_Err gf_gz_decompress_payload(char *data, u32 data_len, char **uncompressed_da *uncompressed_data = NULL; } return e; -} \ No newline at end of file +} diff --git a/src/utils/bitstream.c b/src/utils/bitstream.c index 5091850..f59fcf7 100644 --- a/src/utils/bitstream.c +++ b/src/utils/bitstream.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -56,6 +57,10 @@ struct __tag_bitstream void (*EndOfStream)(void *par); void *par; + + + char *buffer_io; + u32 buffer_io_size, buffer_written; }; @@ -137,12 +142,47 @@ GF_BitStream *gf_bs_from_file(FILE *f, u32 mode) return tmp; } +static void bs_flush_cache(GF_BitStream *bs) +{ + if (bs->buffer_written) { + u32 nb_write = fwrite(bs->buffer_io, 1, bs->buffer_written, bs->stream); + bs->size += nb_write; + bs->position += nb_write; + bs->buffer_written = 0; + } +} + + +GF_EXPORT +GF_Err gf_bs_set_output_buffering(GF_BitStream *bs, u32 size) +{ + if (!bs->stream) return GF_OK; + if (bs->bsmode != GF_BITSTREAM_FILE_WRITE) { + return GF_OK; + } + bs_flush_cache(bs); + bs->buffer_io = gf_realloc(bs->buffer_io, size); + if (!bs->buffer_io) return GF_IO_ERR; + bs->buffer_io_size = size; + bs->buffer_written = 0; + return GF_OK; +} + + +GF_EXPORT +u32 gf_bs_get_output_buffering(GF_BitStream *bs) +{ + return bs ? bs->buffer_io_size : 0; +} + GF_EXPORT void gf_bs_del(GF_BitStream *bs) { if (!bs) return; /*if we are in dynamic mode (alloc done by the bitstream), free the buffer if still present*/ if ((bs->bsmode == GF_BITSTREAM_WRITE_DYN) && bs->original) gf_free(bs->original); + if (bs->buffer_io) + bs_flush_cache(bs); gf_free(bs); } @@ -170,6 +210,9 @@ static u8 BS_ReadByte(GF_BitStream *bs) } return (u32) bs->original[bs->position++]; } + if (bs->buffer_io) + bs_flush_cache(bs); + /*we are in FILE mode, test for end of file*/ if (!feof(bs->stream)) { bs->position++; @@ -336,6 +379,8 @@ u32 gf_bs_read_data(GF_BitStream *bs, char *data, u32 nbBytes) return nbBytes; case GF_BITSTREAM_FILE_READ: case GF_BITSTREAM_FILE_WRITE: + if (bs->buffer_io) + bs_flush_cache(bs); nbBytes = fread(data, 1, nbBytes, bs->stream); bs->position += nbBytes; return nbBytes; @@ -374,6 +419,14 @@ static void BS_WriteByte(GF_BitStream *bs, u8 val) bs->position++; return; } + if (bs->buffer_io && (bs->buffer_writtenbuffer_io_size)) { + bs->buffer_io[bs->buffer_written] = val; + bs->buffer_written++; + if (bs->buffer_written == bs->buffer_io_size) { + bs_flush_cache(bs); + } + return; + } /*we are in FILE mode, no pb for any gf_realloc...*/ fputc(val, bs->stream); /*check we didn't rewind the stream*/ @@ -462,7 +515,7 @@ void gf_bs_write_u64(GF_BitStream *bs, u64 value) GF_EXPORT u32 gf_bs_write_byte(GF_BitStream *bs, u8 byte, u32 repeat_count) { - if (!BS_IsAlign(bs)) { + if (!BS_IsAlign(bs) || bs->buffer_io) { u32 count = 0; while (countstream) != repeat_count) return 0; if (bs->size == bs->position) bs->size += repeat_count; bs->position += repeat_count; @@ -564,6 +618,18 @@ u32 gf_bs_write_data(GF_BitStream *bs, const char *data, u32 nbBytes) return nbBytes; case GF_BITSTREAM_FILE_READ: case GF_BITSTREAM_FILE_WRITE: + if (bs->buffer_io) { + if (bs->buffer_written + nbBytes > bs->buffer_io_size) { + bs_flush_cache(bs); + if (nbBytes>bs->buffer_io_size) { + bs->buffer_io = gf_realloc(bs->buffer_io, 2*nbBytes); + bs->buffer_io_size = 2*nbBytes; + } + } + memcpy(bs->buffer_io+bs->buffer_written, data, nbBytes); + bs->buffer_written+=nbBytes; + return nbBytes; + } if (gf_fwrite(data, nbBytes, 1, bs->stream) != 1) return 0; if (bs->size == bs->position) bs->size += nbBytes; bs->position += nbBytes; @@ -622,6 +688,9 @@ u64 gf_bs_available(GF_BitStream *bs) /*FILE READ: assume size hasn't changed, otherwise the user shall call gf_bs_get_refreshed_size*/ if (bs->bsmode==GF_BITSTREAM_FILE_READ) return (bs->size - bs->position); + if (bs->buffer_io) + bs_flush_cache(bs); + cur = gf_f64_tell(bs->stream); gf_f64_seek(bs->stream, 0, SEEK_END); end = gf_f64_tell(bs->stream); @@ -686,6 +755,8 @@ void gf_bs_skip_bytes(GF_BitStream *bs, u64 nbBytes) /*special case for file skipping...*/ if ((bs->bsmode == GF_BITSTREAM_FILE_WRITE) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) { + if (bs->buffer_io) + bs_flush_cache(bs); gf_f64_seek(bs->stream, nbBytes, SEEK_CUR); bs->position += nbBytes; return; @@ -743,6 +814,9 @@ static GF_Err BS_SeekIntern(GF_BitStream *bs, u64 offset) return GF_OK; } + if (bs->buffer_io) + bs_flush_cache(bs); + gf_f64_seek(bs->stream, offset, SEEK_SET); bs->position = offset; @@ -800,6 +874,8 @@ u64 gf_bs_get_refreshed_size(GF_BitStream *bs) return bs->size; default: + if (bs->buffer_io) + bs_flush_cache(bs); offset = gf_f64_tell(bs->stream); gf_f64_seek(bs->stream, 0, SEEK_END); bs->size = gf_f64_tell(bs->stream); @@ -811,12 +887,16 @@ u64 gf_bs_get_refreshed_size(GF_BitStream *bs) GF_EXPORT u64 gf_bs_get_size(GF_BitStream *bs) { + if (bs->buffer_io) + return bs->size + bs->buffer_written; return bs->size; } GF_EXPORT u64 gf_bs_get_position(GF_BitStream *bs) { + if (bs->buffer_io) + return bs->position + bs->buffer_written; return bs->position; } diff --git a/src/utils/cache.c b/src/utils/cache.c index 56a8471..7b08685 100644 --- a/src/utils/cache.c +++ b/src/utils/cache.c @@ -1,8 +1,8 @@ /* * GPAC Multimedia Framework * -* Authors: Jean Le Feuvre -* Copyright (c) 2005-2005 ENST + * Authors: Pierre Souchay, Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2010-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/color.c b/src/utils/color.c index 75534af..edbbe9c 100644 --- a/src/utils/color.c +++ b/src/utils/color.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -28,20 +29,11 @@ #include -/* original YUV table code from XviD colorspace module */ - -/***************************************************************************** - * - * XVID MPEG-4 VIDEO CODEC - * - colorspace conversion module - - * - * Copyright(C) 2002 Peter Ross - * 2002 Michael Militzer - * - * follows the usual GPL license terms - ****************************************************************************/ +/* YUV -> RGB conversion loading two lines at each call */ #define col_clip(a) MAX(0, MIN(255, a)) +#define SCALEBITS_OUT 13 +#define FIX_OUT(x) ((unsigned short) ((x) * (1L< +#include #include #define MAX_INI_LINE 2046 @@ -200,6 +201,11 @@ GF_Config *gf_cfg_new(const char *filePath, const char* file_name) { GF_Config *tmp = (GF_Config *)gf_malloc(sizeof(GF_Config)); memset((void *)tmp, 0, sizeof(GF_Config)); + if (!filePath && !file_name) { + tmp->sections = gf_list_new(); + return tmp; + } + if (gf_cfg_parse_config_file(tmp, filePath, file_name)){ gf_free( tmp ); tmp = NULL; @@ -224,6 +230,7 @@ GF_Err gf_cfg_save(GF_Config *iniFile) FILE *file; if (!iniFile->hasChanged) return GF_OK; + if (!iniFile->fileName) return GF_OK; file = gf_f64_open(iniFile->fileName, "wt"); if (!file) return GF_IO_ERR; diff --git a/src/utils/downloader.c b/src/utils/downloader.c index b297cb1..bf8f1ff 100644 --- a/src/utils/downloader.c +++ b/src/utils/downloader.c @@ -2,7 +2,7 @@ * GPAC Multimedia Framework * * Authors: Jean Le Feuvre - * Copyright (c) 2005-2005 ENST + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -50,7 +50,7 @@ #define SESSION_RETRY_COUNT 20 #define GF_DOWNLOAD_AGENT_NAME "GPAC/" GPAC_FULL_VERSION -#define GF_DOWNLOAD_BUFFER_SIZE 8192 +#define GF_DOWNLOAD_BUFFER_SIZE 8193 #define GF_WAIT_REPLY_SLEEP 20 @@ -650,18 +650,8 @@ void gf_dm_sess_del(GF_DownloadSession *sess) } if (sess->dm) gf_list_del_item(sess->dm->sessions, sess); - /* - TODO: something to clean an cache files ? - if (sess->cache_name && !sess->use_cache_extension && !(sess->flags & GF_NETIO_SESSION_KEEP_CACHE) ) { - if (sess->dm) - opt = gf_cfg_get_key(sess->dm->cfg, "Downloader", "CleanCache"); - else - opt = NULL; - if (!opt || !stricmp(opt, "yes")) gf_delete_file(sess->cache_name); - gf_free(sess->cache_name); - } - */ - gf_dm_remove_cache_entry_from_session(sess); + + gf_dm_remove_cache_entry_from_session(sess); sess->cache_entry = NULL; if (sess->orig_url) gf_free(sess->orig_url); if (sess->orig_url_before_redirect) gf_free(sess->orig_url_before_redirect); @@ -673,6 +663,8 @@ void gf_dm_sess_del(GF_DownloadSession *sess) if (sess->init_data) gf_free(sess->init_data); sess->orig_url = sess->server_name = sess->remote_path; sess->creds = NULL; + if (sess->sock) + gf_sk_del(sess->sock); gf_free(sess); GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[Downloader] gf_dm_sess_del(%p) : DONE\n", sess )); } @@ -1052,51 +1044,66 @@ static GF_Err gf_dm_read_data(GF_DownloadSession *sess, char *data, u32 data_siz return GF_BAD_PARAM; #ifdef GPAC_HAS_SSL if (sess->ssl) { - u32 size = SSL_read(sess->ssl, data, data_size); - e = GF_OK; - data[size] = 0; - if (!size) e = GF_IP_NETWORK_EMPTY; - *out_read = size; - } else + s32 size = SSL_read(sess->ssl, data, data_size); + if (size < 0) + e = GF_IO_ERR; + else if (!size) + e = GF_IP_NETWORK_EMPTY; + else { + e = GF_OK; + data[size] = 0; + *out_read = size; + } + return e; + } #endif - if (!sess->sock) - return GF_NETIO_DISCONNECTED; - e = gf_sk_receive(sess->sock, data, data_size, 0, out_read); - - return e; + if (!sess->sock) + return GF_NETIO_DISCONNECTED; + return gf_sk_receive(sess->sock, data, data_size, 0, out_read); } #ifdef GPAC_HAS_SSL -/*pattern comp taken from wget*/ -#define ASTERISK_EXCLUDES_DOT /* mandated by rfc2818 */ -#define TOLOWER(x) ('A' <= (x) && (x) <= 'Z' ? (x) - 32 : (x)) +#define LWR(x) ('A' <= (x) && (x) <= 'Z' ? (x) - 32 : (x)) -static Bool pattern_match(const char *pattern, const char *string) +static Bool rfc2818_match(const char *pattern, const char *string) { - const char *p = pattern, *n = string; - char c; - for (; (c = TOLOWER (*p++)) != '\0'; n++) { - if (c == '*') { - for (c = TOLOWER (*p); c == '*'; c = TOLOWER (*++p)) - ; - for (; *n != '\0'; n++) - if (TOLOWER (*n) == c && pattern_match (p, n)) + char c, d; + u32 i=0, k=0; + while (1) { + c = LWR(pattern[i]); + if (c == '\0') break; + + if (c=='*') { + /*remove *** patterns*/ + while (c == '*') { + i++; + c = LWR(pattern[i]); + } + /*look for same c character*/ + while (1) { + d = LWR(string[k]); + if (d == '\0') break; + /*matched c character, check following substrings*/ + if ((d == c) && rfc2818_match (&pattern[i], &string[k])) return 1; -#ifdef ASTERISK_EXCLUDES_DOT - else if (*n == '.') + else if (d == '.') return 0; -#endif - return c == '\0'; - } else { - if (c != TOLOWER (*n)) - return 0; - } - } - return *n == '\0'; + + k++; + } + return (c == '\0') ? 1 : 0; + } else { + if (c != LWR(string[k])) + return 0; + } + i++; + k++; + } + return (string[k]=='\0') ? 1 : 0; } -#undef TOLOWER +#undef LWR #endif @@ -1197,7 +1204,7 @@ static void gf_dm_connect(GF_DownloadSession *sess) X509 *cert; Bool success = 1; - sess->ssl = SSL_new(sess->dm->ssl_ctx); + sess->ssl = SSL_new(sess->dm->ssl_ctx); SSL_set_fd(sess->ssl, gf_sk_get_handle(sess->sock)); SSL_set_connect_state(sess->ssl); ret = SSL_connect(sess->ssl); @@ -1206,13 +1213,27 @@ static void gf_dm_connect(GF_DownloadSession *sess) cert = SSL_get_peer_certificate(sess->ssl); /*if we have a cert, check it*/ if (cert) { + SSL_set_verify_result(sess->ssl, 0); vresult = SSL_get_verify_result(sess->ssl); - if (vresult != X509_V_OK) success = 0; - else { + + if (vresult == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) { + GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[SSL] Cannot locate issuer's certificate on the local system, will not attempt to validate\n")); + SSL_set_verify_result(sess->ssl, 0); + vresult = SSL_get_verify_result(sess->ssl); + } + + if (vresult == X509_V_OK) { common_name[0] = 0; X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, common_name, sizeof (common_name)); - if (!pattern_match(common_name, sess->server_name)) success = 0; - } + if (!rfc2818_match(common_name, sess->server_name)) { + success = 0; + GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[SSL] Mismatch in certificate names: got %s expected %s\n", common_name, sess->server_name)); + } + } else { + success = 0; + GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[SSL] Error verifying certificate %x\n", vresult)); + } + X509_free(cert); if (!success) { @@ -1358,6 +1379,7 @@ GF_Err gf_dm_sess_process(GF_DownloadSession *sess) return sess->last_error; } +GF_EXPORT GF_Err gf_dm_sess_process_headers(GF_DownloadSession *sess) { Bool go; @@ -1990,8 +2012,10 @@ static GF_Err http_send_headers(GF_DownloadSession *sess, char * sHTTP) { #ifdef GPAC_HAS_SSL if (sess->ssl) { - e = GF_IP_NETWORK_FAILURE; - if (!SSL_write(sess->ssl, tmp_buf, len+par.size)) e = GF_OK; + u32 writelen = len+par.size; + e = GF_OK; + if (writelen != SSL_write(sess->ssl, tmp_buf, writelen)) + e = GF_IP_NETWORK_FAILURE; } else #endif e = gf_sk_send(sess->sock, tmp_buf, len+par.size); @@ -2002,9 +2026,11 @@ static GF_Err http_send_headers(GF_DownloadSession *sess, char * sHTTP) { #ifdef GPAC_HAS_SSL if (sess->ssl) { - e = GF_IP_NETWORK_FAILURE; - if (!SSL_write(sess->ssl, sHTTP, strlen(sHTTP))) e = GF_OK; - } else + u32 len = strlen(sHTTP); + e = GF_OK; + if (len != SSL_write(sess->ssl, sHTTP, len)) + e = GF_IP_NETWORK_FAILURE; + } else #endif e = gf_sk_send(sess->sock, sHTTP, strlen(sHTTP)); @@ -2047,7 +2073,7 @@ static GF_Err http_parse_remaining_body(GF_DownloadSession * sess, char * sHTTP) } } #endif - e = gf_dm_read_data(sess, sHTTP, GF_DOWNLOAD_BUFFER_SIZE, &size); + e = gf_dm_read_data(sess, sHTTP, GF_DOWNLOAD_BUFFER_SIZE-1, &size); if (e!= GF_IP_CONNECTION_CLOSED && (!size || e == GF_IP_NETWORK_EMPTY)) { if (e == GF_IP_CONNECTION_CLOSED || (!sess->total_size && (gf_sys_clock() - sess->start_time > 5000))) { sess->total_size = sess->bytes_done; @@ -2112,7 +2138,7 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP) new_location = NULL; sess->use_cache_file = 1; while (1) { - e = gf_dm_read_data(sess, sHTTP + bytesRead, GF_DOWNLOAD_BUFFER_SIZE - bytesRead, &res); + e = gf_dm_read_data(sess, sHTTP + bytesRead, GF_DOWNLOAD_BUFFER_SIZE - 1 - bytesRead, &res); switch (e) { case GF_IP_NETWORK_EMPTY: if (!bytesRead) return GF_OK; @@ -2213,7 +2239,7 @@ static GF_Err wait_for_header_and_parse(GF_DownloadSession *sess, char * sHTTP) gf_dm_sess_user_io(sess, &par); #endif - GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] Processing header %s: %s\n", hdr, hdr_val)); + // GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] Processing header %s: %s\n", hdr, hdr_val)); if (!stricmp(hdr, "Content-Length") ) { ContentLength = (u32) atoi(hdr_val); @@ -2625,20 +2651,20 @@ static void wget_NetIO(void *cbk, GF_NETIO_Parameter *param) GF_EXPORT -GF_Err gf_dm_wget(const char *url, const char *filename) +GF_Err gf_dm_wget(const char *url, const char *filename, u64 start_range, u64 end_range) { GF_Err e; GF_DownloadManager * dm = NULL; dm = gf_dm_new(NULL); if (!dm) return GF_OUT_OF_MEM; - e = gf_dm_wget_with_cache(dm, url, filename); + e = gf_dm_wget_with_cache(dm, url, filename, start_range, end_range); gf_dm_del(dm); return e; } GF_Err gf_dm_wget_with_cache(GF_DownloadManager * dm, - const char *url, const char *filename) + const char *url, const char *filename, u64 start_range, u64 end_range) { GF_Err e; FILE * f; @@ -2656,6 +2682,11 @@ GF_Err gf_dm_wget_with_cache(GF_DownloadManager * dm, } dnload->use_cache_file = 1; dnload->force_data_write_callback = 1; + if (end_range) { + dnload->range_start = start_range; + dnload->range_end = end_range; + dnload->needs_range = 1; + } if (e == GF_OK) { e = gf_dm_sess_process(dnload); } @@ -2897,6 +2928,7 @@ GF_Err gf_dm_sess_reassign(GF_DownloadSession *sess, u32 flags, gf_dm_user_io us } #endif + if (sess->flags & GF_DOWNLOAD_SESSION_USE_SSL) flags |= GF_DOWNLOAD_SESSION_USE_SSL; sess->flags = flags; sess->user_proc = user_io; sess->usr_cbk = cbk; diff --git a/src/utils/error.c b/src/utils/error.c index d1059f6..f6c57d1 100644 --- a/src/utils/error.c +++ b/src/utils/error.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -74,7 +75,7 @@ static const char *szProg[] = static u64 prev_pos = 0; static u64 prev_pc = 0; -static void gf_on_progress_stdout(const char *_title, u64 done, u64 total) +static void gf_on_progress_std(const char *_title, u64 done, u64 total) { Double prog; u32 pos; @@ -89,16 +90,16 @@ static void gf_on_progress_stdout(const char *_title, u64 done, u64 total) } if (done==total) { u32 len = strlen(szT) + 40; - while (len) { fprintf(stdout, " "); len--; }; - fprintf(stdout, "\r"); + while (len) { fprintf(stderr, " "); len--; }; + fprintf(stderr, "\r"); } else { u32 pc = (u32) ( 100 * prog); if ((pos!=prev_pos) || (pc!=prev_pc)) { prev_pos = pos; prev_pc = pc; - fprintf(stdout, "%s: |%s| (%02d/100)\r", szT, szProg[pos], pc); - fflush(stdout); + fprintf(stderr, "%s: |%s| (%02d/100)\r", szT, szProg[pos], pc); + fflush(stderr); } } } @@ -114,7 +115,7 @@ void gf_set_progress(const char *title, u64 done, u64 total) } #ifndef _WIN32_WCE else { - gf_on_progress_stdout(title, done, total); + gf_on_progress_std(title, done, total); } #endif } @@ -151,7 +152,9 @@ static struct log_tool_info {u32 type; const char *name; u32 level; } global_lo { GF_LOG_AUDIO, "audio", GF_LOG_WARNING }, { GF_LOG_MODULE, "module", GF_LOG_WARNING }, { GF_LOG_MUTEX, "mutex", GF_LOG_WARNING }, - { GF_LOG_CONSOLE, "console", GF_LOG_INFO } + { GF_LOG_DASH, "dash", GF_LOG_WARNING }, + { GF_LOG_CONSOLE, "console", GF_LOG_INFO }, + { GF_LOG_APP, "app", GF_LOG_INFO } }; GF_EXPORT @@ -324,7 +327,7 @@ Bool gf_log_tool_level_on(u32 log_tool, u32 log_level) void default_log_callback(void *cbck, u32 level, u32 tool, const char* fmt, va_list vlist) { #ifndef _WIN32_WCE - vfprintf(stdout, fmt, vlist); + vfprintf(stderr, fmt, vlist); #endif } @@ -497,8 +500,6 @@ const char *gf_error_to_string(GF_Err e) } } - -/* crc32 from ffmpeg*/ static const u32 gf_crc_table[256] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, @@ -557,6 +558,7 @@ u32 gf_crc_32(char *data, u32 len) return crc; } + #define CHECK_MAC(_a) "#_a :" ? (_a) ? "yes":"no" GF_EXPORT diff --git a/src/utils/list.c b/src/utils/list.c index 8e8e8f0..1b93a4c 100644 --- a/src/utils/list.c +++ b/src/utils/list.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/math.c b/src/utils/math.c index 7e9b6b3..21df7f9 100644 --- a/src/utils/math.c +++ b/src/utils/math.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/module.c b/src/utils/module.c index 38539dc..0957e05 100644 --- a/src/utils/module.c +++ b/src/utils/module.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/module_wrap.h b/src/utils/module_wrap.h index a6d594f..de3e65f 100644 --- a/src/utils/module_wrap.h +++ b/src/utils/module_wrap.h @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/os_config_init.c b/src/utils/os_config_init.c index 8de4c42..7471fd8 100644 --- a/src/utils/os_config_init.c +++ b/src/utils/os_config_init.c @@ -1,9 +1,9 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Telecom ParisTech 2011- - * All rights reserved * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 + * All rights reserved * * This file is part of GPAC / common tools sub-project * @@ -361,7 +361,7 @@ static GF_Config *create_default_config(char *file_path) if (! get_default_install_path(szPath, GF_PATH_MODULES)) { gf_delete_file(szPath); - fprintf(stdout, "default modules not found\n"); + GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] default modules not found\n")); return NULL; } @@ -376,8 +376,6 @@ static GF_Config *create_default_config(char *file_path) gf_cfg_set_key(cfg, "General", "CacheDirectory", cache_dir); gf_free(cache_dir); } - gf_cfg_set_key(cfg, "DSMCC", "Activated", "false"); - gf_cfg_set_key(cfg, "Compositor", "Raster2D", "GPAC 2D Raster"); gf_cfg_set_key(cfg, "Audio", "ForceConfig", "yes"); gf_cfg_set_key(cfg, "Audio", "NumBuffers", "2"); @@ -490,6 +488,15 @@ GF_Config *gf_cfg_init(const char *file, Bool *new_cfg) if (file) { cfg = gf_cfg_new(NULL, file); + /*force creation of a new config*/ + if (!cfg) { + FILE *fcfg = fopen(file, "wt"); + if (fcfg) { + fclose(fcfg); + cfg = gf_cfg_new(NULL, file); + if (new_cfg) *new_cfg = 1; + } + } if (cfg) { check_modules_dir(cfg); return cfg; @@ -502,16 +509,16 @@ GF_Config *gf_cfg_init(const char *file, Bool *new_cfg) } cfg = gf_cfg_new(szPath, CFG_FILE_NAME); if (!cfg) { - fprintf(stdout, "GPAC config file %s not found in %s - creating new file\n", CFG_FILE_NAME, szPath); + fprintf(stderr, "GPAC config file %s not found in %s - creating new file\n", CFG_FILE_NAME, szPath); cfg = create_default_config(szPath); } if (!cfg) { - fprintf(stdout, "Cannot create config file %s in %s directory\n", CFG_FILE_NAME, szPath); + fprintf(stderr, "Cannot create config file %s in %s directory\n", CFG_FILE_NAME, szPath); return NULL; } - fprintf(stdout, "Using config file in %s directory\n", szPath); + fprintf(stderr, "Using config file in %s directory\n", szPath); check_modules_dir(cfg); diff --git a/src/utils/os_divers.c b/src/utils/os_divers.c index f80e2b8..7c383fb 100644 --- a/src/utils/os_divers.c +++ b/src/utils/os_divers.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -215,14 +216,107 @@ GF_Err gf_cleanup_dir(char* DirPathName) #ifndef gettimeofday #ifdef _WIN32_WCE +#include +//#include + +/* + * Author of first version (timeval.h): by Wu Yongwei + * Author of Windows CE version: Mateusz Loskot (mateusz@loskot.net) + * + * All code here is considered in the public domain though we do wish our names + * could be retained if anyone uses them. + */ + +/* + * Constants used internally by time functions. + */ + +#ifndef _TM_DEFINED +struct tm +{ + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday - [0,6] */ + int tm_yday; /* days since January 1 - [0,365] */ + int tm_isdst; /* daylight savings time flag */ +}; +#define _TM_DEFINED +#endif /* _TM_DEFINED */ + +#ifndef _TIMEZONE_DEFINED +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; +#define _TIMEZONE_DEFINED +#endif /* _TIMEZONE_DEFINED */ + + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + +int gettimeofday(struct timeval *tp, struct timezone *tzp) +{ + SYSTEMTIME st; + FILETIME ft; + LARGE_INTEGER li; + TIME_ZONE_INFORMATION tzi; + __int64 t; + static int tzflag; + + if (NULL != tp) + { + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tp->tv_sec = (long)(t / 1000000); + tp->tv_usec = (long)(t % 1000000); + } + + if (NULL != tzp) + { + GetTimeZoneInformation(&tzi); + + tzp->tz_minuteswest = tzi.Bias; + if (tzi.StandardDate.wMonth != 0) + { + tzp->tz_minuteswest += tzi.StandardBias * 60; + } + + if (tzi.DaylightDate.wMonth != 0) + { + tzp->tz_dsttime = 1; + } + else + { + tzp->tz_dsttime = 0; + } + } + + return 0; +} + + +#if 0 /* - Conversion code for WinCE from pthreads WinCE - (FILETIME in Win32 is from jan 1, 1601) time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds + FILETIME in Win32 is from jan 1, 1601 */ #define TIMESPEC_TO_FILETIME_OFFSET (((LONGLONG)27111902 << 32) + (LONGLONG)3577643008) -s32 gettimeofday(struct timeval *tp, void *tz) +s32 __gettimeofday(struct timeval *tp, void *tz) { FILETIME ft; SYSTEMTIME st; @@ -237,6 +331,8 @@ s32 gettimeofday(struct timeval *tp, void *tz) tp->tv_usec = val; return 0; } +#endif + #elif defined(WIN32) @@ -296,18 +392,21 @@ GF_Err gf_delete_file(const char *fileName) #endif } -void gf_move_file(const char *fileName, const char *newFileName) +GF_EXPORT +GF_Err gf_move_file(const char *fileName, const char *newFileName) { #if defined(_WIN32_WCE) TCHAR swzName[MAX_PATH]; TCHAR swzNewName[MAX_PATH]; CE_CharToWide((char*)fileName, swzName); CE_CharToWide((char*)newFileName, swzNewName); - MoveFile(swzName, swzNewName); + return (MoveFile(swzName, swzNewName) == 0 ) ? GF_IO_ERR : GF_OK; #elif defined(WIN32) - MoveFile(fileName, newFileName); + /* success if != 0 */ + return (MoveFile(fileName, newFileName) == 0 ) ? GF_IO_ERR : GF_OK; #else - rename(fileName, newFileName); + /* success is == 0 */ + return ( rename(fileName, newFileName) == 0) ? GF_OK : GF_IO_ERR; #endif } @@ -815,7 +914,7 @@ static void init_keyboard() static void close_keyboard(Bool new_line) { tcsetattr(0,TCSANOW, &t_orig); - if (new_line) fprintf(stdout, "\n"); + if (new_line) fprintf(stderr, "\n"); } void gf_prompt_set_echo_off(Bool echo_off) diff --git a/src/utils/os_module.c b/src/utils/os_module.c index 7a81459..33e5d52 100644 --- a/src/utils/os_module.c +++ b/src/utils/os_module.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/os_net.c b/src/utils/os_net.c index d17ef2f..6053347 100644 --- a/src/utils/os_net.c +++ b/src/utils/os_net.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -59,6 +60,7 @@ #endif /*common win32 redefs*/ +#undef EAGAIN #define EAGAIN WSAEWOULDBLOCK #define EISCONN WSAEISCONN #define ENOTCONN WSAENOTCONN @@ -66,7 +68,9 @@ #define EMSGSIZE WSAEMSGSIZE #define ECONNABORTED WSAECONNABORTED #define ENETDOWN WSAENETDOWN +#undef EINTR #define EINTR WSAEINTR +#undef EBADF #define EBADF WSAEBADF #define LASTSOCKERROR WSAGetLastError() diff --git a/src/utils/os_thread.c b/src/utils/os_thread.c index ec82ad2..9a1c990 100644 --- a/src/utils/os_thread.c +++ b/src/utils/os_thread.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -283,6 +284,7 @@ void Thread_Stop(GF_Thread *t, Bool Destroy) t->status = GF_THREAD_STATUS_DEAD; } +GF_EXPORT void gf_th_stop(GF_Thread *t) { Thread_Stop(t, 0); diff --git a/src/utils/path2d.c b/src/utils/path2d.c index 8a618da..e7ba3c0 100644 --- a/src/utils/path2d.c +++ b/src/utils/path2d.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/ringbuffer.c b/src/utils/ringbuffer.c index 0e5c754..f085358 100644 --- a/src/utils/ringbuffer.c +++ b/src/utils/ringbuffer.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Pierre Souchay + * Copyright (c) Telecom ParisTech 2010 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/symbian_net.cpp b/src/utils/symbian_net.cpp index 7b18e9b..fe4f7a0 100644 --- a/src/utils/symbian_net.cpp +++ b/src/utils/symbian_net.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/symbian_os.cpp b/src/utils/symbian_os.cpp index 5adf6e4..9a2e3aa 100644 --- a/src/utils/symbian_os.cpp +++ b/src/utils/symbian_os.cpp @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/token.c b/src/utils/token.c index 1637669..bb909c8 100644 --- a/src/utils/token.c +++ b/src/utils/token.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/uni_bidi.c b/src/utils/uni_bidi.c index 5043c14..4496735 100644 --- a/src/utils/uni_bidi.c +++ b/src/utils/uni_bidi.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2007-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/src/utils/url.c b/src/utils/url.c index 4f50a04..a14a4f2 100644 --- a/src/utils/url.c +++ b/src/utils/url.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2000-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -95,7 +96,9 @@ char *gf_url_concatenate(const char *parentName, const char *pathName) char *outPath, *name, *rad; char tmp[GF_MAX_PATH]; - if (!pathName || !parentName) return NULL; + if (!pathName && !parentName) return NULL; + if (!pathName) return gf_strdup(parentName); + if (!parentName) return gf_strdup(pathName); if ( (strlen(parentName) > GF_MAX_PATH) || (strlen(pathName) > GF_MAX_PATH) ) return NULL; @@ -179,6 +182,10 @@ char *gf_url_concatenate(const char *parentName, const char *pathName) pathSepCount = 1; name = ""; } + if (!strcmp(pathName, "./")) { + pathSepCount = 0; + name = ""; + } for (i = 0; i< strlen(pathName) - 2; i++) { /*current dir*/ if ( (pathName[i] == '.') @@ -202,6 +209,11 @@ char *gf_url_concatenate(const char *parentName, const char *pathName) if (!name) name = (char *) pathName; strcpy(tmp, parentName); + while (strchr(" \r\n\t", tmp[strlen(tmp)-1])) { + tmp[strlen(tmp)-1] = 0; + } + + /*remove the last /*/ for (i = strlen(parentName); i > 0; i--) { //break our path at each separator if ((parentName[i-1] == GF_PATH_SEPARATOR) || (parentName[i-1] == '/')) { @@ -217,9 +229,6 @@ char *gf_url_concatenate(const char *parentName, const char *pathName) strcat(tmp, "../"); pathSepCount--; } -/* outPath = gf_strdup(pathName); - goto check_spaces; - */ } else { strcat(tmp, "/"); } @@ -300,3 +309,29 @@ char *gf_url_percent_encode(const char *path) } return outpath; } + +GF_EXPORT +const char *gf_url_get_resource_name(const char *sURL) +{ + char *sep; + if (!sURL) return NULL; + sep = strrchr(sURL, '/'); + if (!sep) sep = strrchr(sURL, '\\'); + if (sep) return sep+1; + return sURL; +} + +GF_EXPORT +Bool gf_url_get_resource_path(const char *sURL, char *res_path) +{ + char *sep; + strcpy(res_path, sURL); + sep = strrchr(res_path, '/'); + if (!sep) sep = strrchr(res_path, '\\'); + if (sep) { + sep[1] = 0; + return 1; + } + return 0; +} + diff --git a/src/utils/utf.c b/src/utils/utf.c index 4118ff4..8a27637 100644 --- a/src/utils/utf.c +++ b/src/utils/utf.c @@ -1,7 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Copyright (c) Jean Le Feuvre 2000-2005 + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2007-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project @@ -24,14 +25,370 @@ #include - - /* - * Original code from the GNU UTF-8 Library + +#if 1 + + +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + +typedef u32 UTF32; /* at least 32 bits */ +typedef u16 UTF16; /* at least 16 bits */ +typedef u8 UTF8; /* typically 8 bits */ +typedef u8 Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. */ +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + + + +GF_EXPORT +size_t gf_utf8_wcslen (const unsigned short *s) +{ + const unsigned short* ptr; + for (ptr = s; *ptr != (unsigned short)'\0'; ptr++) { + } + return ptr - s; +} + GF_EXPORT size_t gf_utf8_wcstombs(char* dest, size_t len, const unsigned short** srcp) { + const UTF16** sourceStart = srcp; + const UTF16* sourceEnd = *srcp + gf_utf8_wcslen(*srcp); + UTF8* targetStart = dest; + UTF8* targetEnd = dest + len; + ConversionFlags flags = strictConversion; + + ConversionResult res = ConvertUTF16toUTF8(sourceStart, sourceEnd, &targetStart, targetEnd, flags); + if (res != conversionOK) return (size_t)-1; + *targetStart = 0; + *srcp=NULL; + return strlen(dest); +} + +GF_EXPORT +size_t gf_utf8_mbstowcs(unsigned short* dest, size_t len, const char** srcp) +{ + const UTF8** sourceStart = (const UTF8**) srcp; + const UTF8* sourceEnd = (const UTF8*) ( *srcp + strlen( *srcp) ); + UTF16* targetStart = (UTF16* ) dest; + UTF16* targetEnd = (UTF16* ) (dest + len); + ConversionFlags flags = strictConversion; + ConversionResult res = ConvertUTF8toUTF16(sourceStart, sourceEnd, &targetStart, targetEnd, flags); + if (res != conversionOK) return (size_t)-1; + *targetStart = 0; + *srcp=NULL; + return gf_utf8_wcslen(dest); +} + + +#else + +GF_EXPORT +size_t gf_utf8_wcslen (const unsigned short *s) +{ + const unsigned short* ptr; + for (ptr = s; *ptr != (unsigned short)'\0'; ptr++) { + } + return ptr - s; +} + +GF_EXPORT +size_t gf_utf8_wcstombs(char* dest, size_t len, const unsigned short** srcp) +{ + /* + * Original code from the GNU UTF-8 Library + */ size_t count; const unsigned short * src = *srcp; @@ -175,14 +532,4 @@ bad_input: return (size_t)(-1); } - -GF_EXPORT -size_t gf_utf8_wcslen (const unsigned short *s) -{ - const unsigned short* ptr; - for (ptr = s; *ptr != (unsigned short)'\0'; ptr++) { - } - return ptr - s; -} - - +#endif diff --git a/src/utils/xml_parser.c b/src/utils/xml_parser.c index dafa872..45d742d 100644 --- a/src/utils/xml_parser.c +++ b/src/utils/xml_parser.c @@ -1,8 +1,8 @@ /* * GPAC - Multimedia Framework C SDK * - * Authors: Jean le Feuvre - * Copyright (c) 2005-200X ENST + * Authors: Jean Le Feuvre + * Copyright (c) Telecom ParisTech 2005-2012 * All rights reserved * * This file is part of GPAC / common tools sub-project diff --git a/version.bat b/version.bat index a6ebea7..d0a1bcc 100644 --- a/version.bat +++ b/version.bat @@ -1,10 +1,10 @@ @echo off cd /d %~dp0 for /f "delims=" %%a in ('svnversion') do echo #define GPAC_SVN_REVISION "%%a" > test.h -if not exist include\gpac\version.h goto create -ECHO n|COMP test.h include\gpac\version.h > nul +if not exist include\gpac\revision.h goto create +ECHO n|COMP test.h include\gpac\revision.h > nul if errorlevel 1 goto create DEL test.h exit/b :create -MOVE /Y test.h include\gpac\version.h +MOVE /Y test.h include\gpac\revision.h