diff mbox series

[FFmpeg-devel,07/25] fftools/ffmpeg: remove OutputStream.stream_copy

Message ID 20220803135844.16662-7-anton@khirnov.net
State New
Headers show
Series [FFmpeg-devel,01/25] fftools/ffmpeg_opt: move adding attachments out of open_output_file() | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov Aug. 3, 2022, 1:58 p.m. UTC
There are currently three possible modes for an output stream:
1) The stream is produced by encoding output from some filtergraph. This
   is true when ost->enc_ctx != NULL, or equivalently when
   ost->encoding_needed != 0.
2) The stream is produced by copying some input stream's packets. This
   is true when ost->enc_ctx == NULL && ost->source_index >= 0.
3) The stream is produced by attaching some file directly. This is true
   when ost->enc_ctx == NULL && ost->source_index < 0.

OutputStream.stream_copy is currently used to identify case 2), and
sometimes to confusingly (or even incorrectly) identify case 1). Remove
it, replacing its usage with checking enc_ctx/source_index values.
---
 fftools/ffmpeg.c     | 23 +++++++++--------------
 fftools/ffmpeg.h     |  1 -
 fftools/ffmpeg_opt.c | 33 ++++++++++++---------------------
 3 files changed, 21 insertions(+), 36 deletions(-)

Comments

Michael Niedermayer Aug. 4, 2022, 12:40 p.m. UTC | #1
On Wed, Aug 03, 2022 at 03:58:26PM +0200, Anton Khirnov wrote:
> There are currently three possible modes for an output stream:
> 1) The stream is produced by encoding output from some filtergraph. This
>    is true when ost->enc_ctx != NULL, or equivalently when
>    ost->encoding_needed != 0.
> 2) The stream is produced by copying some input stream's packets. This
>    is true when ost->enc_ctx == NULL && ost->source_index >= 0.
> 3) The stream is produced by attaching some file directly. This is true
>    when ost->enc_ctx == NULL && ost->source_index < 0.
> 
> OutputStream.stream_copy is currently used to identify case 2), and
> sometimes to confusingly (or even incorrectly) identify case 1). Remove
> it, replacing its usage with checking enc_ctx/source_index values.
> ---
>  fftools/ffmpeg.c     | 23 +++++++++--------------
>  fftools/ffmpeg.h     |  1 -
>  fftools/ffmpeg_opt.c | 33 ++++++++++++---------------------
>  3 files changed, 21 insertions(+), 36 deletions(-)

seems to break build with shared libs:

CC	fftools/ffmpeg.o
src/fftools/ffmpeg.c:405:32: warning: suggest braces around initialization of subobject [-Wmissing-braces]
    struct sigaction action = {0};
                               ^
                               {}
src/fftools/ffmpeg.c:1612:37: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_uint_least64_t *' (aka 'const _Atomic(uint_least64_t) *') invalid)
            uint64_t frame_number = atomic_load(&ost->packets_written);
                                    ^           ~~~~~~~~~~~~~~~~~~~~~
/usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
                            ^                 ~~~~~~
1 warning and 1 error generated.
src/ffbuild/common.mak:81: recipe for target 'fftools/ffmpeg.o' failed
make: *** [fftools/ffmpeg.o] Error 1

[...]
Andreas Rheinhardt Aug. 4, 2022, 12:54 p.m. UTC | #2
Michael Niedermayer:
> On Wed, Aug 03, 2022 at 03:58:26PM +0200, Anton Khirnov wrote:
>> There are currently three possible modes for an output stream:
>> 1) The stream is produced by encoding output from some filtergraph. This
>>    is true when ost->enc_ctx != NULL, or equivalently when
>>    ost->encoding_needed != 0.
>> 2) The stream is produced by copying some input stream's packets. This
>>    is true when ost->enc_ctx == NULL && ost->source_index >= 0.
>> 3) The stream is produced by attaching some file directly. This is true
>>    when ost->enc_ctx == NULL && ost->source_index < 0.
>>
>> OutputStream.stream_copy is currently used to identify case 2), and
>> sometimes to confusingly (or even incorrectly) identify case 1). Remove
>> it, replacing its usage with checking enc_ctx/source_index values.
>> ---
>>  fftools/ffmpeg.c     | 23 +++++++++--------------
>>  fftools/ffmpeg.h     |  1 -
>>  fftools/ffmpeg_opt.c | 33 ++++++++++++---------------------
>>  3 files changed, 21 insertions(+), 36 deletions(-)
> 
> seems to break build with shared libs:
> 
> CC	fftools/ffmpeg.o
> src/fftools/ffmpeg.c:405:32: warning: suggest braces around initialization of subobject [-Wmissing-braces]
>     struct sigaction action = {0};
>                                ^
>                                {}
> src/fftools/ffmpeg.c:1612:37: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_uint_least64_t *' (aka 'const _Atomic(uint_least64_t) *') invalid)
>             uint64_t frame_number = atomic_load(&ost->packets_written);
>                                     ^           ~~~~~~~~~~~~~~~~~~~~~
> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>                             ^                 ~~~~~~
> 1 warning and 1 error generated.
> src/ffbuild/common.mak:81: recipe for target 'fftools/ffmpeg.o' failed
> make: *** [fftools/ffmpeg.o] Error 1
> 
> [...]
> 

