diff mbox

[FFmpeg-devel] avformat/dashenc: Only use temporary files when outputting to file protocol

Message ID 1486498832-66828-1-git-send-email-thomas@ustudio.com
State Accepted
Commit 5fe2b437023f46394dfd4a4c991aa4a3ac3d8e72
Headers show

Commit Message

Thomas Stephens Feb. 7, 2017, 8:20 p.m. UTC
Skips using temporary files when outputting to a protocol other than
"file", which enables dash to output content over network
protocols. The logic has been copied from the HLS format.
---
 libavformat/dashenc.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

Comments

Thomas Stephens Feb. 14, 2017, 1:14 p.m. UTC | #1
Has anybody had a chance to look at this patch?

Thanks,
--Thomas

On Tue, Feb 7, 2017, 2:20 PM Thomas Stephens <thomas@ustudio.com> wrote:

> Skips using temporary files when outputting to a protocol other than
> "file", which enables dash to output content over network
> protocols. The logic has been copied from the HLS format.
> ---
>  libavformat/dashenc.c | 29 +++++++++++++++++++++++------
>  1 file changed, 23 insertions(+), 6 deletions(-)
>
> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> index 534fa75..fa56505 100644
> --- a/libavformat/dashenc.c
> +++ b/libavformat/dashenc.c
> @@ -444,9 +444,15 @@ static int write_manifest(AVFormatContext *s, int
> final)
>      AVIOContext *out;
>      char temp_filename[1024];
>      int ret, i;
> +    const char *proto = avio_find_protocol_name(s->filename);
> +    int use_rename = proto && !strcmp(proto, "file");
> +    static unsigned int warned_non_file = 0;
>      AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
>
> -    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
> +    if (!use_rename && !warned_non_file++)
> +        av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol,
> this may lead to races and temporary partial files\n");
> +
> +    snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp"
> : "%s", s->filename);
>      ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
>      if (ret < 0) {
>          av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n",
> temp_filename);
> @@ -548,7 +554,11 @@ static int write_manifest(AVFormatContext *s, int
> final)
>      avio_printf(out, "</MPD>\n");
>      avio_flush(out);
>      ff_format_io_close(s, &out);
> -    return avpriv_io_move(temp_filename, s->filename);
> +
> +    if (use_rename)
> +        return avpriv_io_move(temp_filename, s->filename);
> +
> +    return 0;
>  }
>
>  static int dash_init(AVFormatContext *s)
> @@ -796,6 +806,10 @@ static int dash_flush(AVFormatContext *s, int final,
> int stream)
>  {
>      DASHContext *c = s->priv_data;
>      int i, ret = 0;
> +
> +    const char *proto = avio_find_protocol_name(s->filename);
> +    int use_rename = proto && !strcmp(proto, "file");
> +
>      int cur_flush_segment_index = 0;
>      if (stream >= 0)
>          cur_flush_segment_index = c->streams[stream].segment_index;
> @@ -833,7 +847,7 @@ static int dash_flush(AVFormatContext *s, int final,
> int stream)
>          if (!c->single_file) {
>              dash_fill_tmpl_params(filename, sizeof(filename),
> c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
>              snprintf(full_path, sizeof(full_path), "%s%s", c->dirname,
> filename);
> -            snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
> +            snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp"
> : "%s", full_path);
>              ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE,
> NULL);
>              if (ret < 0)
>                  break;
> @@ -851,9 +865,12 @@ static int dash_flush(AVFormatContext *s, int final,
> int stream)
>              find_index_range(s, full_path, start_pos, &index_length);
>          } else {
>              ff_format_io_close(s, &os->out);
> -            ret = avpriv_io_move(temp_path, full_path);
> -            if (ret < 0)
> -                break;
> +
> +            if (use_rename) {
> +                ret = avpriv_io_move(temp_path, full_path);
> +                if (ret < 0)
> +                    break;
> +            }
>          }
>          add_segment(os, filename, os->start_pts, os->max_pts -
> os->start_pts, start_pos, range_length, index_length);
>          av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d
> written to: %s\n", i, os->segment_index, full_path);
> --
> 2.5.0
>
>
Steven Liu Feb. 14, 2017, 2:18 p.m. UTC | #2
2017-02-14 21:14 GMT+08:00 Thomas Stephens <thomas@ustudio.com>:

