On 12/31/2014 02:14 AM, Michael Niedermayer wrote: > On Wed, Dec 31, 2014 at 01:35:59AM +0530, Anshul wrote: >> On 12/30/2014 10:06 PM, Michael Niedermayer wrote: >>> On Tue, Dec 30, 2014 at 07:39:38PM +0530, Anshul wrote: >>>> On 12/30/2014 03:56 PM, Clément Bœsch wrote: >>>>> They are also probably useless since you can use av_asprintf() directly. >>>>> >>>> Thanks I didn't knew about that function. >>>> >>>> >>>> Attached new patch with removing those function. >>> [...] >>>> --- a/libavcodec/allcodecs.c >>>> +++ b/libavcodec/allcodecs.c >>>> @@ -536,6 +536,8 @@ void avcodec_register_all(void) >>>> REGISTER_ENCODER(LIBAACPLUS, libaacplus); >>>> >>>> /* text */ >>>> + REGISTER_DECODER(SCTE_35, scte_35) >>>> + REGISTER_ENCODER(CUE_XML, cue_xml); >>> you are missing a ; here >>> >> done >>>> REGISTER_DECODER(BINTEXT, bintext); >>>> REGISTER_DECODER(XBIN, xbin); >>>> REGISTER_DECODER(IDF, idf); >>>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h >>>> index 99467bb..bd966d5 100644 >>>> --- a/libavcodec/avcodec.h >>>> +++ b/libavcodec/avcodec.h >>>> @@ -523,6 +523,8 @@ enum AVCodecID { >>>> /* other specific kind of codecs (generally used for attachments) */ >>>> 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_SCTE_35 = MKBETAG('C','U','E','I'), >>>> + AV_CODEC_ID_CUE_XML = MKBETAG('C','U','E','X'), >>>> 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'), >>>> @@ -3157,6 +3159,13 @@ typedef struct AVCodecDefault AVCodecDefault; >>>> >>>> struct AVSubtitle; >>>> >>>> +typedef struct AVData { >>>> + void *data; >>>> + int len; >>>> + int ref_count; >>>> + int valid; >>>> +} AVData; >>> missing documentation >> removed all of it. used AVBuffer instead >>>> + >>>> /** >>>> * AVCodec. >>>> */ >>>> @@ -3233,6 +3242,8 @@ typedef struct AVCodec { >>>> int (*init)(AVCodecContext *); >>>> int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, >>>> const struct AVSubtitle *sub); >>>> + int (*encode_data)(AVCodecContext *avctx, const AVData *input, >>>> AVData *output, >>>> + enum AVCodecID in_codec_id); >>>> /** >>>> * Encode data to an AVPacket. >>>> * >>>> @@ -3246,6 +3257,7 @@ typedef struct AVCodec { >>>> int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame >>>> *frame, >>>> int *got_packet_ptr); >>>> int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, >>>> AVPacket *avpkt); >>>> + int (*decode_data)(AVCodecContext *,AVData *output, const AVPacket >>>> *avpkt); >>>> int (*close)(AVCodecContext *); >>>> /** >>>> * Flush buffers. >>> this breaks ABI >>> >> add at end of structure, if that solve problem >>>> @@ -4195,6 +4207,9 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, >>>> AVSubtitle *sub, >>>> int *got_sub_ptr, >>>> AVPacket *avpkt); >>>> >>>> +int avcodec_decode_data(AVCodecContext *avctx, >>>> + AVData *output, >>>> + const AVPacket *avpkt); >>>> /** >>>> * @defgroup lavc_parsing Frame parsing >>>> * @{ >>>> @@ -4585,6 +4600,8 @@ int avcodec_encode_video2(AVCodecContext *avctx, >>>> AVPacket *avpkt, >>>> >>>> int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int >>>> buf_size, >>>> const AVSubtitle *sub); >>>> +int avcodec_encode_data(AVCodecContext *avctx,const AVData *input, AVData >>>> *output, >>>> + enum AVCodecID in_codec_id); >>>> >>>> >>> this is missing documentation >>> >> added documentation >>> [...] >>>> diff --git a/libavcodec/scte_35.c b/libavcodec/scte_35.c >>>> new file mode 100644 >>>> index 0000000..2723225 >>>> --- /dev/null >>>> +++ b/libavcodec/scte_35.c >>>> @@ -0,0 +1,294 @@ >>>> +/* >>>> + * SCTE 35 decoder >>>> + * Copyright (c) 2014 Anshul Maheshwaari >>>> + * >>>> + * 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 >>>> + */ >>> please add a reference to the spezification & exact revission used >>> to implement this >>> >>> [...] >> I have attached the document on trac, following is link to it. >> here is helper document on how to implement >> http://trac.ffmpeg.org/attachment/ticket/3356/SCTE%2067%202014.pdf >> here is a document What to implement >> http://trac.ffmpeg.org/attachment/ticket/3356/ANSI_SCTE%2035%202013.pdf > please add a reference in the source code to the spezification that > you used. Note you should not upload anything, you should not use > any URLs. Just a proper reference like > "This is based on this and that" or "This is an implementation of ..." > Such reference should contain the full title of the specification and > and any revissions and dates associated > I have used this line "Refrence Material Used" done I was unable to find out dates associated in that spec. I downloaded it from http://www.scte.org/standards/ page
>> To make it really usable I have to write some/one filters, which takes 2 >> program stream >> and give one output program stream. >> Which will use data decoder output to analyse which stream it has to >> accept and >> which stream to be droped. >> >> The Xml format that I have choosen, is made by me and Improvement or >> addition to >> it (comments) would be appriciated. >> >> Attached new patch with review comments on irc from Tim_G about AVBuffer >> and doc related things. >> >> -Anshul > >> ffmpeg.c | 50 +++++++- >> ffmpeg_opt.c | 9 - >> libavcodec/Makefile | 2 >> libavcodec/allcodecs.c | 2 >> libavcodec/avcodec.h | 39 ++++++ >> libavcodec/codec_desc.c | 12 + >> libavcodec/cue_xml.c | 250 ++++++++++++++++++++++++++++++++++++++++ >> libavcodec/scte_35.c | 298 >> ++++++++++++++++++++++++++++++++++++++++++++++++ >> libavcodec/scte_35.h | 31 ++++ >> libavcodec/utils.c | 33 ++++- >> libavformat/avformat.h | 16 ++ >> libavformat/mpegts.c | 45 ++++++- >> libavformat/utils.c | 1 >> 13 files changed, 774 insertions(+), 14 deletions(-) >> 2410fa240726c375505826b320af4cd2a807c945 >> 0001-handle-scte-35-message-cue-data-stream.patch >> From 4e95ec0923af73a07ae9bacb1f371f43be93ca61 Mon Sep 17 00:00:00 2001 >> From: Anshul Maheshwari <anshul.ffm...@gmail.com> >> Date: Wed, 31 Dec 2014 01:23:20 +0530 >> Subject: [PATCH] handle scte 35 message cue data stream >> > missing signoff in the commit message done, Thanks for link,previously I had an interpretation that signoff was done by reviewer. > > [...] >> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h >> index 99467bb..daa7448 100644 >> --- a/libavcodec/avcodec.h >> +++ b/libavcodec/avcodec.h >> @@ -523,6 +523,8 @@ enum AVCodecID { >> /* other specific kind of codecs (generally used for attachments) */ >> 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_SCTE_35 = MKBETAG('C','U','E','I'), >> + AV_CODEC_ID_CUE_XML = MKBETAG('C','U','E','X'), >> 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'), >> @@ -3233,6 +3235,8 @@ typedef struct AVCodec { >> int (*init)(AVCodecContext *); >> int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, >> const struct AVSubtitle *sub); >> + int (*encode_data)(AVCodecContext *avctx, const AVBuffer *input, >> AVBuffer *output, >> + enum AVCodecID in_codec_id); >> /** >> * Encode data to an AVPacket. >> * > breaks ABI > if someone reading this knows of a good introduction about ABI/API > compatibility and such stuff please reply, i think debian had a > guide but also something which described the "why" behind all the ABI > stuff could be usefull > id quote a link but i dunno a good introduction to that stuff I was searching for version number to increase, but thought let other discussion get to end. I have moved this API too down of structure. > >> @@ -3252,6 +3256,7 @@ typedef struct AVCodec { >> * Will be called when seeking >> */ >> void (*flush)(AVCodecContext *); >> + int (*decode_data)(AVCodecContext *,AVBuffer *output, const AVPacket >> *avpkt); >> } AVCodec; >> >> int av_codec_get_max_lowres(const AVCodec *codec); >> @@ -4196,6 +4201,20 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, >> AVSubtitle *sub, >> AVPacket *avpkt); >> >> /** >> + * Decode a subtitle message. > please use avcodec_decode_subtitle2() if thats the case > if not please try to read your patch before submission > > [...] sry fr that. > > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel nfx...@googlemail.com wrote: It's still not clear what the function actually does. What's the output format? Why is avcodec_decode_subtitle2() not used for this? (I'm being naive and dumb here; while I don't know what this patch is actually about, users trying to understand the lavc APIs in general will have the same questions.) Also, it mixes the words "decode" and "decompress". I have tried to elaborate the document. please comment, if still not sufficient. This is far different from subtitle, here only interface is generic but data inside is dependent on decoder and encoder used. Another patch attached. -Anshul
>From 5b7e6eb1dbf9b06c060f595acbb9db6887aa6764 Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari <anshul.ffm...@gmail.com> Date: Wed, 31 Dec 2014 13:38:46 +0530 Subject: [PATCH] handle scte_35 messagecue Signed-off-by: Anshul Maheshwari <anshul.ffm...@gmail.com> --- ffmpeg.c | 50 +++++++- ffmpeg_opt.c | 9 +- libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 2 + libavcodec/avcodec.h | 44 +++++++ libavcodec/codec_desc.c | 12 ++ libavcodec/cue_xml.c | 250 +++++++++++++++++++++++++++++++++++++++ libavcodec/scte_35.c | 309 ++++++++++++++++++++++++++++++++++++++++++++++++ libavcodec/scte_35.h | 31 +++++ libavcodec/utils.c | 33 +++++- libavformat/avformat.h | 16 +++ libavformat/mpegts.c | 45 ++++++- libavformat/utils.c | 1 + 13 files changed, 790 insertions(+), 14 deletions(-) create mode 100644 libavcodec/cue_xml.c create mode 100644 libavcodec/scte_35.c create mode 100644 libavcodec/scte_35.h diff --git a/ffmpeg.c b/ffmpeg.c index ddf4272..153ff4f 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -60,6 +60,7 @@ #include "libavutil/bprint.h" #include "libavutil/time.h" #include "libavutil/threadmessage.h" +#include "libavutil/buffer_internal.h" #include "libavformat/os_support.h" #include "libavformat/ffm.h" // not public API @@ -2063,6 +2064,47 @@ fail: return err < 0 ? err : ret; } +static int transcode_data(InputStream *ist, AVPacket *pkt, int *got_output) +{ + AVCodecContext *dec = ist->dec_ctx; + enum AVCodecID in_codec_id = AV_CODEC_ID_NONE; + AVBuffer input; + AVBuffer output; + AVPacket outpkt; + int ret, i; + + if (dec->codec) + in_codec_id = dec->codec->id; + + input.size = 0; + update_benchmark(NULL); + ret = avcodec_decode_data(dec, &input, pkt); + update_benchmark("decode_data %d.%d", ist->file_index, ist->st->index); + + if (ret < 0 || !input.size) { + return ret; + } + for (i = 0; i < nb_output_streams && input.size; i++) { + OutputStream *ost = output_streams[i]; + + if (!check_output_constraints(ist, ost) || !ost->encoding_needed + || ost->enc->type != AVMEDIA_TYPE_DATA) + continue; + ret = avcodec_encode_data(output_streams[i]->enc_ctx, &input, &output, in_codec_id); + if ( ret >= 0 || output.size) { + av_init_packet(&outpkt); + outpkt.data = output.data; + outpkt.size = output.size; + write_frame(output_files[ost->file_index]->ctx, &outpkt, ost); + output.free(output.opaque, output.data); + } + input.free(input.opaque, input.data); + + } + + return ret; + +} static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) { AVSubtitle subtitle; @@ -2203,6 +2245,9 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt) case AVMEDIA_TYPE_SUBTITLE: ret = transcode_subtitles(ist, &avpkt, &got_output); break; + case AVMEDIA_TYPE_DATA: + ret = transcode_data(ist, &avpkt, &got_output); + break; default: return -1; } @@ -2907,6 +2952,8 @@ static int transcode_init(void) enc_ctx->height = input_streams[ost->source_index]->st->codec->height; } break; + case AVMEDIA_TYPE_DATA: + break; default: abort(); break; @@ -3464,7 +3511,8 @@ static int process_input(int file_index) OutputStream *ost = output_streams[j]; if (ost->source_index == ifile->ist_index + i && - (ost->stream_copy || ost->enc->type == AVMEDIA_TYPE_SUBTITLE)) + (ost->stream_copy || ost->enc->type == AVMEDIA_TYPE_SUBTITLE + || ost->enc->type == AVMEDIA_TYPE_DATA )) finish_output_stream(ost); } } diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c index ac93eb5..f7b20fd 100644 --- a/ffmpeg_opt.c +++ b/ffmpeg_opt.c @@ -804,6 +804,7 @@ static int open_input_file(OptionsContext *o, const char *filename) char * video_codec_name = NULL; char * audio_codec_name = NULL; char *subtitle_codec_name = NULL; + char * data_codec_name = NULL; int scan_all_pmts_set = 0; if (o->format) { @@ -864,6 +865,8 @@ static int open_input_file(OptionsContext *o, const char *filename) find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)->id : AV_CODEC_ID_NONE; ic->subtitle_codec_id= subtitle_codec_name ? find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : AV_CODEC_ID_NONE; + ic->data_codec_id = data_codec_name ? + find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)->id : AV_CODEC_ID_NONE; if (video_codec_name) av_format_set_video_codec (ic, find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)); @@ -871,6 +874,8 @@ static int open_input_file(OptionsContext *o, const char *filename) av_format_set_audio_codec (ic, find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)); if (subtitle_codec_name) av_format_set_subtitle_codec(ic, find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)); + if (data_codec_name) + av_format_set_data_codec(ic, find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)); ic->flags |= AVFMT_FLAG_NONBLOCK; ic->interrupt_callback = int_cb; @@ -1522,10 +1527,6 @@ static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int OutputStream *ost; ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index); - if (!ost->stream_copy) { - av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); - exit_program(1); - } return ost; } diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 107661b..c7cb069 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -293,6 +293,7 @@ OBJS-$(CONFIG_LOCO_DECODER) += loco.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o +OBJS-$(CONFIG_CUE_XML_ENCODER) += cue_xml.o OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \ twinvq.o OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o @@ -412,6 +413,7 @@ OBJS-$(CONFIG_SAMI_DECODER) += samidec.o ass.o OBJS-$(CONFIG_S302M_DECODER) += s302m.o OBJS-$(CONFIG_S302M_ENCODER) += s302menc.o OBJS-$(CONFIG_SANM_DECODER) += sanm.o +OBJS-$(CONFIG_SCTE_35_DECODER) += scte_35.o OBJS-$(CONFIG_SGI_DECODER) += sgidec.o OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o OBJS-$(CONFIG_SGIRLE_DECODER) += sgirledec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8ceee2f..6c0036d 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -536,6 +536,8 @@ void avcodec_register_all(void) REGISTER_ENCODER(LIBAACPLUS, libaacplus); /* text */ + REGISTER_DECODER(SCTE_35, scte_35); + REGISTER_ENCODER(CUE_XML, cue_xml); REGISTER_DECODER(BINTEXT, bintext); REGISTER_DECODER(XBIN, xbin); REGISTER_DECODER(IDF, idf); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 99467bb..345dd48 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -523,6 +523,8 @@ enum AVCodecID { /* other specific kind of codecs (generally used for attachments) */ 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_SCTE_35 = MKBETAG('C','U','E','I'), + AV_CODEC_ID_CUE_XML = MKBETAG('C','U','E','X'), 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'), @@ -3252,6 +3254,11 @@ typedef struct AVCodec { * Will be called when seeking */ void (*flush)(AVCodecContext *); + + int (*decode_data)(AVCodecContext *,AVBuffer *output, const AVPacket *avpkt); + + int (*encode_data)(AVCodecContext *avctx, const AVBuffer *input, AVBuffer *output, + enum AVCodecID in_codec_id); } AVCodec; int av_codec_get_max_lowres(const AVCodec *codec); @@ -4196,6 +4203,24 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, AVPacket *avpkt); /** + * Decode a Data packet. + * Return a negative value on error, otherwise return the number of bytes used. + * If no data was decoded then size parameter of output is zero. + * In Output AVBuffer format of data parameter is based on the codec used, to use the + * data directly from output buffer one might need to use header file of + * codec used as interface. This output buffer can be directly given to + * avcodec_encode_data api if encoder support that decoder output. + * + * @param avctx the codec context + * @param[out] output The Preallocated AVBuffer in which the decoded data will + * be stored, must be freed with free parameter of AVBuffer + * if size is not 0. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_data(AVCodecContext *avctx, + AVBuffer *output, + const AVPacket *avpkt); +/** * @defgroup lavc_parsing Frame parsing * @{ */ @@ -4585,6 +4610,25 @@ int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub); +/** + * Encode Data Stream. + * + * Takes generic input buffer and writes to generic output buffer. + * User cant give any input buffer blankly, Its user responsibility + * to take care of encoder understanding, Data encoder are very + * specific to there input format. So either use FFmpeg decoder + * to get the specific input buffer, or use the header files as + * interface of encoder. + * + * + * @param avctx codec context + * @param[in] input Preallocated input Buffer. + * @param[out] output Preallocated input Buffer. + * @param[in] in_codec_id codec id of input buffer + * @return 0 on success, negative error code on failure + */ +int avcodec_encode_data(AVCodecContext *avctx,const AVBuffer *input, AVBuffer *output, + enum AVCodecID in_codec_id); /** diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0af66f4..d26cd2f 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2739,6 +2739,18 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("binary data"), .mime_types= MT("application/octet-stream"), }, + { + .id = AV_CODEC_ID_SCTE_35, + .type = AVMEDIA_TYPE_DATA, + .name = "scte_35", + .long_name = NULL_IF_CONFIG_SMALL("SCTE 35 Message Queue"), + }, + { + .id = AV_CODEC_ID_CUE_XML, + .type = AVMEDIA_TYPE_DATA, + .name = "cue_xml", + .long_name = NULL_IF_CONFIG_SMALL("Message Queue to Insert Add"), + }, /* deprecated codec ids */ { diff --git a/libavcodec/cue_xml.c b/libavcodec/cue_xml.c new file mode 100644 index 0000000..490fe2e --- /dev/null +++ b/libavcodec/cue_xml.c @@ -0,0 +1,250 @@ +/* + * SCTE 35 Cue Xml encoder + * Copyright (c) 2014 Anshul Maheshwaari + * + * 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 + */ +#include "avcodec.h" +#include "libavutil/opt.h" +#include "libavutil/bprint.h" +#include "scte_35.h" +#include "libavutil/buffer_internal.h" + +struct varList{ + char *var; + char *value; + struct varList *next; +}; +struct node { + char *name; + struct varList *vlist; + struct node *child; + struct node *parent; + struct node *sibling; +}; + +struct cue_xml_ctx { + AVClass *class; + struct node xml_tree; +}; +static void add_child(struct node *parent, struct node* n) +{ + struct node *tmp; + + /* add to parent node + * parent keep only address of one child , other children are kept in sibling */ + if(!parent->child) + parent->child = n; + else { + tmp = parent->child; + while(tmp->sibling) { + tmp = tmp->sibling; + } + tmp->sibling = n; + } + n->parent = parent; +} + +static void remove_child(struct node *parent, struct node* n) +{ + struct node *tmp = parent->child; + struct node *stmp = NULL; + + while (tmp) { + + if(!strcmp(tmp->name,n->name)) { + break; + } + stmp = tmp; + tmp = tmp->sibling; + } + if(!stmp) + parent->child = NULL; + else + stmp->sibling = tmp->sibling; +} +/** + * memory of value need to be preallocated + */ +static int add_varval_pair(struct node* n,const char *var,char *val) +{ + struct varList *pair; + + pair = av_mallocz(sizeof(*pair)); + if(!pair) + return AVERROR(ENOMEM); + + pair->var = av_strdup(var); + pair->value = val; + + if(!n->vlist) { + n->vlist = pair; + } else { + struct varList *npair = n->vlist; + while (npair->next) { + npair = npair->next; + } + npair->next = pair; + } + return 0; + +} +static int add_varval_pair_char(struct node* n,const char *var,const char *val) +{ + char *val2 = av_strdup(val); + return add_varval_pair(n, var, val2); +} + +static int add_varval_pair_uint32_t(struct node* n,const char *var,const uint32_t val) +{ + char *val2 = av_asprintf("%u", val);; + if(!val2) + return AVERROR(ENOMEM); + return add_varval_pair(n, var, val2); +} + +static int add_varval_pair_uint64_t(struct node* n,const char *var,const uint64_t val) +{ + char *val2 = av_asprintf("%llu", val); + if(!val2) + return AVERROR(ENOMEM); + return add_varval_pair(n, var, val2); +} + +static void write_tree_as_data(struct node* root, AVBuffer *data) +{ + AVBPrint buffer; + struct node *tmp = root->child; + struct node *leaf; + av_bprint_init(&buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + + while(tmp) { + struct varList *npair = tmp->vlist; + av_bprintf(&buffer, "<%s", tmp->name); + while(npair) { + av_bprintf(&buffer, " %s=%s", npair->var, npair->value); + npair = npair->next; + } + av_bprintf(&buffer, ">\n"); + leaf = tmp; + tmp = tmp->child; + } + tmp = leaf; + while(tmp->parent) { + av_bprintf(&buffer, "</%s>\n", tmp->name); + tmp = tmp->parent; + } + data->data = av_strdup(buffer.str); + data->size = strlen(buffer.str); + data->free = av_buffer_default_free; + data->flags = AV_BUFFER_FLAG_READONLY; + + av_log(NULL, AV_LOG_DEBUG, "%s\n",buffer.str); + av_bprint_finalize( &buffer, NULL); + +} +static void free_tree(struct node* root) +{ + struct node *tmp = root; + while(tmp) { + struct varList *npair = tmp->vlist; + struct varList *spair = tmp->vlist; + av_freep(&tmp->name); + while(npair) { + spair = npair->next; + av_freep(&npair->var); + av_freep(&npair->value); + av_freep(&npair); + npair = spair; + } + tmp = tmp->child; + } + +} +static void init_node(struct node* n,const char *name) +{ + n->name = av_strdup(name); + n->vlist = NULL; + n->child = NULL; + n->parent = NULL; + n->sibling = NULL; +} +static void dinit_node(struct node* n) +{ + free_tree(n); +} +static av_cold int init_encoder(AVCodecContext *avctx) +{ + struct cue_xml_ctx *ctx = avctx->priv_data; + init_node(&ctx->xml_tree,"scte35"); + + return 0; +} +static av_cold int close_encoder(AVCodecContext *avctx) +{ + struct cue_xml_ctx *ctx = avctx->priv_data; + free_tree(&ctx->xml_tree); + return 0; +} + +static int encode(AVCodecContext *avctx, const AVBuffer *input, AVBuffer *output, + enum AVCodecID in_codec_id) +{ + struct scte_35_interface *interface; + struct node event; + struct cue_xml_ctx *ctx = avctx->priv_data; + + if(in_codec_id != AV_CODEC_ID_SCTE_35) + return -1; + + interface = (struct scte_35_interface *)input->data; + init_node(&event,"event"); + add_varval_pair_uint32_t(&event, "event_id", interface->event_id); + add_varval_pair_uint32_t(&event, "duration", interface->duration); + add_varval_pair_uint64_t(&event, "pts", interface->pts); + if(interface->inout) + add_varval_pair_char(&event, "CUE", "in"); + else + add_varval_pair_char(&event, "CUE", "out"); + add_child(&ctx->xml_tree, &event); + + write_tree_as_data(&ctx->xml_tree, output); + remove_child(&ctx->xml_tree, &event); + dinit_node(&event); + return 0; +} +static const AVOption options[] = { + {NULL} +}; +static const AVClass cue_xml_dec_class = { + .class_name = "SCTE 35 Decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_cue_xml_encoder = { + .name = "cue_xml", + .long_name = NULL_IF_CONFIG_SMALL("XML Message Queue Ad Insertion"), + .type = AVMEDIA_TYPE_DATA, + .id = AV_CODEC_ID_CUE_XML, + .priv_data_size = sizeof(struct cue_xml_ctx), + .init = init_encoder, + .close = close_encoder, + .encode_data = encode, + .priv_class = &cue_xml_dec_class, +}; diff --git a/libavcodec/scte_35.c b/libavcodec/scte_35.c new file mode 100644 index 0000000..513ed7d --- /dev/null +++ b/libavcodec/scte_35.c @@ -0,0 +1,309 @@ +/* + * SCTE 35 decoder + * Copyright (c) 2014 Anshul Maheshwaari + * + * 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 + */ +/* + * Refrence Material Used + * + * ANSI/SCTE 35 2013 ( Digital Program Insertion Cueing Message for Cable ) + * + * SCTE 67 2014 (Recommended Practice for SCTE 35 + * Digital Program Insertion Cueing Message for Cable ) + */ + + + +#include "avcodec.h" +#include "bytestream.h" +#include "libavutil/opt.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/scte_35.h" +#include "libavutil/buffer_internal.h" + +#define SCTE_CMD_NULL 0x00 +#define SCTE_CMD_SCHEDULE 0x04 +#define SCTE_CMD_INSERT 0x05 +#define SCTE_CMD_SIGNAL 0x06 +#define SCTE_CMD_BANDWIDTH_RESERVATION 0x07 +struct scte_35_ctx { + AVClass *class; + uint64_t pts_adjustment; + uint32_t event_id; + int component_tag; + int64_t duration; + uint16_t u_program_id; + uint8_t avail_num; + uint8_t avail_expect; + /* flags */ + int splice_event_cancel_indicator; + int out_of_network_indicator; + int program_splice_flag; + int duration_flag; + int splice_immediate_flag; + int auto_return; +}; +static av_cold int init_decoder(AVCodecContext *avctx) +{ + struct scte_35_ctx *ctx = avctx->priv_data; + return 0; +} +static av_cold int close_decoder(AVCodecContext *avctx) +{ + struct scte_35_ctx *ctx = avctx->priv_data; + return 0; +} + +/** + * save the parsed time in ctx pts_time + @return length of buffer consumed +*/ +static int parse_splice_time(struct scte_35_ctx *ctx, const uint8_t *buf, uint64_t *pts) +{ + GetBitContext gb; + int ret; + init_get_bits(&gb, buf, 40); + /* is time specified */ + ret = get_bits(&gb, 1); + if(ret) { + skip_bits(&gb, 6); + *pts = get_bits64(&gb,33) + ctx->pts_adjustment; + av_log(ctx, AV_LOG_DEBUG, "time = %lld\n", *pts/90000); + return 5; + } else { + skip_bits(&gb, 7); + return 1; + } +} +static int parse_schedule_cmd(struct scte_35_ctx *ctx, const uint8_t *buf) +{ + const uint8_t *sbuf = buf; + av_log(ctx, AV_LOG_DEBUG, "Schedule cmd\n"); + return buf - sbuf; +} +/** + @return length of buffer used + */ +static int parse_insert_cmd(struct scte_35_ctx *ctx, const uint8_t *buf, AVBuffer *output) +{ + GetBitContext gb; + int ret; + const uint8_t *sbuf = buf; + struct scte_35_interface *iface; + + iface = av_mallocz(sizeof(struct scte_35_interface)); + if(!iface) + return AVERROR(ENOMEM); + output->data = (uint8_t*)iface; + output->size = sizeof(struct scte_35_interface); + output->free = av_buffer_default_free; + output->flags = AV_BUFFER_FLAG_READONLY; + + av_log(ctx, AV_LOG_DEBUG, "Insert cmd\n"); + ctx->event_id = AV_RB32(buf); + av_log(ctx, AV_LOG_DEBUG, "event_id = %x\n", ctx->event_id); + buf +=4; + ctx->splice_event_cancel_indicator = *buf & 0x80; + av_log(ctx, AV_LOG_DEBUG, "splice_event_cancel_indicator = %d\n", ctx->splice_event_cancel_indicator); + buf++; + + iface->event_id = ctx->event_id; + if (!ctx->splice_event_cancel_indicator) { + init_get_bits(&gb, buf, 8); + ctx->out_of_network_indicator = get_bits(&gb, 1); + ctx->program_splice_flag = get_bits(&gb, 1); + ctx->duration_flag = get_bits(&gb, 1); + ctx->splice_immediate_flag = get_bits(&gb, 1); + skip_bits(&gb, 4); + + } + buf++; + + + av_log(ctx, AV_LOG_DEBUG, "out_of_network_indicator = %d\n", ctx->out_of_network_indicator); + av_log(ctx, AV_LOG_DEBUG, "program_splice_flag = %d\n", ctx->program_splice_flag); + av_log(ctx, AV_LOG_DEBUG, "duration_flag = %d\n", ctx->duration_flag); + av_log(ctx, AV_LOG_DEBUG, "splice_immediate_flag = %d\n", ctx->splice_immediate_flag); + + iface->inout = ctx->out_of_network_indicator; + if (ctx->program_splice_flag && !ctx->splice_immediate_flag) { + ret = parse_splice_time(ctx, buf, &iface->pts); + buf += ret; + } + if ( ctx->program_splice_flag == 0) { + int comp_cnt = *buf++; + int i; + av_log(ctx, AV_LOG_DEBUG, "component_count = %d\n", comp_cnt); + for ( i = 0; i < comp_cnt; i++) { + ctx->component_tag = *buf++; + av_log(ctx, AV_LOG_DEBUG, "component_tag = %d\n", ctx->component_tag); + if (ctx->splice_immediate_flag) { + ret = parse_splice_time(ctx, buf, &iface->pts); + buf += ret; + } + } + } + if ( ctx->duration_flag ) { + init_get_bits(&gb, buf, 40); + ctx->auto_return = get_bits(&gb, 1); + av_log(ctx, AV_LOG_DEBUG, "autoreturn = %d\n", ctx->auto_return); + skip_bits(&gb, 6); + ctx->duration = get_bits64(&gb,33) + ctx->pts_adjustment; + av_log(ctx, AV_LOG_DEBUG, "duration = %lld\n", ctx->duration/90000); + buf += 5; + } + ctx->u_program_id = AV_RB16(buf); + av_log(ctx, AV_LOG_DEBUG, "u_program_id = %hd\n", ctx->u_program_id); + buf += 2; + ctx->avail_num = *buf++; + av_log(ctx, AV_LOG_DEBUG, "avail_num = %hhd\n", ctx->avail_num); + ctx->avail_expect = *buf++; + av_log(ctx, AV_LOG_DEBUG, "avail_expect = %hhd\n", ctx->avail_expect); + + return buf - sbuf; +} +static int parse_time_signal_cmd(struct scte_35_ctx *ctx, const uint8_t *buf) +{ + const uint8_t *sbuf = buf; + av_log(ctx, AV_LOG_DEBUG, "Time Signal cmd\n"); + return buf - sbuf; +} +static int parse_bandwidth_reservation_cmd(struct scte_35_ctx *ctx, const uint8_t *buf) +{ + const uint8_t *sbuf = buf; + av_log(ctx, AV_LOG_DEBUG, "Band Width reservation cmd\n"); + return buf - sbuf; +} + +static int decode(AVCodecContext *avctx, AVBuffer *output, + const AVPacket *avpkt) +{ + struct scte_35_ctx *ctx = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int len = avpkt->size; + int section_length; + int cmd_length; + uint8_t cmd_type; + int16_t tier; + GetBitContext gb; + int ret; + + if (!buf) + return AVERROR_EOF; + + /* check table id */ + if (*buf != 0xfc) + av_log(ctx, AV_LOG_ERROR, "Invalid SCTE packet\n"); + + init_get_bits(&gb, buf + 1, 104); + + /* section_syntax_indicator should be 0 */ + ret = get_bits(&gb,1); + if (ret) + av_log(ctx, AV_LOG_WARNING, "Section indicator should be 0, since MPEG short sections are to be used.\n"); + + /* private indicator */ + ret = get_bits(&gb,1); + if (ret) + av_log(ctx, AV_LOG_WARNING, "corrupt packet\n"); + + skip_bits(&gb,2); + + /* section length may be there */ + section_length = get_bits(&gb,12); + if( section_length > 4093) + if(ret) { + av_log(ctx, AV_LOG_ERROR, "Invalid length of section\n"); + return AVERROR_INVALIDDATA; + } + + /* protocol version */ + skip_bits(&gb,8); + + ret = get_bits(&gb,1); + if(ret) { + av_log(ctx, AV_LOG_ERROR, "Encrytion not yet supported\n"); + return AVERROR_PATCHWELCOME; + } + /* encryption algo */ + skip_bits(&gb,6); + + ctx->pts_adjustment = get_bits64(&gb, 33); + + /* cw_index: used in encryption */ + skip_bits(&gb,8); + + + /* tier */ + tier = get_bits(&gb,12); + if( (tier & 0xfff) == 0xfff) + tier = -1; + + cmd_length = get_bits(&gb,12); + if((cmd_length & 0xfff) == 0xfff ) + cmd_length = -1; + + cmd_type = get_bits(&gb,8); + switch(cmd_type) { + case SCTE_CMD_NULL: + av_log(ctx, AV_LOG_DEBUG, "NULL packet\n"); + break; + case SCTE_CMD_SCHEDULE: + ret = parse_schedule_cmd(ctx, buf + 14); + break; + case SCTE_CMD_INSERT: + ret = parse_insert_cmd(ctx, buf + 14, output); + break; + case SCTE_CMD_SIGNAL: + ret = parse_time_signal_cmd(ctx, buf + 14); + break; + case SCTE_CMD_BANDWIDTH_RESERVATION: + ret = parse_bandwidth_reservation_cmd(ctx, buf + 14); + break; + default: + break; + /* reserved yet */ + } + if(ret < 0) + goto fail; + buf += ret; + +fail: + return ret; +} +static const AVOption options[] = { + {NULL} +}; +static const AVClass scte_35_dec_class = { + .class_name = "SCTE 35 Decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_scte_35_decoder = { + .name = "scte_35", + .long_name = NULL_IF_CONFIG_SMALL("SCTE 35"), + .type = AVMEDIA_TYPE_DATA, + .id = AV_CODEC_ID_SCTE_35, + .priv_data_size = sizeof(struct scte_35_ctx), + .init = init_decoder, + .close = close_decoder, + .decode_data = decode, + .priv_class = &scte_35_dec_class, +}; diff --git a/libavcodec/scte_35.h b/libavcodec/scte_35.h new file mode 100644 index 0000000..63bbac5 --- /dev/null +++ b/libavcodec/scte_35.h @@ -0,0 +1,31 @@ +/* + * SCTE 35 decoder + * Copyright (c) 2014 Anshul Maheshwaari + * + * 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 SCTE_35_H +#define SCTE_35_H +struct scte_35_interface { + int32_t event_id; + uint64_t pts; + int64_t duration; + /* flag */ + int inout; + int cancel; +}; +#endif diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 1ec5cae..a490fbb 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -186,12 +186,12 @@ static av_cold void avcodec_init(void) int av_codec_is_encoder(const AVCodec *codec) { - return codec && (codec->encode_sub || codec->encode2); + return codec && (codec->encode_sub || codec->encode2 || codec->encode_data); } int av_codec_is_decoder(const AVCodec *codec) { - return codec && codec->decode; + return codec && ( codec->decode || codec->decode_data); } av_cold void avcodec_register(AVCodec *codec) @@ -2173,7 +2173,14 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, avctx->frame_number++; return ret; } - +int avcodec_encode_data(AVCodecContext *avctx, const AVBuffer *input, AVBuffer *output, + enum AVCodecID in_codec_id) +{ + int ret; + ret = avctx->codec->encode_data(avctx, input, output, in_codec_id); + avctx->frame_number++; + return ret; +} /** * Attempt to guess proper monotonic timestamps for decoded video frames * which might have incorrect times. Input timestamps may wrap around, in @@ -2624,6 +2631,26 @@ fail: return ret; } +int attribute_align_arg avcodec_decode_data(AVCodecContext *avctx, + AVBuffer *output, + const AVPacket *avpkt) +{ + AVCodecInternal *avci = avctx->internal; + int ret = 0; + + if (!avctx->codec) + return AVERROR(EINVAL); + if (avctx->codec->type != AVMEDIA_TYPE_DATA) { + av_log(avctx, AV_LOG_ERROR, "Invalid media type for data\n"); + return AVERROR(EINVAL); + } + + ret = avctx->codec->decode_data(avctx, output, avpkt); + + return ret; + + +} #define UTF8_MAX_BYTES 4 /* 5 and 6 bytes sequences should not be used */ static int recode_subtitle(AVCodecContext *avctx, AVPacket *outpkt, const AVPacket *inpkt) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 2e54ed1..7fd96ac 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1367,6 +1367,12 @@ typedef struct AVFormatContext { enum AVCodecID subtitle_codec_id; /** + * Forced Data codec_id. + * Demuxing: Set by user. + */ + enum AVCodecID data_codec_id; + + /** * Maximum amount of memory in bytes to use for the index of each stream. * If the index exceeds this size, entries will be discarded as * needed to maintain a smaller size. This can lead to slower or less @@ -1705,6 +1711,14 @@ typedef struct AVFormatContext { AVCodec *subtitle_codec; /** + * Forced data codec. + * This allows forcing a specific decoder, even when there are multiple with + * the same codec_id. + * Demuxing: Set by user via av_format_set_data_codec (NO direct access). + */ + AVCodec *data_codec; + + /** * Number of bytes to be written as padding in a metadata header. * Demuxing: Unused. * Muxing: Set by user via av_format_set_metadata_header_padding. @@ -1764,6 +1778,8 @@ AVCodec * av_format_get_audio_codec(const AVFormatContext *s); void av_format_set_audio_codec(AVFormatContext *s, AVCodec *c); AVCodec * av_format_get_subtitle_codec(const AVFormatContext *s); void av_format_set_subtitle_codec(AVFormatContext *s, AVCodec *c); +AVCodec * av_format_get_data_codec(const AVFormatContext *s); +void av_format_set_data_codec(AVFormatContext *s, AVCodec *c); int av_format_get_metadata_header_padding(const AVFormatContext *s); void av_format_set_metadata_header_padding(AVFormatContext *s, int c); void * av_format_get_opaque(const AVFormatContext *s); diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index f61388b..6971e93 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -57,6 +57,7 @@ enum MpegTSFilterType { MPEGTS_PES, MPEGTS_SECTION, MPEGTS_PCR, + MPEGTS_DATA, }; typedef struct MpegTSFilter MpegTSFilter; @@ -498,6 +499,11 @@ static MpegTSFilter *mpegts_open_pcr_filter(MpegTSContext *ts, unsigned int pid) return mpegts_open_filter(ts, pid, MPEGTS_PCR); } +static MpegTSFilter *mpegts_open_data_filter(MpegTSContext *ts, unsigned int pid) +{ + return mpegts_open_filter(ts, pid, MPEGTS_DATA); +} + static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) { int pid; @@ -676,6 +682,7 @@ static const StreamType ISO_types[] = { { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, + { 0x86, AVMEDIA_TYPE_DATA, AV_CODEC_ID_SCTE_35 }, { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, @@ -824,6 +831,12 @@ static void reset_pes_packet_state(PESContext *pes) av_buffer_unref(&pes->buffer); } +static void new_data_packet(const uint8_t *buffer, int len, AVPacket *pkt) +{ + av_init_packet(pkt); + pkt->data = buffer; + pkt->size = len; +} static void new_pes_packet(PESContext *pes, AVPacket *pkt) { av_init_packet(pkt); @@ -1886,7 +1899,20 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len pes->st->id = pes->pid; } st = pes->st; - } else if (stream_type != 0x13) { + } else if (stream_type == 0x86 ) { + int idx = ff_find_stream_index(ts->stream, pid); + if (idx >= 0) { + st = ts->stream->streams[idx]; + } else { + st = avformat_new_stream(ts->stream, NULL); + if (!st) + goto out; + st->id = pid; + st->codec->codec_type = AVMEDIA_TYPE_DATA; + mpegts_find_stream_type(st, stream_type, ISO_types); + mpegts_open_data_filter(ts, pid); + } + }else if (stream_type != 0x13 ) { if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably pes = add_pes_stream(ts, pid, pcr_pid); @@ -2222,14 +2248,17 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } } - } else { + } else if (tss->type == MPEGTS_DATA) { + /* may be pointer field is 0 and to be ignored*/ + p++; + new_data_packet(p,p_end - p, ts->pkt); + ts->stop_parse = 1; + } else if (tss->type == MPEGTS_PES) { int ret; // Note: The position here points actually behind the current packet. - if (tss->type == MPEGTS_PES) { - if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, + if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, pos - ts->raw_packet_size)) < 0) - return ret; - } + return ret; } return 0; @@ -2616,6 +2645,10 @@ static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt) ret = 0; break; } + } else if (ts->pids[i] && ts->pids[i]->type == MPEGTS_DATA) { + // ret = 0; + //ts->pkt->size = 0; + return ret; } } diff --git a/libavformat/utils.c b/libavformat/utils.c index 752270d..b8fef74 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -110,6 +110,7 @@ MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec) +MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, data_codec) MAKE_ACCESSORS(AVFormatContext, format, int, metadata_header_padding) MAKE_ACCESSORS(AVFormatContext, format, void *, opaque) MAKE_ACCESSORS(AVFormatContext, format, av_format_control_message, control_message_cb) -- 1.8.1.4
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel