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

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2010-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / OpenSVC Decoder 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             : 
      27             : #include <gpac/filters.h>
      28             : 
      29             : #ifdef GPAC_HAS_OPENSVC
      30             : 
      31             : #include <gpac/avparse.h>
      32             : #include <gpac/constants.h>
      33             : #include <gpac/internal/media_dev.h>
      34             : 
      35             : 
      36             : #if (defined(WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__)
      37             : #  pragma comment(lib, "OpenSVCDecoder")
      38             : #endif
      39             : 
      40             : #include <OpenSVCDecoder/SVCDecoder_ietr_api.h>
      41             : 
      42             : #define SVC_MAX_STREAMS 3
      43             : 
      44             : typedef struct
      45             : {
      46             :         GF_FilterPid *ipid;
      47             :         u32 cfg_crc;
      48             :         u32 id;
      49             :         u32 dep_id;
      50             : } GF_SVCStream;
      51             : 
      52             : typedef struct
      53             : {
      54             :         GF_FilterPid *opid;
      55             :         GF_SVCStream streams[SVC_MAX_STREAMS];
      56             :         u32 nb_streams, active_streams;
      57             :         u32 width, stride, height, out_size;
      58             :         GF_Fraction pixel_ar;
      59             : 
      60             :         u32 nalu_size_length;
      61             : 
      62             :         /*OpenSVC things*/
      63             :         void *codec;
      64             :         int LimitDqId;
      65             :         int MaxDqId;
      66             :         int DqIdTable[8];
      67             :         int TemporalId;
      68             :         int TemporalCom;
      69             : 
      70             :         int layers[4];
      71             :         GF_List *src_packets;
      72             : } GF_OSVCDecCtx;
      73             : 
      74             : static GF_Err osvcdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
      75             : {
      76             :         Bool found=GF_TRUE;
      77             :         const GF_PropertyValue *p;
      78             :         u32 i, count, dep_id=0, id=0, cfg_crc=0;
      79             :         s32 res;
      80             :         OPENSVCFRAME Picture;
      81             :         GF_OSVCDecCtx *ctx = (GF_OSVCDecCtx*) gf_filter_get_udta(filter);
      82             : 
      83             :         if (is_remove) {
      84             :                 if (ctx->streams[0].ipid == pid) {
      85             :                         memset(ctx->streams, 0, SVC_MAX_STREAMS*sizeof(GF_SVCStream));
      86             :                         if (ctx->opid) {
      87             :                                 gf_filter_pid_remove(ctx->opid);
      88             :                                 ctx->opid = NULL;
      89             :                         }
      90             :                         ctx->nb_streams = ctx->active_streams = 0;
      91             :                         if (ctx->codec) SVCDecoder_close(ctx->codec);
      92             :                         ctx->codec = NULL;
      93             :                         return GF_OK;
      94             :                 } else {
      95             :                         for (i=0; i<ctx->nb_streams; i++) {
      96             :                                 if (ctx->streams[i].ipid == pid) {
      97             :                                         ctx->streams[i].ipid = NULL;
      98             :                                         ctx->streams[i].cfg_crc = 0;
      99             :                                         memmove(&ctx->streams[i], &ctx->streams[i+1], sizeof(GF_SVCStream)*(ctx->nb_streams-1));
     100             :                                         ctx->nb_streams--;
     101             :                                         ctx->active_streams--;
     102             :                                         return GF_OK;
     103             :                                 }
     104             :                         }
     105             :                 }
     106             :                 return GF_OK;
     107             :         }
     108             :         if (! gf_filter_pid_check_caps(pid))
     109             :                 return GF_NOT_SUPPORTED;
     110             : 
     111             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DEPENDENCY_ID);
     112             :         if (p) dep_id = p->value.uint;
     113             : 
     114             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     115             :         if (!p) p = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID);
     116             :         if (p) id = p->value.uint;
     117             : 
     118             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     119             :         if (p && p->value.data.ptr && p->value.data.size) {
     120             :                 cfg_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
     121             :                 for (i=0; i<ctx->nb_streams; i++) {
     122             :                         if ((ctx->streams[i].ipid == pid) && (ctx->streams[i].cfg_crc == cfg_crc)) return GF_OK;
     123             :                 }
     124             :         }
     125             : 
     126             :         found = GF_FALSE;
     127             :         for (i=0; i<ctx->active_streams; i++) {
     128             :                 if (ctx->streams[i].ipid == pid) {
     129             :                         ctx->streams[i].cfg_crc = cfg_crc;
     130             :                         found = GF_TRUE;
     131             :                 }
     132             :         }
     133             :         if (!found) {
     134             :                 if (ctx->nb_streams==SVC_MAX_STREAMS) {
     135             :                         return GF_NOT_SUPPORTED;
     136             :                 }
     137             :                 //insert new pid in order of dependencies
     138             :                 for (i=0; i<ctx->nb_streams; i++) {
     139             : 
     140             :                         if (!dep_id && !ctx->streams[i].dep_id) {
     141             :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[SVC Decoder] Detected multiple independent base (%s and %s)\n", gf_filter_pid_get_name(pid), gf_filter_pid_get_name(ctx->streams[i].ipid)));
     142             :                                 return GF_REQUIRES_NEW_INSTANCE;
     143             :                         }
     144             : 
     145             :                         if (ctx->streams[i].id == dep_id) {
     146             :                                 if (ctx->nb_streams > i+2)
     147             :                                         memmove(&ctx->streams[i+1], &ctx->streams[i+2], sizeof(GF_SVCStream) * (ctx->nb_streams-i-1));
     148             : 
     149             :                                 ctx->streams[i+1].ipid = pid;
     150             :                                 ctx->streams[i+1].cfg_crc = cfg_crc;
     151             :                                 ctx->streams[i+1].dep_id = dep_id;
     152             :                                 ctx->streams[i+1].id = id;
     153             :                                 gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     154             :                                 found = GF_TRUE;
     155             :                                 if (!p)
     156             :                                         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT);
     157             : 
     158             :                                 break;
     159             :                         }
     160             :                         if (ctx->streams[i].dep_id == id) {
     161             :                                 if (ctx->nb_streams > i+1)
     162             :                                         memmove(&ctx->streams[i+1], &ctx->streams[i], sizeof(GF_SVCStream) * (ctx->nb_streams-i));
     163             : 
     164             :                                 ctx->streams[i].ipid = pid;
     165             :                                 ctx->streams[i].cfg_crc = cfg_crc;
     166             :                                 ctx->streams[i].dep_id = dep_id;
     167             :                                 ctx->streams[i].id = id;
     168             :                                 gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     169             :                                 found = GF_TRUE;
     170             :                                 break;
     171             :                         }
     172             :                 }
     173             :                 if (!found) {
     174             :                         ctx->streams[ctx->nb_streams].ipid = pid;
     175             :                         ctx->streams[ctx->nb_streams].cfg_crc = cfg_crc;
     176             :                         ctx->streams[ctx->nb_streams].id = id;
     177             :                         ctx->streams[ctx->nb_streams].dep_id = dep_id;
     178             :                         gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     179             :                 }
     180             :                 ctx->nb_streams++;
     181             :                 ctx->active_streams = ctx->nb_streams;
     182             :         }
     183             : 
     184             :         if (p && p->value.data.ptr) {
     185             :                 GF_AVCConfig *cfg = gf_odf_avc_cfg_read(p->value.data.ptr, p->value.data.size);
     186             :                 if (!cfg) return GF_NON_COMPLIANT_BITSTREAM;
     187             :                 if (!dep_id) {
     188             :                         ctx->nalu_size_length = cfg->nal_unit_size;
     189             :                         if (SVCDecoder_init(&ctx->codec) == SVC_STATUS_ERROR) return GF_IO_ERR;
     190             :                 }
     191             : 
     192             :                 /*decode all NALUs*/
     193             :                 count = gf_list_count(cfg->sequenceParameterSets);
     194             :                 SetCommandLayer(ctx->layers, 255, 0, &res, 0);//bufindex can be reset without pb
     195             :                 for (i=0; i<count; i++) {
     196             :                         u32 w=0, h=0;
     197             : #ifndef GPAC_DISABLE_AV_PARSERS
     198             :                         u32 sid;
     199             :                         s32 par_n=0, par_d=0;
     200             : #endif
     201             :                         GF_NALUFFParam *slc = (GF_NALUFFParam*)gf_list_get(cfg->sequenceParameterSets, i);
     202             : 
     203             : #ifndef GPAC_DISABLE_AV_PARSERS
     204             :                         gf_avc_get_sps_info(slc->data, slc->size, &sid, &w, &h, &par_n, &par_d);
     205             : #endif
     206             :                         /*by default use the base layer*/
     207             :                         if (!i) {
     208             :                                 if ((ctx->width<w) || (ctx->height<h)) {
     209             :                                         ctx->width = w;
     210             :                                         ctx->height = h;
     211             : #ifndef GPAC_DISABLE_AV_PARSERS
     212             :                                         if ( ((s32)par_n>0) && ((s32)par_d>0) ) {
     213             :                                                 ctx->pixel_ar.num = par_n;
     214             :                                                 ctx->pixel_ar.den = par_d;
     215             :                                         }
     216             : #endif
     217             :                                 }
     218             :                         }
     219             :                         res = decodeNAL(ctx->codec, (unsigned char *) slc->data, slc->size, &Picture, ctx->layers);
     220             :                         if (res<0) {
     221             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding SPS %d\n", res));
     222             :                         }
     223             :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] Attach: SPS id=\"%d\" code=\"%d\" size=\"%d\"\n", slc->id, slc->data[0] & 0x1F, slc->size));
     224             :                 }
     225             : 
     226             :                 count = gf_list_count(cfg->pictureParameterSets);
     227             :                 for (i=0; i<count; i++) {
     228             :                         GF_NALUFFParam *slc = (GF_NALUFFParam*)gf_list_get(cfg->pictureParameterSets, i);
     229             : #ifndef GPAC_DISABLE_AV_PARSERS
     230             :                         u32 sps_id, pps_id;
     231             :                         gf_avc_get_pps_info(slc->data, slc->size, &pps_id, &sps_id);
     232             : #endif
     233             :                         res = decodeNAL(ctx->codec, (unsigned char *) slc->data, slc->size, &Picture, ctx->layers);
     234             :                         if (res<0) {
     235             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
     236             :                         }
     237             : #ifndef GPAC_DISABLE_AV_PARSERS
     238             :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] Attach: PPS id=\"%d\" code=\"%d\" size=\"%d\" sps_id=\"%d\"\n", pps_id, slc->data[0] & 0x1F, slc->size, sps_id));
     239             : #endif
     240             : 
     241             :                 }
     242             :                 gf_odf_avc_cfg_del(cfg);
     243             :         } else {
     244             :                 if (ctx->nalu_size_length) {
     245             :                         return GF_NOT_SUPPORTED;
     246             :                 }
     247             :                 ctx->nalu_size_length = 0;
     248             :                 if (!ctx->codec) {
     249             :                         if (SVCDecoder_init(&ctx->codec) == SVC_STATUS_ERROR) return GF_IO_ERR;
     250             :                         SetCommandLayer(ctx->layers, 255, 0, &res, 0);
     251             :                 }
     252             :                 ctx->pixel_ar = (GF_Fraction){1, 1};
     253             :         }
     254             :         ctx->stride = ctx->width + 32;
     255             :         ctx->LimitDqId = -1;
     256             :         ctx->MaxDqId = 0;
     257             :         ctx->out_size = ctx->stride * ctx->height * 3 / 2;
     258             : 
     259             :         if (!ctx->opid) {
     260             :                 ctx->opid = gf_filter_pid_new(filter);
     261             :         }
     262             : 
     263             :         //copy properties at init or reconfig
     264             :         gf_filter_pid_copy_properties(ctx->opid, ctx->streams[0].ipid);
     265             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
     266             :         
     267             :         if (ctx->width) {
     268             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) );
     269             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->height) );
     270             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->stride) );
     271             :                 if (ctx->pixel_ar.num)
     272             :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PAR, &PROP_FRAC(ctx->pixel_ar) );
     273             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(GF_PIXEL_YUV) );
     274             :         }
     275             :         return GF_OK;
     276             : }
     277             : 
     278             : 
     279             : static Bool osvcdec_process_event(GF_Filter *filter, const GF_FilterEvent *fevt)
     280             : {
     281             :         GF_OSVCDecCtx *ctx = (GF_OSVCDecCtx*) gf_filter_get_udta(filter);
     282             : 
     283             :         if (fevt->base.type == GF_FEVT_QUALITY_SWITCH) {
     284             :                 if (fevt->quality_switch.up) {
     285             :                         if (ctx->LimitDqId == -1)
     286             :                                 ctx->LimitDqId = ctx->MaxDqId;
     287             :                         if (ctx->LimitDqId < ctx->MaxDqId)
     288             :                                 // set layer up (command=1)
     289             :                                 UpdateLayer( ctx->DqIdTable, &ctx->LimitDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 1 );
     290             :                 } else {
     291             :                         if (ctx->LimitDqId > 0)
     292             :                                 // set layer down (command=0)
     293             :                                 UpdateLayer( ctx->DqIdTable, &ctx->LimitDqId, &ctx->TemporalCom, &ctx->TemporalId, ctx->MaxDqId, 0 );
     294             :                 }
     295             :                 //todo: we should get the set of pids active and trigger the switch up/down based on that
     296             :                 //rather than not canceling the event
     297             :                 return GF_FALSE;
     298             :         }
     299             :         return GF_FALSE;
     300             : }
     301             : 
     302             : static GF_Err osvcdec_process(GF_Filter *filter)
     303             : {
     304             :         s32 got_pic;
     305             :         u64 min_dts = GF_FILTER_NO_TS;
     306             :         u64 min_cts = GF_FILTER_NO_TS;
     307             :         OPENSVCFRAME pic;
     308             :         u32 i, count, idx, nalu_size, sc_size, nb_eos=0;
     309             :         u8 *ptr;
     310             :         u32 data_size;
     311             :         u8 *data;
     312             :         Bool has_pic = GF_FALSE;
     313             :         GF_OSVCDecCtx *ctx = (GF_OSVCDecCtx*) gf_filter_get_udta(filter);
     314             :         GF_FilterPacket *dst_pck, *src_pck, *pck_ref = NULL;
     315             : 
     316             :         for (idx=0; idx<ctx->active_streams; idx++) {
     317             :                 u64 dts, cts;
     318             :                 if (!ctx->streams[idx].ipid) {
     319             :                         if (nb_eos) nb_eos++;
     320             :                         continue;
     321             :                 }
     322             :                 
     323             :                 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->streams[idx].ipid);
     324             :                 if (!pck) {
     325             :                         if (gf_filter_pid_is_eos(ctx->streams[idx].ipid)) nb_eos++;
     326             :                         //make sure we do have a packet on the enhancement
     327             :                         else {
     328             :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[OpenSVC] no input packets on running pid %s - postponing decode\n", gf_filter_pid_get_name(ctx->streams[idx].ipid) ) );
     329             :                                 return GF_OK;
     330             :                         }
     331             :                         continue;
     332             :                 }
     333             :                 dts = gf_filter_pck_get_dts(pck);
     334             :                 cts = gf_filter_pck_get_cts(pck);
     335             : 
     336             :                 data = (char *) gf_filter_pck_get_data(pck, &data_size);
     337             :                 //TODO: this is a clock signaling, for now just trash ..
     338             :                 if (!data) {
     339             :                         gf_filter_pid_drop_packet(ctx->streams[idx].ipid);
     340             :                         idx--;
     341             :                         continue;
     342             :                 }
     343             :                 if (dts==GF_FILTER_NO_TS) dts = cts;
     344             :                 //get packet with min dts (either a timestamp or a decode order number)
     345             :                 if (min_dts > dts) {
     346             :                         min_dts = dts;
     347             :                         if (cts == GF_FILTER_NO_TS) min_cts = min_dts;
     348             :                         else min_cts = cts;
     349             :                         pck_ref = pck;
     350             :                 }
     351             :         }
     352             :         if (nb_eos == ctx->active_streams) {
     353             :                 gf_filter_pid_set_eos(ctx->opid);
     354             :                 return GF_OK;
     355             :         }
     356             :         if (min_cts == GF_FILTER_NO_TS) return GF_OK;
     357             : 
     358             :         //append in cts order since we get output frames in cts order
     359             :         gf_filter_pck_ref_props(&pck_ref);
     360             :         count = gf_list_count(ctx->src_packets);
     361             :         src_pck = NULL;
     362             :         for (i=0; i<count; i++) {
     363             :                 u64 acts;
     364             :                 src_pck = gf_list_get(ctx->src_packets, i);
     365             :                 acts = gf_filter_pck_get_cts(src_pck);
     366             :                 if (acts==min_cts) {
     367             :                         gf_filter_pck_unref(pck_ref);
     368             :                         break;
     369             :                 }
     370             :                 if (acts>min_cts) {
     371             :                         gf_list_insert(ctx->src_packets, pck_ref, i);
     372             :                         break;
     373             :                 }
     374             :                 src_pck = NULL;
     375             :         }
     376             :         if (!src_pck)
     377             :                 gf_list_add(ctx->src_packets, pck_ref);
     378             : 
     379             :         pic.Width = pic.Height = 0;
     380             :         for (idx=0; idx<ctx->nb_streams; idx++) {
     381             :                 u64 dts, cts;
     382             : #ifndef GPAC_DISABLE_AV_PARSERS
     383             : #ifndef GPAC_DISABLE_LOG
     384             :                 u32 sps_id, pps_id;
     385             : #endif
     386             : #endif
     387             :                 u32 maxDqIdInAU;
     388             :                 if (!ctx->streams[idx].ipid) continue;
     389             : 
     390             :                 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->streams[idx].ipid);
     391             :                 if (!pck) continue;
     392             : 
     393             :                 if (idx>=ctx->active_streams) {
     394             :                         gf_filter_pid_drop_packet(ctx->streams[idx].ipid);
     395             :                         continue;
     396             :                 }
     397             : 
     398             :                 dts = gf_filter_pck_get_dts(pck);
     399             :                 cts = gf_filter_pck_get_cts(pck);
     400             :                 if (dts==GF_FILTER_NO_TS) dts = cts;
     401             : 
     402             :                 if (min_dts != GF_FILTER_NO_TS) {
     403             :                         if (min_dts != dts) continue;
     404             :                 } else if (min_cts != cts) {
     405             :                         continue;
     406             :                 }
     407             : 
     408             :                 data = (char *) gf_filter_pck_get_data(pck, &data_size);
     409             : 
     410             :                 maxDqIdInAU = GetDqIdMax((unsigned char *) data, data_size, ctx->nalu_size_length, ctx->DqIdTable, ctx->nalu_size_length ? 1 : 0);
     411             :                 if (ctx->MaxDqId <= (s32) maxDqIdInAU) {
     412             :                         ctx->MaxDqId = (s32) maxDqIdInAU;
     413             :                 }
     414             :                 GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[OpenSVC] decode from stream %s - DTS "LLU" PTS "LLU" size %d - max DQID %d\n", gf_filter_pid_get_name(ctx->streams[idx].ipid), dts, cts, data_size, maxDqIdInAU) );
     415             : 
     416             : 
     417             :                 //we are asked to use a lower quality
     418             :                 if ((ctx->LimitDqId>=0) && (ctx->LimitDqId < (s32) maxDqIdInAU))
     419             :                         maxDqIdInAU = ctx->LimitDqId;
     420             : 
     421             :                 /*decode only current layer*/
     422             :                 SetCommandLayer(ctx->layers, ctx->MaxDqId, maxDqIdInAU, &ctx->TemporalCom, ctx->TemporalId);
     423             : 
     424             :                 got_pic = 0;
     425             :                 nalu_size = 0;
     426             :                 ptr = (u8 *) data;
     427             :                 sc_size = 0;
     428             : 
     429             :                 if (!ctx->nalu_size_length) {
     430             : #ifndef GPAC_DISABLE_AV_PARSERS
     431             :                         u32 size = gf_media_nalu_next_start_code((u8 *) data, data_size, &sc_size);
     432             :                         if (sc_size) {
     433             :                                 ptr += size+sc_size;
     434             :                                 assert(data_size >= size+sc_size);
     435             :                                 data_size -= size+sc_size;
     436             :                         } else
     437             : #endif
     438             :                         {
     439             :                                 /*no annex-B start-code found, discard */
     440             :                                 gf_filter_pid_drop_packet(ctx->streams[idx].ipid);
     441             :                                 idx--;
     442             :                                 continue;
     443             :                         }
     444             :                 }
     445             : 
     446             :                 while (data_size) {
     447             :                         int res;
     448             :                         if (ctx->nalu_size_length) {
     449             :                                 for (i=0; i<ctx->nalu_size_length; i++) {
     450             :                                         nalu_size = (nalu_size<<8) + ptr[i];
     451             :                                 }
     452             :                                 ptr += ctx->nalu_size_length;
     453             :                         } else {
     454             : #ifndef GPAC_DISABLE_AV_PARSERS
     455             :                                 nalu_size = gf_media_nalu_next_start_code(ptr, data_size, &sc_size);
     456             : #else
     457             :                                 nalu_size = data_size;
     458             :                                 sc_size=0;
     459             : #endif
     460             : 
     461             :                         }
     462             : 
     463             : #if !defined(GPAC_DISABLE_LOG) && !defined(GPAC_DISABLE_AV_PARSERS)
     464             :                         if (gf_log_tool_level_on(GF_LOG_CODEC, GF_LOG_DEBUG)) {
     465             :                                 switch (ptr[0] & 0x1F) {
     466             :                                 case GF_AVC_NALU_SEQ_PARAM:
     467             :                                 case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
     468             :                                         gf_avc_get_sps_info((char *)ptr, nalu_size, &sps_id, NULL, NULL, NULL, NULL);
     469             :                                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVCDec] PID %s: SPS id=\"%d\" code=\"%d\" size=\"%d\"\n", gf_filter_pid_get_name(ctx->streams[idx].ipid), sps_id, ptr[0] & 0x1F, nalu_size));
     470             :                                         break;
     471             :                                 case GF_AVC_NALU_PIC_PARAM:
     472             :                                         gf_avc_get_pps_info((char *)ptr, nalu_size, &pps_id, &sps_id);
     473             :                                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] PID %s: PPS id=\"%d\" code=\"%d\" size=\"%d\" sps_id=\"%d\"\n", gf_filter_pid_get_name(ctx->streams[idx].ipid), pps_id, ptr[0] & 0x1F, nalu_size, sps_id));
     474             :                                         break;
     475             :                                 case GF_AVC_NALU_VDRD:
     476             :                                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] PID %s: VDRD found\n", gf_filter_pid_get_name(ctx->streams[idx].ipid)));
     477             :                                         break;
     478             :                                 default:
     479             :                                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] PID %s: NALU code=\"%d\" size=\"%d\"\n", gf_filter_pid_get_name(ctx->streams[idx].ipid), ptr[0] & 0x1F, nalu_size));
     480             :                                 }
     481             :                         }
     482             : #endif
     483             : 
     484             :                         if (!got_pic) {
     485             :                                 res = decodeNAL(ctx->codec, ptr, nalu_size, &pic, ctx->layers);
     486             :                                 if (res>0) got_pic = res;
     487             :                         } else {
     488             :                                 res = decodeNAL(ctx->codec, ptr, nalu_size, &pic, ctx->layers);
     489             :                         }
     490             :                         if (res<0) {
     491             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding NAL: %d\n", res));
     492             :                         }
     493             : 
     494             :                         ptr += nalu_size;
     495             :                         if (ctx->nalu_size_length) {
     496             :                                 if (data_size < nalu_size + ctx->nalu_size_length) break;
     497             :                                 data_size -= nalu_size + ctx->nalu_size_length;
     498             :                         } else {
     499             :                                 if (!sc_size || (data_size < nalu_size + sc_size)) break;
     500             :                                 data_size -= nalu_size + sc_size;
     501             :                                 ptr += sc_size;
     502             :                         }
     503             :                 }
     504             :                 gf_filter_pid_drop_packet(ctx->streams[idx].ipid);
     505             : 
     506             :                 if (got_pic) has_pic = GF_TRUE;
     507             :         }
     508             :         if (!has_pic) return GF_OK;
     509             : 
     510             :         if ((pic.Width != ctx->width) || (pic.Height!=ctx->height)) {
     511             :                 GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[SVC Decoder] Resizing from %dx%d to %dx%d\n", ctx->width, ctx->height, pic.Width, pic.Height ));
     512             :                 ctx->width = pic.Width;
     513             :                 ctx->stride = pic.Width + 32;
     514             :                 ctx->height = pic.Height;
     515             :                 ctx->out_size = ctx->stride * ctx->height * 3 / 2;
     516             : 
     517             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) );
     518             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->height) );
     519             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->stride) );
     520             :                 if (ctx->pixel_ar.num)
     521             :                         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PAR, &PROP_FRAC(ctx->pixel_ar) );
     522             : 
     523             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(GF_PIXEL_YUV) );
     524             :         }
     525             : 
     526             :         src_pck = gf_list_pop_front(ctx->src_packets);
     527             : 
     528             :         if (src_pck && gf_filter_pck_get_seek_flag(src_pck)) {
     529             :                 gf_filter_pck_unref(src_pck);
     530             :                 return GF_OK;
     531             :         }
     532             : 
     533             :         dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->out_size, &data);
     534             :         if (!dst_pck) return GF_OUT_OF_MEM;
     535             : 
     536             :         memcpy(data, pic.pY[0], ctx->stride*ctx->height);
     537             :         memcpy(data + ctx->stride * ctx->height, pic.pU[0], ctx->stride*ctx->height/4);
     538             :         memcpy(data + 5*ctx->stride * ctx->height/4, pic.pV[0], ctx->stride*ctx->height/4);
     539             : 
     540             :         if (src_pck) {
     541             :                 gf_filter_pck_merge_properties(src_pck, dst_pck);
     542             :                 gf_filter_pck_unref(src_pck);
     543             :         }
     544             : 
     545             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[OpenSVC] decoded out frame PTS "LLU"\n", gf_filter_pck_get_cts(dst_pck) ));
     546             :         gf_filter_pck_send(dst_pck);
     547             :         return GF_OK;
     548             : }
     549             : 
     550             : static GF_Err osvcdec_initialize(GF_Filter *filter)
     551             : {
     552             :         GF_OSVCDecCtx *ctx = (GF_OSVCDecCtx*) gf_filter_get_udta(filter);
     553             :         ctx->src_packets = gf_list_new();
     554             :         return GF_OK;
     555             : }
     556             : 
     557             : static void osvcdec_finalize(GF_Filter *filter)
     558             : {
     559             :         GF_OSVCDecCtx *ctx = (GF_OSVCDecCtx*) gf_filter_get_udta(filter);
     560             :         if (ctx->codec) SVCDecoder_close(ctx->codec);
     561             :         while (gf_list_count(ctx->src_packets)) {
     562             :                 GF_FilterPacket *pck = gf_list_pop_back(ctx->src_packets);
     563             :                 gf_filter_pck_unref(pck);
     564             :         }
     565             :         gf_list_del(ctx->src_packets);
     566             : }
     567             : 
     568             : static const GF_FilterCapability OSVCDecCaps[] =
     569             : {
     570             :         CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
     571             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     572             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
     573             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_SVC),
     574             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
     575             : };
     576             : 
     577             : GF_FilterRegister OSVCDecRegister = {
     578             :         .name = "osvcdec",
     579             :         GF_FS_SET_DESCRIPTION("OpenSVC decoder")
     580             :         GF_FS_SET_HELP("This filter decodes scalable AVC|H264 streams through OpenSVC library.")
     581             :         .private_size = sizeof(GF_OSVCDecCtx),
     582             :         SETCAPS(OSVCDecCaps),
     583             :         .initialize = osvcdec_initialize,
     584             :         .finalize = osvcdec_finalize,
     585             :         .configure_pid = osvcdec_configure_pid,
     586             :         .process = osvcdec_process,
     587             :         .process_event = osvcdec_process_event,
     588             :         .max_extra_pids = (SVC_MAX_STREAMS-1),
     589             :         .priority = 255
     590             : };
     591             : 
     592             : #endif //GPAC_HAS_OPENSVC
     593             : 
     594        2877 : const GF_FilterRegister *osvcdec_register(GF_FilterSession *session)
     595             : {
     596             : #ifdef GPAC_HAS_OPENSVC
     597             :         return &OSVCDecRegister;
     598             : #else
     599        2877 :         return NULL;
     600             : #endif
     601             : }

Generated by: LCOV version 1.13