On Tue,  1 Jul 2014 01:23:45 -0400
Vittorio Giovara <vittorio.giov...@gmail.com> wrote:

> Rather than using deprecated *J pixel formats, keep the full scale ones in
> a separate list, and check for avctx->color_range before opening the encoder.
> 
> This slightly changes the format handshaking behaviour, instead of setting the
> first compatible format, the full range ones are always preferred (since
> they are checked last).
> ---
> This is my attempt at cleansing lavc of the yuvj pixel formats. The main
> design goal of this solution is that API is not broken, at least until the
> deprecated formats are around. This is so that our users can safely keep using
> the existing code and update it only when deprecated pixel formats are 
> actually
> removed (which may be very far in time).
> 
> As for the remaining libraries:
> -lavu: it should be enough to add deprecation guards;
> -lavf: unaffected;
> -lavr: unaffected;

> -lsws: until avscale is available, there are two options, either add a new
>        function which solely sets pixel format color range or break
>        sws_getCachedContext and add the missing color range fields there;

Yes, libswscale supports setting range perfectly fine, and the only
problem are the various insufficient APIs like sws_getCachedContext
that can't express this stuff. For what's it worth, I have an old patch
that adds an AVFrame->AVFrame conversion API to libswscale, and which
could pick up the color range (and various other things) automatically.
So the question is whether to wait on the vaporware, or whether a new
API should be added to libswscale. (To be fair, this would add only 1
new public function - or 3, if you also want to support some of the
obscure aspects of libswscale.)

> -lavfi: this is the hard one, I have a few ideas but I believe it warrants
>         a separate patchset and discussion thread.

Indeed. I guess the main problem is colorspace negotiation...

