On 10/10/2012 12:04 AM, Martin Storsjö wrote:
> On Tue, 9 Oct 2012, Luca Barbato wrote:
> 
>> ---
>>
>> Should be ok now, Martin, did I overlook something else?
>>
>> libavformat/segment.c | 49
>> +++++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 47 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavformat/segment.c b/libavformat/segment.c
>> index 8ac04e2..9a53333 100644
>> --- a/libavformat/segment.c
>> +++ b/libavformat/segment.c
>> @@ -37,6 +37,7 @@ typedef struct {
>>     AVFormatContext *avf;
>>     char *format;          /**< Set by a private option. */
>>     char *list;            /**< Set by a private option. */
>> +    int  list_type;        /**< Set by a private option. */
>>     float time;            /**< Set by a private option. */
>>     int  size;             /**< Set by a private option. */
>>     int  wrap;             /**< Set by a private option. */
>> @@ -48,6 +49,11 @@ typedef struct {
>>     AVIOContext *pb;
>> } SegmentContext;
>>
>> +enum {
>> +    LIST_FLAT,
>> +    LIST_HLS
>> +};
>> +
>> static int segment_mux_init(AVFormatContext *s)
>> {
>>     SegmentContext *seg = s->priv_data;
>> @@ -72,6 +78,34 @@ static int segment_mux_init(AVFormatContext *s)
>>     return 0;
>> }
>>
>> +static void segment_hls_header(SegmentContext *seg)
>> +{
>> +    avio_printf(seg->pb, "#EXTM3U\n");
>> +
>> +    avio_printf(seg->pb, "#EXT-X-VERSION:3\n");
>> +
>> +    avio_printf(seg->pb, "#EXT-X-TARGETDURATION:%d\n", (int)seg->time);
>> +
>> +    avio_printf(seg->pb, "#EXT-X-MEDIA-SEQUENCE:%d\n",
>> +                FFMAX(0, seg->number - seg->size));
>> +}
> 
> The extra newlines just look weird here to me.
> 
>> +
>> +static void segment_hls_window(AVFormatContext *s)
>> +{
>> +    SegmentContext *seg = s->priv_data;
>> +    int i;
>> +    char buf[1024];
>> +
>> +    segment_hls_header(seg);
>> +    for (i = FFMAX(0, seg->number - seg->size);
>> +         i < seg->number; i++) {
>> +        avio_printf(seg->pb, "#EXTINF:%d,\n", (int)seg->time);
>> +        av_get_frame_filename(buf, sizeof(buf), s->filename, i);
>> +        avio_printf(seg->pb, "%s\n", buf);
>> +    }
>> +    avio_flush(seg->pb);
>> +}
>> +
>> static int segment_start(AVFormatContext *s, int write_header)
>> {
>>     SegmentContext *c = s->priv_data;
>> @@ -211,6 +245,10 @@ static int seg_write_header(AVFormatContext *s)
>>     }
>>
>>     if (seg->list) {
>> +        if (seg->list_type == LIST_HLS) {
>> +            segment_hls_header(seg);
>> +            avio_printf(seg->pb, "#EXTINF:%d,\n", (int)seg->time);
>> +        }
>>         avio_printf(seg->pb, "%s\n", oc->filename);
>>         avio_flush(seg->pb);
>>     }
>> @@ -252,14 +290,18 @@ static int seg_write_packet(AVFormatContext *s,
>> AVPacket *pkt)
>>         oc = seg->avf;
>>
>>         if (seg->list) {
>> -            avio_printf(seg->pb, "%s\n", oc->filename);
>> +            if (seg->list_type != LIST_HLS)
>> +//                avio_printf(seg->pb, "#EXTINF:%d,\n", (int)seg->time);
>> +                avio_printf(seg->pb, "%s\n", oc->filename);
>>             avio_flush(seg->pb);
>> -            if (seg->size && !(seg->number % seg->size)) {
>> +            if (seg->list_type == LIST_HLS ||
>> +                seg->size && !(seg->number % seg->size)) {
>>                 avio_close(seg->pb);
>>                 if ((ret = avio_open2(&seg->pb, seg->list,
>> AVIO_FLAG_WRITE,
>>                                       &s->interrupt_callback, NULL)) < 0)
>>                     goto fail;
>>             }
>> +            segment_hls_window(s);
> 
> Hmm, I guess this works, although it keeps the file open for writing all
> the time (instead of just opening, writing and closing each time you
> want to update it).
> 
>>         }
>>     }
>>
>> @@ -301,6 +343,9 @@ static const AVOption options[] = {
>>     { "segment_time",      "segment length in seconds",              
>> OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E },
>>     { "segment_list",      "output the segment list",                
>> OFFSET(list),    AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E },
>>     { "segment_list_size", "maximum number of playlist entries",     
>> OFFSET(size),    AV_OPT_TYPE_INT,    {.i64 = 5},     0, INT_MAX, E },
>> +    { "segment_list_type", "segment list format",                    
>> OFFSET(list_type),    AV_OPT_TYPE_INT,    {.i64 = 0},     0, 2, E,
>> "list_type" },
> 
> This could use LIST_FLAT instead of 0 as default here
> 
>> +    {   "flat",            "plain list (default)",                   
>> 0,               AV_OPT_TYPE_CONST,  {.i64 = LIST_FLAT}, 0, 0, E,
>> "list_type" },
>> +    {   "hls",             "Apple HTTP Live Streaming compatible",   
>> 0,               AV_OPT_TYPE_CONST,  {.i64 = LIST_HLS},  0, 0, E,
>> "list_type" },
>>     { "segment_wrap",      "number after which the index wraps",     
>> OFFSET(wrap),    AV_OPT_TYPE_INT,    {.i64 = 0},     0, INT_MAX, E },
>>     { "individual_header_trailer", "write header/trailer to each
>> segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 =
>> 1}, 0, 1, E },
>>     { "write_header_trailer", "write a header to the first segment and
>> a trailer to the last one", OFFSET(write_header_trailer),
>> AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E },
>> -- 
>> 1.7.12
> 
> You might want to write a list terminator to the file when the muxer is
> closed, to indicate to players that no more segments will be added (that
> is, the stream transitions from live to on-demand).
> 
> Other than that, this looks acceptable to me.
> 

Ok. Let me address those comments.

lu

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to