> Has anybody had a chance to look at this patch?
>
> Thanks,
> --Thomas
>
> On Tue, Feb 7, 2017, 2:20 PM Thomas Stephens <thomas@ustudio.com> wrote:
>
> > Skips using temporary files when outputting to a protocol other than
> > "file", which enables dash to output content over network
> > protocols. The logic has been copied from the HLS format.
> > ---
> >  libavformat/dashenc.c | 29 +++++++++++++++++++++++------
> >  1 file changed, 23 insertions(+), 6 deletions(-)
> >
> > diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> > index 534fa75..fa56505 100644
> > --- a/libavformat/dashenc.c
> > +++ b/libavformat/dashenc.c
> > @@ -444,9 +444,15 @@ static int write_manifest(AVFormatContext *s, int
> > final)
> >      AVIOContext *out;
> >      char temp_filename[1024];
> >      int ret, i;
> > +    const char *proto = avio_find_protocol_name(s->filename);
> > +    int use_rename = proto && !strcmp(proto, "file");
> > +    static unsigned int warned_non_file = 0;
> >      AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL,
> 0);
> >
> > -    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp",
> s->filename);
> > +    if (!use_rename && !warned_non_file++)
> > +        av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol,
> > this may lead to races and temporary partial files\n");
> > +
> > +    snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp"
> > : "%s", s->filename);
> >      ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
> >      if (ret < 0) {
> >          av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n",
> > temp_filename);
> > @@ -548,7 +554,11 @@ static int write_manifest(AVFormatContext *s, int
> > final)
> >      avio_printf(out, "</MPD>\n");
> >      avio_flush(out);
> >      ff_format_io_close(s, &out);
> > -    return avpriv_io_move(temp_filename, s->filename);
> > +
> > +    if (use_rename)
> > +        return avpriv_io_move(temp_filename, s->filename);
> > +
> > +    return 0;
> >  }
> >
> >  static int dash_init(AVFormatContext *s)
> > @@ -796,6 +806,10 @@ static int dash_flush(AVFormatContext *s, int final,
> > int stream)
> >  {
> >      DASHContext *c = s->priv_data;
> >      int i, ret = 0;
> > +
> > +    const char *proto = avio_find_protocol_name(s->filename);
> > +    int use_rename = proto && !strcmp(proto, "file");
> > +
> >      int cur_flush_segment_index = 0;
> >      if (stream >= 0)
> >          cur_flush_segment_index = c->streams[stream].segment_index;
> > @@ -833,7 +847,7 @@ static int dash_flush(AVFormatContext *s, int final,
> > int stream)
> >          if (!c->single_file) {
> >              dash_fill_tmpl_params(filename, sizeof(filename),
> > c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
> >              snprintf(full_path, sizeof(full_path), "%s%s", c->dirname,
> > filename);
> > -            snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
> > +            snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp"
> > : "%s", full_path);
> >              ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE,
> > NULL);
> >              if (ret < 0)
> >                  break;
> > @@ -851,9 +865,12 @@ static int dash_flush(AVFormatContext *s, int final,
> > int stream)
> >              find_index_range(s, full_path, start_pos, &index_length);
> >          } else {
> >              ff_format_io_close(s, &os->out);
> > -            ret = avpriv_io_move(temp_path, full_path);
> > -            if (ret < 0)
> > -                break;
> > +
> > +            if (use_rename) {
> > +                ret = avpriv_io_move(temp_path, full_path);
> > +                if (ret < 0)
> > +                    break;
> > +            }
> >          }
> >          add_segment(os, filename, os->start_pts, os->max_pts -
> > os->start_pts, start_pos, range_length, index_length);
> >          av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d
> > written to: %s\n", i, os->segment_index, full_path);
> > --
> > 2.5.0
> >
> >
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


LGTM