> 
> Comments, ideas, suggestions are always welcome.
> Vittorio
> 
>  doc/APIchanges        |  4 ++++
>  libavcodec/avcodec.h  |  3 +++
>  libavcodec/ljpegenc.c |  6 ++++++
>  libavcodec/mjpegenc.c |  5 +++++
>  libavcodec/svq3.c     |  4 ++++
>  libavcodec/utils.c    | 29 +++++++++++++++++++++++------
>  libavcodec/version.h  |  5 ++++-
>  7 files changed, 49 insertions(+), 7 deletions(-)
> 
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 0e96837..be14778 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -13,6 +13,10 @@ libavutil:     2013-12-xx
>  
>  API changes, most recent first:
>  
> +2014-xx-xx - xxxxxxx - lavc 55.55.1 - avcodec.h
> +  Add pix_fmts_full to AVCodec to list supported full range pixel formats.
> +  Enabled on the next lavc major bump.
> +
>  2014-xx-xx - xxxxxxx - lsws 2.2.0
>    Add sws_setColorrangeDetails() to set the input and output color range.
>  
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index cc74aee..7ab2572 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -2784,6 +2784,9 @@ typedef struct AVCodec {
>      int capabilities;
>      const AVRational *supported_framerates; ///< array of supported 
> framerates, or NULL if any, array is terminated by {0,0}
>      const enum AVPixelFormat *pix_fmts;     ///< array of supported pixel 
> formats, or NULL if unknown, array is terminated by -1
> +#if FF_API_PIX_FMT_FULL
> +    const enum AVPixelFormat *pix_fmts_full; ///< array of supported full 
> range pixel formats, or NULL if unknown, array is terminated by -1
> +#endif
>      const int *supported_samplerates;       ///< array of supported audio 
> samplerates, or NULL if unknown, array is terminated by 0
>      const enum AVSampleFormat *sample_fmts; ///< array of supported sample 
> formats, or NULL if unknown, array is terminated by -1
>      const uint64_t *channel_layouts;         ///< array of support channel 
> layouts, or NULL if unknown. array is terminated by 0
> diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c
> index e111c8c..05b57db 100644
> --- a/libavcodec/ljpegenc.c
> +++ b/libavcodec/ljpegenc.c
> @@ -332,4 +332,10 @@ AVCodec ff_ljpeg_encoder = {
>                                                      AV_PIX_FMT_YUV422P,
>                                                      AV_PIX_FMT_YUV444P,
>                                                      AV_PIX_FMT_NONE },
> +#if FF_API_PIX_FMT_FULL
> +    .pix_fmts_full  = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
> +                                                    AV_PIX_FMT_YUV422P,
> +                                                    AV_PIX_FMT_YUV444P,
> +                                                    AV_PIX_FMT_NONE }
> +#endif
>  };
> diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
> index 30433c3..6205ad7 100644
> --- a/libavcodec/mjpegenc.c
> +++ b/libavcodec/mjpegenc.c
> @@ -449,4 +449,9 @@ AVCodec ff_mjpeg_encoder = {
>      .pix_fmts       = (const enum AVPixelFormat[]){
>          AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_NONE
>      },
> +#if FF_API_PIX_FMT_FULL
> +    .pix_fmts_full  = (const enum AVPixelFormat[]) {
> +        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE
> +    },
> +#endif
>  };
> diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c
> index fc2120b..e7cae2c 100644
> --- a/libavcodec/svq3.c
> +++ b/libavcodec/svq3.c
> @@ -1334,4 +1334,8 @@ AVCodec ff_svq3_decoder = {
>                        CODEC_CAP_DELAY,
>      .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P,
>                                                       AV_PIX_FMT_NONE},
> +#if FF_API_PIX_FMT_FULL
> +    .pix_fmts_full  = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
> +                                                     AV_PIX_FMT_NONE },
> +#endif
>  };
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index d6019d9..1c75f24 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -1130,7 +1130,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext 
> *avctx, const AVCodec *code
>          avctx->thread_count = 1;
>  
>      if (av_codec_is_encoder(avctx->codec)) {
> -        int i;
> +        int i, j;
>          if (avctx->codec->sample_fmts) {
>              for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; 
> i++) {
>                  if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
> @@ -1148,15 +1148,32 @@ int attribute_align_arg avcodec_open2(AVCodecContext 
> *avctx, const AVCodec *code
>                  goto free_and_end;
>              }
>          }
> +        /* Pixel formats */
>          if (avctx->codec->pix_fmts) {
>              for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++)
> +#if FF_API_PIX_FMT_FULL
> +                if (avctx->pix_fmt == avctx->codec->pix_fmts[i] &&
> +                    avctx->color_range != AVCOL_RANGE_JPEG)
> +#else
>                  if (avctx->pix_fmt == avctx->codec->pix_fmts[i])
> +#endif
>                      break;
> -            if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE) {
> -                av_log(avctx, AV_LOG_ERROR, "Specified pix_fmt is not 
> supported\n");
> -                ret = AVERROR(EINVAL);
> -                goto free_and_end;
> -            }
> +        }
> +#if FF_API_PIX_FMT_FULL
> +        if (avctx->codec->pix_fmts_full) {
> +            for (j = 0; avctx->codec->pix_fmts_full[j] != AV_PIX_FMT_NONE; 
> j++)
> +                if (avctx->pix_fmt == avctx->codec->pix_fmts_full[j] &&
> +                    avctx->color_range == AVCOL_RANGE_JPEG)

Assuming the color_range gets set from the (possible still J*) pixfmt
earlier, which AFAIK is already done in git master.

> +                    break;
> +        }
> +        if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE &&
> +            avctx->codec->pix_fmts_full[j] == AV_PIX_FMT_NONE) {
> +#else
> +        if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE) {
> +#endif
> +            av_log(avctx, AV_LOG_ERROR, "Specified pix_fmt is not 
> supported\n");
> +            ret = AVERROR(EINVAL);
> +            goto free_and_end;
>          }
>          if (avctx->codec->supported_samplerates) {
>              for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++)
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index dee6615..2f24d86 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -30,7 +30,7 @@
>  
>  #define LIBAVCODEC_VERSION_MAJOR 55
>  #define LIBAVCODEC_VERSION_MINOR 55
> -#define LIBAVCODEC_VERSION_MICRO  0
> +#define LIBAVCODEC_VERSION_MICRO  1
>  
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
>                                                 LIBAVCODEC_VERSION_MINOR, \
> @@ -144,5 +144,8 @@
>  #ifndef FF_API_CODEC_NAME
>  #define FF_API_CODEC_NAME        (LIBAVCODEC_VERSION_MAJOR < 57)
>  #endif
> +#ifndef FF_API_PIX_FMT_FULL
> +#define FF_API_PIX_FMT_FULL      (LIBAVCODEC_VERSION_MAJOR >= 56)
> +#endif
>  
>  #endif /* AVCODEC_VERSION_H */

Like I said on IRC, IMHO this is ok for now. It's not very elegant and
doesn't cover everything you'd want to do in theory/in future, but it's
probably much better than a more complicated solution that essentially
does the same thing. It's also nicely compatible.
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to