This has nothing to do with shared libs. It is just that C11 defines
atomic_load in such a way that it does not allow a pointer to const
atomic; presumably because atomic types might be emulated via mutexes in
which case even a read involves a write.

- Andreas
Anton Khirnov Aug. 4, 2022, 2:37 p.m. UTC | #3
Quoting Andreas Rheinhardt (2022-08-04 14:54:41)
> Michael Niedermayer:
> > On Wed, Aug 03, 2022 at 03:58:26PM +0200, Anton Khirnov wrote:
> >> There are currently three possible modes for an output stream:
> >> 1) The stream is produced by encoding output from some filtergraph. This
> >>    is true when ost->enc_ctx != NULL, or equivalently when
> >>    ost->encoding_needed != 0.
> >> 2) The stream is produced by copying some input stream's packets. This
> >>    is true when ost->enc_ctx == NULL && ost->source_index >= 0.
> >> 3) The stream is produced by attaching some file directly. This is true
> >>    when ost->enc_ctx == NULL && ost->source_index < 0.
> >>
> >> OutputStream.stream_copy is currently used to identify case 2), and
> >> sometimes to confusingly (or even incorrectly) identify case 1). Remove
> >> it, replacing its usage with checking enc_ctx/source_index values.
> >> ---
> >>  fftools/ffmpeg.c     | 23 +++++++++--------------
> >>  fftools/ffmpeg.h     |  1 -
> >>  fftools/ffmpeg_opt.c | 33 ++++++++++++---------------------
> >>  3 files changed, 21 insertions(+), 36 deletions(-)
> > 
> > seems to break build with shared libs:
> > 
> > CC	fftools/ffmpeg.o
> > src/fftools/ffmpeg.c:405:32: warning: suggest braces around initialization of subobject [-Wmissing-braces]
> >     struct sigaction action = {0};
> >                                ^
> >                                {}
> > src/fftools/ffmpeg.c:1612:37: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_uint_least64_t *' (aka 'const _Atomic(uint_least64_t) *') invalid)
> >             uint64_t frame_number = atomic_load(&ost->packets_written);
> >                                     ^           ~~~~~~~~~~~~~~~~~~~~~
> > /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> > #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
> >                             ^                 ~~~~~~
> > 1 warning and 1 error generated.
> > src/ffbuild/common.mak:81: recipe for target 'fftools/ffmpeg.o' failed
> > make: *** [fftools/ffmpeg.o] Error 1
> > 
> > [...]
> > 
> 
> This has nothing to do with shared libs. It is just that C11 defines
> atomic_load in such a way that it does not allow a pointer to const
> atomic; presumably because atomic types might be emulated via mutexes in
> which case even a read involves a write.

I don't even get a warning with gcc 11 or clang 13.
Andreas Rheinhardt Aug. 4, 2022, 2:51 p.m. UTC | #4
Anton Khirnov:
> Quoting Andreas Rheinhardt (2022-08-04 14:54:41)
>> Michael Niedermayer:
>>> On Wed, Aug 03, 2022 at 03:58:26PM +0200, Anton Khirnov wrote:
>>>> There are currently three possible modes for an output stream:
>>>> 1) The stream is produced by encoding output from some filtergraph. This
>>>>    is true when ost->enc_ctx != NULL, or equivalently when
>>>>    ost->encoding_needed != 0.
>>>> 2) The stream is produced by copying some input stream's packets. This
>>>>    is true when ost->enc_ctx == NULL && ost->source_index >= 0.
>>>> 3) The stream is produced by attaching some file directly. This is true
>>>>    when ost->enc_ctx == NULL && ost->source_index < 0.
>>>>
>>>> OutputStream.stream_copy is currently used to identify case 2), and
>>>> sometimes to confusingly (or even incorrectly) identify case 1). Remove
>>>> it, replacing its usage with checking enc_ctx/source_index values.
>>>> ---
>>>>  fftools/ffmpeg.c     | 23 +++++++++--------------
>>>>  fftools/ffmpeg.h     |  1 -
>>>>  fftools/ffmpeg_opt.c | 33 ++++++++++++---------------------
>>>>  3 files changed, 21 insertions(+), 36 deletions(-)
>>>
>>> seems to break build with shared libs:
>>>
>>> CC	fftools/ffmpeg.o
>>> src/fftools/ffmpeg.c:405:32: warning: suggest braces around initialization of subobject [-Wmissing-braces]
>>>     struct sigaction action = {0};
>>>                                ^
>>>                                {}
>>> src/fftools/ffmpeg.c:1612:37: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_uint_least64_t *' (aka 'const _Atomic(uint_least64_t) *') invalid)
>>>             uint64_t frame_number = atomic_load(&ost->packets_written);
>>>                                     ^           ~~~~~~~~~~~~~~~~~~~~~
>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>>>                             ^                 ~~~~~~
>>> 1 warning and 1 error generated.
>>> src/ffbuild/common.mak:81: recipe for target 'fftools/ffmpeg.o' failed
>>> make: *** [fftools/ffmpeg.o] Error 1
>>>
>>> [...]
>>>
>>
>> This has nothing to do with shared libs. It is just that C11 defines
>> atomic_load in such a way that it does not allow a pointer to const
>> atomic; presumably because atomic types might be emulated via mutexes in
>> which case even a read involves a write.
> 
> I don't even get a warning with gcc 11 or clang 13.
> 

