04.10.2016, 02:14, Carlos Fernandez Sanz kirjoitti: > From: Carlos Fernandez <car...@ccextractor.org> > > Signed-off-by: Carlos Fernandez <car...@ccextractor.org> > --- > libavformat/Makefile | 2 +- > libavformat/hlsenc.c | 108 +++++++++-- > libavformat/scte_35.c | 527 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > libavformat/scte_35.h | 86 ++++++++ > 4 files changed, 701 insertions(+), 22 deletions(-) > create mode 100644 libavformat/scte_35.c > create mode 100644 libavformat/scte_35.h > > diff --git a/libavformat/Makefile b/libavformat/Makefile > index 5d827d31..9218606 100644 > --- a/libavformat/Makefile > +++ b/libavformat/Makefile > @@ -205,7 +205,7 @@ OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o > OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o > OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o > OBJS-$(CONFIG_HLS_DEMUXER) += hls.o > -OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o > +OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o scte_35.o > OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o > OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o > OBJS-$(CONFIG_ICO_MUXER) += icoenc.o > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index c161937..44259ec 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -38,6 +38,7 @@ > #include "avio_internal.h" > #include "internal.h" > #include "os_support.h" > +#include "scte_35.h" > > #define KEYSIZE 16 > #define LINE_BUFFER_SIZE 1024 > @@ -48,6 +49,10 @@ typedef struct HLSSegment { > double duration; /* in seconds */ > int64_t pos; > int64_t size; > + struct scte_35_event *event; > + int out;
At least 'out' should be documented (or renamed) here as it is not obvious what it means. > + int adv_count; > + int64_t start_pts; > > char key_uri[LINE_BUFFER_SIZE + 1]; > char iv_string[KEYSIZE*2 + 1]; > @@ -92,6 +97,8 @@ typedef struct HLSContext { > uint32_t flags; // enum HLSFlags > uint32_t pl_type; // enum PlaylistType > char *segment_filename; > + char *adv_filename; > + char *adv_subfilename; > > int use_localtime; ///< flag to expand filename with localtime > int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename > @@ -108,6 +115,8 @@ typedef struct HLSContext { > int nb_entries; > int discontinuity_set; > > + int adv_count; > + struct scte_35_interface *scte_iface; > HLSSegment *segments; > HLSSegment *last_segment; > HLSSegment *old_segments; > @@ -241,6 +250,8 @@ static int hls_delete_old_segments(HLSContext *hls) { > av_freep(&path); > previous_segment = segment; > segment = previous_segment->next; > + if (hls->scte_iface) > + hls->scte_iface->unref_scte35_event(&previous_segment->event); > av_free(previous_segment); > } > > @@ -360,8 +371,8 @@ static int hls_mux_init(AVFormatContext *s) > } > > /* Create a new segment and append it to the segment list */ > -static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, > double duration, > - int64_t pos, int64_t size) > +static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, > double duration, int64_t pos, > + int64_t start_pts, struct scte_35_event > *event, int64_t size) > { > HLSSegment *en = av_malloc(sizeof(*en)); > char *tmp, *p; > @@ -397,9 +408,23 @@ static int hls_append_segment(struct AVFormatContext *s, > HLSContext *hls, double > > en->duration = duration; > en->pos = pos; > + en->event = event; > en->size = size; > + en->start_pts = start_pts; > en->next = NULL; > > + if (hls->scte_iface) { > + if (hls->scte_iface->event_state == EVENT_OUT_CONT) { > + en->adv_count = hls->adv_count;; Double semicolon. > + hls->adv_count++; > + en->out = hls->scte_iface->event_state; > + } else { > + hls->adv_count = 0; > + en->out = hls->scte_iface->event_state; Assignment could be moved outside the if condition. > + } > + } > + > + > if (hls->key_info_file) { > av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri)); > av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string)); > @@ -473,7 +498,7 @@ static int parse_playlist(AVFormatContext *s, const char > *url) > new_start_pos = avio_tell(hls->avf->pb); > hls->size = new_start_pos - hls->start_pos; > av_strlcpy(hls->avf->filename, line, sizeof(line)); > - ret = hls_append_segment(s, hls, hls->duration, > hls->start_pos, hls->size); > + ret = hls_append_segment(s, hls, hls->duration, > hls->start_pos, 0, NULL, hls->size); > if (ret < 0) > goto fail; > hls->start_pos = new_start_pos; > @@ -603,9 +628,23 @@ static int hls_window(AVFormatContext *s, int last) > avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, > milli, buf1); > prog_date_time += en->duration; > } > - if (hls->baseurl) > - avio_printf(out, "%s", hls->baseurl); > - avio_printf(out, "%s\n", en->filename); > + if (hls->scte_iface && (en->event || en->out) ) { Drop extra space between ')'. Same for other instances. > + char *str; > + char fname[1024] = ""; > + if (hls->adv_filename) { > + str = hls->scte_iface->get_hls_string(hls->scte_iface, > en->event, hls->adv_filename, en->out, en->adv_count, en->start_pts); > + } else { > + if (hls->baseurl) > + strncat(fname, hls->baseurl, 1024); > + strncat(fname, en->filename, 1024 - strlen(fname) ); Still missing sizeof (Michael's comment on Aug 10). strncat(fname, hls->baseurl, sizeof(fname)); [...] > diff --git a/libavformat/scte_35.c b/libavformat/scte_35.c > new file mode 100644 > index 0000000..1a01d14 > --- /dev/null > +++ b/libavformat/scte_35.c > @@ -0,0 +1,527 @@ > +/* > + * SCTE 35 decoder > + * Copyright (c) 2016 Carlos Fernandez > + * > + * 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 Reference material: > + * > + * 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) > + */ > + > + > + [...] > diff --git a/libavformat/scte_35.h b/libavformat/scte_35.h > new file mode 100644 > index 0000000..cac49ea > --- /dev/null > +++ b/libavformat/scte_35.h > @@ -0,0 +1,86 @@ > +/* > + * SCTE-35 parser > + * Copyright (c) 2016 Carlos Fernandez > + * > + * 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_SCTE_35_H > +#define AVFORMAT_SCTE_35_H > + > +#include "libavutil/bprint.h" > + > +struct scte_35_event { > + /* ID given for each seprate event */ > + int32_t id; > + /* pts specify time when event starts */ > + uint64_t in_pts; > + uint64_t nearest_in_pts; > + /* pts specify ehen events end */ > + uint64_t out_pts; > + /* duration of the event */ > + int64_t duration; > + int64_t start_pos; > + int running; > + int ref_count; > + /* to traverse the list of events */ > + struct scte_35_event *next; > + struct scte_35_event *prev; > +}; > + > +enum event_state { > + /* NO event */ > + EVENT_NONE, > + /* Commercials need to end */ > + EVENT_IN, > + /* Commercials can start from here */ > + EVENT_OUT, > + /* commercial can continue */ > + EVENT_OUT_CONT, > +}; > + > +struct scte_35_interface { > + /* contain all the events */ > + struct scte_35_event *event_list; > + /* state of current event */ > + enum event_state event_state; > + /* time base of pts used in parser */ > + AVRational timebase; > + struct scte_35_event *current_event; > + /* saved previous state to correctly transition > + the event state */ > + int prev_event_state; > + //TODO use AV_BASE64_SIZE to dynamically allocate the array > + char pkt_base64[1024]; > + /* keep context of its parent for log */ > + void *parent; > + /* general purpose str */ > + AVBPrint avbstr; > + > + void (*update_video_pts)(struct scte_35_interface *iface, uint64_t pts); > + struct scte_35_event* (*update_event_state)(struct scte_35_interface > *iface); > + char* (*get_hls_string)(struct scte_35_interface *iface, struct > scte_35_event *event, > + const char *adv_filename, int out_state, int seg_count, > int64_t pos); > + > + void (*unref_scte35_event)(struct scte_35_event **event); > + void (*ref_scte35_event)(struct scte_35_event *event); Function pointers are not useful here as they always point to the same functions. Also, the members of this "interface" struct seem to be mostly scte_35.c internal stuff that shouldn't be in a header. What I'd probably do is to just call the functions directly, rename the scte_35_interface to scte_35_parser and move the struct definition to scte_35.c. > +}; > + > +int ff_parse_scte35_pkt(struct scte_35_interface *iface, const AVPacket > *avpkt); > + > +struct scte_35_interface* ff_alloc_scte35_parser(void *parent, AVRational > timebase); > +void ff_delete_scte35_parser(struct scte_35_interface* iface); > +#endif > -- Anssi Hannula _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel