LCOV - code coverage report
Current view: top level - filters - reframe_av1.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 412 561 73.4 %
Date: 2021-04-29 23:48:07 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Romain Bouqueau, Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2018-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / AV1 IVF/OBU/annexB reframer 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/avparse.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/filters.h>
      29             : #include <gpac/internal/media_dev.h>
      30             : 
      31             : #ifndef GPAC_DISABLE_AV_PARSERS
      32             : 
      33             : typedef struct
      34             : {
      35             :         u64 pos;
      36             :         Double duration;
      37             : } AV1Idx;
      38             : 
      39             : typedef enum {
      40             :         NOT_SET,   /*Section 5*/
      41             :         OBUs,   /*Section 5*/
      42             :         AnnexB,
      43             :         IVF,
      44             :         UNSUPPORTED
      45             : } AV1BitstreamSyntax;
      46             : 
      47             : typedef struct
      48             : {
      49             :         //filter args
      50             :         GF_Fraction fps;
      51             :         Double index;
      52             :         Bool importer;
      53             :         Bool deps;
      54             :         
      55             :         u32 bsdbg;
      56             : 
      57             :         //only one input pid declared
      58             :         GF_FilterPid *ipid;
      59             :         //only one output pid declared
      60             :         GF_FilterPid *opid;
      61             : 
      62             :         AV1BitstreamSyntax bsmode;
      63             : 
      64             :         GF_BitStream *bs;
      65             :         u64 cts;
      66             :         u32 width, height;
      67             :         GF_Fraction64 duration;
      68             :         Double start_range;
      69             :         Bool in_seek;
      70             :         u32 timescale;
      71             :         GF_Fraction cur_fps;
      72             : 
      73             :         u32 resume_from;
      74             : 
      75             :         char *buffer;
      76             :         u32 buf_size, alloc_size;
      77             : 
      78             :         //ivf header for now
      79             :         u32 file_hdr_size;
      80             : 
      81             :         Bool is_av1;
      82             :         Bool is_vp9;
      83             :         Bool is_vpX;
      84             :         u32 codecid;
      85             :         GF_VPConfig *vp_cfg;
      86             : 
      87             :         Bool is_playing;
      88             :         Bool is_file, file_loaded;
      89             :         Bool initial_play_done;
      90             : 
      91             :         GF_FilterPacket *src_pck;
      92             : 
      93             :         AV1Idx *indexes;
      94             :         u32 index_alloc_size, index_size;
      95             : 
      96             :         AV1State state;
      97             :         u32 dsi_crc;
      98             : 
      99             :         Bool pts_from_file;
     100             :         u64 cumulated_dur, last_pts;
     101             :         u32 bitrate;
     102             : } GF_AV1DmxCtx;
     103             : 
     104             : 
     105          87 : GF_Err av1dmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     106             : {
     107             :         const GF_PropertyValue *p;
     108          87 :         GF_AV1DmxCtx *ctx = gf_filter_get_udta(filter);
     109             : 
     110          87 :         if (is_remove) {
     111           0 :                 ctx->ipid = NULL;
     112           0 :                 if (ctx->opid) {
     113           0 :                         gf_filter_pid_remove(ctx->opid);
     114           0 :                         ctx->opid = NULL;
     115             :                 }
     116             :                 return GF_OK;
     117             :         }
     118          87 :         if (! gf_filter_pid_check_caps(pid))
     119             :                 return GF_NOT_SUPPORTED;
     120             : 
     121          87 :         ctx->ipid = pid;
     122          87 :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
     123          87 :         if (p) ctx->timescale = p->value.uint;
     124          87 :         ctx->state.mem_mode = GF_TRUE;
     125          87 :         if (ctx->timescale && !ctx->opid) {
     126           0 :                 ctx->opid = gf_filter_pid_new(filter);
     127           0 :                 gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     128           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL);
     129             :         }
     130          87 :         if (ctx->timescale) {
     131             :                 //if we have a FPS prop, use it
     132           0 :                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
     133           0 :                 if (p) ctx->cur_fps = p->value.frac;
     134             :         }
     135             :         return GF_OK;
     136             : }
     137             : 
     138       21045 : GF_Err av1dmx_check_format(GF_Filter *filter, GF_AV1DmxCtx *ctx, GF_BitStream *bs, u32 *last_obu_end)
     139             : {
     140             :         GF_Err e;
     141       21045 :         if (last_obu_end) (*last_obu_end) = 0;
     142             :         //probing av1 bs mode
     143       21045 :         if (ctx->bsmode != NOT_SET) return GF_OK;
     144             : 
     145             : 
     146          87 :         if (!ctx->state.config)
     147          87 :                 ctx->state.config = gf_odf_av1_cfg_new();
     148             : 
     149          87 :         ctx->is_av1 = ctx->is_vp9 = ctx->is_vpX = GF_FALSE;
     150          87 :         ctx->codecid = 0;
     151          87 :         if (ctx->vp_cfg) gf_odf_vp_cfg_del(ctx->vp_cfg);
     152          87 :         ctx->vp_cfg = NULL;
     153          87 :         ctx->cur_fps = ctx->fps;
     154          87 :         if (!ctx->fps.num || !ctx->fps.den) {
     155          87 :                 ctx->cur_fps.num = 25000;
     156          87 :                 ctx->cur_fps.den = 1000;
     157             :         }
     158             : 
     159          87 :         ctx->pts_from_file = GF_FALSE;
     160          87 :         if (gf_media_probe_ivf(bs)) {
     161          16 :                 u32 width = 0, height = 0;
     162          16 :                 u32 codec_fourcc = 0, timebase_den = 0, timebase_num = 0, num_frames = 0;
     163          16 :                 ctx->bsmode = IVF;
     164             : 
     165          16 :                 e = gf_media_parse_ivf_file_header(bs, &width, &height, &codec_fourcc, &timebase_num, &timebase_den, &num_frames);
     166          16 :                 if (e) return e;
     167             : 
     168          16 :                 switch (codec_fourcc) {
     169           6 :                 case GF_4CC('A', 'V', '0', '1'):
     170           6 :                         ctx->is_av1 = GF_TRUE;
     171           6 :                         ctx->codecid = GF_CODECID_AV1;
     172           6 :                         break;
     173           8 :                 case GF_4CC('V', 'P', '9', '0'):
     174           8 :                         ctx->is_vp9 = GF_TRUE;
     175           8 :                         ctx->codecid = GF_CODECID_VP9;
     176           8 :                         ctx->vp_cfg = gf_odf_vp_cfg_new();
     177           8 :                         break;
     178           2 :                 case GF_4CC('V', 'P', '8', '0'):
     179           2 :                         ctx->codecid = GF_CODECID_VP8;
     180           2 :                         ctx->vp_cfg = gf_odf_vp_cfg_new();
     181           2 :                         break;
     182           0 :                 case GF_4CC('V', 'P', '1', '0'):
     183           0 :                         ctx->codecid = GF_CODECID_VP10;
     184           0 :                         ctx->vp_cfg = gf_odf_vp_cfg_new();
     185           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[IVF] %s parsing not implemented, import might be uncomplete or broken\n", gf_4cc_to_str(codec_fourcc) ));
     186             :                         break;
     187           0 :                 default:
     188           0 :                         ctx->codecid = codec_fourcc;
     189           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[IVF] Unsupported codec FourCC %s\n", gf_4cc_to_str(codec_fourcc) ));
     190             :                         return GF_NON_COMPLIANT_BITSTREAM;
     191             :                 }
     192          16 :                 if (ctx->vp_cfg && !ctx->is_vp9) {
     193           2 :                         ctx->is_vpX = GF_TRUE;
     194           2 :                         ctx->vp_cfg->profile = 1;
     195           2 :                         ctx->vp_cfg->level = 10;
     196           2 :                         ctx->vp_cfg->bit_depth = 8;
     197             :                         //leave the rest as 0
     198             :                 }
     199             : 
     200          16 :                 ctx->state.width = ctx->state.width < width ? width : ctx->state.width;
     201          16 :                 ctx->state.height = ctx->state.height < height ? height : ctx->state.height;
     202          16 :                 ctx->state.tb_num = timebase_num;
     203          16 :                 ctx->state.tb_den = timebase_den;
     204             : 
     205          16 :                 if ((!ctx->fps.num || !ctx->fps.den) && ctx->state.tb_num && ctx->state.tb_den && ! ( (ctx->state.tb_num<=1) && (ctx->state.tb_den<=1) ) ) {
     206          16 :                         ctx->cur_fps.num = ctx->state.tb_num;
     207          16 :                         ctx->cur_fps.den = ctx->state.tb_den;
     208          16 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[AV1Dmx] Detected IVF format FPS %d/%d\n", ctx->cur_fps.num, ctx->cur_fps.den));
     209          16 :                         ctx->pts_from_file = GF_TRUE;
     210             :                 } else {
     211           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[AV1Dmx] Detected IVF format\n"));
     212             :                 }
     213          16 :                 ctx->file_hdr_size = (u32) gf_bs_get_position(bs);
     214          16 :                 if (last_obu_end) (*last_obu_end) = (u32) gf_bs_get_position(bs);
     215             :                 return GF_OK;
     216          71 :         } else if (gf_media_aom_probe_annexb(bs)) {
     217          53 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[AV1Dmx] Detected Annex B format\n"));
     218          53 :                 ctx->bsmode = AnnexB;
     219             :         } else {
     220          18 :                 gf_bs_seek(bs, 0);
     221          18 :                 e = aom_av1_parse_temporal_unit_from_section5(bs, &ctx->state);
     222          18 :                 if (e && !gf_list_count(ctx->state.frame_state.frame_obus) ) {
     223           0 :                         gf_filter_setup_failure(filter, e);
     224           0 :                         ctx->bsmode = UNSUPPORTED;
     225           0 :                         return e;
     226             :                 }
     227          18 :                 if (ctx->state.obu_type != OBU_TEMPORAL_DELIMITER) {
     228           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AV1Dmx] Error OBU stream start with %s, not a temporal delimiter - NOT SUPPORTED\n", gf_av1_get_obu_name(ctx->state.obu_type) ));
     229           0 :                         gf_filter_setup_failure(filter, e);
     230           0 :                         ctx->bsmode = UNSUPPORTED;
     231           0 :                         return e;
     232             :                 }
     233          18 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[AV1Dmx] Detected OBUs Section 5 format\n"));
     234          18 :                 ctx->bsmode = OBUs;
     235             : 
     236          18 :                 gf_av1_reset_state(&ctx->state, GF_FALSE);
     237          18 :                 gf_bs_seek(bs, 0);
     238             :         }
     239          71 :         ctx->is_av1 = GF_TRUE;
     240          71 :         ctx->state.unframed = GF_TRUE;
     241          71 :         ctx->codecid = GF_CODECID_AV1;
     242          71 :         return GF_OK;
     243             : }
     244             : 
     245             : 
     246       21033 : static void av1dmx_check_dur(GF_Filter *filter, GF_AV1DmxCtx *ctx)
     247             : {
     248             :         FILE *stream;
     249             :         GF_Err e;
     250             :         GF_BitStream *bs;
     251             :         u64 duration, cur_dur, last_cdur, rate, max_pts, last_pts;
     252             :         AV1State av1state;
     253             :         const char *filepath=NULL;
     254             :         const GF_PropertyValue *p;
     255       42058 :         if (!ctx->opid || ctx->timescale || ctx->file_loaded) return;
     256             : 
     257          87 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILE_CACHED);
     258          87 :         if (p && p->value.boolean) ctx->file_loaded = GF_TRUE;
     259             : 
     260          87 :         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
     261          87 :         if (!p || !p->value.string || !strncmp(p->value.string, "gmem://", 7)) {
     262           0 :                 ctx->is_file = GF_FALSE;
     263           0 :                 ctx->file_loaded = GF_TRUE;
     264             :                 return;
     265             :         }
     266             :         filepath = p->value.string;
     267          87 :         ctx->is_file = GF_TRUE;
     268             : 
     269          87 :         if (ctx->index<0) {
     270           8 :                 if (gf_opts_get_bool("temp", "force_indexing")) {
     271           0 :                         ctx->index = 1.0;
     272             :                 } else {
     273           8 :                         p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_DOWN_SIZE);
     274           8 :                         if (!p || (p->value.longuint > 20000000)) {
     275           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("[AV1/VP9] Source file larger than 20M, skipping indexing\n"));
     276             :                         } else {
     277           8 :                                 ctx->index = -ctx->index;
     278             :                         }
     279             :                 }
     280             :         }
     281          87 :         if (ctx->index<=0)
     282             :                 return;
     283             : 
     284           8 :         stream = gf_fopen(filepath, "rb");
     285           8 :         if (!stream) return;
     286             : 
     287           8 :         ctx->index_size = 0;
     288             : 
     289           8 :         bs = gf_bs_from_file(stream, GF_BITSTREAM_READ);
     290             : 
     291           8 :         if (ctx->file_hdr_size) {
     292           3 :                 gf_bs_seek(bs, ctx->file_hdr_size);
     293             :         }
     294           8 :         gf_av1_init_state(&av1state);
     295           8 :         av1state.skip_frames = GF_TRUE;
     296           8 :         av1state.config = gf_odf_av1_cfg_new();
     297             : 
     298             :         max_pts = last_pts = 0;
     299             :         duration = 0;
     300             :         cur_dur = last_cdur = 0;
     301        1478 :         while (gf_bs_available(bs)) {
     302             :                 Bool is_sap=GF_FALSE;
     303        1470 :                 u64 pts = GF_FILTER_NO_TS;
     304        1470 :                 u64 frame_start = gf_bs_get_position(bs);
     305        1470 :                 gf_av1_reset_state(&av1state, GF_FALSE);
     306             : 
     307             :                 /*we process each TU and extract only the necessary OBUs*/
     308        1470 :                 switch (ctx->bsmode) {
     309         870 :                 case OBUs:
     310         870 :                         e = aom_av1_parse_temporal_unit_from_section5(bs, &av1state);
     311             :                         break;
     312           0 :                 case AnnexB:
     313           0 :                         e = aom_av1_parse_temporal_unit_from_annexb(bs, &av1state);
     314             :                         break;
     315         600 :                 case IVF:
     316         600 :                         if (ctx->is_av1) {
     317           0 :                                 e = aom_av1_parse_temporal_unit_from_ivf(bs, &av1state);
     318             :                         } else {
     319             :                                 u64 frame_size;
     320         600 :                                 e = gf_media_parse_ivf_frame_header(bs, &frame_size, &pts);
     321         600 :                                 if (!e) gf_bs_skip_bytes(bs, frame_size);
     322             :                                 is_sap = GF_TRUE;
     323             :                         }
     324             :                         break;
     325             :                 default:
     326             :                         e = GF_NOT_SUPPORTED;
     327             :                 }
     328        1470 :                 if (e)
     329             :                         break;
     330             : 
     331        1470 :                 if (pts != GF_FILTER_NO_TS) {
     332         600 :                         if (pts + max_pts < last_pts) {
     333           0 :                                 max_pts = last_pts + ctx->cur_fps.den;
     334             :                         }
     335         600 :                         pts += max_pts;
     336             :                         duration = pts;
     337         600 :                         cur_dur = pts - last_cdur;
     338             : 
     339             :                         last_pts = pts;
     340             :                 } else {
     341         870 :                         duration += ctx->cur_fps.den;
     342         870 :                         cur_dur += ctx->cur_fps.den;
     343             :                 }
     344        1470 :                 if (av1state.frame_state.key_frame)
     345             :                         is_sap = GF_TRUE;
     346             : 
     347             :                 //only index at I-frame start
     348        1470 :                 if (frame_start && is_sap && (cur_dur > ctx->index * ctx->cur_fps.num) ) {
     349         447 :                         if (!ctx->index_alloc_size) ctx->index_alloc_size = 10;
     350         444 :                         else if (ctx->index_alloc_size == ctx->index_size) ctx->index_alloc_size *= 2;
     351         447 :                         ctx->indexes = gf_realloc(ctx->indexes, sizeof(AV1Idx)*ctx->index_alloc_size);
     352         447 :                         ctx->indexes[ctx->index_size].pos = frame_start;
     353         447 :                         ctx->indexes[ctx->index_size].duration = (Double) duration;
     354         447 :                         ctx->indexes[ctx->index_size].duration /= ctx->cur_fps.num;
     355         447 :                         ctx->index_size ++;
     356             :                         last_cdur = cur_dur;
     357             :                         cur_dur = 0;
     358             :                 }
     359             :         }
     360           8 :         rate = gf_bs_get_position(bs);
     361           8 :         gf_bs_del(bs);
     362           8 :         gf_fclose(stream);
     363           8 :         gf_odf_av1_cfg_del(av1state.config);
     364           8 :         gf_av1_reset_state(&av1state, GF_TRUE);
     365             : 
     366           8 :         if (!ctx->duration.num || (ctx->duration.num  * ctx->cur_fps.num != duration * ctx->duration.den)) {
     367           8 :                 ctx->duration.num = (s32) duration;
     368           8 :                 ctx->duration.den = ctx->cur_fps.num;
     369             : 
     370           8 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
     371             : 
     372           8 :                 if (duration && (!gf_sys_is_test_mode() || gf_opts_get_bool("temp", "force_indexing"))) {
     373           0 :                         rate *= 8 * ctx->duration.den;
     374           0 :                         rate /= ctx->duration.num;
     375           0 :                         ctx->bitrate = (u32) rate;
     376             :                 }
     377             :         }
     378             : 
     379             :         //currently not supported because of OBU size field rewrite - could work on some streams but we would
     380             :         //need to analyse all OBUs in the stream for that
     381           8 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CAN_DATAREF, & PROP_BOOL(GF_FALSE) );
     382             : }
     383             : 
     384             : 
     385       21138 : static Bool av1dmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     386             : {
     387             :         u32 i;
     388             :         u64 file_pos = 0;
     389             :         GF_FilterEvent fevt;
     390       21138 :         GF_AV1DmxCtx *ctx = gf_filter_get_udta(filter);
     391             : 
     392       21138 :         switch (evt->base.type) {
     393          87 :         case GF_FEVT_PLAY:
     394          87 :                 if (!ctx->is_playing) {
     395          87 :                         ctx->is_playing = GF_TRUE;
     396          87 :                         ctx->cts = 0;
     397             :                 }
     398          87 :                 if (! ctx->is_file) {
     399           0 :                         ctx->buf_size = 0;
     400           0 :                         return GF_FALSE;
     401             :                 }
     402          87 :                 ctx->start_range = evt->play.start_range;
     403          87 :                 ctx->in_seek = GF_TRUE;
     404             : 
     405          87 :                 if (ctx->start_range) {
     406             : 
     407           0 :                         if (ctx->index<0) {
     408           0 :                                 ctx->index = -ctx->index;
     409           0 :                                 ctx->file_loaded = GF_FALSE;
     410           0 :                                 ctx->duration.den = ctx->duration.num = 0;
     411           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("[AV1/VP9Demx] Play request from %d, building index\n", ctx->start_range));
     412           0 :                                 av1dmx_check_dur(filter, ctx);
     413             :                         }
     414             : 
     415           0 :                         for (i=1; i<ctx->index_size; i++) {
     416           0 :                                 if (ctx->indexes[i].duration>ctx->start_range) {
     417           0 :                                         ctx->cts = (u64) (ctx->indexes[i-1].duration * ctx->cur_fps.num);
     418           0 :                                         file_pos = ctx->indexes[i-1].pos;
     419           0 :                                         break;
     420             :                                 }
     421             :                         }
     422             :                 }
     423          87 :                 if (!ctx->initial_play_done) {
     424          87 :                         ctx->initial_play_done = GF_TRUE;
     425             :                         //seek will not change the current source state, don't send a seek
     426          87 :                         if (!file_pos)
     427             :                                 return GF_TRUE;
     428             :                 }
     429           0 :                 ctx->buf_size = 0;
     430           0 :                 if (!file_pos)
     431           0 :                         file_pos = ctx->file_hdr_size;
     432             : 
     433             :                 //post a seek
     434           0 :                 GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
     435           0 :                 fevt.seek.start_offset = file_pos;
     436           0 :                 gf_filter_pid_send_event(ctx->ipid, &fevt);
     437             : 
     438             :                 //cancel event
     439           0 :                 return GF_TRUE;
     440             : 
     441          12 :         case GF_FEVT_STOP:
     442             :                 //don't cancel event
     443          12 :                 ctx->is_playing = GF_FALSE;
     444          12 :                 return GF_FALSE;
     445             : 
     446             :         case GF_FEVT_SET_SPEED:
     447             :                 //cancel event
     448             :                 return GF_TRUE;
     449             :         default:
     450             :                 break;
     451             :         }
     452             :         //by default don't cancel event - to rework once we have downloading in place
     453       21039 :         return GF_FALSE;
     454             : }
     455             : 
     456             : static GFINLINE void av1dmx_update_cts(GF_AV1DmxCtx *ctx)
     457             : {
     458             :         assert(ctx->cur_fps.num);
     459             :         assert(ctx->cur_fps.den);
     460             : 
     461       38684 :         if (ctx->timescale) {
     462           0 :                 u64 inc = ctx->cur_fps.den;
     463           0 :                 inc *= ctx->timescale;
     464           0 :                 inc /= ctx->cur_fps.num;
     465           0 :                 ctx->cts += inc;
     466             :         } else {
     467       38684 :                 ctx->cts += ctx->cur_fps.den;
     468             :         }
     469             : }
     470             : 
     471       59147 : static void av1dmx_check_pid(GF_Filter *filter, GF_AV1DmxCtx *ctx)
     472             : {
     473             :         u8 *dsi;
     474             :         u32 dsi_size, crc;
     475             : 
     476             :         //no config or no config change
     477      118207 :         if (ctx->is_av1 && !gf_list_count(ctx->state.frame_state.header_obus)) return;
     478             : 
     479        1768 :         if (!ctx->opid) {
     480          87 :                 ctx->opid = gf_filter_pid_new(filter);
     481          87 :                 av1dmx_check_dur(filter, ctx);
     482             :         }
     483        1768 :         dsi = NULL;
     484        1768 :         dsi_size = 0;
     485             : 
     486        1768 :         if (ctx->vp_cfg) {
     487        1376 :                 gf_odf_vp_cfg_write(ctx->vp_cfg, &dsi, &dsi_size, ctx->vp_cfg->codec_initdata_size ? GF_TRUE : GF_FALSE);
     488         392 :         } else if (ctx->is_av1) {
     489             :                 //first or config changed, compute dsi
     490         707 :                 while (gf_list_count(ctx->state.config->obu_array)) {
     491         315 :                         GF_AV1_OBUArrayEntry *a = (GF_AV1_OBUArrayEntry*) gf_list_pop_back(ctx->state.config->obu_array);
     492         315 :                         if (a->obu) gf_free(a->obu);
     493         315 :                         gf_free(a);
     494             :                 }
     495         392 :                 dsi = NULL;
     496         392 :                 dsi_size = 0;
     497        1176 :                 while (gf_list_count(ctx->state.frame_state.header_obus)) {
     498         392 :                         GF_AV1_OBUArrayEntry *a = (GF_AV1_OBUArrayEntry*) gf_list_get(ctx->state.frame_state.header_obus, 0);
     499         392 :                         gf_list_add(ctx->state.config->obu_array, a);
     500         392 :                         gf_list_rem(ctx->state.frame_state.header_obus, 0);
     501             :                 }
     502         392 :                 gf_odf_av1_cfg_write(ctx->state.config, &dsi, &dsi_size);
     503             : 
     504         392 :                 if ((!ctx->fps.num || !ctx->fps.den) && ctx->state.tb_num && ctx->state.tb_den && ! ( (ctx->state.tb_num<=1) && (ctx->state.tb_den<=1) ) ) {
     505         310 :                         ctx->cur_fps.num = ctx->state.tb_num;
     506         310 :                         ctx->cur_fps.den = ctx->state.tb_den;
     507             :                 }
     508             : 
     509             :         }
     510        1768 :         crc = gf_crc_32(dsi, dsi_size);
     511             : 
     512        1768 :         if (crc == ctx->dsi_crc) {
     513        1681 :                 gf_free(dsi);
     514        1681 :                 return;
     515             :         }
     516          87 :         ctx->dsi_crc = crc;
     517             : 
     518             :         //copy properties at init or reconfig
     519          87 :         gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
     520          87 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT(GF_STREAM_VISUAL));
     521             : 
     522          87 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT(ctx->codecid));
     523             : 
     524          87 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, & PROP_UINT(ctx->cur_fps.num));
     525          87 :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FPS, & PROP_FRAC(ctx->cur_fps));
     526          87 :         if (ctx->state.sequence_width && ctx->state.sequence_height) {
     527          77 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, & PROP_UINT(ctx->state.sequence_width));
     528          77 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, & PROP_UINT(ctx->state.sequence_height));
     529             :         } else {
     530          10 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, & PROP_UINT(ctx->state.width));
     531          10 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, & PROP_UINT(ctx->state.height));
     532             :         }
     533             : 
     534          87 :         if (ctx->duration.num)
     535           8 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
     536             : 
     537          87 :         if (ctx->bitrate) {
     538           0 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_BITRATE, & PROP_UINT(ctx->bitrate));
     539             :         }
     540             : 
     541          87 :         if (dsi && dsi_size)
     542          87 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, & PROP_DATA_NO_COPY(dsi, dsi_size));
     543             : 
     544          87 :         if (ctx->is_file && ctx->index) {
     545           8 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PLAYBACK_MODE, & PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD) );
     546             :         }
     547             : 
     548          87 :         if (ctx->is_av1) {
     549          77 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_PRIMARIES, & PROP_UINT(ctx->state.color_primaries) );
     550          77 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_TRANSFER, & PROP_UINT(ctx->state.transfer_characteristics) );
     551          77 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, & PROP_UINT(ctx->state.matrix_coefficients) );
     552          77 :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, & PROP_BOOL(ctx->state.color_range) );
     553             :         }
     554             :         //disabled for the time being, matchin `colr` box will be injected by mp43mx if needed
     555             :         //check vpX specs to see if always needed
     556             : #if 0
     557             :         else if (ctx->vp_cfg) {
     558             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_PRIMARIES, & PROP_UINT(ctx->vp_cfg->colour_primaries) );
     559             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_TRANSFER, & PROP_UINT(ctx->vp_cfg->transfer_characteristics) );
     560             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, & PROP_UINT(ctx->vp_cfg->matrix_coefficients) );
     561             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, & PROP_BOOL(ctx->vp_cfg->video_fullRange_flag) );
     562             :         }
     563             : #endif
     564             : }
     565             : 
     566          60 : GF_Err av1dmx_parse_ivf(GF_Filter *filter, GF_AV1DmxCtx *ctx)
     567             : {
     568             :         GF_Err e;
     569             :         u32 pck_size;
     570          60 :         u64 frame_size = 0, pts = GF_FILTER_NO_TS;
     571             :         GF_FilterPacket *pck;
     572             :         u64 pos, pos_ivf_hdr;
     573             :         u8 *output;
     574             : 
     575          60 :         pos_ivf_hdr = gf_bs_get_position(ctx->bs);
     576          60 :         e = gf_media_parse_ivf_frame_header(ctx->bs, &frame_size, &pts);
     577          60 :         if (e) return e;
     578             : 
     579          60 :         pos = gf_bs_get_position(ctx->bs);
     580          60 :         if (gf_bs_available(ctx->bs) < frame_size) {
     581           0 :                 gf_bs_seek(ctx->bs, pos_ivf_hdr);
     582           0 :                 return GF_EOS;
     583             :         }
     584             : 
     585          60 :         if (ctx->pts_from_file) {
     586          60 :                 pts += ctx->cumulated_dur;
     587          60 :                 if (ctx->last_pts && (ctx->last_pts>pts)) {
     588           0 :                         pts -= ctx->cumulated_dur;
     589           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[IVF/AV1] Corrupted timestamp "LLU" less than previous timestamp "LLU", assuming concatenation\n", pts, ctx->last_pts));
     590           0 :                         ctx->cumulated_dur = ctx->last_pts + ctx->cur_fps.den;
     591           0 :                         ctx->cumulated_dur -= pts;
     592           0 :                         pts = ctx->cumulated_dur;
     593             :                 }
     594          60 :                 ctx->last_pts = pts;
     595             :         }
     596             : 
     597             : 
     598             :         //check pid state
     599          60 :         av1dmx_check_pid(filter, ctx);
     600             : 
     601          60 :         if (!ctx->opid) {
     602             :                 return GF_OK;
     603             :         }
     604             : 
     605          60 :         if (!ctx->is_playing) {
     606           2 :                 gf_bs_seek(ctx->bs, pos_ivf_hdr);
     607           2 :                 return GF_EOS;
     608             :         }
     609             : 
     610          58 :         pck_size = (u32)frame_size;
     611          58 :         pck = gf_filter_pck_new_alloc(ctx->opid, pck_size, &output);
     612          58 :         if (!pck) {
     613           0 :                 gf_bs_seek(ctx->bs, pos_ivf_hdr);
     614           0 :                 return GF_OUT_OF_MEM;
     615             :         }
     616          58 :         if (ctx->src_pck) gf_filter_pck_merge_properties(ctx->src_pck, pck);
     617             : 
     618          58 :         if (ctx->pts_from_file) {
     619          58 :                 gf_filter_pck_set_cts(pck, pts);
     620             :         } else {
     621           0 :                 gf_filter_pck_set_cts(pck, ctx->cts);
     622             :         }
     623             : 
     624          58 :         gf_bs_seek(ctx->bs, pos);
     625          58 :         gf_bs_read_data(ctx->bs, output, pck_size);
     626             : 
     627          58 :         if (output[0] & 0x80)
     628          32 :                 gf_filter_pck_set_sap(pck, GF_FILTER_SAP_1);
     629             :         else
     630          26 :                 gf_filter_pck_set_sap(pck, GF_FILTER_SAP_NONE);
     631             : 
     632          58 :         gf_filter_pck_send(pck);
     633             : 
     634             :         av1dmx_update_cts(ctx);
     635             :         return GF_OK;
     636             : }
     637             : 
     638        1833 : GF_Err av1dmx_parse_vp9(GF_Filter *filter, GF_AV1DmxCtx *ctx)
     639             : {
     640        1833 :         Bool key_frame = GF_FALSE;
     641        1833 :         u64 frame_size = 0, pts = 0;
     642             :         u64 pos, pos_ivf_hdr;
     643        1833 :         u32 width = 0, height = 0, renderWidth, renderHeight;
     644        1833 :         u32 num_frames_in_superframe = 0, superframe_index_size = 0, i = 0;
     645             :         u32 frame_sizes[VP9_MAX_FRAMES_IN_SUPERFRAME];
     646             :         u8 *output;
     647             :         GF_Err e;
     648             : 
     649        1833 :         pos_ivf_hdr = gf_bs_get_position(ctx->bs);
     650        1833 :         e = gf_media_parse_ivf_frame_header(ctx->bs, &frame_size, &pts);
     651        1833 :         if (e) return e;
     652        1833 :         if (!frame_size) {
     653           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[IVF/VP9] Corrupted frame header !\n"));
     654             :                 return GF_NON_COMPLIANT_BITSTREAM;
     655             :         }
     656             : 
     657        1833 :         pos = gf_bs_get_position(ctx->bs);
     658        1833 :         if (gf_bs_available(ctx->bs) < frame_size) {
     659         517 :                 gf_bs_seek(ctx->bs, pos_ivf_hdr);
     660         517 :                 return GF_EOS;
     661             :         }
     662             : 
     663        1316 :         if (ctx->pts_from_file) {
     664        1316 :                 pts += ctx->cumulated_dur;
     665        1316 :                 if (ctx->last_pts && (ctx->last_pts>pts)) {
     666           0 :                         pts -= ctx->cumulated_dur;
     667           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[IVF/VP9] Corrupted timestamp "LLU" less than previous timestamp "LLU", assuming concatenation\n", pts, ctx->last_pts));
     668           0 :                         ctx->cumulated_dur = ctx->last_pts + ctx->cur_fps.den;
     669           0 :                         ctx->cumulated_dur -= pts;
     670           0 :                         pts = ctx->cumulated_dur;
     671             :                 }
     672        1316 :                 ctx->last_pts = pts;
     673             :         }
     674             : 
     675             :         /*check if it is a superframe*/
     676        1316 :         e = gf_media_vp9_parse_superframe(ctx->bs, frame_size, &num_frames_in_superframe, frame_sizes, &superframe_index_size);
     677        1316 :         if (e) {
     678           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[VP9Dmx] Error parsing superframe structure\n"));
     679             :                 return e;
     680             :         }
     681             : 
     682        1316 :         for (i = 0; i < num_frames_in_superframe; ++i) {
     683        1316 :                 u64 pos2 = gf_bs_get_position(ctx->bs);
     684        1316 :                 if (gf_media_vp9_parse_sample(ctx->bs, ctx->vp_cfg, &key_frame, &width, &height, &renderWidth, &renderHeight) != GF_OK) {
     685           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[VP9Dmx] Error parsing frame\n"));
     686             :                         return e;
     687             :                 }
     688        1316 :                 e = gf_bs_seek(ctx->bs, pos2 + frame_sizes[i]);
     689        1316 :                 if (e) {
     690           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[VP9Dmx] Seek bad param (offset "LLU") (1)", pos2 + frame_sizes[i]));
     691             :                         return e;
     692             :                 }
     693             :         }
     694        1316 :         if (gf_bs_get_position(ctx->bs) + superframe_index_size != pos + frame_size) {
     695           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[VP9Dmx] Inconsistent IVF frame size of "LLU" bytes.\n", frame_size));
     696           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("      Detected %d frames (+ %d bytes for the superframe index):\n", num_frames_in_superframe, superframe_index_size));
     697           0 :                 for (i = 0; i < num_frames_in_superframe; ++i) {
     698           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("         superframe %d, size is %u bytes\n", i, frame_sizes[i]));
     699             :                 }
     700           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("\n"));
     701             :         }
     702        1316 :         e = gf_bs_seek(ctx->bs, pos + frame_size);
     703        1316 :         if (e) {
     704           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[VP9Dmx] Seek bad param (offset "LLU") (2)", pos + frame_size));
     705             :                 return e;
     706             :         }
     707             : 
     708        1316 :         u32 pck_size = (u32)(gf_bs_get_position(ctx->bs) - pos);
     709             :         assert(pck_size == frame_size);
     710             : 
     711             :         //check pid state
     712        1316 :         av1dmx_check_pid(filter, ctx);
     713             : 
     714        1316 :         if (!ctx->opid) {
     715             :                 return GF_OK;
     716             :         }
     717             : 
     718        1316 :         if (!ctx->is_playing) {
     719           8 :                 gf_bs_seek(ctx->bs, pos_ivf_hdr);
     720           8 :                 return GF_EOS;
     721             :         }
     722             : 
     723        1308 :         GF_FilterPacket *pck = gf_filter_pck_new_alloc(ctx->opid, pck_size, &output);
     724        1308 :         if (!pck) {
     725           0 :                 gf_bs_seek(ctx->bs, pos_ivf_hdr);
     726           0 :                 return GF_OUT_OF_MEM;
     727             :         }
     728        1308 :         if (ctx->src_pck) gf_filter_pck_merge_properties(ctx->src_pck, pck);
     729             : 
     730        1308 :         if (ctx->pts_from_file) {
     731        1308 :                 gf_filter_pck_set_cts(pck, pts);
     732             :         } else {
     733           0 :                 gf_filter_pck_set_cts(pck, ctx->cts);
     734             :         }
     735             : 
     736             : 
     737        1308 :         if (key_frame) {
     738          41 :                 gf_filter_pck_set_sap(pck, GF_FILTER_SAP_1);
     739             :         }
     740             : 
     741        1308 :         if (ctx->deps) {
     742             :                 u8 flags = 0;
     743             :                 //dependsOn
     744           0 :                 flags = (key_frame) ? 2 : 1;
     745             :                 flags <<= 2;
     746             :                 //dependedOn
     747             :                 //flags |= 2;
     748           0 :                 flags <<= 2;
     749             :                 //hasRedundant
     750             :                 //flags |= ctx->has_redundant ? 1 : 2;
     751           0 :                 gf_filter_pck_set_dependency_flags(pck, flags);
     752             :         }
     753             : 
     754        1308 :         gf_bs_seek(ctx->bs, pos);
     755        1308 :         gf_bs_read_data(ctx->bs, output, pck_size);
     756        1308 :         gf_filter_pck_send(pck);
     757             : 
     758             :         av1dmx_update_cts(ctx);
     759             :         return GF_OK;
     760             : }
     761             : 
     762       37318 : static GF_Err av1dmx_parse_flush_sample(GF_Filter *filter, GF_AV1DmxCtx *ctx)
     763             : {
     764             :         u32 pck_size;
     765             :         GF_FilterPacket *pck;
     766             :         u8 *output;
     767             : 
     768       37318 :         if (!ctx->opid)
     769             :                 return GF_NON_COMPLIANT_BITSTREAM;
     770             :                 
     771       37318 :         gf_bs_get_content_no_truncate(ctx->state.bs, &ctx->state.frame_obus, &pck_size, &ctx->state.frame_obus_alloc);
     772             : 
     773       37318 :         if (!pck_size) {
     774           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[AV1Dmx] no frame OBU, skipping OBU\n"));
     775             :                 return GF_OK;
     776             :         }
     777             : 
     778       37318 :         pck = gf_filter_pck_new_alloc(ctx->opid, pck_size, &output);
     779       37318 :         if (!pck) return GF_OUT_OF_MEM;
     780             : 
     781       37318 :         if (ctx->src_pck)
     782           0 :                 gf_filter_pck_merge_properties(ctx->src_pck, pck);
     783             : 
     784       37318 :         gf_filter_pck_set_cts(pck, ctx->cts);
     785       37318 :         gf_filter_pck_set_sap(pck, ctx->state.frame_state.key_frame ? GF_FILTER_SAP_1 : 0);
     786             : 
     787       37318 :         memcpy(output, ctx->state.frame_obus, pck_size);
     788             : 
     789       37318 :         if (ctx->deps) {
     790             :                 u8 flags = 0;
     791             :                 //dependsOn
     792           0 :                 flags = ( ctx->state.frame_state.key_frame) ? 2 : 1;
     793           0 :                 flags <<= 2;
     794             :                 //dependedOn
     795           0 :                 flags |= ctx->state.frame_state.refresh_frame_flags ? 1 : 2;
     796           0 :                 flags <<= 2;
     797             :                 //hasRedundant
     798             :                 //flags |= ctx->has_redundant ? 1 : 2;
     799           0 :                 gf_filter_pck_set_dependency_flags(pck, flags);
     800             :         }
     801             : 
     802       37318 :         gf_filter_pck_send(pck);
     803             : 
     804             :         av1dmx_update_cts(ctx);
     805       37318 :         gf_av1_reset_state(&ctx->state, GF_FALSE);
     806             : 
     807             :         return GF_OK;
     808             : 
     809             : }
     810       57771 : GF_Err av1dmx_parse_av1(GF_Filter *filter, GF_AV1DmxCtx *ctx)
     811             : {
     812             :         GF_Err e = GF_OK;
     813             :         u64 start;
     814             : 
     815       57771 :         if (!ctx->is_playing) {
     816          95 :                 ctx->state.frame_state.is_first_frame = GF_TRUE;
     817             :         }
     818             : 
     819             :         /*we process each TU and extract only the necessary OBUs*/
     820       57771 :         start = gf_bs_get_position(ctx->bs);
     821       57771 :         switch (ctx->bsmode) {
     822        1477 :         case OBUs:
     823             :                 //first frame loaded !
     824        1477 :                 if (ctx->state.bs && gf_bs_get_position(ctx->state.bs) && (ctx->state.obu_type == OBU_TEMPORAL_DELIMITER)) {
     825             :                         e = GF_OK;
     826             :                 } else {
     827        1461 :                         e = aom_av1_parse_temporal_unit_from_section5(ctx->bs, &ctx->state);
     828             :                 }
     829             :                 break;
     830          61 :         case AnnexB:
     831             :                 //first TU loaded !
     832          61 :                 if (ctx->state.bs && gf_bs_get_position(ctx->state.bs)) {
     833             :                         e = GF_OK;
     834             :                 } else {
     835          59 :                         e = aom_av1_parse_temporal_unit_from_annexb(ctx->bs, &ctx->state);
     836          59 :                         if (e==GF_BUFFER_TOO_SMALL) {
     837           0 :                                 gf_av1_reset_state(&ctx->state, GF_FALSE);
     838           0 :                                 gf_bs_seek(ctx->bs, start);
     839             :                         }
     840             :                 }
     841             :                 break;
     842       56233 :         case IVF:
     843             :                 //first frame loaded !
     844       56233 :                 if (ctx->state.bs && gf_bs_get_position(ctx->state.bs)) {
     845             :                         e = GF_OK;
     846             :                 } else {
     847       56227 :                         e = aom_av1_parse_temporal_unit_from_ivf(ctx->bs, &ctx->state);
     848             :                 }
     849             :                 break;
     850             :         default:
     851             :                 e = GF_NOT_SUPPORTED;
     852             :         }
     853             : 
     854             :         //check pid state
     855       57771 :         av1dmx_check_pid(filter, ctx);
     856             : 
     857       57771 :         if (e) return e;
     858             : 
     859             : 
     860       37345 :         if (!ctx->opid) {
     861          18 :                 if (ctx->state.obu_type != OBU_TEMPORAL_DELIMITER) {
     862           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[AV1Dmx] output pid not configured (no sequence header yet ?), skipping OBU\n"));
     863             :                 }
     864          18 :                 gf_av1_reset_state(&ctx->state, GF_FALSE);
     865          18 :                 return GF_OK;
     866             :         }
     867             : 
     868       37327 :         if (!ctx->is_playing) {
     869             :                 //don't reset state we would skip seq header obu in first frame
     870             :                 //gf_av1_reset_state(&ctx->state, GF_FALSE);
     871             :                 return GF_OK;
     872             :         }
     873             : 
     874       37252 :         return av1dmx_parse_flush_sample(filter, ctx);
     875             : 
     876             : }
     877             : 
     878             : GF_Err gf_bs_set_logger(GF_BitStream *bs, void (*on_bs_log)(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3), void *udta);
     879           0 : static void av1dmx_bs_log(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3)
     880             : {
     881             :         GF_AV1DmxCtx *ctx = (GF_AV1DmxCtx *) udta;
     882           0 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, (" %s", field_name));
     883           0 :         if (idx1>=0) {
     884           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("_%d", idx1));
     885           0 :                 if (idx2>=0) {
     886           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("_%d", idx2));
     887           0 :                         if (idx3>=0) {
     888           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("_%d", idx3));
     889             :                         }
     890             :                 }
     891             :         }
     892           0 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("=\""LLD, field_val));
     893           0 :         if ((ctx->bsdbg==2) && ((s32) nb_bits > 1) )
     894           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("(%u)", nb_bits));
     895             : 
     896           0 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("\" "));
     897           0 : }
     898             : 
     899       21045 : GF_Err av1dmx_process_buffer(GF_Filter *filter, GF_AV1DmxCtx *ctx, const char *data, u32 data_size, Bool is_copy)
     900             : {
     901       21045 :         u32 last_obu_end = 0;
     902             :         GF_Err e = GF_OK;
     903             : 
     904       21045 :         if (!ctx->bs) ctx->bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
     905       20958 :         else gf_bs_reassign_buffer(ctx->bs, data, data_size);
     906             : 
     907             : #ifndef GPAC_DISABLE_LOG
     908       21045 :         if (ctx->bsdbg && gf_log_tool_level_on(GF_LOG_PARSER, GF_LOG_DEBUG))
     909           0 :                 gf_bs_set_logger(ctx->bs, av1dmx_bs_log, ctx);
     910             : #endif
     911             : 
     912             :         //check ivf vs obu vs annexB
     913       21045 :         e = av1dmx_check_format(filter, ctx, ctx->bs, &last_obu_end);
     914       21045 :         if (e) return e;
     915             : 
     916       59681 :         while (gf_bs_available(ctx->bs)) {
     917             : 
     918       59664 :                 if (ctx->is_vp9) {
     919        1833 :                         e = av1dmx_parse_vp9(filter, ctx);
     920       57831 :                 } else if (ctx->is_av1) {
     921       57771 :                         e = av1dmx_parse_av1(filter, ctx);
     922             :                 } else {
     923          60 :                         e = av1dmx_parse_ivf(filter, ctx);
     924             :                 }
     925             : 
     926       59664 :                 if (e!=GF_EOS)
     927       38788 :                         last_obu_end = (u32) gf_bs_get_position(ctx->bs);
     928             : 
     929       59664 :                 if (e) {
     930             :                         break;
     931             :                 }
     932       38711 :                 if (!ctx->is_playing && ctx->opid)
     933             :                         break;
     934             :         }
     935             : 
     936       21045 :         if (is_copy && last_obu_end) {
     937             :                 assert(ctx->buf_size>=last_obu_end);
     938       10879 :                 memmove(ctx->buffer, ctx->buffer+last_obu_end, sizeof(char) * (ctx->buf_size-last_obu_end));
     939       10879 :                 ctx->buf_size -= last_obu_end;
     940             :         }
     941       21045 :         if (e==GF_EOS) return GF_OK;
     942         169 :         if (e==GF_BUFFER_TOO_SMALL) return GF_OK;
     943          92 :         return e;
     944             : }
     945             : 
     946       21238 : GF_Err av1dmx_process(GF_Filter *filter)
     947             : {
     948             :         GF_Err e;
     949       21238 :         GF_AV1DmxCtx *ctx = gf_filter_get_udta(filter);
     950             :         GF_FilterPacket *pck;
     951             :         char *data;
     952             :         u32 pck_size;
     953             : 
     954       21238 :         if (ctx->bsmode == UNSUPPORTED) return GF_EOS;
     955             : 
     956             :         //always reparse duration
     957       21238 :         if (!ctx->duration.num)
     958       20946 :                 av1dmx_check_dur(filter, ctx);
     959             : 
     960       21238 :         if (!ctx->is_playing && ctx->opid)
     961             :                 return GF_OK;
     962             : 
     963       21113 :         pck = gf_filter_pid_get_packet(ctx->ipid);
     964       21113 :         if (!pck) {
     965          80 :                 if (gf_filter_pid_is_eos(ctx->ipid)) {
     966             :                         //flush
     967          91 :                         while (ctx->buf_size) {
     968             :                                 u32 buf_size = ctx->buf_size;
     969          12 :                                 e = av1dmx_process_buffer(filter, ctx, ctx->buffer, ctx->buf_size, GF_TRUE);
     970          12 :                                 if (e) break;
     971          12 :                                 if (buf_size == ctx->buf_size) {
     972             :                                         break;
     973             :                                 }
     974             :                         }
     975          80 :                         if (ctx->state.bs && gf_bs_get_position(ctx->state.bs))
     976          66 :                                 av1dmx_parse_flush_sample(filter, ctx);
     977             : 
     978          80 :                         ctx->buf_size = 0;
     979          80 :                         if (ctx->opid)
     980          80 :                                 gf_filter_pid_set_eos(ctx->opid);
     981          80 :                         if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
     982          80 :                         ctx->src_pck = NULL;
     983          80 :                         return GF_EOS;
     984             :                 }
     985             :                 return GF_OK;
     986             :         }
     987             : 
     988       21033 :         if (ctx->opid) {
     989       20938 :                 if (!ctx->is_playing || gf_filter_pid_would_block(ctx->opid))
     990             :                         return GF_OK;
     991             :         }
     992             : 
     993       21033 :         data = (char *) gf_filter_pck_get_data(pck, &pck_size);
     994             : 
     995             :         //input pid sets some timescale - we flushed pending data , update cts
     996       21033 :         if (ctx->timescale) {
     997             :                 Bool start, end;
     998             :                 u64 cts;
     999             : 
    1000             :                 e = GF_OK;
    1001             : 
    1002           0 :                 gf_filter_pck_get_framing(pck, &start, &end);
    1003             :                 //middle or end of frame, reaggregation
    1004           0 :                 if (!start) {
    1005           0 :                         if (ctx->alloc_size < ctx->buf_size + pck_size) {
    1006           0 :                                 ctx->alloc_size = ctx->buf_size + pck_size;
    1007           0 :                                 ctx->buffer = gf_realloc(ctx->buffer, ctx->alloc_size);
    1008             :                         }
    1009           0 :                         memcpy(ctx->buffer+ctx->buf_size, data, pck_size);
    1010           0 :                         ctx->buf_size += pck_size;
    1011             : 
    1012             :                         //end of frame, process av1
    1013           0 :                         if (end) {
    1014           0 :                                 e = av1dmx_process_buffer(filter, ctx, ctx->buffer, ctx->buf_size, GF_TRUE);
    1015             :                         }
    1016           0 :                         ctx->buf_size=0;
    1017           0 :                         gf_filter_pid_drop_packet(ctx->ipid);
    1018           0 :                         return e;
    1019             :                 }
    1020             :                 //flush of pending frame (might have lost something)
    1021           0 :                 if (ctx->buf_size) {
    1022           0 :                         e = av1dmx_process_buffer(filter, ctx, ctx->buffer, ctx->buf_size, GF_TRUE);
    1023           0 :                         ctx->buf_size = 0;
    1024           0 :                         if (e) return e;
    1025             :                 }
    1026             : 
    1027             :                 //beginning of a new frame
    1028           0 :                 cts = gf_filter_pck_get_cts(pck);
    1029           0 :                 if (cts != GF_FILTER_NO_TS)
    1030           0 :                         ctx->cts = cts;
    1031           0 :                 if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
    1032           0 :                 ctx->src_pck = pck;
    1033           0 :                 gf_filter_pck_ref_props(&ctx->src_pck);
    1034           0 :                 ctx->buf_size = 0;
    1035             : 
    1036           0 :                 if (!end) {
    1037           0 :                         if (ctx->alloc_size < ctx->buf_size + pck_size) {
    1038           0 :                                 ctx->alloc_size = ctx->buf_size + pck_size;
    1039           0 :                                 ctx->buffer = gf_realloc(ctx->buffer, ctx->alloc_size);
    1040             :                         }
    1041           0 :                         memcpy(ctx->buffer+ctx->buf_size, data, pck_size);
    1042           0 :                         ctx->buf_size += pck_size;
    1043           0 :                         gf_filter_pid_drop_packet(ctx->ipid);
    1044           0 :                         return GF_OK;
    1045             :                 }
    1046             :                 assert(start && end);
    1047             :                 //process
    1048           0 :                 e = av1dmx_process_buffer(filter, ctx, data, pck_size, GF_FALSE);
    1049             : 
    1050           0 :                 gf_filter_pid_drop_packet(ctx->ipid);
    1051           0 :                 return e;
    1052             :         }
    1053             : 
    1054             :         //not from framed stream, copy buffer
    1055       21033 :         if (ctx->alloc_size < ctx->buf_size + pck_size) {
    1056         166 :                 ctx->alloc_size = ctx->buf_size + pck_size;
    1057         166 :                 ctx->buffer = gf_realloc(ctx->buffer, ctx->alloc_size);
    1058             :         }
    1059       21033 :         memcpy(ctx->buffer+ctx->buf_size, data, pck_size);
    1060       21033 :         ctx->buf_size += pck_size;
    1061       21033 :         e = av1dmx_process_buffer(filter, ctx, ctx->buffer, ctx->buf_size, GF_TRUE);
    1062       21033 :         gf_filter_pid_drop_packet(ctx->ipid);
    1063       21033 :         return e;
    1064             : }
    1065             : 
    1066          87 : static void av1dmx_finalize(GF_Filter *filter)
    1067             : {
    1068          87 :         GF_AV1DmxCtx *ctx = gf_filter_get_udta(filter);
    1069          87 :         if (ctx->bs) gf_bs_del(ctx->bs);
    1070          87 :         if (ctx->indexes) gf_free(ctx->indexes);
    1071             : 
    1072          87 :         gf_av1_reset_state(&ctx->state, GF_TRUE);
    1073          87 :         if (ctx->state.config) gf_odf_av1_cfg_del(ctx->state.config);
    1074          87 :         if (ctx->state.bs) gf_bs_del(ctx->state.bs);
    1075          87 :         if (ctx->state.frame_obus) gf_free(ctx->state.frame_obus);
    1076          87 :         if (ctx->buffer) gf_free(ctx->buffer);
    1077             : 
    1078          87 :         if (ctx->vp_cfg) gf_odf_vp_cfg_del(ctx->vp_cfg);
    1079          87 : }
    1080             : 
    1081        3065 : static const char * av1dmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
    1082             : {
    1083        3065 :         GF_BitStream *bs = gf_bs_new(data, size, GF_BITSTREAM_READ);
    1084             :         Bool res;
    1085             :         u32 lt;
    1086             :         const char *mime = "video/av1";
    1087        3065 :         lt = gf_log_get_tool_level(GF_LOG_CODING);
    1088        3065 :         gf_log_set_tool_level(GF_LOG_CODING, GF_LOG_QUIET);
    1089             : 
    1090        3065 :         res = gf_media_probe_ivf(bs);
    1091        3065 :         if (res) {
    1092          16 :                 *score = GF_FPROBE_SUPPORTED;
    1093             :                 mime = "video/x-ivf";
    1094             :         } else {
    1095        3049 :                 res = gf_media_aom_probe_annexb(bs);
    1096        3049 :                 if (res) {
    1097          53 :                         *score = GF_FPROBE_SUPPORTED;
    1098             :                 } else {
    1099             :                         AV1State state;
    1100             :                         GF_Err e;
    1101             :                         u32 nb_units = 0;
    1102             : 
    1103        2996 :                         gf_av1_init_state(&state);
    1104        2996 :                         state.config = gf_odf_av1_cfg_new();
    1105        6032 :                         while (gf_bs_available(bs)) {
    1106        3036 :                                 e = aom_av1_parse_temporal_unit_from_section5(bs, &state);
    1107        3036 :                                 if ((e==GF_OK) || (nb_units && (e==GF_BUFFER_TOO_SMALL) ) ) {
    1108          60 :                                         if (!nb_units || gf_list_count(state.frame_state.header_obus) || gf_list_count(state.frame_state.frame_obus)) {
    1109          58 :                                                 nb_units++;
    1110          58 :                                                 if (e==GF_BUFFER_TOO_SMALL)
    1111           2 :                                                         nb_units++;
    1112             :                                         } else {
    1113             :                                                 break;
    1114             :                                         }
    1115             :                                 } else {
    1116             :                                         break;
    1117             :                                 }
    1118          58 :                                 gf_av1_reset_state(&state, GF_FALSE);
    1119          58 :                                 if (nb_units>2) {
    1120             :                                         res = GF_TRUE;
    1121          18 :                                         *score = GF_FPROBE_SUPPORTED;
    1122          18 :                                         break;
    1123             :                                 }
    1124             :                         }
    1125        2996 :                         gf_odf_av1_cfg_del(state.config);
    1126        2996 :                         gf_av1_reset_state(&state, GF_TRUE);
    1127             :                 }
    1128             :         }
    1129             : 
    1130        3065 :         gf_log_set_tool_level(GF_LOG_CODING, lt);
    1131             : 
    1132        3065 :         gf_bs_del(bs);
    1133        3065 :         if (res) return mime;
    1134        2978 :         return NULL;
    1135             : }
    1136             : 
    1137             : static const GF_FilterCapability AV1DmxCaps[] =
    1138             : {
    1139             :         CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1140             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "ivf|obu|av1b|av1"),
    1141             :         CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "video/x-ivf|video/av1"),
    1142             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1143             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_AV1),
    1144             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_VP8),
    1145             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_VP9),
    1146             :         CAP_UINT(GF_CAPS_OUTPUT_STATIC, GF_PROP_PID_CODECID, GF_CODECID_VP10),
    1147             :         CAP_BOOL(GF_CAPS_OUTPUT_STATIC_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    1148             :         {0},
    1149             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1150             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AV1),
    1151             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VP8),
    1152             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VP9),
    1153             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_VP10),
    1154             :         CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
    1155             : };
    1156             : 
    1157             : #define OFFS(_n)        #_n, offsetof(GF_AV1DmxCtx, _n)
    1158             : static const GF_FilterArgs AV1DmxArgs[] =
    1159             : {
    1160             :         { OFFS(fps), "import frame rate (0 default to FPS from bitstream or 25 Hz)", GF_PROP_FRACTION, "0/1000", NULL, 0},
    1161             :         { OFFS(index), "indexing window length. If 0, bitstream is not probed for duration. A negative value skips the indexing if the source file is larger than 100M (slows down importers) unless a play with start range > 0 is issued, otherwise uses the positive value", GF_PROP_DOUBLE, "-1.0", NULL, 0},
    1162             : 
    1163             :         { OFFS(importer), "compatibility with old importer", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
    1164             :         { OFFS(deps), "import samples dependencies information", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_EXPERT},
    1165             : 
    1166             :         { OFFS(bsdbg), "debug NAL parsing in parser@debug logs\n"
    1167             :                 "- off: not enabled\n"
    1168             :                 "- on: enabled\n"
    1169             :                 "- full: enable with number of bits dumped", GF_PROP_UINT, "off", "off|on|full", GF_FS_ARG_HINT_EXPERT},
    1170             :         {0}
    1171             : };
    1172             : 
    1173             : 
    1174             : GF_FilterRegister AV1DmxRegister = {
    1175             :         .name = "rfav1",
    1176             :         GF_FS_SET_DESCRIPTION("AV1/IVF/VP9 reframer")
    1177             :         GF_FS_SET_HELP("This filter parses AV1 OBU, AV1 AnnexB or IVF with AV1 or VP9 files/data and outputs corresponding visual PID and frames.")
    1178             :         .private_size = sizeof(GF_AV1DmxCtx),
    1179             :         .args = AV1DmxArgs,
    1180             :         .finalize = av1dmx_finalize,
    1181             :         SETCAPS(AV1DmxCaps),
    1182             :         .configure_pid = av1dmx_configure_pid,
    1183             :         .process = av1dmx_process,
    1184             :         .probe_data = av1dmx_probe_data,
    1185             :         .process_event = av1dmx_process_event
    1186             : };
    1187             : 
    1188             : 
    1189        2877 : const GF_FilterRegister *av1dmx_register(GF_FilterSession *session)
    1190             : {
    1191        2877 :         return &AV1DmxRegister;
    1192             : }
    1193             : 
    1194             : #else
    1195             : const GF_FilterRegister *av1dmx_register(GF_FilterSession *session)
    1196             : {
    1197             :         return NULL;
    1198             : }
    1199             : #endif // GPAC_DISABLE_AV_PARSERS
    1200             : 

Generated by: LCOV version 1.13