Yes, same for me (this is meant literally:
https://ffmpeg.org/pipermail/ffmpeg-devel/2022-July/298360.html). Maybe
the spec has been modified since then:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1807.htm and
https://en.cppreference.com/w/c/atomic/atomic_load indicate this.

- Andreas
diff mbox series

Patch

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 62ff1a98df..0a1dc5bb3b 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1566,9 +1566,7 @@  static void print_final_stats(int64_t total_size)
 static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
 {
     AVBPrint buf, buf_script;
-    OutputStream *ost;
     int64_t total_size = of_filesize(output_files[0]);
-    AVCodecContext *enc;
     int vid, i;
     double bitrate;
     double speed;
@@ -1600,11 +1598,9 @@  static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
     av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
     for (i = 0; i < nb_output_streams; i++) {
-        float q = -1;
-        ost = output_streams[i];
-        enc = ost->enc_ctx;
-        if (!ost->stream_copy)
-            q = ost->quality / (float) FF_QP2LAMBDA;
+        const OutputStream   * const ost = output_streams[i];
+        const AVCodecContext * const enc = ost->enc_ctx;
+        const float q = enc ? ost->quality / (float) FF_QP2LAMBDA : -1;
 
         if (vid && ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             av_bprintf(&buf, "q=%2.1f ", q);
@@ -3258,7 +3254,7 @@  static int init_output_stream(OutputStream *ost, AVFrame *frame,
         // copy estimated duration as a hint to the muxer
         if (ost->st->duration <= 0 && ist && ist->st->duration > 0)
             ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base);
-    } else if (ost->stream_copy) {
+    } else if (ost->source_index >= 0) {
         ret = init_output_stream_streamcopy(ost);
         if (ret < 0)
             return ret;
@@ -3343,7 +3339,7 @@  static int transcode_init(void)
      *   known after the encoder is initialized.
      */
     for (i = 0; i < nb_output_streams; i++) {
-        if (!output_streams[i]->stream_copy &&
+        if (output_streams[i]->enc_ctx &&
             (output_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
              output_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))
             continue;
@@ -3417,9 +3413,7 @@  static int transcode_init(void)
             av_log(NULL, AV_LOG_INFO, " [sync #%d:%d]",
                    ost->sync_ist->file_index,
                    ost->sync_ist->st->index);
-        if (ost->stream_copy)
-            av_log(NULL, AV_LOG_INFO, " (copy)");
-        else {
+        if (ost->enc_ctx) {
             const AVCodec *in_codec    = input_streams[ost->source_index]->dec;
             const AVCodec *out_codec   = ost->enc;
             const char *decoder_name   = "?";
@@ -3449,7 +3443,8 @@  static int transcode_init(void)
             av_log(NULL, AV_LOG_INFO, " (%s (%s) -> %s (%s))",
                    in_codec_name, decoder_name,
                    out_codec_name, encoder_name);
-        }
+        } else
+            av_log(NULL, AV_LOG_INFO, " (copy)");
         av_log(NULL, AV_LOG_INFO, "\n");
     }
 
@@ -3959,7 +3954,7 @@  static int process_input(int file_index)
                 OutputStream *ost = output_streams[j];
 
                 if (ost->source_index == ifile->ist_index + i &&
-                    (ost->stream_copy || ost->enc->type == AVMEDIA_TYPE_SUBTITLE)) {
+                    (!ost->enc_ctx || ost->enc->type == AVMEDIA_TYPE_SUBTITLE)) {
                     OutputFile *of = output_files[ost->file_index];
                     output_packet(of, ost->pkt, ost, 1);
                 }
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 6417db03bd..713de42e2b 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -540,7 +540,6 @@  typedef struct OutputStream {
     char *apad;
     OSTFinished finished;        /* no more packets should be written for this stream */
     int unavailable;                     /* true if the steram is unavailable (possibly temporarily) */
-    int stream_copy;
 
     // init_output_stream() has been called for this stream
     // The encoder and the bitstream filters have been initialized and the stream
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 12cde4b617..784209e770 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1555,16 +1555,13 @@  static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *o
                        avcodec_get_name(ost->st->codecpar->codec_id));
                 return AVERROR_ENCODER_NOT_FOUND;
             }
-        } else if (!strcmp(codec_name, "copy"))
-            ost->stream_copy = 1;
-        else {
+        } else if (strcmp(codec_name, "copy")) {
             ost->enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1);
             ost->st->codecpar->codec_id = ost->enc->id;
         }
-        ost->encoding_needed = !ost->stream_copy;
+        ost->encoding_needed = !!ost->enc;
     } else {
         /* no encoding supported for other media types */
-        ost->stream_copy     = 1;
         ost->encoding_needed = 0;
     }
 
@@ -1898,7 +1895,7 @@  static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
     MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st);
     MATCH_PER_STREAM_OPT(filters,        str, ost->filters,        oc, st);
 
