LCOV - code coverage report
Current view: top level - filters - ff_dec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 408 497 82.1 %
Date: 2021-04-29 23:48:07 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2017-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ffmpeg decode filter
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/setup.h>
      27             : 
      28             : #ifdef GPAC_HAS_FFMPEG
      29             : 
      30             : #include "ff_common.h"
      31             : 
      32             : #include <libswscale/swscale.h>
      33             : 
      34             : #define FF_CHECK_PROP(_name, _ffname, _type)    if (ctx->_name != ctx->decoder->_ffname) { \
      35             :                 gf_filter_pid_set_property(ctx->out_pid, _type, &PROP_UINT( (u32) ctx->decoder->_ffname ) );       \
      36             :                 ctx->_name = (u32) ctx->decoder->_ffname;      \
      37             :         } \
      38             : 
      39             : #define FF_CHECK_PROPL(_name, _ffname, _type)   if (ctx->_name != ctx->decoder->_ffname) { \
      40             :         gf_filter_pid_set_property(ctx->out_pid, _type, &PROP_LONGUINT( (u32) ctx->decoder->_ffname ) );   \
      41             :         ctx->_name = (u32) ctx->decoder->_ffname;      \
      42             : } \
      43             : 
      44             : #define FF_CHECK_PROP_VAL(_name, _val, _type)   if (ctx->_name != _val) { \
      45             :                 gf_filter_pid_set_property(ctx->out_pid, _type, &PROP_UINT( _val ) );    \
      46             :                 ctx->_name = _val;   \
      47             :         } \
      48             : 
      49             : static GF_Err ffdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove);
      50             : 
      51             : 
      52             : typedef struct _gf_ffdec_ctx
      53             : {
      54             :         //internal data
      55             :         Bool initialized;
      56             : 
      57             :         Bool owns_context;
      58             :         AVCodecContext *decoder;
      59             :         //decode options
      60             :         AVDictionary *options;
      61             : 
      62             :         Bool reconfig_pending;
      63             : 
      64             :         GF_FilterPid *in_pid, *out_pid;
      65             :         //media type
      66             :         u32 type;
      67             :         //CRC32 of extra_data
      68             :         u32 extra_data_crc;
      69             : 
      70             :         GF_Err (*process)(GF_Filter *filter, struct _gf_ffdec_ctx *ctx);
      71             : 
      72             :         u32 flush_done;
      73             : 
      74             :         //for now we don't share the data
      75             :         AVFrame *frame;
      76             :         //audio state
      77             :         u32 channels, sample_rate, sample_fmt, bytes_per_sample;
      78             :         u64 channel_layout;
      79             :         u32 frame_start;
      80             :         u32 nb_samples_already_in_frame;
      81             : 
      82             :         //video state
      83             :         u32 width, height, pixel_fmt, stride, stride_uv;
      84             :         GF_Fraction sar;
      85             :         struct SwsContext *sws_ctx;
      86             : 
      87             :         GF_List *src_packets;
      88             : 
      89             :         u32 o_ff_pfmt;
      90             :         Bool force_full_range;
      91             :         Bool drop_non_refs;
      92             : 
      93             :         s64 first_cts_plus_one;
      94             :         s64 delay;
      95             :         u32 ts_offset;
      96             : } GF_FFDecodeCtx;
      97             : 
      98         141 : static GF_Err ffdec_initialize(GF_Filter *filter)
      99             : {
     100         141 :         GF_FFDecodeCtx *ctx = (GF_FFDecodeCtx *) gf_filter_get_udta(filter);
     101         141 :         ctx->initialized = GF_TRUE;
     102         141 :         ctx->src_packets = gf_list_new();
     103             : 
     104         141 :         ffmpeg_setup_logs(GF_LOG_CODEC);
     105         141 :         return GF_OK;
     106             : }
     107             : 
     108         140 : static void ffdec_finalize(GF_Filter *filter)
     109             : {
     110         140 :         GF_FFDecodeCtx *ctx = (GF_FFDecodeCtx *) gf_filter_get_udta(filter);
     111             : 
     112         140 :         if (ctx->options) av_dict_free(&ctx->options);
     113         140 :         if (ctx->frame) av_frame_free(&ctx->frame);
     114         140 :         if (ctx->sws_ctx) sws_freeContext(ctx->sws_ctx);
     115             : 
     116         159 :         while (gf_list_count(ctx->src_packets)) {
     117          19 :                 GF_FilterPacket *pck = gf_list_pop_back(ctx->src_packets);
     118          19 :                 gf_filter_pck_unref(pck);
     119             :         }
     120         140 :         gf_list_del(ctx->src_packets);
     121             : 
     122         140 :         if (ctx->owns_context && ctx->decoder) {
     123         140 :                 avcodec_free_context(&ctx->decoder);
     124             :         }
     125         140 :         return;
     126             : }
     127             : 
     128         128 : static void ffdec_check_pix_fmt_change(struct _gf_ffdec_ctx *ctx, u32 pix_fmt)
     129             : {
     130         128 :         if (ctx->pixel_fmt != pix_fmt) {
     131         124 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_PIXFMT, &PROP_UINT(pix_fmt));
     132         124 :                 ctx->pixel_fmt = pix_fmt;
     133         124 :                 ctx->force_full_range = GF_FALSE;
     134         124 :                 if (ctx->decoder->color_range==AVCOL_RANGE_JPEG)
     135           2 :                         ctx->force_full_range = GF_TRUE;
     136         122 :                 else if (ffmpeg_pixfmt_is_fullrange(ctx->decoder->pix_fmt))
     137           0 :                         ctx->force_full_range = GF_TRUE;
     138             :                 else
     139         122 :                         ctx->force_full_range = GF_FALSE;
     140             : 
     141         124 :                 if (ctx->force_full_range)
     142           2 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_RANGE, &PROP_BOOL(GF_TRUE) );
     143             :                 else
     144         122 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_RANGE, NULL );
     145             : 
     146         124 :                 if (ctx->decoder->color_primaries!=AVCOL_PRI_UNSPECIFIED)
     147           0 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_PRIMARIES, &PROP_UINT(ctx->decoder->color_primaries) );
     148             :                 else
     149         124 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_PRIMARIES, NULL );
     150             : 
     151         124 :                 if (ctx->decoder->colorspace!=AVCOL_SPC_UNSPECIFIED)
     152           1 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_MX, &PROP_UINT(ctx->decoder->colorspace) );
     153             :                 else
     154         123 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_MX, NULL );
     155             : 
     156         124 :                 if (ctx->decoder->color_trc!=AVCOL_TRC_UNSPECIFIED)
     157           0 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_TRANSFER, &PROP_UINT(ctx->decoder->color_trc) );
     158             :                 else
     159         124 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_TRANSFER, NULL );
     160             :         }
     161         128 : }
     162             : 
     163      157688 : static GF_Err ffdec_process_video(GF_Filter *filter, struct _gf_ffdec_ctx *ctx)
     164             : {
     165             :         AVPacket pkt;
     166             :         AVFrame *frame;
     167             :         AVPicture pict;
     168             :         Bool is_eos=GF_FALSE;
     169             :         s32 res;
     170             :         s32 gotpic;
     171             :         u64 out_cts;
     172             :         const char *data = NULL;
     173             :         Bool seek_flag = GF_FALSE;
     174             :         u32 i, count, ff_pfmt;
     175      157688 :         u32 size=0, outsize, pix_out, stride, stride_uv, uv_height, nb_planes;
     176             :         u8 *out_buffer;
     177             :         GF_FilterPacket *pck_src;
     178             :         GF_FilterPacket *dst_pck;
     179      157688 :         GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->in_pid);
     180             : 
     181      157688 :         if (ctx->reconfig_pending) {
     182             :                 pck = NULL;
     183      157666 :         } else if (!pck) {
     184       76105 :                 is_eos = gf_filter_pid_is_eos(ctx->in_pid);
     185       76105 :                 if (!is_eos) return GF_OK;
     186             :         }
     187             : 
     188      156973 :         if (pck && ctx->drop_non_refs && !gf_filter_pck_get_sap(pck)) {
     189           1 :                 gf_filter_pid_drop_packet(ctx->in_pid);
     190           1 :                 return GF_OK;
     191             :         }
     192             :     //we don't own the codec and we're in end of stream, don't try to decode (the context might have been closed)
     193      156994 :     if (!pck && !ctx->owns_context) {
     194           0 :         gf_filter_pid_set_eos(ctx->out_pid);
     195           0 :         return GF_EOS;
     196             :     }
     197             : 
     198      156994 :         frame = ctx->frame;
     199             : 
     200      156994 :         av_init_packet(&pkt);
     201             : 
     202      156994 :         if (pck) {
     203       81560 :                 data = gf_filter_pck_get_data(pck, &size);
     204             : 
     205       81560 :                 if (!size) {
     206           0 :                         gf_filter_pid_drop_packet(ctx->in_pid);
     207           0 :                         return GF_OK;
     208             :                 }
     209             : 
     210       81560 :                 pck_src = pck;
     211       81560 :                 gf_filter_pck_ref_props(&pck_src);
     212       81560 :                 if (pck_src) gf_list_add(ctx->src_packets, pck_src);
     213             : 
     214             :                 //seems ffmpeg is not properly handling the decoding after a flush, we close and reopen the codec
     215       81560 :                 if (ctx->flush_done) {
     216             : #if 0
     217             :                         AVDictionary *options = NULL;
     218             :                         const AVCodec *codec = ctx->decoder->codec;
     219             :                         avcodec_free_context(&ctx->decoder);
     220             : 
     221             :                         av_dict_copy(&options, ctx->options, 0);
     222             :                         avcodec_open2(ctx->decoder, codec, &options );
     223             :                         if (options) av_dict_free(&options);
     224             : #else
     225           2 :                         avcodec_flush_buffers(ctx->decoder);
     226             : #endif
     227           2 :                         ctx->flush_done = GF_FALSE;
     228             :                 }
     229             : 
     230       81560 :                 pkt.dts = gf_filter_pck_get_dts(pck);
     231       81560 :                 pkt.pts = gf_filter_pck_get_cts(pck);
     232       81560 :                 pkt.duration = gf_filter_pck_get_duration(pck);
     233       81560 :                 if (gf_filter_pck_get_sap(pck)>0)
     234        3317 :                         pkt.flags = AV_PKT_FLAG_KEY;
     235             :         }
     236      156994 :         pkt.data = (uint8_t*)data;
     237      156994 :         pkt.size = size;
     238             : 
     239             :         /*TOCHECK: for AVC bitstreams after ISMA decryption, in case (as we do) the decryption DRM tool
     240             :         doesn't put back nalu size, we have to do it ourselves, but we can't modify input data...*/
     241             : 
     242      156994 :         gotpic=0;
     243      156994 :         res = avcodec_decode_video2(ctx->decoder, frame, &gotpic, &pkt);
     244      156994 :         if (pck) gf_filter_pid_drop_packet(ctx->in_pid);
     245             : 
     246      156994 :         if (!gotpic) {
     247       75474 :                 if (is_eos) {
     248       75336 :                         ctx->flush_done = GF_TRUE;
     249       75336 :                         gf_filter_pid_set_eos(ctx->out_pid);
     250       75336 :                         return GF_EOS;
     251             :                 }
     252         138 :                 if (ctx->reconfig_pending) {
     253           7 :                         avcodec_free_context(&ctx->decoder);
     254           7 :                         ctx->decoder = NULL;
     255           7 :                         ctx->reconfig_pending = GF_FALSE;
     256             :                         //these properties are checked after decode, when we reconfigure we copy props from input to output
     257             :                         //so we need to make sure we retrigger pid config even if these did not change
     258           7 :                         ctx->pixel_fmt = 0;
     259           7 :                         ctx->width = 0;
     260           7 :                         ctx->height = 0;
     261           7 :                         ctx->stride = 0;
     262           7 :                         ctx->stride_uv = 0;
     263           7 :                         ctx->sar.num = ctx->sar.den = 0;
     264          14 :                         while (gf_list_count(ctx->src_packets)) {
     265           0 :                                 GF_FilterPacket *ref_pck = gf_list_pop_back(ctx->src_packets);
     266           0 :                                 gf_filter_pck_unref(ref_pck);
     267             :                         }
     268           7 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[FFDec] PID %s reconfigure pending and all frames flushed, reconfguring\n", gf_filter_pid_get_name(ctx->in_pid) ));
     269           7 :                         return ffdec_configure_pid(filter, ctx->in_pid, GF_FALSE);
     270             :                 }
     271             :         }
     272             : 
     273       81651 :         if (res < 0) {
     274           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] PID %s failed to decode frame PTS "LLU": %s\n", gf_filter_pid_get_name(ctx->in_pid), pkt.pts, av_err2str(res) ));
     275             :                 return GF_NON_COMPLIANT_BITSTREAM;
     276             :         }
     277       81651 :         if (!gotpic) return GF_OK;
     278             : 
     279       81520 :         if (ctx->decoder->pix_fmt != ctx->o_ff_pfmt) {
     280           8 :                 u32 pix_fmt = ffmpeg_pixfmt_to_gpac(ctx->decoder->pix_fmt);
     281           8 :                 ctx->o_ff_pfmt = ctx->decoder->pix_fmt;
     282           8 :                 if (!pix_fmt) {
     283             :                         pix_fmt = GF_PIXEL_RGB;
     284           0 :                         ctx->o_ff_pfmt = AV_PIX_FMT_RGB24;
     285             :                 }
     286           8 :                 ffdec_check_pix_fmt_change(ctx, pix_fmt);
     287             :         }
     288             :         //update all props
     289       81520 :         FF_CHECK_PROP(width, width, GF_PROP_PID_WIDTH)
     290       81520 :         FF_CHECK_PROP(height, height, GF_PROP_PID_HEIGHT)
     291             : 
     292       81520 :         stride = stride_uv = uv_height = nb_planes = 0;
     293       81520 :         if (! gf_pixel_get_size_info(ctx->pixel_fmt, ctx->width, ctx->height, &outsize, &stride, &stride_uv, &nb_planes, &uv_height) ) {
     294           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] PID %s failed to query pixelformat size infon", gf_filter_pid_get_name(ctx->in_pid) ));
     295             :                 return GF_NOT_SUPPORTED;
     296             :         }
     297             : 
     298       81520 :         FF_CHECK_PROP_VAL(stride, stride, GF_PROP_PID_STRIDE)
     299       81520 :         FF_CHECK_PROP_VAL(stride_uv, stride_uv, GF_PROP_PID_STRIDE_UV)
     300       81520 :         if (ctx->sar.num * ctx->decoder->sample_aspect_ratio.den != ctx->sar.den * ctx->decoder->sample_aspect_ratio.num) {
     301           0 :                 ctx->sar.num = ctx->decoder->sample_aspect_ratio.num;
     302           0 :                 ctx->sar.den = ctx->decoder->sample_aspect_ratio.den;
     303             : 
     304           0 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_SAR, &PROP_FRAC( ctx->sar ) );
     305             :         }
     306             : 
     307             :         memset(&pict, 0, sizeof(pict));
     308             : 
     309       81520 :         pck_src = NULL;
     310       81520 :         count = gf_list_count(ctx->src_packets);
     311      145631 :         for (i=0; i<count; i++) {
     312             :                 u64 cts;
     313      145631 :                 pck_src = gf_list_get(ctx->src_packets, i);
     314      145631 :                 cts = gf_filter_pck_get_cts(pck_src);
     315      145631 :                 if (cts == frame->pts)
     316             :                         break;
     317       64111 :                 if (cts == frame->pkt_pts)
     318             :                         break;
     319       64111 :                 pck_src = NULL;
     320             :         }
     321             : 
     322             :         seek_flag = GF_FALSE;
     323       81520 :         if (pck_src) {
     324       81520 :                 seek_flag = gf_filter_pck_get_seek_flag(pck_src);
     325       81520 :                 out_cts = gf_filter_pck_get_cts(pck_src);
     326             :         } else {
     327           0 :                 out_cts = frame->pts;
     328             :         }
     329             :         //this was a seek frame, do not dispatch
     330       81520 :         if (seek_flag) {
     331          33 :                 if (pck_src) {
     332          33 :                         gf_list_del_item(ctx->src_packets, pck_src);
     333          33 :                         gf_filter_pck_unref(pck_src);
     334             :                 }
     335             :                 return GF_OK;
     336             :         }
     337             : 
     338       81487 :         dst_pck = gf_filter_pck_new_alloc(ctx->out_pid, outsize, &out_buffer);
     339       81487 :         if (!dst_pck) return GF_OUT_OF_MEM;
     340             : 
     341       81487 :         if (pck_src) {
     342       81487 :                 gf_filter_pck_merge_properties(pck_src, dst_pck);
     343       81487 :                 gf_list_del_item(ctx->src_packets, pck_src);
     344       81487 :                 gf_filter_pck_unref(pck_src);
     345             :         } else {
     346           0 :                 gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
     347             :         }
     348             : 
     349             :     //rewrite dts and pts to PTS value
     350       81487 :     gf_filter_pck_set_dts(dst_pck, out_cts);
     351       81487 :     gf_filter_pck_set_cts(dst_pck, out_cts);
     352             : 
     353       81487 :         ff_pfmt = ctx->decoder->pix_fmt;
     354       81487 :         if (ff_pfmt==AV_PIX_FMT_YUVJ420P) {
     355             :                 ff_pfmt = AV_PIX_FMT_YUV420P;
     356           1 :                 if (!ctx->force_full_range) {
     357           1 :                         ctx->force_full_range = GF_TRUE;
     358           1 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_RANGE, &PROP_BOOL(GF_TRUE));
     359             :                 }
     360             :         }
     361             : 
     362             :         //TODO: cleanup, we should not convert pixel format in the decoder but through filters !
     363       81487 :         switch (ctx->pixel_fmt) {
     364           1 :         case GF_PIXEL_RGB:
     365           1 :                 pict.data[0] =  (uint8_t *)out_buffer;
     366           1 :                 pict.linesize[0] = 3*ctx->width;
     367             :                 pix_out = AV_PIX_FMT_RGB24;
     368           1 :                 break;
     369           1 :         case GF_PIXEL_RGBA:
     370           1 :                 pict.data[0] =  (uint8_t *)out_buffer;
     371           1 :                 pict.linesize[0] = 4*ctx->width;
     372             :                 pix_out = AV_PIX_FMT_RGBA;
     373           1 :                 break;
     374       21441 :         case GF_PIXEL_YUV:
     375             :         case GF_PIXEL_YUV_10:
     376       21441 :                 pict.data[0] =  (uint8_t *)out_buffer;
     377       21441 :                 pict.data[1] =  (uint8_t *)out_buffer + ctx->stride * ctx->height;
     378       21441 :                 pict.data[2] =  (uint8_t *)pict.data[1] + ctx->stride_uv * uv_height;
     379       21441 :                 pict.linesize[0] = ctx->stride;
     380       21441 :                 pict.linesize[1] = pict.linesize[2] = ctx->stride_uv;
     381       21441 :                 if (ctx->pixel_fmt == GF_PIXEL_YUV_10)
     382             :                         pix_out = AV_PIX_FMT_YUV420P10LE;
     383             :                 else
     384             :                         pix_out = AV_PIX_FMT_YUV420P;
     385             :                 break;
     386             : 
     387       30022 :         case GF_PIXEL_YUV422:
     388             :         case GF_PIXEL_YUV422_10:
     389       30022 :                 pict.data[0] =  (uint8_t *)out_buffer;
     390       30022 :                 pict.data[1] =  (uint8_t *)out_buffer + ctx->stride * ctx->height;
     391       30022 :                 pict.data[2] =  (uint8_t *)pict.data[1] + ctx->stride_uv * ctx->height;
     392       30022 :                 pict.linesize[0] = ctx->stride;
     393       30022 :                 pict.linesize[1] = pict.linesize[2] = ctx->stride_uv;
     394       30022 :                 if (ctx->pixel_fmt == GF_PIXEL_YUV422_10)
     395             :                         pix_out = AV_PIX_FMT_YUV422P10LE;
     396             :                 else
     397             :                         pix_out = AV_PIX_FMT_YUV422P;
     398             :                 break;
     399             : 
     400       30022 :         case GF_PIXEL_YUV444:
     401             :         case GF_PIXEL_YUV444_10:
     402       30022 :                 pict.data[0] =  (uint8_t *)out_buffer;
     403       30022 :                 pict.data[1] =  (uint8_t *)out_buffer + ctx->stride * ctx->height;
     404       30022 :                 pict.data[2] =  (uint8_t *)out_buffer + 2*ctx->stride * ctx->height;
     405       30022 :                 pict.linesize[0] = pict.linesize[1] = pict.linesize[2] = ctx->stride;
     406       30022 :                 if (ctx->pixel_fmt == GF_PIXEL_YUV444_10)
     407             :                         pix_out = AV_PIX_FMT_YUV444P10LE;
     408             :                 else
     409             :                         pix_out = AV_PIX_FMT_YUV444P;
     410             :                 break;
     411             : 
     412           0 :         default:
     413           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] Unsupported pixel format %s, patch welcome\n", av_get_pix_fmt_name(ctx->decoder->pix_fmt) ));
     414             : 
     415           0 :                 gf_filter_pck_discard(dst_pck);
     416             : 
     417           0 :                 return GF_NOT_SUPPORTED;
     418             :         }
     419             : 
     420      325948 :         ctx->sws_ctx = sws_getCachedContext(ctx->sws_ctx,
     421       81487 :                                            ctx->decoder->width, ctx->decoder->height, ff_pfmt,
     422      162974 :                                            ctx->width, ctx->height, pix_out, SWS_BICUBIC, NULL, NULL, NULL);
     423       81487 :         if (ctx->sws_ctx) {
     424       81487 :                 sws_scale(ctx->sws_ctx, (const uint8_t * const*)frame->data, frame->linesize, 0, ctx->height, pict.data, pict.linesize);
     425             :         }
     426             : 
     427       81487 :         gf_filter_pck_set_seek_flag(dst_pck, GF_FALSE);
     428             : 
     429       81487 :         if (frame->interlaced_frame)
     430           0 :                 gf_filter_pck_set_interlaced(dst_pck, frame->top_field_first ? 2 : 1);
     431             : 
     432       81487 :         gf_filter_pck_send(dst_pck);
     433       81487 :         return GF_OK;
     434             : }
     435             : 
     436             : 
     437        3978 : static GF_Err ffdec_process_audio(GF_Filter *filter, struct _gf_ffdec_ctx *ctx)
     438             : {
     439             :         AVPacket pkt;
     440             :         s32 gotpic;
     441             :         s32 len, in_size, i;
     442             :         u32 samples_to_trash;
     443             :         u32 output_size, prev_afmt;
     444             :         Bool is_eos=GF_FALSE;
     445             :         u8 *data;
     446             :         AVFrame *frame;
     447             :         GF_FilterPacket *dst_pck, *src_pck;
     448             :         GF_FilterPacket *pck;
     449             : 
     450             : decode_next:
     451        5900 :         pck = gf_filter_pid_get_packet(ctx->in_pid);
     452        5900 :         in_size = 0;
     453             :         
     454        5900 :         if (ctx->reconfig_pending) {
     455             :                 pck = NULL;
     456        5900 :         } else if (!pck) {
     457        3024 :                 is_eos = gf_filter_pid_is_eos(ctx->in_pid);
     458        3024 :                 if (!is_eos) return GF_OK;
     459             :         }
     460             : 
     461        3018 :         av_init_packet(&pkt);
     462        3018 :         if (pck) pkt.data = (uint8_t *) gf_filter_pck_get_data(pck, &in_size);
     463             : 
     464        3018 :         if (pck) {
     465        2876 :                 src_pck = pck;
     466        2876 :                 gf_filter_pck_ref_props(&src_pck);
     467        2876 :                 if (src_pck) gf_list_add(ctx->src_packets, src_pck);
     468             : 
     469        2876 :                 if (!pkt.data) {
     470           0 :                         gf_filter_pid_drop_packet(ctx->in_pid);
     471           0 :                         return GF_OK;
     472             :                 }
     473             : 
     474        2876 :                 pkt.pts = gf_filter_pck_get_cts(pck);
     475        2876 :                 pkt.dts = gf_filter_pck_get_dts(pck);
     476             : 
     477        2876 :                 pkt.size = in_size;
     478        2876 :                 if ((s32) ctx->frame_start > pkt.size) ctx->frame_start = 0;
     479             :                 //seek to last byte consumed by the previous decode4()
     480        2876 :                 else if (ctx->frame_start) {
     481           0 :                         pkt.data += ctx->frame_start;
     482           0 :                         pkt.size -= ctx->frame_start;
     483             :                 }
     484        2876 :                 pkt.duration = gf_filter_pck_get_duration(pck);
     485        2876 :                 if (gf_filter_pck_get_sap(pck)>0)
     486        2876 :                         pkt.flags = AV_PKT_FLAG_KEY;
     487             : 
     488        2876 :                 if (!ctx->first_cts_plus_one)
     489          31 :                         ctx->first_cts_plus_one = pkt.pts + 1;
     490             : 
     491             :         } else {
     492         142 :                 pkt.size = 0;
     493             :         }
     494             : 
     495        3018 :         prev_afmt = ctx->decoder->sample_fmt;
     496        3018 :         frame = ctx->frame;
     497        3018 :         len = avcodec_decode_audio4(ctx->decoder, frame, &gotpic, &pkt);
     498             : 
     499             :         samples_to_trash = 0;
     500        3018 :         if ( gotpic && (ctx->delay<0)) {
     501           0 :                 if (pkt.pts + 1 - ctx->first_cts_plus_one + ctx->delay < 0) {
     502           0 :                         if (pkt.duration + ctx->delay < 0) {
     503           0 :                                 frame->nb_samples = 0;
     504             :                                 samples_to_trash = 0;
     505           0 :                                 ctx->delay += pkt.duration;
     506             :                         } else {
     507           0 :                                 samples_to_trash = (u32) -ctx->delay;
     508             :                         }
     509             :                         
     510           0 :                         if (!samples_to_trash || (samples_to_trash > (u32) frame->nb_samples) ) {
     511           0 :                                 frame->nb_samples = 0;
     512             :                                 samples_to_trash = 0;
     513             :                         }
     514           0 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, NULL);
     515             :                 } else {
     516           0 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DELAY, NULL);
     517           0 :                         ctx->delay = 0;
     518             :                 }
     519             :         }
     520             : 
     521             :         //this will handle eos as well
     522        3018 :         if ((len<0) || !gotpic) {
     523         169 :                 ctx->frame_start = 0;
     524         169 :                 if (pck) gf_filter_pid_drop_packet(ctx->in_pid);
     525         169 :                 if (pkt.size && (len<0)) {
     526           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] PID %s failed to decode frame PTS "LLU": %s\n", gf_filter_pid_get_name(ctx->in_pid), pkt.pts, av_err2str(len) ));
     527             :                         return GF_NON_COMPLIANT_BITSTREAM;
     528             :                 }
     529         169 :                 if (is_eos) {
     530         142 :                         gf_filter_pid_set_eos(ctx->out_pid);
     531         142 :                         return GF_EOS;
     532             :                 }
     533          27 :                 if (ctx->reconfig_pending) {
     534           0 :                         avcodec_free_context(&ctx->decoder);
     535           0 :                         ctx->decoder = NULL;
     536           0 :                         ctx->reconfig_pending = GF_FALSE;
     537             :                         //these properties are checked after decode, when we reconfigure we copy props from input to output
     538             :                         //so we need to make sure we retrigger pid config even if these did not change
     539           0 :                         ctx->sample_fmt = 0;
     540           0 :                         ctx->sample_rate = 0;
     541           0 :                         ctx->channels = 0;
     542           0 :                         ctx->channel_layout = 0;
     543           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[FFDec] PID %s reconfigure pending and all frames flushed, reconfguring\n", gf_filter_pid_get_name(ctx->in_pid) ));
     544           0 :                         return ffdec_configure_pid(filter, ctx->in_pid, GF_FALSE);
     545             :                 }
     546             :                 return GF_OK;
     547             :         }
     548             : 
     549        2849 :         FF_CHECK_PROP(channels, channels, GF_PROP_PID_NUM_CHANNELS)
     550        2849 :         FF_CHECK_PROPL(channel_layout, channel_layout, GF_PROP_PID_CHANNEL_LAYOUT)
     551        2849 :         FF_CHECK_PROP(sample_rate, sample_rate, GF_PROP_PID_SAMPLE_RATE)
     552             : 
     553        2849 :         if (prev_afmt != ctx->decoder->sample_fmt) {
     554           0 :                 ctx->sample_fmt = ffmpeg_audio_fmt_to_gpac(ctx->decoder->sample_fmt);
     555           0 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(ctx->sample_fmt) );
     556           0 :                 ctx->bytes_per_sample = gf_audio_fmt_bit_depth(ctx->sample_fmt) / 8;
     557             :         }
     558             : 
     559        2849 :         if (pck && gf_filter_pid_eos_received(ctx->in_pid)) {
     560         433 :                 u32 timescale = gf_filter_pck_get_timescale(pck);
     561         433 :                 u64 odur = gf_filter_pck_get_duration(pck);
     562         433 :                 if (timescale != ctx->sample_rate) {
     563           0 :                         odur *= ctx->sample_rate;
     564           0 :                         odur /= timescale;
     565             :                 }
     566         433 :                 if (odur < frame->nb_samples) {
     567           0 :                         frame->nb_samples = (int) odur;
     568             :                 }
     569             :         }
     570             : 
     571             : 
     572        2849 :         output_size = (frame->nb_samples - samples_to_trash) * ctx->channels * ctx->bytes_per_sample;
     573        2849 :         dst_pck = gf_filter_pck_new_alloc(ctx->out_pid, output_size, &data);
     574        2849 :         if (!dst_pck) return GF_OUT_OF_MEM;
     575             : 
     576        2849 :         switch (frame->format) {
     577             :         case AV_SAMPLE_FMT_U8P:
     578             :         case AV_SAMPLE_FMT_S16P:
     579             :         case AV_SAMPLE_FMT_S32P:
     580             :         case AV_SAMPLE_FMT_FLTP:
     581             :         case AV_SAMPLE_FMT_DBLP:
     582        5550 :                 for (i=0; (u32) i< ctx->channels; i++) {
     583        5550 :                         char *inputChannel = frame->extended_data[i] + samples_to_trash * ctx->bytes_per_sample;
     584        5550 :                         memcpy(data, inputChannel, ctx->bytes_per_sample * (frame->nb_samples-samples_to_trash) );
     585        5550 :                         data += ctx->bytes_per_sample * (frame->nb_samples-samples_to_trash);
     586             :                 }
     587             :                 break;
     588          68 :         default:
     589          68 :                 memcpy(data, ctx->frame->data[0] + samples_to_trash * ctx->bytes_per_sample, ctx->bytes_per_sample * (frame->nb_samples - samples_to_trash) * ctx->channels);
     590             :                 break;
     591             :         }
     592             : 
     593             :         //we don't follow the same approach as in video, we assume the codec works with one in one out
     594             :         //and use the first entry in src packets to match in order to copy the properties
     595             :         //a nicer approach would be to count delay frames (number of frames used to initialize)
     596             :         //and backmerge properties from the last packet in to the last-nb_init_frames
     597        2849 :         src_pck = gf_list_get(ctx->src_packets, 0);
     598             : 
     599        2849 :         if (src_pck) {
     600        2849 :                 gf_filter_pck_merge_properties(src_pck, dst_pck);
     601        2849 :                 gf_list_rem(ctx->src_packets, 0);
     602        2849 :                 gf_filter_pck_unref(src_pck);
     603             :         }
     604             : 
     605        2849 :         if (output_size) {
     606        2849 :                 if (frame->pkt_pts != AV_NOPTS_VALUE) {
     607        2849 :                         u64 pts = frame->pkt_pts;
     608        2849 :                         u32 timescale = gf_filter_pck_get_timescale(pck);
     609        2849 :                         if (ctx->nb_samples_already_in_frame) {
     610           0 :                                 if (ctx->sample_rate == timescale) {
     611           0 :                                         pts += ctx->nb_samples_already_in_frame;
     612             :                                 }
     613             :                         }
     614        2849 :                         if (pts >= ctx->ts_offset) pts -= ctx->ts_offset;
     615             :                         else pts = 0;
     616        2849 :                         gf_filter_pck_set_cts(dst_pck, pts);
     617        2849 :                         gf_filter_pck_set_dts(dst_pck, pts);
     618             :                 }
     619        2849 :                 gf_filter_pck_send(dst_pck);
     620             :         } else {
     621           0 :                 gf_filter_pck_discard(dst_pck);
     622             :         }
     623             : 
     624        2849 :         ctx->frame_start += len;
     625             :         //done with this input packet
     626        2849 :         if (in_size <= (s32) ctx->frame_start) {
     627        2849 :                 frame->nb_samples = 0;
     628        2849 :                 ctx->frame_start = 0;
     629        2849 :                 ctx->nb_samples_already_in_frame = 0;
     630        2849 :                 gf_filter_pid_drop_packet(ctx->in_pid);
     631             : 
     632        2849 :                 if (gf_filter_pid_would_block(ctx->out_pid))
     633             :                         return GF_OK;
     634             : 
     635             :                 //if space available in ouput, decode right away - needed for audio formats with very short frames
     636             :                 //avoid recursion
     637             :                 goto decode_next;
     638             :         }
     639             :         //still some data to decode in packet, don't drop it
     640             :         //todo: check if frame->pkt_pts or frame->pts is updated by ffmpeg, otherwise do it ourselves !
     641           0 :         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] Code not yet tested  - frame PTS was "LLU" - nb samples dec %d\n", frame->pkt_pts, frame->nb_samples));
     642           0 :         ctx->nb_samples_already_in_frame += frame->nb_samples;
     643           0 :         frame->nb_samples = 0;
     644             : 
     645             :         //avoid recursion
     646           0 :         goto decode_next;
     647             : 
     648             : //      return ffdec_process_audio(filter, ctx);
     649             : }
     650             : 
     651             : #ifdef FF_SUB_SUPPORT
     652             : static GF_Err ffdec_process_subtitle(GF_Filter *filter, struct _gf_ffdec_ctx *ctx)
     653             : {
     654             :         AVPacket pkt;
     655             :         AVSubtitle subs;
     656             :         s32 gotpic;
     657             :         s32 len, in_size;
     658             :         Bool is_eos=GF_FALSE;
     659             : 
     660             :         GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->in_pid);
     661             : 
     662             :         if (!pck) {
     663             :                 is_eos = gf_filter_pid_is_eos(ctx->in_pid);
     664             :                 if (!is_eos) return GF_OK;
     665             :         }
     666             :         av_init_packet(&pkt);
     667             :         if (pck) pkt.data = (uint8_t *) gf_filter_pck_get_data(pck, &in_size);
     668             : 
     669             :         if (!is_eos) {
     670             :                 u64 dts;
     671             :                 pkt.pts = gf_filter_pck_get_cts(pck);
     672             : 
     673             :                 //copy over SAP and duration in dts
     674             :                 dts = gf_filter_pck_get_sap(pck);
     675             :                 dts <<= 32;
     676             :                 dts |= gf_filter_pck_get_duration(pck);
     677             :                 pkt.dts = dts;
     678             : 
     679             :                 pkt.size = in_size;
     680             :                 if (ctx->frame_start > pkt.size) ctx->frame_start = 0;
     681             :                 //seek to last byte consumed by the previous decode4()
     682             :                 else if (ctx->frame_start) {
     683             :                         pkt.data += ctx->frame_start;
     684             :                         pkt.size -= ctx->frame_start;
     685             :                 }
     686             :         } else {
     687             :                 pkt.size = 0;
     688             :         }
     689             : 
     690             :         memset(&subs, 0, sizeof(AVSubtitle));
     691             :         len = avcodec_decode_subtitle2(ctx->decoder, &subs, &gotpic, &pkt);
     692             : 
     693             :         //this will handle eos as well
     694             :         if ((len<0) || !gotpic) {
     695             :                 ctx->frame_start = 0;
     696             :                 if (pck) gf_filter_pid_drop_packet(ctx->in_pid);
     697             :                 if (len<0) {
     698             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] PID %s failed to decode frame PTS "LLU": %s\n", gf_filter_pid_get_name(ctx->in_pid), pkt.pts, av_err2str(len) ));
     699             :                         return GF_NON_COMPLIANT_BITSTREAM;
     700             :                 }
     701             :                 if (is_eos) {
     702             :                         gf_filter_pid_set_eos(ctx->out_pid);
     703             :                         return GF_EOS;
     704             :                 }
     705             :                 return GF_OK;
     706             :         }
     707             :         //TODO - do we want to remap to TX3G/other and handle the rendering some place else, or do we do the rendering here ?
     708             : 
     709             : 
     710             :         avsubtitle_free(&subs);
     711             :         if (pck) gf_filter_pid_drop_packet(ctx->in_pid);
     712             :         return GF_OK;
     713             : }
     714             : #endif
     715             : 
     716      161666 : static GF_Err ffdec_process(GF_Filter *filter)
     717             : {
     718      161666 :         GF_FFDecodeCtx *ctx = (GF_FFDecodeCtx *) gf_filter_get_udta(filter);
     719      161666 :         if (gf_filter_pid_would_block(ctx->out_pid))
     720             :                 return GF_OK;
     721             : 
     722      161666 :         return ctx->process(filter, ctx);
     723             : }
     724             : 
     725             : static const GF_FilterCapability FFDecodeAnnexBCaps[] =
     726             : {
     727             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     728             :         CAP_BOOL(GF_CAPS_INPUT, GF_PROP_PID_UNFRAMED, GF_TRUE),
     729             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_VVC),
     730             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_AVC),
     731             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_CODECID, GF_CODECID_HEVC),
     732             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
     733             : };
     734             : 
     735             : 
     736         161 : static GF_Err ffdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     737             : {
     738             :         s32 res;
     739             :         u32 type=0, gpac_codecid=0;
     740         161 :         AVDictionary *options = NULL;
     741             :         const GF_PropertyValue *prop;
     742             :         AVCodec *codec=NULL;
     743         161 :         GF_FFDecodeCtx *ctx = (GF_FFDecodeCtx *) gf_filter_get_udta(filter);
     744             : 
     745             :         //disconnect of src pid (not yet supported)
     746         161 :         if (is_remove) {
     747             :                 //one in one out, this is simple
     748           3 :                 if (ctx->out_pid) {
     749           3 :                         gf_filter_pid_remove(ctx->out_pid);
     750           3 :                         ctx->out_pid = NULL;
     751             :                 }
     752             :                 return GF_OK;
     753             :         }
     754             : 
     755             :         //check our PID: streamtype and codecid
     756         158 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
     757         158 :         if (!prop) return GF_NOT_SUPPORTED;
     758             : 
     759         158 :         type = prop->value.uint;
     760         158 :         switch (type) {
     761             :         case GF_STREAM_AUDIO:
     762             :         case GF_STREAM_VISUAL:
     763             : #ifdef FF_SUB_SUPPORT
     764             :         case GF_STREAM_TEXT:
     765             : #endif
     766             :                 break;
     767             :         default:
     768             :                 return GF_NOT_SUPPORTED;
     769             :         }
     770         158 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
     771         158 :         if (!prop) return GF_NOT_SUPPORTED;
     772         158 :         gpac_codecid = prop->value.uint;
     773         158 :         if (gpac_codecid==GF_CODECID_RAW)
     774             :                 return GF_NOT_SUPPORTED;
     775             : 
     776             : 
     777             :         //initial config or update
     778         158 :         if (!ctx->in_pid || (ctx->in_pid==pid)) {
     779         158 :                 ctx->in_pid = pid;
     780         158 :                 if (!ctx->type) ctx->type = type;
     781          17 :                 else if (ctx->type != type) {
     782             :                         return GF_NOT_SUPPORTED;
     783             :                 }
     784             :         } else {
     785             :                 //only one input pid in ctx
     786             :                 if (ctx->in_pid) return GF_REQUIRES_NEW_INSTANCE;
     787             :         }
     788             : 
     789         158 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
     790         158 :         ctx->width = prop ? prop->value.uint : 0;
     791         158 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
     792         158 :         ctx->height = prop ? prop->value.uint : 0;
     793         158 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE);
     794         158 :         ctx->sample_rate = prop ? prop->value.uint : 0;
     795         158 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS);
     796         158 :         ctx->channels = prop ? prop->value.uint : 0;
     797             : 
     798         158 :         if (gpac_codecid==GF_CODECID_VVC) {
     799           0 :                 u32 codec_id = ffmpeg_codecid_from_gpac(gpac_codecid, NULL);
     800           0 :                 codec = codec_id ? avcodec_find_decoder(codec_id) : NULL;
     801             :                 //libvvdec only supports annexB, request ufnalu adaptation filter
     802           0 :                 if (codec && codec->name && strstr(codec->name, "vvdec")) {
     803           0 :                         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_UNFRAMED);
     804           0 :                         if (!prop || !prop->value.boolean) {
     805           0 :                                 gf_filter_override_caps(filter, FFDecodeAnnexBCaps, GF_ARRAY_LENGTH(FFDecodeAnnexBCaps));
     806           0 :                                 gf_filter_pid_negociate_property(ctx->in_pid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) );
     807           0 :                                 return GF_OK;
     808             :                         }
     809             :                 }
     810             :         }
     811             : 
     812             : 
     813         158 :         if (gpac_codecid == GF_CODECID_FFMPEG) {
     814           0 :                 prop = gf_filter_pid_get_property(pid, GF_FFMPEG_DECODER_CONFIG);
     815           0 :                 if (!prop || !prop->value.ptr) {
     816           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] PID %s codec context not exposed by demuxer !\n", gf_filter_pid_get_name(pid) ));
     817             :                         return GF_SERVICE_ERROR;
     818             :                 }
     819           0 :                 ctx->decoder = prop->value.ptr;
     820           0 :                 codec = avcodec_find_decoder(ctx->decoder->codec_id);
     821           0 :                 if (!codec) return GF_NOT_SUPPORTED;
     822             : 
     823           0 :         ctx->owns_context = GF_FALSE;
     824             :         }
     825             :         //we reconfigure the stream
     826             :         else {
     827         158 :                 u32 codec_id, ff_codectag=0;
     828             :         
     829         158 :         if (!ctx->owns_context) {
     830         141 :             ctx->decoder = NULL;
     831             :         }
     832         158 :                 if (ctx->decoder) {
     833          10 :                         codec_id = ffmpeg_codecid_from_gpac(gpac_codecid, NULL);
     834             :                         //same codec, same config, don't reinit
     835          10 :                         if (ctx->decoder->codec->id == codec_id) {
     836             :                                 u32 cfg_crc=0;
     837          10 :                                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     838          10 :                                 if (prop && prop->value.data.ptr && prop->value.data.size) {
     839          10 :                                         cfg_crc = gf_crc_32(prop->value.data.ptr, prop->value.data.size);
     840             :                                 }
     841          10 :                                 if (cfg_crc == ctx->extra_data_crc) {
     842             :                                         goto reuse_codec_context;
     843             :                                 }
     844             :                         }
     845             : 
     846             :             
     847             :                         //we could further optimize by detecting we have the same codecid and injecting the extradata
     848             :                         //but this is not 100% reliable, and will require parsing AVC/HEVC config
     849             :                         //since this seems to work properly with decoder close/open, we keep it as is
     850           7 :                         ctx->reconfig_pending = GF_TRUE;
     851           7 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[FFDec] PID %s reconfigure detected, flushing frame\n", gf_filter_pid_get_name(pid) ));
     852           7 :                         return GF_OK;
     853             :                 }
     854             : 
     855         148 :                 codec_id = ffmpeg_codecid_from_gpac(gpac_codecid, &ff_codectag);
     856             :                 //specific remaps
     857         148 :                 if (!codec_id) {
     858           0 :                         switch (gpac_codecid) {
     859             :                         case GF_CODECID_MVC: codec_id = AV_CODEC_ID_H264; break;
     860             :                         }
     861             : 
     862             :                 }
     863         148 :                 if (codec_id) codec = avcodec_find_decoder(codec_id);
     864         148 :                 if (!codec) {
     865           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] No decoder found for codec %s\n", gf_codecid_name(gpac_codecid) ));
     866             :                         return GF_NOT_SUPPORTED;
     867             :                 }
     868             : 
     869         148 :                 ctx->decoder = avcodec_alloc_context3(NULL);
     870         148 :                 if (! ctx->decoder) return GF_OUT_OF_MEM;
     871         148 :                 ctx->owns_context = GF_TRUE;
     872         148 :                 if (ff_codectag)
     873           0 :                         ctx->decoder->codec_tag = ff_codectag;
     874             : 
     875         148 :                 ffmpeg_set_enc_dec_flags(ctx->options, ctx->decoder);
     876             : 
     877             :                 //for some raw codecs
     878         148 :                 if (ctx->width && ctx->height) {
     879         117 :                         ctx->decoder->width = ctx->width;
     880         117 :                         ctx->decoder->height = ctx->height;
     881             :                 }
     882         148 :                 if (ctx->sample_rate && ctx->channels) {
     883          31 :                         ctx->decoder->sample_rate = ctx->sample_rate;
     884          31 :                         ctx->decoder->channels = ctx->channels;
     885             :                 }
     886             : 
     887             :                 //we may have a dsi here!
     888         148 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     889         148 :                 if (prop && prop->value.data.ptr && prop->value.data.size) {
     890             :                         //looks like ffmpeg wants the fLaC keyword
     891         140 :                         if (gpac_codecid==GF_CODECID_FLAC) {
     892           1 :                                 ctx->decoder->extradata_size = prop->value.data.size+4;
     893           1 :                                 ctx->decoder->extradata = av_malloc(sizeof(char) * prop->value.data.size+4);
     894           1 :                                 memcpy(ctx->decoder->extradata, "fLaC", 4);
     895           1 :                                 memcpy(ctx->decoder->extradata+4, prop->value.data.ptr, prop->value.data.size);
     896             :                         } else {
     897         139 :                                 ctx->decoder->extradata_size = prop->value.data.size;
     898         139 :                                 ctx->decoder->extradata = av_malloc(sizeof(char) * prop->value.data.size);
     899         139 :                                 memcpy(ctx->decoder->extradata, prop->value.data.ptr, prop->value.data.size);
     900             :                         }
     901         140 :                         ctx->extra_data_crc = gf_crc_32(prop->value.data.ptr, prop->value.data.size);
     902             :                 }
     903             :         }
     904             : 
     905             :         //by default let libavcodec decide - if single thread is required, let the user define -threads option
     906         148 :         if (codec->capabilities & AV_CODEC_CAP_AUTO_THREADS)
     907           0 :                 ctx->decoder->thread_count = 0;
     908             : 
     909             :         //clone options (in case we need to destroy/recreate the codec) and open codec
     910         148 :         av_dict_copy(&options, ctx->options, 0);
     911         148 :         res = avcodec_open2(ctx->decoder, codec, &options);
     912         148 :         if (res < 0) {
     913           0 :                 if (options) av_dict_free(&options);
     914           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] PID %s failed to open codec context: %s\n", gf_filter_pid_get_name(pid), av_err2str(res) ));
     915             :                 return GF_NON_COMPLIANT_BITSTREAM;
     916             :         }
     917             : 
     918         148 :         if (options) {
     919          42 :                 ffmpeg_report_unused_options(filter, options);
     920          42 :                 av_dict_free(&options);
     921             :         }
     922             : 
     923             :         //we're good to go, declare our output pid
     924         148 :         ctx->in_pid = pid;
     925         148 :         if (!ctx->out_pid) {
     926             :                 char szCodecName[1000];
     927         141 :                 ctx->out_pid = gf_filter_pid_new(filter);
     928             : 
     929             :                 //to change once we implement on-the-fly codec change
     930         141 :                 sprintf(szCodecName, "ffdec:%s", ctx->decoder->codec->name ? ctx->decoder->codec->name : "unknown");
     931         141 :                 gf_filter_set_name(filter, szCodecName);
     932         141 :                 gf_filter_pid_set_framing_mode(ctx->in_pid, GF_TRUE);
     933             :         }
     934             : 
     935         158 : reuse_codec_context:
     936             :         //copy props it at init config or at reconfig
     937         151 :         if (ctx->out_pid) {
     938         151 :                 gf_filter_pid_copy_properties(ctx->out_pid, ctx->in_pid);
     939         151 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
     940         151 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_DECODER_CONFIG, NULL );
     941             :         }
     942             : 
     943         151 :         if (type==GF_STREAM_VISUAL) {
     944             :                 u32 pix_fmt;
     945         120 :                 ctx->force_full_range = GF_FALSE;
     946         120 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_RANGE, NULL );
     947         120 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_MX, NULL );
     948         120 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_TRANSFER, NULL );
     949         120 :                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_COLR_PRIMARIES, NULL );
     950             : 
     951         120 :                 ctx->process = ffdec_process_video;
     952             :                 //for some streams, we don't have w/h/pixfmt after opening the decoder
     953             :                 //to make sure we are not confusing potential filters expecting them, init to default values
     954         120 :                 if (ctx->decoder->pix_fmt>=0) {
     955          19 :                         ctx->o_ff_pfmt = ctx->decoder->pix_fmt;
     956          19 :                         pix_fmt = ffmpeg_pixfmt_to_gpac(ctx->decoder->pix_fmt);
     957          19 :                         if (!pix_fmt) {
     958           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFDec] Unsupported pixel format %d, defaulting to RGB\n", ctx->decoder->pix_fmt));
     959             :                                 pix_fmt = GF_PIXEL_RGB;
     960           0 :                                 ctx->o_ff_pfmt = AV_PIX_FMT_RGB24;
     961             :                         }
     962             :                 } else {
     963             :                         pix_fmt = GF_PIXEL_YUV;
     964         101 :                         ctx->o_ff_pfmt = AV_PIX_FMT_YUV420P;
     965             :                 }
     966         120 :                 ffdec_check_pix_fmt_change(ctx, pix_fmt);
     967             : 
     968         120 :                 if (ctx->decoder->width) {
     969         120 :                         FF_CHECK_PROP(width, width, GF_PROP_PID_WIDTH)
     970             :                 } else {
     971           0 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_WIDTH, &PROP_UINT( ctx->width) );
     972             :                 }
     973         120 :                 if (ctx->decoder->height) {
     974         120 :                         FF_CHECK_PROP(height, height, GF_PROP_PID_HEIGHT)
     975             :                 } else {
     976           0 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_HEIGHT, &PROP_UINT( ctx->height) );
     977             :                 }
     978         120 :                 if (ctx->decoder->sample_aspect_ratio.num && ctx->decoder->sample_aspect_ratio.den) {
     979           4 :                         ctx->sar.num = ctx->decoder->sample_aspect_ratio.num;
     980           4 :                         ctx->sar.den = ctx->decoder->sample_aspect_ratio.den;
     981           4 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_SAR, &PROP_FRAC( ctx->sar) );
     982             :                 }
     983         120 :                 if (!ctx->frame)
     984         110 :                         ctx->frame = av_frame_alloc();
     985             : 
     986         120 :                 if (ctx->pixel_fmt) {
     987         120 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_PIXFMT, &PROP_UINT( ctx->pixel_fmt) );
     988             :                 }
     989             : 
     990          31 :         } else if (type==GF_STREAM_AUDIO) {
     991          31 :                 ctx->process = ffdec_process_audio;
     992          31 :                 if (ctx->decoder->sample_fmt != AV_SAMPLE_FMT_NONE) {
     993          31 :                         ctx->sample_fmt = ffmpeg_audio_fmt_to_gpac(ctx->decoder->sample_fmt);
     994          31 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(ctx->sample_fmt) );
     995          31 :                         ctx->bytes_per_sample = gf_audio_fmt_bit_depth(ctx->sample_fmt) / 8;
     996             :                 }
     997             : 
     998             :                 //override PID props with what decoder gives us
     999          31 :                 if (ctx->decoder->channels) {
    1000          31 :                         ctx->channels = 0;
    1001          31 :                         FF_CHECK_PROP(channels, channels, GF_PROP_PID_NUM_CHANNELS)
    1002             :                 }
    1003          31 :                 if (ctx->decoder->channel_layout) {
    1004          28 :                         u64 ch_lay = ffmpeg_channel_layout_to_gpac(ctx->decoder->channel_layout);
    1005          28 :                         if (ctx->channel_layout != ch_lay) {
    1006          28 :                                 gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(ch_lay ) );
    1007          28 :                                 ctx->channel_layout = ch_lay;
    1008             :                         }
    1009             :                 }
    1010          31 :                 if (ctx->decoder->sample_rate) {
    1011          31 :                         ctx->sample_rate = 0;
    1012          31 :                         FF_CHECK_PROP(sample_rate, sample_rate, GF_PROP_PID_SAMPLE_RATE)
    1013             :                 }
    1014          31 :                 if (!ctx->frame)
    1015          31 :                         ctx->frame = av_frame_alloc();
    1016             : 
    1017          31 :                 if (ctx->sample_fmt) {
    1018          31 :                         gf_filter_pid_set_property(ctx->out_pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT( ctx->sample_fmt) );
    1019             :                 }
    1020             : 
    1021          31 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_NO_PRIMING);
    1022          31 :                 if (prop && prop->value.boolean) {
    1023           0 :                         ctx->delay = 0;
    1024             :                 } else {
    1025          31 :                         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DELAY);
    1026          31 :                         ctx->delay = prop ? prop->value.longsint : 0;
    1027          31 :                         ctx->first_cts_plus_one = 0;
    1028             : 
    1029          31 :                         if (ctx->delay<0)
    1030           0 :                                 ctx->ts_offset = (u32) -ctx->delay;
    1031             :                         else
    1032          31 :                                 ctx->ts_offset = 0;
    1033             :                 }
    1034             : 
    1035             :         } else {
    1036             : #ifdef FF_SUB_SUPPORT
    1037             :                 ctx->process = ffdec_process_subtitle;
    1038             : #endif
    1039             :         }
    1040             :         return GF_OK;
    1041             : }
    1042             : 
    1043             : 
    1044          60 : static GF_Err ffdec_update_arg(GF_Filter *filter, const char *arg_name, const GF_PropertyValue *arg_val)
    1045             : {
    1046             :         s32 res;
    1047          60 :         GF_FFDecodeCtx *ctx = gf_filter_get_udta(filter);
    1048             : 
    1049             :         //initial parsing of arguments
    1050          60 :         if (!ctx->initialized) {
    1051          60 :                 switch (arg_val->type) {
    1052          60 :                 case GF_PROP_STRING:
    1053          60 :                         res = av_dict_set(&ctx->options, arg_name, arg_val->value.string, 0);
    1054          60 :                         if (res<0) {
    1055           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] Failed to set option %s:%s\n", arg_name, arg_val ));
    1056             :                         }
    1057             :                         break;
    1058           0 :                 default:
    1059           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FFDec] Failed to set option %s:%s, unrecognized type %d\n", arg_name, arg_val, arg_val->type ));
    1060             :                         return GF_NOT_SUPPORTED;
    1061             :                 }
    1062             :                 return GF_OK;
    1063             :         }
    1064             :         //updates of arguments, not supported for ffmpeg decoders
    1065             :         return GF_NOT_SUPPORTED;
    1066             : }
    1067             : 
    1068        3552 : static Bool ffdec_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
    1069             : {
    1070        3552 :         GF_FFDecodeCtx *ctx = (GF_FFDecodeCtx *) gf_filter_get_udta(filter);
    1071             : 
    1072        3552 :         if ((evt->base.type==GF_FEVT_PLAY) || (evt->base.type==GF_FEVT_SET_SPEED) || (evt->base.type==GF_FEVT_RESUME)) {
    1073         162 :                 ctx->drop_non_refs = evt->play.drop_non_ref;
    1074             :         }
    1075             :         //play request, detach all pending source packets and trigger a reconfig to start from a clean state
    1076        3390 :         else if (evt->base.type==GF_FEVT_STOP) {
    1077         100 :                 while (gf_list_count(ctx->src_packets)) {
    1078          48 :                         GF_FilterPacket *pck = gf_list_pop_back(ctx->src_packets);
    1079          48 :                         gf_filter_pck_unref(pck);
    1080             :                         //for video, this will reset the decoder
    1081          48 :                         ctx->flush_done = GF_TRUE;
    1082             :                 }
    1083             :         }
    1084             : 
    1085        3552 :         return GF_FALSE;
    1086             : }
    1087             : 
    1088             : static const GF_FilterCapability FFDecodeCaps[] =
    1089             : {
    1090             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1091             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    1092             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1093             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_NONE),
    1094             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_SVC),
    1095             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_LHVC),
    1096             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_HEVC_TILES),
    1097             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1098             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_TILE_BASE, GF_TRUE),
    1099             :         { .code=GF_PROP_PID_SCALABLE, .val={.type=GF_PROP_BOOL, .value.boolean = GF_TRUE}, .flags=(GF_CAPS_INPUT_OPT), .priority=255 },
    1100             :         {0},
    1101             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
    1102             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    1103             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_NONE),
    1104             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1105             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1106             : 
    1107             : #ifdef FF_SUB_SUPPORT
    1108             :         {0},
    1109             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_TEXT),
    1110             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_TEXT_MPEG4),
    1111             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_TX3G),
    1112             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_WEBVTT),
    1113             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_SUBS_XML),
    1114             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_CODECID, GF_CODECID_SIMPLE_TEXT),
    1115             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_TEXT),
    1116             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1117             : #endif
    1118             : 
    1119             : };
    1120             : 
    1121             : GF_FilterRegister FFDecodeRegister = {
    1122             :         .name = "ffdec",
    1123             :         .version = LIBAVCODEC_IDENT,
    1124             :         GF_FS_SET_DESCRIPTION("FFMPEG decoder")
    1125             :         GF_FS_SET_HELP("Decodes audio and video streams.\n"
    1126             :         "See FFMPEG documentation (https://ffmpeg.org/documentation.html) for more details.\n"
    1127             :         "To list all supported decoders for your GPAC build, use `gpac -h ffdec:*`.\n"
    1128             :         "\n"
    1129             :         "Options can be passed from prompt using `-+OPT=VAL`\n"
    1130             :         "The default threading mode is to let libavcodec decide how many threads to use. To enforce single thread, use `-+threads=1`\n"
    1131             :         )
    1132             :         .private_size = sizeof(GF_FFDecodeCtx),
    1133             :         SETCAPS(FFDecodeCaps),
    1134             :         .initialize = ffdec_initialize,
    1135             :         .finalize = ffdec_finalize,
    1136             :         .configure_pid = ffdec_configure_pid,
    1137             :         .process = ffdec_process,
    1138             :         .update_arg = ffdec_update_arg,
    1139             :         .process_event = ffdec_process_event,
    1140             :         .flags = GF_FS_REG_META,
    1141             :         //use middle priorty, so that hardware decs/other native impl in gpac can take over if needed
    1142             :         //don't use lowest one since we use this for scalable codecs
    1143             :         .priority = 128
    1144             : 
    1145             : };
    1146             : 
    1147             : 
    1148             : static const GF_FilterArgs FFDecodeArgs[] =
    1149             : {
    1150             :         { "*", -1, "any possible options defined for AVCodecContext and sub-classes. See `gpac -hx ffdec` and `gpac -hx ffdec:*`", GF_PROP_STRING, NULL, NULL, GF_FS_ARG_META},
    1151             :         {0}
    1152             : };
    1153             : 
    1154        2877 : const GF_FilterRegister *ffdec_register(GF_FilterSession *session)
    1155             : {
    1156        2877 :         ffmpeg_build_register(session, &FFDecodeRegister, FFDecodeArgs, 1, FF_REG_TYPE_DECODE);
    1157        2877 :         return &FFDecodeRegister;
    1158             : }
    1159             : 
    1160             : #else
    1161             : #include <gpac/filters.h>
    1162             : const GF_FilterRegister *ffdec_register(GF_FilterSession *session)
    1163             : {
    1164             :         return NULL;
    1165             : }
    1166             : #endif
    1167             : 

Generated by: LCOV version 1.13