[FFmpeg-devel] [PATCH 4/4 v3] avcodec/av1dec: add an option to select an operating point

James Almer jamrial at gmail.com
Wed Dec 9 23:48:28 EET 2020


On 12/9/2020 6:36 PM, Mark Thompson wrote:
> On 15/11/2020 21:55, James Almer wrote:
>> Signed-off-by: James Almer <jamrial at gmail.com>
>> ---
>>   doc/decoders.texi   | 13 +++++++++++++
>>   libavcodec/av1dec.c | 30 ++++++++++++++++++++++++++++++
>>   libavcodec/av1dec.h |  4 ++++
>>   3 files changed, 47 insertions(+)
>>
>> diff --git a/doc/decoders.texi b/doc/decoders.texi
>> index bfab562fb2..27c6ba4a5d 100644
>> --- a/doc/decoders.texi
>> +++ b/doc/decoders.texi
>> @@ -25,6 +25,19 @@ enabled decoders.
>>   A description of some of the currently available video decoders
>>   follows.
>> + at section av1
>> +
>> +AOMedia Video 1 (AV1) decoder.
>> +
>> + at subsection Options
>> +
>> + at table @option
>> +
>> + at item operating_point
>> +Select an operating point of a scalable AV1 bitstream (0 - 31). 
>> Default is 0.
>> +
>> + at end table
>> +
>>   @section rawvideo
>>   Raw video decoder.
>> diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
>> index c1967f03bd..b7ee307159 100644
>> --- a/libavcodec/av1dec.c
>> +++ b/libavcodec/av1dec.c
>> @@ -19,6 +19,7 @@
>>    */
>>   #include "libavutil/pixdesc.h"
>> +#include "libavutil/opt.h"
>>   #include "avcodec.h"
>>   #include "av1dec.h"
>>   #include "bytestream.h"
>> @@ -615,6 +616,8 @@ static av_cold int av1_decode_init(AVCodecContext 
>> *avctx)
>>       if (ret < 0)
>>           return ret;
>> +    av_opt_set_int(s->cbc->priv_data, "operating_point", 
>> s->operating_point, 0);
>> +
>>       if (avctx->extradata && avctx->extradata_size) {
>>           ret = ff_cbs_read(s->cbc, &s->current_obu, avctx->extradata,
>>                             avctx->extradata_size);
>> @@ -704,6 +707,11 @@ static int set_output_frame(AVCodecContext 
>> *avctx, AVFrame *frame,
>>       const AVFrame *srcframe = s->cur_frame.tf.f;
>>       int ret;
>> +    // TODO: all layers
>> +    if (s->operating_point_idc &&
>> +        av_log2(s->operating_point_idc >> 8) > s->cur_frame.spatial_id)
>> +        return 0;
> 
> I'm confused by what this is doing.  Shouldn't it be checking that the 
> spatial_id is in the mask, rather than a numerical comparison?

It's what dav1d does. Checking that the current frame's spatial layer is 
the highest, which is also the highest quality one, and skipping the rest.

Ensuring it's in the mask is done by CBS.

> 
> Also, what about temporal_id?

That's also handled by CBS, in the drop_obu() change from patch 3.

> 
>> +
>>       ret = av_frame_ref(frame, srcframe);
>>       if (ret < 0)
>>           return ret;
>> @@ -809,6 +817,8 @@ static int av1_decode_frame(AVCodecContext *avctx, 
>> void *frame,
>>                   goto end;
>>               }
>> +            s->operating_point_idc = 
>> s->raw_seq->operating_point_idc[s->operating_point];
>> +
>>               if (s->pix_fmt == AV_PIX_FMT_NONE) {
>>                   ret = get_pixel_format(avctx);
>>                   if (ret < 0) {
>> @@ -888,6 +898,9 @@ static int av1_decode_frame(AVCodecContext *avctx, 
>> void *frame,
>>               s->cur_frame.spatial_id  = header->spatial_id;
>>               s->cur_frame.temporal_id = header->temporal_id;
>> +            s->cur_frame.spatial_id  = header->spatial_id;
>> +            s->cur_frame.temporal_id = header->temporal_id;
>> +
>>               if (avctx->hwaccel) {
>>                   ret = avctx->hwaccel->start_frame(avctx, unit->data,
>>                                                     unit->data_size);
>> @@ -979,12 +992,28 @@ static void av1_decode_flush(AVCodecContext *avctx)
>>           av1_frame_unref(avctx, &s->ref[i]);
>>       av1_frame_unref(avctx, &s->cur_frame);
>> +    s->operating_point_idc = 0;
>>       s->raw_frame_header = NULL;
>>       s->raw_seq = NULL;
>>       ff_cbs_flush(s->cbc);
>>   }
>> +#define OFFSET(x) offsetof(AV1DecContext, x)
>> +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
>> +static const AVOption av1_options[] = {
>> +    { "operating_point",  "Select an operating point of the scalable 
>> bitstream",
>> +                          OFFSET(operating_point), AV_OPT_TYPE_INT, { 
>> .i64 = 0 }, 0, AV1_MAX_OPERATING_POINTS - 1, VD },
>> +    { NULL }
>> +};
>> +
>> +static const AVClass av1_class = {
>> +    .class_name = "AV1 decoder",
>> +    .item_name  = av_default_item_name,
>> +    .option     = av1_options,
>> +    .version    = LIBAVUTIL_VERSION_INT,
>> +};
>> +
>>   AVCodec ff_av1_decoder = {
>>       .name                  = "av1",
>>       .long_name             = NULL_IF_CONFIG_SMALL("Alliance for Open 
>> Media AV1"),
>> @@ -1000,6 +1029,7 @@ AVCodec ff_av1_decoder = {
>>                                FF_CODEC_CAP_SETS_PKT_DTS,
>>       .flush                 = av1_decode_flush,
>>       .profiles              = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
>> +    .priv_class            = &av1_class,
>>       .hw_configs            = (const AVCodecHWConfigInternal * []) {
>>   #if CONFIG_AV1_DXVA2_HWACCEL
>>           HWACCEL_DXVA2(av1),
>> diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h
>> index 4b218f64bb..70414c9ca3 100644
>> --- a/libavcodec/av1dec.h
>> +++ b/libavcodec/av1dec.h
>> @@ -74,9 +74,13 @@ typedef struct AV1DecContext {
>>       uint16_t tg_start;
>>       uint16_t tg_end;
>> +    int operating_point_idc;
>> +
>>       AV1Frame ref[AV1_NUM_REF_FRAMES];
>>       AV1Frame cur_frame;
>> +    // AVOptions
>> +    int operating_point;
>>   } AV1DecContext;
>>   #endif /* AVCODEC_AV1DEC_H */
>>
> 
> - Mark
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".



More information about the ffmpeg-devel mailing list