-    if (!ost->stream_copy) {
+    if (ost->enc_ctx) {
         AVCodecContext *video_enc = ost->enc_ctx;
         const char *p = NULL;
         char *frame_size = NULL;
@@ -2087,9 +2084,7 @@  static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
         ost->last_frame = av_frame_alloc();
         if (!ost->last_frame)
             exit_program(1);
-    }
-
-    if (ost->stream_copy)
+    } else
         check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO);
 
     return ost;
@@ -2107,7 +2102,7 @@  static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
     MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st);
     MATCH_PER_STREAM_OPT(filters,        str, ost->filters,        oc, st);
 
-    if (!ost->stream_copy) {
+    if (ost->enc_ctx) {
         AVCodecContext *audio_enc = ost->enc_ctx;
         int channels = 0;
         char *layout = NULL;
@@ -2186,9 +2181,7 @@  static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
             }
         }
 #endif
-    }
-
-    if (ost->stream_copy)
+    } else
         check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO);
 
     return ost;
@@ -2199,7 +2192,7 @@  static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int
     OutputStream *ost;
 
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index);
-    if (!ost->stream_copy) {
+    if (ost->enc_ctx) {
         av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
         exit_program(1);
     }
@@ -2212,7 +2205,7 @@  static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc,
     OutputStream *ost;
 
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_UNKNOWN, source_index);
-    if (!ost->stream_copy) {
+    if (ost->enc_ctx) {
         av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n");
         exit_program(1);
     }
@@ -2223,7 +2216,6 @@  static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc,
 static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
 {
     OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index);
-    ost->stream_copy = 1;
     ost->finished    = 1;
     return ost;
 }
@@ -2236,7 +2228,7 @@  static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc,
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index);
     st  = ost->st;
 
-    if (!ost->stream_copy) {
+    if (ost->enc_ctx) {
         AVCodecContext *subtitle_enc = ost->enc_ctx;
         char *frame_size = NULL;
 
@@ -2401,7 +2393,7 @@  static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
     ofilter->ost      = ost;
     ofilter->format   = -1;
 
-    if (ost->stream_copy) {
+    if (!ost->enc_ctx) {
         av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, "
                "which is fed from a complex filtergraph. Filtering and streamcopy "
                "cannot be used together.\n", ost->file_index, ost->index);
@@ -2768,7 +2760,6 @@  static void of_add_attachments(AVFormatContext *oc, OptionsContext *o)
         memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 
         ost = new_attachment_stream(o, oc, -1);
-        ost->stream_copy               = 0;
         ost->attachment_filename       = o->attachments[i];
         ost->st->codecpar->extradata      = attachment;
         ost->st->codecpar->extradata_size = len;
@@ -3068,7 +3059,7 @@  static int open_output_file(OptionsContext *o, const char *filename)
                     exit_program(1);
                 }
             }
-        } else if (ost->stream_copy && ost->source_index >= 0) {
+        } else if (ost->source_index >= 0) {
             InputStream *ist = input_streams[ost->source_index];
             ist->processing_needed = 1;
         }
@@ -3193,7 +3184,7 @@  static int open_output_file(OptionsContext *o, const char *filename)
                 continue;
             ist = input_streams[output_streams[i]->source_index];
             av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
-            if (!output_streams[i]->stream_copy) {
+            if (output_streams[i]->enc_ctx) {
                 av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0);
             }
         }