[FFmpeg-devel] [PATCH v2] lavf/dashenc: Write media trailers when DASH trailer is written.

Andrey Semashev andrey.semashev at gmail.com
Mon Dec 3 13:20:05 EET 2018


On 12/3/18 8:45 AM, Jeyapal, Karthick wrote:
> 
> On 11/30/18 11:42 AM, Jeyapal, Karthick wrote:
>>
>> On 11/29/18 11:58 PM, Andrey Semashev wrote:
>>> This commit ensures that all (potentially, long) filesystem activity is
>>> performed when the user calls av_write_trailer on the DASH libavformat
>>> context, not when freeing the context. Also, this defers media segment
>>> deletion until after the media trailers are written.
>>> ---
>>>   libavformat/dashenc.c | 82 ++++++++++++++++++++++++++++++-------------
>>>   1 file changed, 58 insertions(+), 24 deletions(-)
>>>
>>> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
>>> index 6ce70e0076..ecfd84a32c 100644
>>> --- a/libavformat/dashenc.c
>>> +++ b/libavformat/dashenc.c
>>> @@ -424,8 +424,6 @@ static void dash_free(AVFormatContext *s)
>>>           return;
>>>       for (i = 0; i < s->nb_streams; i++) {
>>>           OutputStream *os = &c->streams[i];
>>> -        if (os->ctx && os->ctx_inited)
>>> -            av_write_trailer(os->ctx);
>>>           if (os->ctx && os->ctx->pb)
>>>               ffio_free_dyn_buf(&os->ctx->pb);
>>>           ff_format_io_close(s, &os->out);
>>> @@ -1331,6 +1329,47 @@ static void dashenc_delete_file(AVFormatContext *s, char *filename) {
>>>       }
>>>   }
>>>   
>>> +static int dashenc_delete_segment_file(AVFormatContext *s, const char* file)
>>> +{
>>> +    DASHContext *c = s->priv_data;
>>> +    size_t dirname_len, file_len;
>>> +    char filename[1024];
>>> +
>>> +    dirname_len = strlen(c->dirname);
>>> +    if (dirname_len >= sizeof(filename)) {
>>> +        av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n",
>>> +            (uint64_t)dirname_len, c->dirname);
>>> +        return AVERROR(ENAMETOOLONG);
>>> +    }
>>> +
>>> +    memcpy(filename, c->dirname, dirname_len);
>>> +
>>> +    file_len = strlen(file);
>>> +    if ((dirname_len + file_len) >= sizeof(filename)) {
>>> +        av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n",
>>> +            (uint64_t)(dirname_len + file_len), c->dirname, file);
>>> +        return AVERROR(ENAMETOOLONG);
>>> +    }
>>> +
>>> +    memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero
>>> +    dashenc_delete_file(s, filename);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
>>> +{
>>> +    for (int i = 0; i < remove_count; ++i) {
>>> +        dashenc_delete_segment_file(s, os->segments[i]->file);
>>> +
>>> +        // Delete the segment regardless of whether the file was successfully deleted
>>> +        av_free(os->segments[i]);
>>> +    }
>>> +
>>> +    os->nb_segments -= remove_count;
>>> +    memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
>>> +}
>>> +
>>>   static int dash_flush(AVFormatContext *s, int final, int stream)
>>>   {
>>>       DASHContext *c = s->priv_data;
>>> @@ -1420,23 +1459,12 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
>>>           os->pos += range_length;
>>>       }
>>>   
>>> -    if (c->window_size || (final && c->remove_at_exit)) {
>>> +    if (c->window_size) {
>>>           for (i = 0; i < s->nb_streams; i++) {
>>>               OutputStream *os = &c->streams[i];
>>> -            int j;
>>> -            int remove = os->nb_segments - c->window_size - c->extra_window_size;
>>> -            if (final && c->remove_at_exit)
>>> -                remove = os->nb_segments;
>>> -            if (remove > 0) {
>>> -                for (j = 0; j < remove; j++) {
>>> -                    char filename[1024];
>>> -                    snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->segments[j]->file);
>>> -                    dashenc_delete_file(s, filename);
>>> -                    av_free(os->segments[j]);
>>> -                }
>>> -                os->nb_segments -= remove;
>>> -                memmove(os->segments, os->segments + remove, os->nb_segments * sizeof(*os->segments));
>>> -            }
>>> +            int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
>>> +            if (remove_count > 0)
>>> +                dashenc_delete_media_segments(s, os, remove_count);
>>>           }
>>>       }
>>>   
>>> @@ -1584,6 +1612,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
>>>   static int dash_write_trailer(AVFormatContext *s)
>>>   {
>>>       DASHContext *c = s->priv_data;
>>> +    int i;
>>>   
>>>       if (s->nb_streams > 0) {
>>>           OutputStream *os = &c->streams[0];
>>> @@ -1599,14 +1628,19 @@ static int dash_write_trailer(AVFormatContext *s)
>>>       }
>>>       dash_flush(s, 1, -1);
>>>   
>>> -    if (c->remove_at_exit) {
>>> -        char filename[1024];
>>> -        int i;
>>> -        for (i = 0; i < s->nb_streams; i++) {
>>> -            OutputStream *os = &c->streams[i];
>>> -            snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
>>> -            dashenc_delete_file(s, filename);
>>> +    for (i = 0; i < s->nb_streams; ++i) {
>>> +        OutputStream *os = &c->streams[i];
>>> +        if (os->ctx && os->ctx_inited) {
>>> +            av_write_trailer(os->ctx);
>>> +        }
>>> +
>>> +        if (c->remove_at_exit) {
>>> +            dashenc_delete_media_segments(s, os, os->nb_segments);
>>> +            dashenc_delete_segment_file(s, os->initfile);
>>>           }
>>> +    }
>>> +
>>> +    if (c->remove_at_exit) {
>>>           dashenc_delete_file(s, s->url);
>>>       }
>>>   
>> LGTM
> Hi Andrey,
> 
> Could you please rebase this patch with the latest git master. It is throwing some build errors with the latest version.

Yes, some code was made invalid by other patches. I've send the updated 
version.


More information about the ffmpeg-devel mailing list