and looks like segments, hlsenc
Michael Niedermayer Feb. 14, 2017, 3:53 p.m. UTC | #3
On Tue, Feb 14, 2017 at 10:18:02PM +0800, Steven Liu wrote:
> 2017-02-14 21:14 GMT+08:00 Thomas Stephens <thomas@ustudio.com>:
> 
> > Has anybody had a chance to look at this patch?
> >
> > Thanks,
> > --Thomas
> >
> > On Tue, Feb 7, 2017, 2:20 PM Thomas Stephens <thomas@ustudio.com> wrote:
> >
> > > Skips using temporary files when outputting to a protocol other than
> > > "file", which enables dash to output content over network
> > > protocols. The logic has been copied from the HLS format.
> > > ---
> > >  libavformat/dashenc.c | 29 +++++++++++++++++++++++------
> > >  1 file changed, 23 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> > > index 534fa75..fa56505 100644
> > > --- a/libavformat/dashenc.c
> > > +++ b/libavformat/dashenc.c
> > > @@ -444,9 +444,15 @@ static int write_manifest(AVFormatContext *s, int
> > > final)
> > >      AVIOContext *out;
> > >      char temp_filename[1024];
> > >      int ret, i;
> > > +    const char *proto = avio_find_protocol_name(s->filename);
> > > +    int use_rename = proto && !strcmp(proto, "file");
> > > +    static unsigned int warned_non_file = 0;
> > >      AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL,
> > 0);
> > >
> > > -    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp",
> > s->filename);
> > > +    if (!use_rename && !warned_non_file++)
> > > +        av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol,
> > > this may lead to races and temporary partial files\n");
> > > +
> > > +    snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp"
> > > : "%s", s->filename);
> > >      ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
> > >      if (ret < 0) {
> > >          av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n",
> > > temp_filename);
> > > @@ -548,7 +554,11 @@ static int write_manifest(AVFormatContext *s, int
> > > final)
> > >      avio_printf(out, "</MPD>\n");
> > >      avio_flush(out);
> > >      ff_format_io_close(s, &out);
> > > -    return avpriv_io_move(temp_filename, s->filename);
> > > +
> > > +    if (use_rename)
> > > +        return avpriv_io_move(temp_filename, s->filename);
> > > +
> > > +    return 0;
> > >  }
> > >
> > >  static int dash_init(AVFormatContext *s)
> > > @@ -796,6 +806,10 @@ static int dash_flush(AVFormatContext *s, int final,
> > > int stream)
> > >  {
> > >      DASHContext *c = s->priv_data;
> > >      int i, ret = 0;
> > > +
> > > +    const char *proto = avio_find_protocol_name(s->filename);
> > > +    int use_rename = proto && !strcmp(proto, "file");
> > > +
> > >      int cur_flush_segment_index = 0;
> > >      if (stream >= 0)
> > >          cur_flush_segment_index = c->streams[stream].segment_index;
> > > @@ -833,7 +847,7 @@ static int dash_flush(AVFormatContext *s, int final,
> > > int stream)
> > >          if (!c->single_file) {
> > >              dash_fill_tmpl_params(filename, sizeof(filename),
> > > c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
> > >              snprintf(full_path, sizeof(full_path), "%s%s", c->dirname,
> > > filename);
> > > -            snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
> > > +            snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp"
> > > : "%s", full_path);
> > >              ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE,
> > > NULL);
> > >              if (ret < 0)
> > >                  break;
> > > @@ -851,9 +865,12 @@ static int dash_flush(AVFormatContext *s, int final,
> > > int stream)
> > >              find_index_range(s, full_path, start_pos, &index_length);
> > >          } else {
> > >              ff_format_io_close(s, &os->out);
> > > -            ret = avpriv_io_move(temp_path, full_path);
> > > -            if (ret < 0)
> > > -                break;
> > > +
> > > +            if (use_rename) {
> > > +                ret = avpriv_io_move(temp_path, full_path);
> > > +                if (ret < 0)
> > > +                    break;
> > > +            }
> > >          }
> > >          add_segment(os, filename, os->start_pts, os->max_pts -
> > > os->start_pts, start_pos, range_length, index_length);
> > >          av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d
> > > written to: %s\n", i, os->segment_index, full_path);
> > > --
> > > 2.5.0
> > >
> > >
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> 
> 
> LGTM

will apply

thx

[...]
--
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Breaking DRM is a little like attempting to break through a door even
though the window is wide open and the only thing in the house is a bunch
of things you dont want and which you would get tomorrow for free anyway
diff mbox

Patch

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 534fa75..fa56505 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -444,9 +444,15 @@  static int write_manifest(AVFormatContext *s, int final)
     AVIOContext *out;
     char temp_filename[1024];
     int ret, i;
+    const char *proto = avio_find_protocol_name(s->filename);
+    int use_rename = proto && !strcmp(proto, "file");
+    static unsigned int warned_non_file = 0;
     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
 
-    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
+    if (!use_rename && !warned_non_file++)
+        av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
+
+    snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
     ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
@@ -548,7 +554,11 @@  static int write_manifest(AVFormatContext *s, int final)
     avio_printf(out, "</MPD>\n");
     avio_flush(out);
     ff_format_io_close(s, &out);
-    return avpriv_io_move(temp_filename, s->filename);
+
+    if (use_rename)
+        return avpriv_io_move(temp_filename, s->filename);
+
+    return 0;
 }
 
 static int dash_init(AVFormatContext *s)
@@ -796,6 +806,10 @@  static int dash_flush(AVFormatContext *s, int final, int stream)
 {
     DASHContext *c = s->priv_data;
     int i, ret = 0;
+
+    const char *proto = avio_find_protocol_name(s->filename);
+    int use_rename = proto && !strcmp(proto, "file");
+
     int cur_flush_segment_index = 0;
     if (stream >= 0)
         cur_flush_segment_index = c->streams[stream].segment_index;
@@ -833,7 +847,7 @@  static int dash_flush(AVFormatContext *s, int final, int stream)
         if (!c->single_file) {
             dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
             snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
-            snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
+            snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path);
             ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL);
             if (ret < 0)
                 break;
@@ -851,9 +865,12 @@  static int dash_flush(AVFormatContext *s, int final, int stream)
             find_index_range(s, full_path, start_pos, &index_length);
         } else {
             ff_format_io_close(s, &os->out);
-            ret = avpriv_io_move(temp_path, full_path);
-            if (ret < 0)
-                break;
+
+            if (use_rename) {
+                ret = avpriv_io_move(temp_path, full_path);
+                if (ret < 0)
+                    break;
+            }
         }
         add_segment(os, filename, os->start_pts, os->max_pts - os->start_pts, start_pos, range_length, index_length);
         av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, full_path);