Re: [FFmpeg-devel] [PATCH v3 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse
>On 11/24/17, 9:44 AM, "刘歧"wrote: > > >> 在 2017年11月24日,11:55,Karthick J 写道: >> >> --- >> libavformat/hlsenc.c | 238 >> +++ >> libavformat/hlsenc.h | 68 +++ >> 2 files changed, 194 insertions(+), 112 deletions(-) >> create mode 100644 libavformat/hlsenc.h >[…] >I suggest move the ff_ functions to a common file, because the hlsenc file >modify frequently, >there have risk to be modify by other contributor, these functions maybe need >design clearly, >it is used only by hlsenc and dashenc, i cannot sure it be used by other >module future, >so modify it is hard work for the modules after this commit. >Move them to segment_common.c or a good filename.c maybe better than in hlsenc. >What about your mind? Thanks for the reply. I have segregated ff_ functions into a separate .c file as you suggested, in patchset v4. > >Thanks regards, Karthick ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH v3 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse
> 在 2017年11月24日,11:55,Karthick J写道: > > --- > libavformat/hlsenc.c | 238 +++ > libavformat/hlsenc.h | 68 +++ > 2 files changed, 194 insertions(+), 112 deletions(-) > create mode 100644 libavformat/hlsenc.h > > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index 30ccf73..5c4f459 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -45,6 +45,7 @@ > > #include "avformat.h" > #include "avio_internal.h" > +#include "hlsenc.h" > #include "internal.h" > #include "os_support.h" > > @@ -73,36 +74,11 @@ typedef struct HLSSegment { > struct HLSSegment *next; > } HLSSegment; > > -typedef enum HLSFlags { > -// Generate a single media file and use byte ranges in the playlist. > -HLS_SINGLE_FILE = (1 << 0), > -HLS_DELETE_SEGMENTS = (1 << 1), > -HLS_ROUND_DURATIONS = (1 << 2), > -HLS_DISCONT_START = (1 << 3), > -HLS_OMIT_ENDLIST = (1 << 4), > -HLS_SPLIT_BY_TIME = (1 << 5), > -HLS_APPEND_LIST = (1 << 6), > -HLS_PROGRAM_DATE_TIME = (1 << 7), > -HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in > segment filenames when use_localtime e.g.: %%03d > -HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment > duration (microsec) in segment filenames when use_localtime e.g.: %%09t > -HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size > (bytes) in segment filenames when use_localtime e.g.: %%014s > -HLS_TEMP_FILE = (1 << 11), > -HLS_PERIODIC_REKEY = (1 << 12), > -HLS_INDEPENDENT_SEGMENTS = (1 << 13), > -} HLSFlags; > - > typedef enum { > SEGMENT_TYPE_MPEGTS, > SEGMENT_TYPE_FMP4, > } SegmentType; > > -typedef enum { > -PLAYLIST_TYPE_NONE, > -PLAYLIST_TYPE_EVENT, > -PLAYLIST_TYPE_VOD, > -PLAYLIST_TYPE_NB, > -} PlaylistType; > - > typedef struct VariantStream { > unsigned number; > int64_t sequence; > @@ -207,6 +183,113 @@ typedef struct HLSContext { > unsigned int master_publish_rate; > } HLSContext; > > +void ff_hls_write_playlist_version(AVIOContext *out, int version) { > +if (!out) > +return; > +avio_printf(out, "#EXTM3U\n"); > +avio_printf(out, "#EXT-X-VERSION:%d\n", version); > +} > + > +void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, > + int bandwidth, char *filename) { > +if (!out || !filename) > +return; > + > +if (!bandwidth) { > +av_log(NULL, AV_LOG_WARNING, > +"Bandwidth info not available, set audio and video > bitrates\n"); > +return; > +} > + > +avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth); > +if (st && st->codecpar->width > 0 && st->codecpar->height > 0) > +avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, > +st->codecpar->height); > +avio_printf(out, "\n%s\n\n", filename); > +} > + > +void ff_hls_write_playlist_header(AVIOContext *out, int version, int > allowcache, > + int target_duration, int64_t sequence, > + uint32_t playlist_type) { > +if (!out) > +return; > +ff_hls_write_playlist_version(out, version); > +if (allowcache == 0 || allowcache == 1) { > +avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", allowcache == 0 ? "NO" : > "YES"); > +} > +avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration); > +avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); > +av_log(NULL, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", > sequence); > + > +if (playlist_type == PLAYLIST_TYPE_EVENT) { > +avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); > +} else if (playlist_type == PLAYLIST_TYPE_VOD) { > +avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n"); > +} > +} > + > +void ff_hls_write_init_file(AVIOContext *out, char *filename, > +int byterange_mode, int64_t size, int64_t pos) { > +avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename); > +if (byterange_mode) { > +avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos); > +} > +avio_printf(out, "\n"); > +} > + > +void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, > +int byterange_mode, uint32_t flags, double > duration, > +int64_t size, int64_t pos, //Used only if > HLS_SINGLE_FILE flag is set > +char *baseurl, //Ignored if NULL > +char *filename, double *prog_date_time) { > +if (!out || !filename) > +return; > + > +if (insert_discont) { > +avio_printf(out, "#EXT-X-DISCONTINUITY\n"); > +} > +if (flags & HLS_ROUND_DURATIONS) > +avio_printf(out, "#EXTINF:%ld,\n", lrint(duration)); > +else > +avio_printf(out, "#EXTINF:%f,\n", duration); > +if
[FFmpeg-devel] [PATCH v3 1/2] avformat/hlsenc: Modularized playlist creation to allow reuse
--- libavformat/hlsenc.c | 238 +++ libavformat/hlsenc.h | 68 +++ 2 files changed, 194 insertions(+), 112 deletions(-) create mode 100644 libavformat/hlsenc.h diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 30ccf73..5c4f459 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -45,6 +45,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "hlsenc.h" #include "internal.h" #include "os_support.h" @@ -73,36 +74,11 @@ typedef struct HLSSegment { struct HLSSegment *next; } HLSSegment; -typedef enum HLSFlags { -// Generate a single media file and use byte ranges in the playlist. -HLS_SINGLE_FILE = (1 << 0), -HLS_DELETE_SEGMENTS = (1 << 1), -HLS_ROUND_DURATIONS = (1 << 2), -HLS_DISCONT_START = (1 << 3), -HLS_OMIT_ENDLIST = (1 << 4), -HLS_SPLIT_BY_TIME = (1 << 5), -HLS_APPEND_LIST = (1 << 6), -HLS_PROGRAM_DATE_TIME = (1 << 7), -HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime e.g.: %%03d -HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime e.g.: %%09t -HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s -HLS_TEMP_FILE = (1 << 11), -HLS_PERIODIC_REKEY = (1 << 12), -HLS_INDEPENDENT_SEGMENTS = (1 << 13), -} HLSFlags; - typedef enum { SEGMENT_TYPE_MPEGTS, SEGMENT_TYPE_FMP4, } SegmentType; -typedef enum { -PLAYLIST_TYPE_NONE, -PLAYLIST_TYPE_EVENT, -PLAYLIST_TYPE_VOD, -PLAYLIST_TYPE_NB, -} PlaylistType; - typedef struct VariantStream { unsigned number; int64_t sequence; @@ -207,6 +183,113 @@ typedef struct HLSContext { unsigned int master_publish_rate; } HLSContext; +void ff_hls_write_playlist_version(AVIOContext *out, int version) { +if (!out) +return; +avio_printf(out, "#EXTM3U\n"); +avio_printf(out, "#EXT-X-VERSION:%d\n", version); +} + +void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, + int bandwidth, char *filename) { +if (!out || !filename) +return; + +if (!bandwidth) { +av_log(NULL, AV_LOG_WARNING, +"Bandwidth info not available, set audio and video bitrates\n"); +return; +} + +avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth); +if (st && st->codecpar->width > 0 && st->codecpar->height > 0) +avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, +st->codecpar->height); +avio_printf(out, "\n%s\n\n", filename); +} + +void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, + int target_duration, int64_t sequence, + uint32_t playlist_type) { +if (!out) +return; +ff_hls_write_playlist_version(out, version); +if (allowcache == 0 || allowcache == 1) { +avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", allowcache == 0 ? "NO" : "YES"); +} +avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration); +avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); +av_log(NULL, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); + +if (playlist_type == PLAYLIST_TYPE_EVENT) { +avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); +} else if (playlist_type == PLAYLIST_TYPE_VOD) { +avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n"); +} +} + +void ff_hls_write_init_file(AVIOContext *out, char *filename, +int byterange_mode, int64_t size, int64_t pos) { +avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename); +if (byterange_mode) { +avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos); +} +avio_printf(out, "\n"); +} + +void ff_hls_write_file_entry(AVIOContext *out, int insert_discont, +int byterange_mode, uint32_t flags, double duration, +int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set +char *baseurl, //Ignored if NULL +char *filename, double *prog_date_time) { +if (!out || !filename) +return; + +if (insert_discont) { +avio_printf(out, "#EXT-X-DISCONTINUITY\n"); +} +if (flags & HLS_ROUND_DURATIONS) +avio_printf(out, "#EXTINF:%ld,\n", lrint(duration)); +else +avio_printf(out, "#EXTINF:%f,\n", duration); +if (byterange_mode) +avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", size, pos); + +if ((flags & HLS_PROGRAM_DATE_TIME) && prog_date_time) { +time_t tt, wrongsecs; +int milli; +struct tm *tm, tmpbuf; +char buf0[128], buf1[128]; +tt =