LCOV - code coverage report
Current view: top level - filters - dec_vtb.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 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / VideoToolBox 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             : //do not include math.h we would have a conflict with Fixed ... we're lucky we don't need maths routines here
      27             : #define _GF_MATH_H_
      28             : 
      29             : #include <gpac/thread.h>
      30             : 
      31             : #if !defined(GPAC_DISABLE_AV_PARSERS) && ( defined(GPAC_CONFIG_DARWIN) || defined(GPAC_CONFIG_IOS) ) && defined(GPAC_HAS_VTB)
      32             : 
      33             : #include <stdint.h>
      34             : 
      35             : #define Picture QuickdrawPicture
      36             : #include <VideoToolbox/VideoToolbox.h>
      37             : #undef Picture
      38             : 
      39             : #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
      40             : #  define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
      41             : #endif
      42             : 
      43             : #include <gpac/maths.h>
      44             : #include <gpac/internal/media_dev.h>
      45             : #include <gpac/constants.h>
      46             : #include <gpac/filters.h>
      47             : 
      48             : #include "../../src/compositor/gl_inc.h"
      49             : 
      50             : 
      51             : #ifdef GPAC_CONFIG_IOS
      52             : #define VTB_GL_TEXTURE
      53             : 
      54             : #define GF_CVGLTextureREF CVOpenGLESTextureRef
      55             : #define GF_CVGLTextureCacheREF CVOpenGLESTextureCacheRef
      56             : #define GF_kCVPixelBufferOpenGLCompatibilityKey kCVPixelBufferOpenGLESCompatibilityKey
      57             : #define GF_CVOpenGLTextureCacheFlush CVOpenGLESTextureCacheFlush
      58             : #define GF_CVOpenGLTextureGetTarget CVOpenGLESTextureGetTarget
      59             : #define GF_CVOpenGLTextureGetName CVOpenGLESTextureGetName
      60             : 
      61             : #else
      62             : 
      63             : //not working yet, not sure why
      64             : //#define VTB_GL_TEXTURE
      65             : 
      66             : #include <CoreVideo/CVOpenGLTexture.h>
      67             : 
      68             : #define GF_CVGLTextureREF CVOpenGLTextureRef
      69             : #define GF_CVGLTextureCacheREF CVOpenGLTextureCacheRef
      70             : #define GF_kCVPixelBufferOpenGLCompatibilityKey kCVPixelBufferOpenGLCompatibilityKey
      71             : #define GF_CVOpenGLTextureCacheFlush CVOpenGLTextureCacheFlush
      72             : #define GF_CVOpenGLTextureGetTarget CVOpenGLTextureGetTarget
      73             : #define GF_CVOpenGLTextureGetName CVOpenGLTextureGetName
      74             : 
      75             : 
      76             : #endif
      77             : 
      78             : #ifndef GPAC_DISABLE_AV_PARSERS
      79             : 
      80             : typedef struct
      81             : {
      82             :         //opts
      83             :         u32 reorder, ofmt;
      84             :         Bool no_copy;
      85             :         Bool disable_hw;
      86             : 
      87             :         //internal
      88             : //      GF_FilterPid *ipid;
      89             :         GF_List *streams;
      90             :         GF_FilterPid *opid;
      91             :         u32 width, height, stride;
      92             :         GF_Fraction pixel_ar;
      93             :         u32 pix_fmt;
      94             :         u32 out_size;
      95             :         u32 cfg_crc;
      96             :         u32 codecid;
      97             :         Bool is_hardware;
      98             : 
      99             :         GF_Err last_error;
     100             :         
     101             :         int vtb_type;
     102             :         VTDecompressionSessionRef vtb_session;
     103             :     CMFormatDescriptionRef fmt_desc;
     104             : 
     105             :     GF_List *frames, *frames_res;
     106             :     GF_FilterPacket *cur_pck;
     107             : 
     108             :         u8 chroma_format, luma_bit_depth, chroma_bit_depth;
     109             :         Bool frame_size_changed;
     110             :         Bool reorder_detected;
     111             :         Bool drop_non_refs;
     112             : 
     113             :         volatile u32 decoded_frames_pending;
     114             :         u32 reorder_probe;
     115             :         Bool reconfig_needed;
     116             :         u64 last_cts_out;
     117             :         u32 last_timescale_out;
     118             : 
     119             :         //MPEG-1/2 specific
     120             :         Bool init_mpeg12;
     121             :         
     122             :         //MPEG-4 specific
     123             :         Bool skip_mpeg4_vosh;
     124             :         char *vosh;
     125             :         u32 vosh_size;
     126             : 
     127             :         //NAL-based specific
     128             :         GF_BitStream *nal_bs;
     129             :         GF_BitStream *ps_bs;
     130             : 
     131             :         GF_BitStream *nalu_rewrite_bs;
     132             :         u8 *nalu_buffer;
     133             :         u32 nalu_buffer_alloc;
     134             : 
     135             :         Bool is_avc;
     136             :         Bool is_annex_b;
     137             : 
     138             :         u32 nalu_size_length;
     139             : 
     140             :         GF_List *SPSs, *PPSs, *VPSs;
     141             :         s32 active_sps, active_pps, active_vps;
     142             :         u32 active_sps_crc, active_pps_crc, active_vps_crc;
     143             : 
     144             :         AVCState avc;
     145             :         Bool check_h264_isma;
     146             : 
     147             :         HEVCState hevc;
     148             :         Bool is_hevc;
     149             : 
     150             :         Bool profile_supported, can_reconfig;
     151             :         u32 nb_consecutive_errors;
     152             :         //openGL output
     153             : #ifdef VTB_GL_TEXTURE
     154             :         Bool use_gl_textures;
     155             :         GF_CVGLTextureCacheREF cache_texture;
     156             : #endif
     157             :         void *gl_context;
     158             : 
     159             :         struct __vtb_frame_ifce *last_frame_sent;
     160             : } GF_VTBDecCtx;
     161             : 
     162             : 
     163             : typedef struct __vtb_frame_ifce
     164             : {
     165             :         GF_FilterFrameInterface frame_ifce;
     166             : 
     167             :         Bool locked;
     168             :         CVPixelBufferRef frame;
     169             :         GF_VTBDecCtx *ctx;
     170             :         GF_FilterPacket *pck_src;
     171             :         //openGL mode
     172             : #ifdef VTB_GL_TEXTURE
     173             :         GF_CVGLTextureREF y, u, v;
     174             : #endif
     175             : } GF_VTBHWFrame;
     176             : 
     177             : static void vtbdec_delete_decoder(GF_VTBDecCtx *ctx);
     178             : static GF_Err vtbdec_flush_frame(GF_Filter *filter, GF_VTBDecCtx *ctx);
     179             : 
     180             : static void vtbdec_on_frame(void *opaque, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags flags, CVImageBufferRef image, CMTime pts, CMTime duration)
     181             : {
     182             :         GF_VTBDecCtx *ctx = (GF_VTBDecCtx *)opaque;
     183             :         GF_VTBHWFrame *frame;
     184             :         u32 i, count, timescale;
     185             :         u64 cts, dts;
     186             :         assert(ctx->cur_pck);
     187             : 
     188             :     if (!image) {
     189             :                 if (status != kCVReturnSuccess) {
     190             :                         ctx->last_error = GF_NON_COMPLIANT_BITSTREAM;
     191             :                         ctx->nb_consecutive_errors++;
     192             :                         //if we can reconfigure and this is a SAP, reconfig if too many errors or first frame after reconfig
     193             :                         if (ctx->can_reconfig && gf_filter_pck_get_sap(ctx->cur_pck)
     194             :                                 && (!ctx->profile_supported || (ctx->nb_consecutive_errors>10))
     195             :                         ) {
     196             :                                 ctx->last_error = GF_PROFILE_NOT_SUPPORTED;
     197             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Decode error - status %d - trying filter chain reload\n", status));
     198             :                         } else {
     199             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Decode error - status %d\n", status));
     200             :                         }
     201             :                         return;
     202             :                 }
     203             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[VTB] No output buffer\n"));
     204             :         return;
     205             :     }
     206             :         if (gf_filter_pck_get_seek_flag(ctx->cur_pck) ) {
     207             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[VTB] Frame marked as seek, not dispatching - status %d\n", status));
     208             :                 return;
     209             :         }
     210             : 
     211             :         if (ctx->reorder_probe) {
     212             :                 ctx->reorder_probe--;
     213             :         }
     214             : 
     215             :         ctx->profile_supported = GF_TRUE;
     216             :         ctx->nb_consecutive_errors=0;
     217             :         frame = gf_list_pop_back(ctx->frames_res);
     218             :         if (!frame) {
     219             :                 GF_SAFEALLOC(frame, GF_VTBHWFrame);
     220             :                 if (!frame) return;
     221             :         } else {
     222             :                 memset(frame, 0, sizeof(GF_VTBHWFrame));
     223             :         }
     224             : 
     225             :         assert( gf_filter_pck_get_seek_flag(ctx->cur_pck) == 0 );
     226             : 
     227             :         frame->frame_ifce.user_data = frame;
     228             :         frame->frame = CVPixelBufferRetain(image);
     229             :         frame->pck_src = ctx->cur_pck;
     230             :         gf_filter_pck_ref_props(&frame->pck_src);
     231             : 
     232             :         frame->ctx = ctx;
     233             :         cts = gf_filter_pck_get_cts(frame->pck_src);
     234             :         dts = gf_filter_pck_get_dts(frame->pck_src);
     235             :         timescale = gf_filter_pck_get_timescale(frame->pck_src);
     236             : 
     237             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[VTB] Decoded frame DTS "LLU" CTS "LLU" timescale %d\n", dts, cts, timescale));
     238             : 
     239             :         if (!ctx->last_timescale_out)
     240             :                 ctx->last_timescale_out = gf_filter_pck_get_timescale(frame->pck_src);
     241             : 
     242             :         count = gf_list_count(ctx->frames);
     243             :         for (i=0; i<count; i++) {
     244             :                 GF_VTBHWFrame *aframe = gf_list_get(ctx->frames, i);
     245             :                 Bool insert = GF_FALSE;
     246             :                 u64 acts, adts, atimescale;
     247             :                 s64 diff;
     248             : 
     249             :                 acts = gf_filter_pck_get_cts(aframe->pck_src);
     250             :                 adts = gf_filter_pck_get_dts(aframe->pck_src);
     251             :                 atimescale = gf_filter_pck_get_timescale(aframe->pck_src);
     252             : 
     253             :                 if (adts > dts) {
     254             :                         ctx->reorder_probe=0;
     255             :                         ctx->reorder_detected=GF_FALSE;
     256             :                         break;
     257             :                 }
     258             :                 if ((timescale == atimescale) && (ctx->last_timescale_out == timescale)) {
     259             :                         diff = (s64) acts - (s64) cts;
     260             :                         if ((diff>0) && (cts > ctx->last_cts_out) ) {
     261             :                                 insert = GF_TRUE;
     262             :                         }
     263             :                 } else {
     264             :                         diff = (s64) (acts * timescale) - (s64) (cts * atimescale);
     265             :                         if ((diff>0) && (ctx->last_timescale_out * cts > timescale * ctx->last_cts_out) ) {
     266             :                                 insert = GF_TRUE;
     267             :                         }
     268             :                 }
     269             :                 if (insert) {
     270             :                         gf_list_insert(ctx->frames, frame, i);
     271             :                         ctx->reorder_detected = GF_TRUE;
     272             :                         return;
     273             :                 }
     274             :         }
     275             :         gf_list_add(ctx->frames, frame);
     276             : }
     277             : 
     278             : static CFDictionaryRef vtbdec_create_buffer_attributes(GF_VTBDecCtx *ctx, OSType pix_fmt)
     279             : {
     280             :     CFMutableDictionaryRef buffer_attributes;
     281             :     CFMutableDictionaryRef surf_props;
     282             :     CFNumberRef w;
     283             :     CFNumberRef h;
     284             :     CFNumberRef pixel_fmt;
     285             : 
     286             :     w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctx->width);
     287             :     h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctx->height);
     288             :     pixel_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
     289             : 
     290             :     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     291             :     surf_props = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     292             :         
     293             :     CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
     294             :     CFRelease(w);
     295             :     CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
     296             :     CFRelease(h);
     297             :     CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, pixel_fmt);
     298             :     CFRelease(pixel_fmt);
     299             : 
     300             : #ifdef VTB_GL_TEXTURE
     301             :         if (ctx->use_gl_textures)
     302             :                 CFDictionarySetValue(buffer_attributes, GF_kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
     303             : #endif
     304             : 
     305             :     CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, surf_props);
     306             :     CFRelease(surf_props);
     307             : 
     308             :     return buffer_attributes;
     309             : }
     310             : 
     311             : static GF_Err vtbdec_init_decoder(GF_Filter *filter, GF_VTBDecCtx *ctx)
     312             : {
     313             :         CFMutableDictionaryRef dec_dsi, dec_type;
     314             :         CFMutableDictionaryRef dsi;
     315             :         VTDecompressionOutputCallbackRecord cbacks;
     316             :     CFDictionaryRef buffer_attribs;
     317             :     OSStatus status;
     318             :         OSType kColorSpace;
     319             :         const GF_PropertyValue *p;
     320             :         CFDataRef data = NULL;
     321             :         u8 *dsi_data=NULL;
     322             :         u32 dsi_data_size=0;
     323             :         u32 w, h;
     324             :         GF_FilterPid *pid;
     325             :         const char *codec_name = NULL;
     326             :         w = h = 0;
     327             :         
     328             :     dec_dsi = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     329             : 
     330             :         if (ctx->ofmt==1) {
     331             :                 kColorSpace = kCVPixelFormatType_420YpCbCr8Planar;
     332             :                 ctx->pix_fmt = GF_PIXEL_YUV;
     333             :         } else if (ctx->ofmt==2) {
     334             :                 kColorSpace = kCVPixelFormatType_24RGB;
     335             :                 ctx->pix_fmt = GF_PIXEL_RGB;
     336             :         } else {
     337             :                 kColorSpace = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
     338             :                 ctx->pix_fmt = GF_PIXEL_NV12;
     339             :         }
     340             : 
     341             :         ctx->reorder_probe = ctx->reorder;
     342             :         ctx->reorder_detected = GF_FALSE;
     343             :         pid = gf_list_get(ctx->streams, 0);
     344             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
     345             :         if (p) w = p->value.uint;
     346             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
     347             :         if (p) h = p->value.uint;
     348             :         if (w && h) {
     349             :                 ctx->width = w;
     350             :                 ctx->height = h;
     351             :         }
     352             : 
     353             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     354             : 
     355             :         switch (ctx->codecid) {
     356             :     case GF_CODECID_AVC:
     357             :                 if (gf_list_count(ctx->SPSs) && gf_list_count(ctx->PPSs)) {
     358             :                         s32 idx;
     359             :                         u32 i;
     360             :                         GF_AVCConfig *cfg;
     361             :                         GF_NALUFFParam *sps = NULL;
     362             :                         GF_NALUFFParam *pps = NULL;
     363             : 
     364             :                         for (i=0; i<gf_list_count(ctx->SPSs); i++) {
     365             :                                 sps = gf_list_get(ctx->SPSs, i);
     366             :                                 if (ctx->active_sps<0) ctx->active_sps = sps->id;
     367             : 
     368             :                                 if (sps->id==ctx->active_sps) {
     369             :                                         ctx->active_sps_crc = gf_crc_32(sps->data, sps->size);
     370             :                                         break;
     371             :                                 }
     372             :                                 sps = NULL;
     373             :                         }
     374             :                         if (!sps) return GF_NON_COMPLIANT_BITSTREAM;
     375             :                         for (i=0; i<gf_list_count(ctx->PPSs); i++) {
     376             :                                 pps = gf_list_get(ctx->PPSs, i);
     377             :                                 if (ctx->active_pps<0) ctx->active_pps = pps->id;
     378             : 
     379             :                                 if (pps->id==ctx->active_pps) {
     380             :                                         ctx->active_pps_crc = gf_crc_32(pps->data, pps->size);
     381             :                                         break;
     382             :                                 }
     383             :                                 pps = NULL;
     384             :                         }
     385             :                         if (!pps) return GF_NON_COMPLIANT_BITSTREAM;
     386             :                         ctx->reconfig_needed = GF_FALSE;
     387             :                         
     388             :                         ctx->vtb_type = 'avc1'; //kCMVideoCodecType_H264;
     389             :                         codec_name = "AVC|H264";
     390             : 
     391             :                         if (gf_avc_read_sps(sps->data, sps->size, &ctx->avc, 0, NULL)<0)
     392             :                                 return GF_NON_COMPLIANT_BITSTREAM;
     393             :                         if (gf_avc_read_pps(pps->data, pps->size, &ctx->avc)<0)
     394             :                                 return GF_NON_COMPLIANT_BITSTREAM;
     395             : 
     396             :                         idx = ctx->active_sps;
     397             :                         ctx->width = ctx->avc.sps[idx].width;
     398             :                         ctx->height = ctx->avc.sps[idx].height;
     399             :                         if (ctx->avc.sps[idx].vui.par_num && ctx->avc.sps[idx].vui.par_den) {
     400             :                                 ctx->pixel_ar.num = ctx->avc.sps[idx].vui.par_num;
     401             :                                 ctx->pixel_ar.den = ctx->avc.sps[idx].vui.par_den;
     402             :                         } else {
     403             :                                 ctx->pixel_ar.num = ctx->pixel_ar.den = 1;
     404             :                         }
     405             :                         ctx->chroma_format = ctx->avc.sps[idx].chroma_format;
     406             :                         ctx->luma_bit_depth = 8 + ctx->avc.sps[idx].luma_bit_depth_m8;
     407             :                         ctx->chroma_bit_depth = 8 + ctx->avc.sps[idx].chroma_bit_depth_m8;
     408             :                 
     409             :                         switch (ctx->chroma_format) {
     410             :                         case 2:
     411             : #ifndef GPAC_CONFIG_IOS
     412             :                                 //422 decoding doesn't seem supported ...
     413             :                                 if (ctx->luma_bit_depth>8) {
     414             :                                         kColorSpace = kCVPixelFormatType_422YpCbCr10;
     415             :                                         ctx->pix_fmt = GF_PIXEL_YUV422_10;
     416             :                                 } else
     417             : #endif
     418             :                                 {
     419             :                                         kColorSpace = kCVPixelFormatType_422YpCbCr8;
     420             :                                         ctx->pix_fmt = GF_PIXEL_YUV422;
     421             :                                 }
     422             :                                 break;
     423             :                         case 3:
     424             : #ifndef GPAC_CONFIG_IOS
     425             :                                 if (ctx->luma_bit_depth>8) {
     426             :                                         kColorSpace = kCVPixelFormatType_444YpCbCr10;
     427             :                                         ctx->pix_fmt = GF_PIXEL_YUV444_10;
     428             :                                 } else
     429             : #endif
     430             :                                 {
     431             :                                         kColorSpace = kCVPixelFormatType_444YpCbCr8;
     432             :                                         ctx->pix_fmt = GF_PIXEL_YUV444;
     433             :                                 }
     434             :                                 break;
     435             :                         default:
     436             : #if !defined(GPAC_CONFIG_IOS) && defined(AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER)
     437             :                                 if (ctx->luma_bit_depth>8) {
     438             :                                         kColorSpace = kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange;
     439             :                                         ctx->pix_fmt = GF_PIXEL_NV12_10;
     440             :                                 }
     441             : #endif
     442             :                                 break;
     443             :                         }
     444             :                         //always rewrite with current sps and pps
     445             :                         cfg = gf_odf_avc_cfg_new();
     446             :                         cfg->configurationVersion = 1;
     447             :                         cfg->profile_compatibility = ctx->avc.sps[idx].prof_compat;
     448             :                         cfg->AVCProfileIndication = ctx->avc.sps[idx].profile_idc;
     449             :                         cfg->AVCLevelIndication = ctx->avc.sps[idx].level_idc;
     450             :                         cfg->chroma_format = ctx->avc.sps[idx].chroma_format;
     451             :                         cfg->luma_bit_depth = 8 + ctx->avc.sps[idx].luma_bit_depth_m8;
     452             :                         cfg->chroma_bit_depth = 8 + ctx->avc.sps[idx].chroma_bit_depth_m8;
     453             :                         cfg->nal_unit_size = 4;
     454             :                                 
     455             :                         //we send only the active SPS and PPS, otherwise vtb complains !!
     456             :                         gf_list_add(cfg->sequenceParameterSets, sps);
     457             :                         gf_list_add(cfg->pictureParameterSets, pps);
     458             :                         gf_odf_avc_cfg_write(cfg, &dsi_data, &dsi_data_size);
     459             :                         gf_list_reset(cfg->sequenceParameterSets);
     460             :                         gf_list_reset(cfg->pictureParameterSets);
     461             :                         gf_odf_avc_cfg_del((cfg));
     462             :                         
     463             :                         dsi = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     464             :                         data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)dsi_data, dsi_data_size);
     465             :                         if (data) {
     466             :                                 CFDictionarySetValue(dsi, CFSTR("avcC"), data);
     467             :                                 CFDictionarySetValue(dec_dsi, kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, dsi);
     468             :                                 CFRelease(data);
     469             :                         }
     470             :                         CFRelease(dsi);
     471             :                 
     472             :                         gf_free(dsi_data);
     473             :                 }
     474             :         break;
     475             : 
     476             :     case GF_CODECID_HEVC:
     477             :                 if (gf_list_count(ctx->SPSs) && gf_list_count(ctx->PPSs) && gf_list_count(ctx->VPSs)) {
     478             :                         s32 idx;
     479             :                         u32 i;
     480             :                         GF_HEVCConfig *cfg;
     481             :                         GF_NALUFFParamArray *vpsa = NULL;
     482             :                         GF_NALUFFParamArray *spsa = NULL;
     483             :                         GF_NALUFFParamArray *ppsa = NULL;
     484             :                         GF_NALUFFParam *vps = NULL;
     485             :                         GF_NALUFFParam *sps = NULL;
     486             :                         GF_NALUFFParam *pps = NULL;
     487             : 
     488             :                         for (i=0; i<gf_list_count(ctx->VPSs); i++) {
     489             :                                 vps = gf_list_get(ctx->VPSs, i);
     490             :                                 if (ctx->active_vps<0) ctx->active_vps = vps->id;
     491             : 
     492             :                                 if (vps->id==ctx->active_vps) break;
     493             :                                 vps = NULL;
     494             :                         }
     495             :                         if (!vps) return GF_NON_COMPLIANT_BITSTREAM;
     496             : 
     497             :                         for (i=0; i<gf_list_count(ctx->SPSs); i++) {
     498             :                                 sps = gf_list_get(ctx->SPSs, i);
     499             :                                 if (ctx->active_sps<0) ctx->active_sps = sps->id;
     500             : 
     501             :                                 if (sps->id==ctx->active_sps) break;
     502             :                                 sps = NULL;
     503             :                         }
     504             :                         if (!sps) return GF_NON_COMPLIANT_BITSTREAM;
     505             :                         for (i=0; i<gf_list_count(ctx->PPSs); i++) {
     506             :                                 pps = gf_list_get(ctx->PPSs, i);
     507             :                                 if (ctx->active_pps<0) ctx->active_pps = pps->id;
     508             : 
     509             :                                 if (pps->id==ctx->active_pps) break;
     510             :                                 pps = NULL;
     511             :                         }
     512             :                         if (!pps) return GF_NON_COMPLIANT_BITSTREAM;
     513             :                         ctx->reconfig_needed = GF_FALSE;
     514             : 
     515             :                         ctx->vtb_type = 'hvc1'; //kCMVideoCodecType_HEVC;
     516             :                         codec_name = "HEVC";
     517             : 
     518             :                         idx = ctx->active_sps;
     519             :                         ctx->width = ctx->hevc.sps[idx].width;
     520             :                         ctx->height = ctx->hevc.sps[idx].height;
     521             :                         if (ctx->hevc.sps[idx].aspect_ratio_info_present_flag && ctx->hevc.sps[idx].sar_width && ctx->hevc.sps[idx].sar_height) {
     522             :                                 ctx->pixel_ar.num = ctx->hevc.sps[idx].sar_width;
     523             :                                 ctx->pixel_ar.den = ctx->hevc.sps[idx].sar_height;
     524             :                         } else {
     525             :                                 ctx->pixel_ar.num = ctx->pixel_ar.den = 1;
     526             :                         }
     527             :                         ctx->chroma_format = ctx->hevc.sps[idx].chroma_format_idc;
     528             :                         ctx->luma_bit_depth = ctx->hevc.sps[idx].bit_depth_luma;
     529             :                         ctx->chroma_bit_depth = ctx->hevc.sps[idx].bit_depth_chroma;
     530             : 
     531             :                         switch (ctx->chroma_format) {
     532             :                         case 2:
     533             :                                 //422 decoding doesn't seem supported ...
     534             :                                 if (ctx->luma_bit_depth>8) {
     535             :                                         kColorSpace = kCVPixelFormatType_422YpCbCr10;
     536             :                                         ctx->pix_fmt = GF_PIXEL_YUV422_10;
     537             :                                 } else {
     538             :                                         kColorSpace = kCVPixelFormatType_422YpCbCr8;
     539             :                                         ctx->pix_fmt = GF_PIXEL_YUV422;
     540             :                                 }
     541             :                                 break;
     542             :                         case 3:
     543             :                                 if (ctx->luma_bit_depth>8) {
     544             :                                         kColorSpace = kCVPixelFormatType_444YpCbCr10;
     545             :                                         ctx->pix_fmt = GF_PIXEL_YUV444_10;
     546             :                                 } else {
     547             :                                         kColorSpace = kCVPixelFormatType_444YpCbCr8;
     548             :                                         ctx->pix_fmt = GF_PIXEL_YUV444;
     549             :                                 }
     550             :                                 break;
     551             :                         default:
     552             :                                 if (ctx->luma_bit_depth>8) {
     553             :                                         kColorSpace = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
     554             :                                         ctx->pix_fmt = GF_PIXEL_NV12;
     555             :                                 }
     556             :                                 break;
     557             :                         }
     558             :                         //always rewrite with current sps and pps
     559             :                         cfg = gf_odf_hevc_cfg_new();
     560             :                         cfg->configurationVersion = 1;
     561             :                         cfg->profile_space = ctx->hevc.sps[idx].ptl.profile_space;
     562             :                         cfg->tier_flag = ctx->hevc.sps[idx].ptl.tier_flag;
     563             :                         cfg->profile_idc = ctx->hevc.sps[idx].ptl.profile_idc;
     564             :                         cfg->general_profile_compatibility_flags = ctx->hevc.sps[idx].ptl.profile_compatibility_flag;
     565             :                         cfg->progressive_source_flag = ctx->hevc.sps[idx].ptl.general_progressive_source_flag;
     566             :                         cfg->interlaced_source_flag = ctx->hevc.sps[idx].ptl.general_interlaced_source_flag;
     567             :                         cfg->non_packed_constraint_flag = ctx->hevc.sps[idx].ptl.general_non_packed_constraint_flag;
     568             :                         cfg->frame_only_constraint_flag = ctx->hevc.sps[idx].ptl.general_frame_only_constraint_flag;
     569             : 
     570             :                         cfg->constraint_indicator_flags = ctx->hevc.sps[idx].ptl.general_reserved_44bits;
     571             :                         cfg->level_idc = ctx->hevc.sps[idx].ptl.level_idc;
     572             : 
     573             :                         cfg->luma_bit_depth = ctx->hevc.sps[idx].bit_depth_luma;
     574             :                         cfg->chroma_bit_depth = ctx->hevc.sps[idx].bit_depth_chroma;
     575             :                         cfg->chromaFormat = ctx->hevc.sps[idx].chroma_format_idc;
     576             :                         cfg->complete_representation = GF_TRUE;
     577             : 
     578             :                         cfg->nal_unit_size = 4;
     579             : 
     580             :                         GF_SAFEALLOC(vpsa, GF_NALUFFParamArray);
     581             :                         if (!vpsa) return GF_OUT_OF_MEM;
     582             :                         vpsa->array_completeness = 1;
     583             :                         vpsa->type = GF_HEVC_NALU_VID_PARAM;
     584             :                         vpsa->nalus = gf_list_new();
     585             :                         gf_list_add(vpsa->nalus, vps);
     586             :                         gf_list_add(cfg->param_array, vpsa);
     587             : 
     588             :                         GF_SAFEALLOC(spsa, GF_NALUFFParamArray);
     589             :                         if (!spsa) return GF_OUT_OF_MEM;
     590             :                         spsa->array_completeness = 1;
     591             :                         spsa->type = GF_HEVC_NALU_SEQ_PARAM;
     592             :                         spsa->nalus = gf_list_new();
     593             :                         gf_list_add(spsa->nalus, sps);
     594             :                         gf_list_add(cfg->param_array, spsa);
     595             : 
     596             :                         GF_SAFEALLOC(ppsa, GF_NALUFFParamArray);
     597             :                         if (!ppsa) return GF_OUT_OF_MEM;
     598             :                         ppsa->array_completeness = 1;
     599             :                         ppsa->type = GF_HEVC_NALU_PIC_PARAM;
     600             :                         //we send all PPS
     601             :                         ppsa->nalus = ctx->PPSs;
     602             : 
     603             :                         gf_list_add(cfg->param_array, ppsa);
     604             : 
     605             :                         gf_odf_hevc_cfg_write(cfg, &dsi_data, &dsi_data_size);
     606             :                         gf_list_reset(vpsa->nalus);
     607             :                         gf_list_reset(spsa->nalus);
     608             :                         ppsa->nalus = NULL;
     609             :                         gf_odf_hevc_cfg_del(cfg);
     610             : 
     611             :                         dsi = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     612             :                         data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)dsi_data, dsi_data_size);
     613             :                         if (data) {
     614             :                                 CFDictionarySetValue(dsi, CFSTR("hvcC"), data);
     615             :                                 CFDictionarySetValue(dec_dsi, kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, dsi);
     616             :                                 CFRelease(data);
     617             :                         }
     618             :                         CFRelease(dsi);
     619             : 
     620             :                         gf_free(dsi_data);
     621             :                 }
     622             :         break;
     623             : 
     624             :         case GF_CODECID_MPEG2_SIMPLE:
     625             :         case GF_CODECID_MPEG2_MAIN:
     626             :         case GF_CODECID_MPEG2_SNR:
     627             :         case GF_CODECID_MPEG2_SPATIAL:
     628             :         case GF_CODECID_MPEG2_HIGH:
     629             :         case GF_CODECID_MPEG2_422:
     630             : 
     631             :         ctx->vtb_type = 'mp2v'; //kCMVideoCodecType_MPEG2Video;
     632             :                 codec_name = "MPEG2";
     633             :                 if (!ctx->width || !ctx->height) {
     634             :                         ctx->init_mpeg12 = GF_TRUE;
     635             :                         return GF_OK;
     636             :                 }
     637             :                 ctx->init_mpeg12 = GF_FALSE;
     638             :                 ctx->reconfig_needed = GF_FALSE;
     639             :         break;
     640             :                 
     641             :         case GF_CODECID_MPEG1:
     642             :                 ctx->vtb_type = 'mp1v'; //kCMVideoCodecType_MPEG1Video;
     643             :                 codec_name = "MPEG1";
     644             :                 if (!ctx->width || !ctx->height) {
     645             :                         ctx->init_mpeg12 = GF_TRUE;
     646             :                         return GF_OK;
     647             :                 }
     648             :                 ctx->init_mpeg12 = GF_FALSE;
     649             :                 ctx->reconfig_needed = GF_FALSE;
     650             :                 break;
     651             :     case GF_CODECID_MPEG4_PART2 :
     652             :         {
     653             :                 char *vosh = NULL;
     654             :                 u32 vosh_size = 0;
     655             :                 ctx->vtb_type = 'mp4v'; //kCMVideoCodecType_MPEG4Video;
     656             :                 codec_name = "MPEG4";
     657             : 
     658             :                 if (!p || !p->value.data.ptr) {
     659             :                         vosh = ctx->vosh;
     660             :                         vosh_size = ctx->vosh_size;
     661             :                 } else {
     662             :                         vosh = p->value.data.ptr;
     663             :                         vosh_size = p->value.data.size;
     664             :                 }
     665             :                 ctx->reconfig_needed = GF_FALSE;
     666             : 
     667             :                 if (vosh) {
     668             :                         GF_M4VDecSpecInfo vcfg;
     669             :                         GF_BitStream *bs;
     670             :                         GF_ESD *esd;
     671             : 
     672             :                         gf_m4v_get_config(vosh, vosh_size, &vcfg);
     673             :                         ctx->width = vcfg.width;
     674             :                         ctx->height = vcfg.height;
     675             :                         esd = gf_odf_desc_esd_new(2);
     676             :                         esd->decoderConfig->decoderSpecificInfo->data = vosh;
     677             :                         esd->decoderConfig->decoderSpecificInfo->dataLength = vosh_size;
     678             :                         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     679             :                         gf_bs_write_u32(bs, 0);
     680             :                         gf_odf_desc_write_bs((GF_Descriptor *) esd, bs);
     681             :                         gf_bs_get_content(bs, &dsi_data, &dsi_data_size);
     682             :                         gf_bs_del(bs);
     683             :                         esd->decoderConfig->decoderSpecificInfo->data = NULL;
     684             :                         esd->decoderConfig->decoderSpecificInfo->dataLength = 0;
     685             :                         gf_odf_desc_del((GF_Descriptor*)esd);
     686             : 
     687             :                         dsi = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     688             :                         data = CFDataCreate(kCFAllocatorDefault, (const UInt8*) dsi_data, dsi_data_size);
     689             :                         gf_free(dsi_data);
     690             :                         
     691             :                         if (data) {
     692             :                                 CFDictionarySetValue(dsi, CFSTR("esds"), data);
     693             :                                 CFDictionarySetValue(dec_dsi, kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms, dsi);
     694             :                                 CFRelease(data);
     695             :                         }
     696             :                         CFRelease(dsi);
     697             :                         
     698             :                         ctx->skip_mpeg4_vosh = GF_FALSE;
     699             :                 } else {
     700             :                         ctx->skip_mpeg4_vosh = GF_TRUE;
     701             :                         return GF_OK;
     702             :                 }
     703             :         break;
     704             :     }
     705             :         case GF_CODECID_H263:
     706             :         case GF_CODECID_S263:
     707             :                 ctx->reorder_probe = 0;
     708             :                 ctx->reconfig_needed = GF_FALSE;
     709             :                 ctx->vtb_type = 'h263'; //kCMVideoCodecType_H263;
     710             :                 codec_name = "H263";
     711             :                 break;
     712             : 
     713             :         case GF_CODECID_AP4X:
     714             :                 ctx->vtb_type = 'ap4x'; //kCMVideoCodecType_AppleProRes4444XQ;
     715             :                 codec_name = "ProRes.AP4X";
     716             :                 break;
     717             :         case GF_CODECID_AP4H:
     718             :                 ctx->vtb_type = 'ap4h'; //kCMVideoCodecType_AppleProRes4444;
     719             :                 codec_name = "ProRes.AP4H";
     720             :                 break;
     721             :         case GF_CODECID_APCH:
     722             :                 ctx->vtb_type = 'apch'; // kCMVideoCodecType_AppleProRes422HQ;
     723             :                 codec_name = "ProRes.APCH";
     724             :                 break;
     725             :         case GF_CODECID_APCN:
     726             :                 ctx->vtb_type = 'apcn'; // kCMVideoCodecType_AppleProRes422;
     727             :                 codec_name = "ProRes.APCN";
     728             :                 break;
     729             :         case GF_CODECID_APCS:
     730             :                 ctx->vtb_type = 'apcs'; // kCMVideoCodecType_AppleProRes422LT;
     731             :                 codec_name = "ProRes.APCS";
     732             :                 break;
     733             :         case GF_CODECID_APCO:
     734             :                 ctx->vtb_type = 'apco'; // kCMVideoCodecType_AppleProRes422Proxy;
     735             :                 codec_name = "ProRes.APCO";
     736             :                 break;
     737             :         default :
     738             :                 ctx->reconfig_needed = GF_FALSE;
     739             :                 return GF_NOT_SUPPORTED;
     740             :     }
     741             :         //not yet ready
     742             :         if (! ctx->width || !ctx->height) return GF_OK;
     743             : 
     744             :     /*status = */CMVideoFormatDescriptionCreate(kCFAllocatorDefault, ctx->vtb_type, ctx->width, ctx->height, dec_dsi, &ctx->fmt_desc);
     745             : 
     746             :     if (!ctx->fmt_desc) {
     747             :                 if (dec_dsi) CFRelease(dec_dsi);
     748             :         return GF_NON_COMPLIANT_BITSTREAM;
     749             :     }
     750             :         buffer_attribs = vtbdec_create_buffer_attributes(ctx, kColorSpace);
     751             :         
     752             :         cbacks.decompressionOutputCallback = vtbdec_on_frame;
     753             :     cbacks.decompressionOutputRefCon   = ctx;
     754             : 
     755             :         status = 1;
     756             :         if (!ctx->disable_hw) {
     757             :                 dec_type = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     758             :                 CFDictionarySetValue(dec_type, kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder, kCFBooleanTrue);
     759             :                 ctx->is_hardware = GF_TRUE;
     760             : 
     761             :                 status = VTDecompressionSessionCreate(NULL, ctx->fmt_desc, dec_type, buffer_attribs, &cbacks, &ctx->vtb_session);
     762             : 
     763             :                 if (dec_type)
     764             :                         CFRelease(dec_type);
     765             :         }
     766             : 
     767             :         //if HW decoder not available or disabled , try soft one
     768             :         if (status) {
     769             :                 status = VTDecompressionSessionCreate(NULL, ctx->fmt_desc, NULL, buffer_attribs, &cbacks, &ctx->vtb_session);
     770             :                 ctx->is_hardware = GF_FALSE;
     771             :         }
     772             :         
     773             :         if (dec_dsi)
     774             :                 CFRelease(dec_dsi);
     775             :     if (buffer_attribs)
     776             :         CFRelease(buffer_attribs);
     777             : 
     778             :     switch (status) {
     779             :     case kVTVideoDecoderNotAvailableNowErr:
     780             :     case kVTVideoDecoderUnsupportedDataFormatErr:
     781             :         return GF_NOT_SUPPORTED;
     782             :     case kVTVideoDecoderMalfunctionErr:
     783             :         return GF_IO_ERR;
     784             :     case kVTVideoDecoderBadDataErr :
     785             :         return GF_NOT_SUPPORTED;
     786             : 
     787             :         case kVTPixelTransferNotSupportedErr:
     788             :         case kVTCouldNotFindVideoDecoderErr:
     789             :                 return GF_NOT_SUPPORTED;
     790             :     case 0:
     791             :         break;
     792             :     default:
     793             :         return GF_SERVICE_ERROR;
     794             :     }
     795             :         
     796             :         //good to go !
     797             :         ctx->stride = ctx->width;
     798             :         if (ctx->pix_fmt == GF_PIXEL_YUV422) {
     799             :                 ctx->out_size = ctx->width*ctx->height*2;
     800             :         } else if (ctx->pix_fmt == GF_PIXEL_YUV444) {
     801             :                 ctx->out_size = ctx->width*ctx->height*3;
     802             :         } else if (ctx->pix_fmt == GF_PIXEL_RGB) {
     803             :                 ctx->out_size = ctx->width*ctx->height*3;
     804             :                 ctx->stride *= 3;
     805             :         } else {
     806             :                 // (ctx->pix_fmt == GF_PIXEL_YUV)
     807             :                 ctx->out_size = ctx->width*ctx->height*3/2;
     808             :         }
     809             :         if (ctx->luma_bit_depth>8) {
     810             :                 ctx->out_size *= 2;
     811             :         }
     812             :         ctx->frame_size_changed = GF_TRUE;
     813             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) );
     814             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->height) );
     815             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->stride) );
     816             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PAR, &PROP_FRAC(ctx->pixel_ar) );
     817             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->pix_fmt) );
     818             :         ctx->profile_supported = GF_FALSE;
     819             :         ctx->can_reconfig = !gf_opts_get_bool("core", "no-reassign");
     820             : 
     821             :         if (codec_name) {
     822             :                 char szName[100];
     823             :                 snprintf(szName, 99, "VTB:%s:%s", ctx->is_hardware ? "Hardware" : "Software", codec_name);
     824             :                 szName[99] = 0;
     825             :                 gf_filter_set_name(filter, szName);
     826             :         }
     827             :         return GF_OK;
     828             : }
     829             : 
     830             : static void vtbdec_register_param_sets(GF_VTBDecCtx *ctx, char *data, u32 size, Bool is_sps, u8 hevc_nal_type)
     831             : {
     832             :         Bool add = GF_TRUE;
     833             :         u32 i, count;
     834             :         s32 ps_id;
     835             :         GF_List *dest = NULL;
     836             : 
     837             :         if (!ctx->ps_bs) ctx->ps_bs = gf_bs_new(data, size, GF_BITSTREAM_READ);
     838             :         else gf_bs_reassign_buffer(ctx->ps_bs, data, size);
     839             : 
     840             :         if (hevc_nal_type) {
     841             : #if !defined(GPAC_DISABLE_HEVC)
     842             :                 if (hevc_nal_type==GF_HEVC_NALU_SEQ_PARAM) {
     843             :                         dest = ctx->SPSs;
     844             :                         ps_id = gf_hevc_read_sps_bs(ctx->ps_bs, &ctx->hevc);
     845             :                         if (ps_id<0) return;
     846             :                 }
     847             :                 else if (hevc_nal_type==GF_HEVC_NALU_PIC_PARAM) {
     848             :                         dest = ctx->PPSs;
     849             :                         ps_id = gf_hevc_read_pps_bs(ctx->ps_bs, &ctx->hevc);
     850             :                         if (ps_id<0) return;
     851             :                 }
     852             :                 else if (hevc_nal_type==GF_HEVC_NALU_VID_PARAM) {
     853             :                         dest = ctx->VPSs;
     854             :                         ps_id = gf_hevc_read_vps_bs(ctx->ps_bs, &ctx->hevc);
     855             :                         if (ps_id<0) return;
     856             :                 }
     857             : #endif //GPAC_DISABLE_HEVC
     858             : 
     859             :         } else {
     860             :                 dest = is_sps ? ctx->SPSs : ctx->PPSs;
     861             : 
     862             :                 if (is_sps) {
     863             :                         ps_id = gf_avc_read_sps_bs(ctx->ps_bs, &ctx->avc, 0, NULL);
     864             :                         if (ps_id<0) return;
     865             :                 } else {
     866             :                         ps_id = gf_avc_read_pps_bs(ctx->ps_bs, &ctx->avc);
     867             :                         if (ps_id<0) return;
     868             :                 }
     869             :         }
     870             :         
     871             :         count = gf_list_count(dest);
     872             :         for (i=0; i<count; i++) {
     873             :                 GF_NALUFFParam *a_slc = gf_list_get(dest, i);
     874             :                 if (a_slc->id != ps_id) continue;
     875             :                 //not same size or different content but same ID, remove old xPS
     876             :                 if ((a_slc->size != size) || memcmp(a_slc->data, data, size) ) {
     877             :                         gf_free(a_slc->data);
     878             :                         gf_free(a_slc);
     879             :                         gf_list_rem(dest, i);
     880             :                         break;
     881             :                 } else {
     882             :                         add = GF_FALSE;
     883             :                 }
     884             :                 break;
     885             :         }
     886             :         if (add) {
     887             :                 GF_NALUFFParam *slc;
     888             :                 GF_SAFEALLOC(slc, GF_NALUFFParam);
     889             :                 if (!slc) return;
     890             :                 slc->data = gf_malloc(size);
     891             :                 if (!slc->data) {
     892             :                         gf_free(slc);
     893             :                         return;
     894             :                 }
     895             :                 memcpy(slc->data, data, size);
     896             :                 slc->size = size;
     897             :                 slc->id = ps_id;
     898             :                 slc->crc = gf_crc_32(data, size);
     899             :                 gf_list_add(dest, slc);
     900             :         }
     901             : }
     902             : 
     903             : static u32 vtbdec_purge_param_sets(GF_VTBDecCtx *ctx, Bool is_sps, s32 idx)
     904             : {
     905             :         u32 i, j, count, crc_res = 0;
     906             :         GF_List *dest = is_sps ? ctx->SPSs : ctx->PPSs;
     907             : 
     908             :         //remove all xPS sharing the same ID, use only the last occurence
     909             :         count = gf_list_count(dest);
     910             :         for (i=0; i<count; i++) {
     911             :                 GF_NALUFFParam *slc = gf_list_get(dest, i);
     912             :                 if (slc->id != idx) continue;
     913             :                 crc_res = slc->crc;
     914             : 
     915             :                 for (j=i+1; j<count; j++) {
     916             :                         GF_NALUFFParam *a_slc = gf_list_get(dest, j);
     917             :                         if (a_slc->id != slc->id) continue;
     918             :                         //not same size or different content but same ID, remove old xPS
     919             :                         if ((slc->size != a_slc->size) || memcmp(a_slc->data, slc->data, a_slc->size) ) {
     920             :                                 crc_res = a_slc->crc;
     921             :                                 gf_free(slc->data);
     922             :                                 gf_free(slc);
     923             :                                 gf_list_rem(dest, i);
     924             :                                 i--;
     925             :                                 count--;
     926             :                                 break;
     927             :                         }
     928             :                 }
     929             :         }
     930             :         return crc_res;
     931             : }
     932             : 
     933             : static void vtbdec_del_param_list(GF_List *list)
     934             : {
     935             :         while (gf_list_count(list)) {
     936             :                 GF_NALUFFParam *slc = gf_list_get(list, 0);
     937             :                 gf_free(slc->data);
     938             :                 gf_free(slc);
     939             :                 gf_list_rem(list, 0);
     940             :         }
     941             :         gf_list_del(list);
     942             : }
     943             : 
     944             : static GF_Err vtbdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     945             : {
     946             :         const GF_PropertyValue *p, *dsi;
     947             :         u32 codecid, dsi_crc;
     948             :         GF_Err e;
     949             :         GF_FilterPid *base_pid = NULL;
     950             :         GF_VTBDecCtx *ctx = gf_filter_get_udta(filter);
     951             : 
     952             :         if (is_remove) {
     953             :                 if (ctx->opid) {
     954             :                         gf_filter_pid_remove(ctx->opid);
     955             :                         ctx->opid = NULL;
     956             :                 }
     957             :                 gf_list_del_item(ctx->streams, pid);
     958             :                 return GF_OK;
     959             :         }
     960             :         if (! gf_filter_pid_check_caps(pid)) {
     961             :                 while (gf_list_count(ctx->frames)) {
     962             :                         vtbdec_flush_frame(filter, ctx);
     963             :                 }
     964             :                 return GF_NOT_SUPPORTED;
     965             :         }
     966             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
     967             :         if (!p) {
     968             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTBDec] Missing codecid, cannot initialize\n"));
     969             :                 return GF_NOT_SUPPORTED;
     970             :         }
     971             :         codecid = p->value.uint;
     972             : 
     973             :         base_pid = gf_list_get(ctx->streams, 0);
     974             :         p = gf_filter_pid_get_property(pid, GF_PROP_PID_DEPENDENCY_ID);
     975             :         if (!p && base_pid && (base_pid != pid)) return GF_REQUIRES_NEW_INSTANCE;
     976             :         else if (p) {
     977             :                 u32 i;
     978             :                 u32 base_idx_plus_one = 0;
     979             : 
     980             :                 if (ctx->codecid != GF_CODECID_HEVC) return GF_REQUIRES_NEW_INSTANCE;
     981             : 
     982             :                 for (i=0; i<gf_list_count(ctx->streams); i++) {
     983             :                         GF_FilterPid *ipid = gf_list_get(ctx->streams, i);
     984             :                         const GF_PropertyValue *p_dep;
     985             :                         if (ipid==pid) continue;
     986             : 
     987             :                         p_dep = gf_filter_pid_get_property(ipid, GF_PROP_PID_ID);
     988             :                         if (p_dep && p_dep->value.uint == p->value.uint) {
     989             :                                 base_idx_plus_one = i+1;
     990             :                                 break;
     991             :                         }
     992             :                 }
     993             :                 if (!base_idx_plus_one) return GF_REQUIRES_NEW_INSTANCE;
     994             : 
     995             :                 //no support for L-HEVC
     996             :                 if (codecid != GF_CODECID_HEVC) return GF_NOT_SUPPORTED;
     997             :                 if (gf_list_find(ctx->streams, pid) < 0) {
     998             :                         gf_list_insert(ctx->streams, pid, base_idx_plus_one);
     999             :                 }
    1000             :                 //no configure for temporal enhancements
    1001             :                 p = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
    1002             :                 if (ctx->opid && p) gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_FPS, p);
    1003             :                 return GF_OK;
    1004             :         }
    1005             : 
    1006             : 
    1007             :         dsi = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
    1008             :         dsi_crc = dsi ? gf_crc_32(dsi->value.data.ptr, dsi->value.data.size) : 0;
    1009             :         if ((codecid==ctx->codecid) && (dsi_crc == ctx->cfg_crc) && ctx->width && ctx->height) {
    1010             :                 gf_filter_pid_copy_properties(ctx->opid, pid);
    1011             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
    1012             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL);
    1013             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, NULL);
    1014             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) );
    1015             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->height) );
    1016             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT(ctx->stride) );
    1017             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PAR, &PROP_FRAC(ctx->pixel_ar) );
    1018             :                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->pix_fmt) );
    1019             :                 return GF_OK;
    1020             :         }
    1021             :         //need a reset !
    1022             :         if (ctx->vtb_session) {
    1023             :                 //flush all pending frames and mark reconfigure as pending
    1024             :                 ctx->reconfig_needed = GF_TRUE;
    1025             :                 while (gf_list_count(ctx->frames)) {
    1026             :                         vtbdec_flush_frame(filter, ctx);
    1027             :                 }
    1028             :         }
    1029             :         if (gf_list_find(ctx->streams, pid) < 0) {
    1030             :                 gf_list_insert(ctx->streams, pid, 0);
    1031             :         }
    1032             :         ctx->cfg_crc = dsi_crc;
    1033             :         ctx->codecid = codecid;
    1034             :         gf_filter_set_max_extra_input_pids(filter, (codecid==GF_CODECID_HEVC) ? 5 : 0);
    1035             : 
    1036             :         if (!ctx->opid) {
    1037             :                 ctx->opid = gf_filter_pid_new(filter);
    1038             :                 gf_filter_pid_set_framing_mode(pid, GF_TRUE);
    1039             :         }
    1040             : 
    1041             :         //copy properties at init or reconfig
    1042             :         gf_filter_pid_copy_properties(ctx->opid, pid);
    1043             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
    1044             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL);
    1045             :         gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, NULL);
    1046             : 
    1047             :         ctx->nalu_size_length = 0;
    1048             :         ctx->is_annex_b = GF_FALSE;
    1049             : 
    1050             :         //check AVC config
    1051             :         if (codecid==GF_CODECID_AVC) {
    1052             : 
    1053             :                 if (ctx->SPSs) vtbdec_del_param_list(ctx->SPSs);
    1054             :                 ctx->SPSs = gf_list_new();
    1055             :                 if (ctx->PPSs) vtbdec_del_param_list(ctx->PPSs);
    1056             :                 ctx->PPSs = gf_list_new();
    1057             : 
    1058             :                 ctx->is_avc = GF_TRUE;
    1059             :                 ctx->check_h264_isma = GF_TRUE;
    1060             : 
    1061             :                 ctx->avc.sps_active_idx = ctx->avc.pps_active_idx = -1;
    1062             :                 ctx->active_sps = ctx->active_pps = -1;
    1063             :                 ctx->active_sps_crc = ctx->active_pps_crc = 0;
    1064             : 
    1065             :                 if (!dsi || !dsi->value.data.ptr) {
    1066             :                         ctx->is_annex_b = GF_TRUE;
    1067             :                         ctx->width=ctx->height=128;
    1068             :                         ctx->out_size = ctx->width*ctx->height*3/2;
    1069             :                         ctx->pix_fmt = GF_PIXEL_YUV;
    1070             :                         return GF_OK;
    1071             :                 } else {
    1072             :                         u32 i;
    1073             :                         GF_NALUFFParam *slc;
    1074             :                         GF_AVCConfig *cfg = gf_odf_avc_cfg_read(dsi->value.data.ptr, dsi->value.data.size);
    1075             :                         for (i=0; i<gf_list_count(cfg->sequenceParameterSets); i++) {
    1076             :                                 slc = gf_list_get(cfg->sequenceParameterSets, i);
    1077             :                                 slc->id = -1;
    1078             :                                 vtbdec_register_param_sets(ctx, slc->data, slc->size, GF_TRUE, 0);
    1079             :                         }
    1080             : 
    1081             :                         for (i=0; i<gf_list_count(cfg->pictureParameterSets); i++) {
    1082             :                                 slc = gf_list_get(cfg->pictureParameterSets, i);
    1083             :                                 slc->id = -1;
    1084             :                                 vtbdec_register_param_sets(ctx, slc->data, slc->size, GF_FALSE, 0);
    1085             :                         }
    1086             : 
    1087             :                         slc = gf_list_get(ctx->SPSs, 0);
    1088             :                         if (slc) {
    1089             :                                 ctx->active_sps = slc->id;
    1090             :                                 ctx->active_sps_crc = gf_crc_32(slc->data, slc->size);
    1091             :                         }
    1092             : 
    1093             :                         slc = gf_list_get(ctx->PPSs, 0);
    1094             :                         if (slc) {
    1095             :                                 ctx->active_pps = slc->id;
    1096             :                                 ctx->active_pps_crc = gf_crc_32(slc->data, slc->size);
    1097             :                         }
    1098             : 
    1099             :                         ctx->nalu_size_length = cfg->nal_unit_size;
    1100             :                         if (gf_list_count(ctx->SPSs) && gf_list_count(ctx->PPSs) && !ctx->reconfig_needed ) {
    1101             :                                 e = vtbdec_init_decoder(filter, ctx);
    1102             :                         } else {
    1103             :                                 e = GF_OK;
    1104             :                         }
    1105             :                         gf_odf_avc_cfg_del(cfg);
    1106             : 
    1107             :                         if (ctx->avc.sps[ctx->active_sps].vui_parameters_present_flag) {
    1108             :                                 Bool full_range = ctx->avc.sps[ctx->active_sps].vui.video_full_range_flag;
    1109             :                                 u32 cmx = ctx->avc.sps[ctx->active_sps].vui.matrix_coefficients;
    1110             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, &PROP_BOOL(full_range));
    1111             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, &PROP_UINT(cmx));
    1112             :                         } else {
    1113             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, NULL);
    1114             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, NULL);
    1115             :                         }
    1116             :                         return e;
    1117             :                 }
    1118             :         }
    1119             : 
    1120             :         //check HEVC config
    1121             :         if (codecid==GF_CODECID_HEVC) {
    1122             :                 if (ctx->SPSs) vtbdec_del_param_list(ctx->SPSs);
    1123             :                 ctx->SPSs = gf_list_new();
    1124             :                 if (ctx->SPSs) vtbdec_del_param_list(ctx->PPSs);
    1125             :                 ctx->PPSs = gf_list_new();
    1126             :                 if (ctx->SPSs) vtbdec_del_param_list(ctx->VPSs);
    1127             :                 ctx->VPSs = gf_list_new();
    1128             :                 ctx->is_hevc = GF_TRUE;
    1129             : 
    1130             :                 ctx->hevc.sps_active_idx = -1;
    1131             :                 ctx->active_sps = ctx->active_pps = ctx->active_vps = -1;
    1132             : 
    1133             :                 if (!dsi || !dsi->value.data.ptr) {
    1134             :                         ctx->is_annex_b = GF_TRUE;
    1135             :                         ctx->width=ctx->height=128;
    1136             :                         ctx->out_size = ctx->width*ctx->height*3/2;
    1137             :                         ctx->pix_fmt = GF_PIXEL_YUV;
    1138             :                         return GF_OK;
    1139             :                 } else {
    1140             :                         u32 i, j;
    1141             :                         GF_NALUFFParam *slc;
    1142             :                         GF_HEVCConfig *cfg = gf_odf_hevc_cfg_read(dsi->value.data.ptr, dsi->value.data.size, GF_FALSE);
    1143             : 
    1144             :                         for (i=0; i<gf_list_count(cfg->param_array); i++) {
    1145             :                                 GF_NALUFFParamArray *pa = gf_list_get(cfg->param_array, i);
    1146             : 
    1147             : 
    1148             :                                 for (j=0; j<gf_list_count(pa->nalus); j++) {
    1149             :                                         slc = gf_list_get(pa->nalus, j);
    1150             :                                         slc->id = -1;
    1151             : 
    1152             :                                         vtbdec_register_param_sets(ctx, slc->data, slc->size, GF_FALSE, pa->type);
    1153             :                                 }
    1154             :                         }
    1155             : 
    1156             :                         slc = gf_list_get(ctx->SPSs, 0);
    1157             :                         if (slc) ctx->active_sps = slc->id;
    1158             : 
    1159             :                         slc = gf_list_get(ctx->PPSs, 0);
    1160             :                         if (slc) ctx->active_pps = slc->id;
    1161             : 
    1162             :                         slc = gf_list_get(ctx->VPSs, 0);
    1163             :                         if (slc) ctx->active_vps = slc->id;
    1164             : 
    1165             :                         ctx->nalu_size_length = cfg->nal_unit_size;
    1166             :                         if (gf_list_count(ctx->SPSs) && gf_list_count(ctx->PPSs)  && gf_list_count(ctx->VPSs)  && !ctx->reconfig_needed) {
    1167             :                                 e = vtbdec_init_decoder(filter, ctx);
    1168             :                         } else {
    1169             :                                 e = GF_OK;
    1170             :                         }
    1171             :                         gf_odf_hevc_cfg_del(cfg);
    1172             : 
    1173             :                         if (ctx->hevc.sps[ctx->active_sps].vui_parameters_present_flag) {
    1174             :                                 Bool full_range = ctx->hevc.sps[ctx->active_sps].video_full_range_flag;
    1175             :                                 u32 cmx = ctx->hevc.sps[ctx->active_sps].matrix_coeffs;
    1176             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, &PROP_BOOL(full_range));
    1177             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, &PROP_UINT(cmx));
    1178             :                         } else {
    1179             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, NULL);
    1180             :                                 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_MX, NULL);
    1181             :                         }
    1182             :                         return e;
    1183             :                 }
    1184             :         }
    1185             : 
    1186             :         if (ctx->vtb_session) {
    1187             :                 assert(ctx->reconfig_needed);
    1188             :                 return GF_OK;
    1189             :         }
    1190             : 
    1191             :         //check VOSH config
    1192             :         if (codecid==GF_CODECID_MPEG4_PART2) {
    1193             :                 if (!dsi || !dsi->value.data.ptr) {
    1194             :                         ctx->width=ctx->height=128;
    1195             :                         ctx->out_size = ctx->width*ctx->height*3/2;
    1196             :                         ctx->pix_fmt = GF_PIXEL_YUV;
    1197             :                 } else {
    1198             :                         return vtbdec_init_decoder(filter, ctx);
    1199             :                 }
    1200             :         }
    1201             : 
    1202             :         return vtbdec_init_decoder(filter, ctx);
    1203             : }
    1204             : 
    1205             : 
    1206             : static void vtbdec_delete_decoder(GF_VTBDecCtx *ctx)
    1207             : {
    1208             :         if (ctx->fmt_desc) {
    1209             :                 CFRelease(ctx->fmt_desc);
    1210             :                 ctx->fmt_desc = NULL;
    1211             :         }
    1212             :         if (ctx->vtb_session) {
    1213             :                 VTDecompressionSessionInvalidate(ctx->vtb_session);
    1214             :                 ctx->vtb_session=NULL;
    1215             :         }
    1216             :         vtbdec_del_param_list(ctx->SPSs);
    1217             :         ctx->SPSs = NULL;
    1218             :         vtbdec_del_param_list(ctx->PPSs);
    1219             :         ctx->PPSs = NULL;
    1220             :         vtbdec_del_param_list(ctx->VPSs);
    1221             :         ctx->VPSs = NULL;
    1222             : }
    1223             : 
    1224             : static GF_Err vtbdec_parse_nal_units(GF_Filter *filter, GF_VTBDecCtx *ctx, char *inBuffer, u32 inBufferLength, char **out_buffer, u32 *out_size)
    1225             : {
    1226             :         u32 i, sc_size=0;
    1227             :         char *ptr = inBuffer;
    1228             :         u32 nal_size;
    1229             :         GF_Err e = GF_OK;
    1230             :         Bool reassign_bs = GF_TRUE;
    1231             :         Bool check_reconfig = GF_FALSE;
    1232             : 
    1233             :         if (out_buffer) {
    1234             :                 *out_buffer = NULL;
    1235             :                 *out_size = 0;
    1236             :         }
    1237             :         
    1238             :         if (!ctx->nalu_size_length) {
    1239             :                 nal_size = gf_media_nalu_next_start_code((u8 *) inBuffer, inBufferLength, &sc_size);
    1240             :                 if (!sc_size) return GF_NON_COMPLIANT_BITSTREAM;
    1241             :                 ptr += nal_size + sc_size;
    1242             :                 assert(inBufferLength >= nal_size + sc_size);
    1243             :                 inBufferLength -= nal_size + sc_size;
    1244             :         }
    1245             :         
    1246             :         while (inBufferLength) {
    1247             :                 Bool add_nal = GF_TRUE;
    1248             :                 u8 nal_type, nal_hdr;
    1249             : 
    1250             :                 if (ctx->nalu_size_length) {
    1251             :                         nal_size = 0;
    1252             :                         for (i=0; i<ctx->nalu_size_length; i++) {
    1253             :                                 nal_size = (nal_size<<8) + ((u8) ptr[i]);
    1254             :                         }
    1255             : 
    1256             :                         if (nal_size > inBufferLength) {
    1257             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error parsing NAL: size indicated %u but %u bytes only in payload\n", nal_size, inBufferLength));
    1258             :                                 break;
    1259             :                         }
    1260             :                         ptr += ctx->nalu_size_length;
    1261             :                 } else {
    1262             :                         nal_size = gf_media_nalu_next_start_code((const u8 *) ptr, inBufferLength, &sc_size);
    1263             :                 }
    1264             : 
    1265             :         if (nal_size==0) {
    1266             :             GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error parsing NAL: size 0 shall never happen\n", nal_size));
    1267             : 
    1268             :             if (ctx->nalu_size_length) {
    1269             :                 if (inBufferLength < ctx->nalu_size_length) break;
    1270             :                 inBufferLength -= ctx->nalu_size_length;
    1271             :             } else {
    1272             :                 if (!sc_size || (inBufferLength < sc_size)) break;
    1273             :                 inBufferLength -= sc_size;
    1274             :                 ptr += sc_size;
    1275             :             }
    1276             :             continue;
    1277             :         }
    1278             :         
    1279             :                 if (ctx->is_avc) {
    1280             :                         if (!ctx->nal_bs) ctx->nal_bs = gf_bs_new(ptr, nal_size, GF_BITSTREAM_READ);
    1281             :                         else gf_bs_reassign_buffer(ctx->nal_bs, ptr, nal_size);
    1282             : 
    1283             :                         nal_hdr = ptr[0];
    1284             :                         nal_type = nal_hdr & 0x1F;
    1285             :                         switch (nal_type) {
    1286             :                         case GF_AVC_NALU_SEQ_PARAM:
    1287             :                                 vtbdec_register_param_sets(ctx, ptr, nal_size, GF_TRUE, 0);
    1288             :                                 add_nal = GF_FALSE;
    1289             :                                 break;
    1290             :                         case GF_AVC_NALU_PIC_PARAM:
    1291             :                                 vtbdec_register_param_sets(ctx, ptr, nal_size, GF_FALSE, 0);
    1292             :                                 add_nal = GF_FALSE;
    1293             :                                 break;
    1294             :                         case GF_AVC_NALU_ACCESS_UNIT:
    1295             :                         case GF_AVC_NALU_END_OF_SEQ:
    1296             :                         case GF_AVC_NALU_END_OF_STREAM:
    1297             :                         case GF_AVC_NALU_FILLER_DATA:
    1298             :                                 add_nal = GF_FALSE;
    1299             :                                 break;
    1300             :                         default:
    1301             :                                 break;
    1302             :                         }
    1303             : 
    1304             :                         gf_avc_parse_nalu(ctx->nal_bs, &ctx->avc);
    1305             : 
    1306             :                         if ((nal_type<=GF_AVC_NALU_IDR_SLICE) && ctx->avc.s_info.sps) {
    1307             :                                 if (ctx->avc.sps_active_idx != ctx->active_sps) {
    1308             :                                         ctx->reconfig_needed = 1;
    1309             :                                         ctx->active_sps = ctx->avc.sps_active_idx;
    1310             :                                         ctx->active_pps = ctx->avc.s_info.pps->id;
    1311             :                                         return GF_OK;
    1312             :                                 }
    1313             :                         }
    1314             :                 } else if (ctx->is_hevc) {
    1315             : #if defined(GPAC_DISABLE_HEVC)
    1316             :                         return GF_NOT_SUPPORTED;
    1317             : #else
    1318             :                         u8 temporal_id, ayer_id;
    1319             : 
    1320             :                         if (!ctx->nal_bs) ctx->nal_bs = gf_bs_new(ptr, nal_size, GF_BITSTREAM_READ);
    1321             :                         else gf_bs_reassign_buffer(ctx->nal_bs, ptr, nal_size);
    1322             : 
    1323             :                         s32 res = gf_hevc_parse_nalu_bs(ctx->nal_bs, &ctx->hevc, &nal_type, &temporal_id, &ayer_id);
    1324             :                         if (res>=0) {
    1325             :                                 switch (nal_type) {
    1326             :                                 case GF_HEVC_NALU_VID_PARAM:
    1327             :                                 case GF_HEVC_NALU_SEQ_PARAM:
    1328             :                                 case GF_HEVC_NALU_PIC_PARAM:
    1329             :                                         vtbdec_register_param_sets(ctx, ptr, nal_size, GF_FALSE, nal_type);
    1330             :                                         add_nal = GF_FALSE;
    1331             :                                         break;
    1332             :                                 case GF_HEVC_NALU_ACCESS_UNIT:
    1333             :                                 case GF_HEVC_NALU_END_OF_SEQ:
    1334             :                                 case GF_HEVC_NALU_END_OF_STREAM:
    1335             :                                 case GF_HEVC_NALU_FILLER_DATA:
    1336             :                                         add_nal = GF_FALSE;
    1337             :                                         break;
    1338             :                                 default:
    1339             :                                         break;
    1340             :                                 }
    1341             : 
    1342             :                                 if ((nal_type<=GF_HEVC_NALU_SLICE_CRA) && ctx->hevc.s_info.sps) {
    1343             :                                         if (ctx->hevc.sps_active_idx != ctx->active_sps) {
    1344             :                                                 ctx->reconfig_needed = 1;
    1345             :                                                 ctx->active_sps = ctx->hevc.sps_active_idx;
    1346             :                                                 ctx->active_pps = ctx->hevc.s_info.pps->id;
    1347             :                                                 ctx->active_vps = ctx->hevc.s_info.sps->vps_id;
    1348             :                                                 return GF_OK;
    1349             :                                         }
    1350             :                                 }
    1351             :                         }
    1352             : #endif
    1353             : 
    1354             :                 }
    1355             :                 
    1356             :                 //if sps and pps are ready, init decoder
    1357             :                 if (!ctx->vtb_session && gf_list_count(ctx->SPSs) && gf_list_count(ctx->PPSs) ) {
    1358             :                         e = vtbdec_init_decoder(filter, ctx);
    1359             :                         if (e) {
    1360             :                                 return e;
    1361             :                         }
    1362             :                 }
    1363             :                 
    1364             :                 if (!out_buffer) add_nal = GF_FALSE;
    1365             :                 else if (add_nal && !ctx->vtb_session) add_nal = GF_FALSE;
    1366             : 
    1367             :                 if (add_nal) {
    1368             :                         if (reassign_bs) {
    1369             :                                 if (!ctx->nalu_rewrite_bs) ctx->nalu_rewrite_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1370             :                                 else {
    1371             :                                         gf_bs_reassign_buffer(ctx->nalu_rewrite_bs, ctx->nalu_buffer, ctx->nalu_buffer_alloc);
    1372             :                                         //detach from context until we get the output of the bistream
    1373             :                                         ctx->nalu_buffer = NULL;
    1374             :                                         ctx->nalu_buffer_alloc = 0;
    1375             :                                 }
    1376             :                                 reassign_bs = GF_FALSE;
    1377             :                         }
    1378             :                         
    1379             :                         gf_bs_write_u32(ctx->nalu_rewrite_bs, nal_size);
    1380             :                         gf_bs_write_data(ctx->nalu_rewrite_bs, ptr, nal_size);
    1381             :                 }
    1382             :                 
    1383             :                 ptr += nal_size;
    1384             :                 if (ctx->nalu_size_length) {
    1385             :                         if (inBufferLength < nal_size + ctx->nalu_size_length) break;
    1386             :                         inBufferLength -= nal_size + ctx->nalu_size_length;
    1387             :                 } else {
    1388             :                         if (!sc_size || (inBufferLength < nal_size + sc_size)) break;
    1389             :                         inBufferLength -= nal_size + sc_size;
    1390             :                         ptr += sc_size;
    1391             :                 }
    1392             :         }
    1393             : 
    1394             :         if (check_reconfig && ctx->avc.s_info.pps ) {
    1395             :                 u32 sps_crc, pps_crc;
    1396             :                 sps_crc = vtbdec_purge_param_sets(ctx, GF_TRUE, ctx->avc.s_info.pps->sps_id);
    1397             :                 pps_crc = vtbdec_purge_param_sets(ctx, GF_FALSE, ctx->avc.s_info.pps->id);
    1398             : 
    1399             :                 if ((sps_crc != ctx->active_sps_crc) || (pps_crc != ctx->active_pps_crc) ) {
    1400             :                         ctx->reconfig_needed = 1;
    1401             :                         ctx->active_sps = ctx->avc.s_info.pps->sps_id;
    1402             :                         ctx->active_pps = ctx->avc.s_info.pps->id;
    1403             :                         ctx->active_sps_crc = sps_crc;
    1404             :                         ctx->active_pps_crc = pps_crc;
    1405             :                 }
    1406             :         }
    1407             : 
    1408             :         if (!reassign_bs) {
    1409             :                 //get output without truncating the allocated buffer, repass the buffer at the next AU
    1410             :                 gf_bs_get_content_no_truncate(ctx->nalu_rewrite_bs, &ctx->nalu_buffer, out_size, &ctx->nalu_buffer_alloc);
    1411             :                 *out_buffer = ctx->nalu_buffer;
    1412             :         }
    1413             :         return e;
    1414             : }
    1415             : 
    1416             : 
    1417             : static GF_Err vtbdec_send_output_frame(GF_Filter *filter, GF_VTBDecCtx *ctx);
    1418             : 
    1419             : static GF_Err vtbdec_flush_frame(GF_Filter *filter, GF_VTBDecCtx *ctx)
    1420             : {
    1421             :         GF_VTBHWFrame *vtbframe;
    1422             :     OSStatus status;
    1423             :         OSType type;
    1424             : 
    1425             :         if (ctx->no_copy) return vtbdec_send_output_frame(filter, ctx);
    1426             : 
    1427             :         vtbframe = gf_list_pop_front(ctx->frames);
    1428             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[VTB] Outputting frame DTS "LLU" CTS "LLU" timescale %d\n", gf_filter_pck_get_dts(vtbframe->pck_src), gf_filter_pck_get_cts(vtbframe->pck_src), gf_filter_pck_get_timescale(vtbframe->pck_src)));
    1429             : 
    1430             : 
    1431             :         status = CVPixelBufferLockBaseAddress(vtbframe->frame, kCVPixelBufferLock_ReadOnly);
    1432             :     if (status != kCVReturnSuccess) {
    1433             :         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error locking frame data\n"));
    1434             :                 gf_list_add(ctx->frames_res, vtbframe);
    1435             :         return GF_IO_ERR;
    1436             :     }
    1437             : 
    1438             :         type = CVPixelBufferGetPixelFormatType(vtbframe->frame);
    1439             : 
    1440             :         if ((type==kCVPixelFormatType_420YpCbCr8Planar)
    1441             :                 || (type==kCVPixelFormatType_420YpCbCr8PlanarFullRange)
    1442             :                 || (type==kCVPixelFormatType_422YpCbCr8_yuvs)
    1443             :                 || (type==kCVPixelFormatType_444YpCbCr8)
    1444             :                 || (type=='444v')
    1445             :                 || (type==kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)
    1446             :                 || (type==kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)
    1447             :         ) {
    1448             :         u32 i, j, nb_planes = (u32) CVPixelBufferGetPlaneCount(vtbframe->frame);
    1449             :                 u8 *dst;
    1450             :                 u32 stride = (u32) CVPixelBufferGetBytesPerRowOfPlane(vtbframe->frame, 0);
    1451             : 
    1452             :                 GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->out_size, &dst);
    1453             :                 if (!dst_pck) return GF_OUT_OF_MEM;
    1454             : 
    1455             :                 //TOCHECK - for now the 3 planes are consecutive in VideoToolbox
    1456             :                 if (stride==ctx->width) {
    1457             :                         char *data = CVPixelBufferGetBaseAddressOfPlane(vtbframe->frame, 0);
    1458             :                         memcpy(dst, data, sizeof(char)*ctx->out_size);
    1459             :                 } else {
    1460             :                         for (i=0; i<nb_planes; i++) {
    1461             :                                 char *data = CVPixelBufferGetBaseAddressOfPlane(vtbframe->frame, i);
    1462             :                                 u32 stride = (u32) CVPixelBufferGetBytesPerRowOfPlane(vtbframe->frame, i);
    1463             :                                 u32 w, h = (u32) CVPixelBufferGetHeightOfPlane(vtbframe->frame, i);
    1464             :                                 w = ctx->width;
    1465             :                                 if (i) {
    1466             :                                         switch (ctx->pix_fmt) {
    1467             :                                         case GF_PIXEL_YUV444:
    1468             :                                                 break;
    1469             :                                         case GF_PIXEL_YUV422:
    1470             :                                         case GF_PIXEL_YUV:
    1471             :                                                 w /= 2;
    1472             :                                                 break;
    1473             :                                         }
    1474             :                                 }
    1475             :                                 if (stride != w) {
    1476             :                                         for (j=0; j<h; j++) {
    1477             :                                                 memcpy(dst, data, sizeof(char)*w);
    1478             :                                                 dst += w;
    1479             :                                                 data += stride;
    1480             :                                         }
    1481             :                                 } else {
    1482             :                                         memcpy(dst, data, sizeof(char)*h*stride);
    1483             :                                         dst += sizeof(char)*h*stride;
    1484             :                                 }
    1485             :                         }
    1486             :                 }
    1487             : 
    1488             :                 gf_filter_pck_merge_properties(vtbframe->pck_src, dst_pck);
    1489             :                 ctx->last_cts_out = gf_filter_pck_get_cts(vtbframe->pck_src);
    1490             :                 ctx->last_timescale_out = gf_filter_pck_get_timescale(vtbframe->pck_src);
    1491             :                 gf_filter_pck_unref(vtbframe->pck_src);
    1492             :                 vtbframe->pck_src = NULL;
    1493             :                 gf_filter_pck_send(dst_pck);
    1494             :         }
    1495             :     CVPixelBufferUnlockBaseAddress(vtbframe->frame, kCVPixelBufferLock_ReadOnly);
    1496             :         gf_list_add(ctx->frames_res, vtbframe);
    1497             :         return GF_OK;
    1498             : }
    1499             : static GF_Err vtbdec_process(GF_Filter *filter)
    1500             : {
    1501             :     OSStatus status;
    1502             :     CMSampleBufferRef sample = NULL;
    1503             :     CMBlockBufferRef block_buffer = NULL;
    1504             :         char *in_data=NULL;
    1505             :         u32 in_data_size;
    1506             :         char *in_buffer;
    1507             :         u32 in_buffer_size, frames_count, i, count, nb_eos;
    1508             :         u64 min_dts;
    1509             :         GF_Err e;
    1510             :         GF_VTBDecCtx *ctx = gf_filter_get_udta(filter);
    1511             :         GF_FilterPacket *pck;
    1512             :         GF_FilterPid *ref_pid = NULL;
    1513             : 
    1514             :         //figure out min DTS
    1515             :         count = gf_list_count(ctx->streams);
    1516             :         nb_eos = 0;
    1517             :         min_dts = 0;
    1518             :         for (i=0; i<count; i++) {
    1519             :                 u64 dts;
    1520             :                 GF_FilterPid *pid = gf_list_get(ctx->streams, i);
    1521             : 
    1522             :                 pck = gf_filter_pid_get_packet(pid);
    1523             :                 if (!pck) {
    1524             :                         if (gf_filter_pid_is_eos(pid)) {
    1525             :                                 nb_eos++;
    1526             :                                 continue;
    1527             :                         } else {
    1528             :                                 return GF_OK;
    1529             :                         }
    1530             :                 }
    1531             :                 dts = gf_filter_pck_get_dts(pck);
    1532             :                 dts *= 1000;
    1533             :                 dts /= gf_filter_pck_get_timescale(pck);
    1534             :                 if (!min_dts || (min_dts>dts)) {
    1535             :                         min_dts = dts;
    1536             :                         ref_pid = pid;
    1537             :                 }
    1538             :         }
    1539             : 
    1540             :         if (nb_eos==count) {
    1541             :                 while (gf_list_count(ctx->frames)) {
    1542             :                         vtbdec_flush_frame(filter, ctx);
    1543             :                 }
    1544             :                 gf_filter_pid_set_eos(ctx->opid);
    1545             :                 return GF_EOS;
    1546             :         }
    1547             :         assert(ref_pid);
    1548             :         pck = gf_filter_pid_get_packet(ref_pid);
    1549             :         assert(pck);
    1550             : 
    1551             :         if (ctx->drop_non_refs && !gf_filter_pck_get_sap(pck)) {
    1552             :                 gf_filter_pid_drop_packet(ref_pid);
    1553             :                 return GF_OK;
    1554             :         }
    1555             : 
    1556             :         in_buffer = (char *) gf_filter_pck_get_data(pck, &in_buffer_size);
    1557             : 
    1558             :         //discard empty packets
    1559             :         if (!in_buffer || !in_buffer_size) {
    1560             :                 gf_filter_pid_drop_packet(ref_pid);
    1561             :                 //if inbuffer is null this is a hardware frame, should never happen
    1562             :                 return in_buffer ? GF_OK : GF_NOT_SUPPORTED;
    1563             :         }
    1564             : 
    1565             :         if (ctx->skip_mpeg4_vosh) {
    1566             :                 GF_M4VDecSpecInfo dsi;
    1567             :                 dsi.width = dsi.height = 0;
    1568             :                 e = gf_m4v_get_config(in_buffer, in_buffer_size, &dsi);
    1569             :                 //found a vosh - remove it from payload, init decoder if needed
    1570             :                 if ((e==GF_OK) && dsi.width && dsi.height) {
    1571             :                         if (!ctx->vtb_session) {
    1572             :                                 ctx->vosh = in_buffer;
    1573             :                                 ctx->vosh_size = dsi.next_object_start;
    1574             :                                 e = vtbdec_init_decoder(filter, ctx);
    1575             :                                 if (e) {
    1576             :                                         gf_filter_pid_drop_packet(ref_pid);
    1577             :                                         return e;
    1578             :                                 }
    1579             : 
    1580             :                                 //enfoce removal for all frames
    1581             :                                 ctx->skip_mpeg4_vosh = GF_TRUE;
    1582             :                         }
    1583             :                         ctx->vosh_size = dsi.next_object_start;
    1584             :                 } else if (!ctx->vtb_session) {
    1585             :                         gf_filter_pid_drop_packet(ref_pid);
    1586             :                         return GF_OK;
    1587             :                 }
    1588             :         }
    1589             : 
    1590             :         if (ctx->init_mpeg12) {
    1591             :                 GF_M4VDecSpecInfo dsi;
    1592             :                 dsi.width = dsi.height = 0;
    1593             :                 
    1594             :                 e = gf_mpegv12_get_config(in_buffer, in_buffer_size, &dsi);
    1595             :                 if ((e==GF_OK) && dsi.width && dsi.height) {
    1596             :                         ctx->width = dsi.width;
    1597             :                         ctx->height = dsi.height;
    1598             :                         ctx->pixel_ar.num = dsi.par_num;
    1599             :                         ctx->pixel_ar.den = dsi.par_den;
    1600             :                         
    1601             :                         e = vtbdec_init_decoder(filter, ctx);
    1602             :                         if (e) {
    1603             :                                 gf_filter_pid_drop_packet(ref_pid);
    1604             :                                 return e;
    1605             :                         }
    1606             :                 }
    1607             : 
    1608             :                 if (!ctx->vtb_session) {
    1609             :                         gf_filter_pid_drop_packet(ref_pid);
    1610             :                         return GF_OK;
    1611             :                 }
    1612             :         }
    1613             :         
    1614             :         if (ctx->check_h264_isma) {
    1615             :                 if (in_buffer && !in_buffer[0] && !in_buffer[1] && !in_buffer[2] && (in_buffer[3]==0x01)) {
    1616             :                         ctx->check_h264_isma=GF_FALSE;
    1617             :                         ctx->nalu_size_length=0;
    1618             :                         ctx->is_annex_b=GF_TRUE;
    1619             :                 }
    1620             :         }
    1621             : 
    1622             :         //Always parse AVC data , remove SPS/PPS/... and reconfig if needed
    1623             :         if (ctx->is_annex_b || ctx->nalu_size_length) {
    1624             : 
    1625             :                 e = vtbdec_parse_nal_units(filter, ctx, in_buffer, in_buffer_size, &in_data, &in_data_size);
    1626             :                 if (e) {
    1627             :                         gf_filter_pid_drop_packet(ref_pid);
    1628             :                         return e;
    1629             :                 }
    1630             :         } else if (ctx->vosh_size) {
    1631             :                 in_data = in_buffer + ctx->vosh_size;
    1632             :                 in_data_size = in_buffer_size - ctx->vosh_size;
    1633             :                 ctx->vosh_size = 0;
    1634             :         } else {
    1635             :                 in_data = in_buffer;
    1636             :                 in_data_size = in_buffer_size;
    1637             :         }
    1638             : 
    1639             :         if (ctx->reconfig_needed) {
    1640             :                 //flush all pending frames
    1641             :                 while (gf_list_count(ctx->frames)) {
    1642             :                         vtbdec_flush_frame(filter, ctx);
    1643             :                 }
    1644             :                 //waiting for last frame to be discarded
    1645             :                 if (ctx->no_copy && ctx->decoded_frames_pending) {
    1646             :                         ctx->last_frame_sent->frame_ifce.flags = GF_FRAME_IFCE_BLOCKING;
    1647             :                         gf_filter_ask_rt_reschedule(filter, 0);
    1648             :                         return GF_OK;
    1649             :                 }
    1650             :                 if (ctx->fmt_desc) {
    1651             :                         CFRelease(ctx->fmt_desc);
    1652             :                         ctx->fmt_desc = NULL;
    1653             :                 }
    1654             :                 if (ctx->vtb_session) {
    1655             :                         VTDecompressionSessionInvalidate(ctx->vtb_session);
    1656             :                         ctx->vtb_session=NULL;
    1657             :                 }
    1658             :                 vtbdec_init_decoder(filter, ctx);
    1659             :                 return GF_OK;
    1660             :         }
    1661             :         if (!ctx->vtb_session) {
    1662             :                 gf_filter_pid_drop_packet(ref_pid);
    1663             :                 return GF_OK;
    1664             :         }
    1665             :         
    1666             : 
    1667             :         status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, in_data, in_data_size, kCFAllocatorNull, NULL, 0, in_data_size, 0, &block_buffer);
    1668             : 
    1669             :         if (status ||  (block_buffer == NULL) ) {
    1670             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Failed to allocate block buffer of %d bytes\n", in_data_size));
    1671             :                 gf_filter_pid_drop_packet(ref_pid);
    1672             :                 return GF_IO_ERR;
    1673             :         }
    1674             : 
    1675             :         status = CMSampleBufferCreate(kCFAllocatorDefault, block_buffer, TRUE, NULL, NULL, ctx->fmt_desc, 1, 0, NULL, 0, NULL, &sample);
    1676             : 
    1677             :     if (status || (sample==NULL)) {
    1678             :                 if (block_buffer)
    1679             :                         CFRelease(block_buffer);
    1680             : 
    1681             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Failed to create sample buffer for %d bytes\n", in_data_size));
    1682             :                 gf_filter_pid_drop_packet(ref_pid);
    1683             :                 return GF_IO_ERR;
    1684             :         }
    1685             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[VTB] Decoding frame DTS "LLU" ms\n", min_dts));
    1686             :         ctx->cur_pck = pck;
    1687             :         ctx->last_error = GF_OK;
    1688             :     status = VTDecompressionSessionDecodeFrame(ctx->vtb_session, sample, 0, NULL, 0);
    1689             :     if (!status)
    1690             :                 status = VTDecompressionSessionWaitForAsynchronousFrames(ctx->vtb_session);
    1691             :         
    1692             : 
    1693             :         CFRelease(block_buffer);
    1694             :         CFRelease(sample);
    1695             : 
    1696             :         //profile not supported, request codec change - do not discard input frame
    1697             :         if (ctx->last_error==GF_PROFILE_NOT_SUPPORTED) {
    1698             :                 ctx->cur_pck = NULL;
    1699             :                 return ctx->last_error;
    1700             :         }
    1701             :         
    1702             :         gf_filter_pid_drop_packet(ref_pid);
    1703             :         ctx->cur_pck = NULL;
    1704             : 
    1705             :         if (ctx->last_error) return ctx->last_error;
    1706             : 
    1707             :         if (status)
    1708             :                 return GF_NON_COMPLIANT_BITSTREAM;
    1709             : 
    1710             :         frames_count = gf_list_count(ctx->frames);
    1711             :         if (!frames_count) {
    1712             :                 return ctx->last_error;
    1713             :         }
    1714             :         //probing for reordering, or reordering is on but not enough frames: wait before we dispatch
    1715             :         if (ctx->reorder_probe) {
    1716             :                 return GF_OK;
    1717             :         }
    1718             : 
    1719             :         if (ctx->reorder_detected && (frames_count<ctx->reorder) )
    1720             :                 return GF_OK;
    1721             : 
    1722             :         return vtbdec_flush_frame(filter, ctx);
    1723             : }
    1724             : 
    1725             : void vtbframe_release(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck)
    1726             : {
    1727             :         GF_FilterFrameInterface *frame = gf_filter_pck_get_frame_interface(pck);
    1728             :         GF_VTBHWFrame *f = (GF_VTBHWFrame *)frame->user_data;
    1729             :         if (f->locked) {
    1730             :                 CVPixelBufferUnlockBaseAddress(f->frame, kCVPixelBufferLock_ReadOnly);
    1731             :         }
    1732             : #ifdef VTB_GL_TEXTURE
    1733             :         if (f->y) CVBufferRelease(f->y);
    1734             :         if (f->u) CVBufferRelease(f->u);
    1735             :         if (f->v) CVBufferRelease(f->v);
    1736             :         if (f->ctx->cache_texture)
    1737             :                 GF_CVOpenGLTextureCacheFlush(f->ctx->cache_texture, 0);
    1738             : #endif
    1739             :         
    1740             :         if (f->frame) {
    1741             :         CVPixelBufferRelease(f->frame);
    1742             :         f->frame = NULL;
    1743             :     }
    1744             : 
    1745             :     safe_int_dec(&f->ctx->decoded_frames_pending);
    1746             :         gf_list_add(f->ctx->frames_res, f);
    1747             : }
    1748             : 
    1749             : GF_Err vtbframe_get_plane(GF_FilterFrameInterface *frame, u32 plane_idx, const u8 **outPlane, u32 *outStride)
    1750             : {
    1751             :     OSStatus status;
    1752             :         GF_Err e;
    1753             :         GF_VTBHWFrame *f = (GF_VTBHWFrame *)frame->user_data;
    1754             :         if (! outPlane || !outStride) return GF_BAD_PARAM;
    1755             :         *outPlane = NULL;
    1756             :         assert(f->frame);
    1757             :         if (!f->locked) {
    1758             :                 status = CVPixelBufferLockBaseAddress(f->frame, kCVPixelBufferLock_ReadOnly);
    1759             :                 if (status != kCVReturnSuccess) {
    1760             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error locking frame data\n"));
    1761             :                         return GF_IO_ERR;
    1762             :                 }
    1763             :                 f->locked = GF_TRUE;
    1764             :         }
    1765             :         e = GF_OK;
    1766             :         
    1767             :     if (CVPixelBufferIsPlanar(f->frame)) {
    1768             :                 *outPlane = CVPixelBufferGetBaseAddressOfPlane(f->frame, plane_idx);
    1769             :                 if (*outPlane)
    1770             :                         *outStride = (u32) CVPixelBufferGetBytesPerRowOfPlane(f->frame, plane_idx);
    1771             :                 else
    1772             :                         e = GF_EOS;
    1773             :         } else if (plane_idx==0) {
    1774             :                 *outStride = (u32) CVPixelBufferGetBytesPerRow(f->frame);
    1775             :                 *outPlane = CVPixelBufferGetBaseAddress(f->frame);
    1776             :         } else {
    1777             :                 e = GF_BAD_PARAM;
    1778             :         }
    1779             :         return e;
    1780             : }
    1781             : 
    1782             : #ifdef VTB_GL_TEXTURE
    1783             : 
    1784             : /*Define codec matrix*/
    1785             : typedef struct __matrix GF_CodecMatrix;
    1786             : 
    1787             : #ifdef GPAC_CONFIG_IOS
    1788             : void *myGetGLContext();
    1789             : #else
    1790             : 
    1791             : #include <OpenGL/CGLCurrent.h>
    1792             : void *myGetGLContext()
    1793             : {
    1794             :         return CGLGetCurrentContext();
    1795             : }
    1796             : #endif
    1797             : 
    1798             : 
    1799             : GF_Err vtbframe_get_gl_texture(GF_FilterFrameInterface *frame, u32 plane_idx, u32 *gl_tex_format, u32 *gl_tex_id, GF_CodecMatrix * texcoordmatrix)
    1800             : {
    1801             :     OSStatus status;
    1802             :         GLenum target_fmt;
    1803             :         u32 w, h;
    1804             :         GF_CVGLTextureREF *outTexture=NULL;
    1805             :         GF_VTBHWFrame *f = (GF_VTBHWFrame *)frame->user_data;
    1806             :         if (! gl_tex_format || !gl_tex_id) return GF_BAD_PARAM;
    1807             :         *gl_tex_format = 0;
    1808             :         *gl_tex_id = 0;
    1809             : 
    1810             :         if (!f->ctx->gl_context) {
    1811             :                 f->ctx->gl_context = myGetGLContext();
    1812             :                 if (!f->ctx->gl_context) {
    1813             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error locating current GL context\n"));
    1814             :                         return GF_IO_ERR;
    1815             :                 }
    1816             :         }
    1817             :         if (! f->ctx->decoded_frames_pending) return GF_IO_ERR;
    1818             :         
    1819             :         if (!f->ctx->cache_texture) {
    1820             : #ifdef GPAC_CONFIG_IOS
    1821             :                 status = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, f->ctx->gl_context, NULL, &f->ctx->cache_texture);
    1822             : #else
    1823             :                 status = CVOpenGLTextureCacheCreate(kCFAllocatorDefault, NULL, f->ctx->gl_context, CGLGetPixelFormat(f->ctx->gl_context), NULL, &f->ctx->cache_texture);
    1824             : #endif
    1825             :                 if (status != kCVReturnSuccess) {
    1826             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error creating cache texture\n"));
    1827             :                         return GF_IO_ERR;
    1828             :                 }
    1829             :         }
    1830             :         
    1831             :         if (!f->locked) {
    1832             :                 status = CVPixelBufferLockBaseAddress(f->frame, kCVPixelBufferLock_ReadOnly);
    1833             :                 if (status != kCVReturnSuccess) {
    1834             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error locking frame data\n"));
    1835             :                         return GF_IO_ERR;
    1836             :                 }
    1837             :                 f->locked = GF_TRUE;
    1838             :         }
    1839             : 
    1840             :     if (CVPixelBufferIsPlanar(f->frame)) {
    1841             :                 w = (u32) CVPixelBufferGetPlaneCount(f->frame);
    1842             :                 if (plane_idx >= (u32) CVPixelBufferGetPlaneCount(f->frame)) {
    1843             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Wrong plane index\n"));
    1844             :                         return GF_BAD_PARAM;
    1845             :                 }
    1846             :         } else if (plane_idx!=0) {
    1847             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Wrong plane index %d on interleaved format\n", plane_idx));
    1848             :                 return GF_BAD_PARAM;
    1849             :         }
    1850             : 
    1851             :         target_fmt = GL_LUMINANCE;
    1852             :         w = f->ctx->width;
    1853             :         h = f->ctx->height;
    1854             :         if (plane_idx) {
    1855             :                 w /= 2;
    1856             :                 h /= 2;
    1857             :                 target_fmt = GL_LUMINANCE_ALPHA;
    1858             :         }
    1859             :         if (plane_idx==0) {
    1860             :                 outTexture = &f->y;
    1861             :         }
    1862             :         else if (plane_idx==1) {
    1863             :                 outTexture = &f->u;
    1864             :         }
    1865             :         //don't create texture if already done !
    1866             :         if ( *outTexture == NULL) {
    1867             : #ifdef GPAC_CONFIG_IOS
    1868             :                 status = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, f->ctx->cache_texture, f->frame, NULL, GL_TEXTURE_2D, target_fmt, w, h, target_fmt, GL_UNSIGNED_BYTE, plane_idx, outTexture);
    1869             : #else
    1870             :                 status = CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, f->ctx->cache_texture, f->frame, NULL, outTexture);
    1871             : #endif
    1872             : 
    1873             :                 if (status != kCVReturnSuccess) {
    1874             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[VTB] Error creating cache texture for plane %d\n", plane_idx));
    1875             :                         return GF_IO_ERR;
    1876             :                 }
    1877             :         }
    1878             :         *gl_tex_format = GF_CVOpenGLTextureGetTarget(*outTexture);
    1879             :         *gl_tex_id = GF_CVOpenGLTextureGetName(*outTexture);
    1880             : 
    1881             :         return GF_OK;
    1882             : }
    1883             : #endif
    1884             : 
    1885             : static GF_Err vtbdec_send_output_frame(GF_Filter *filter, GF_VTBDecCtx *ctx)
    1886             : {
    1887             :         GF_VTBHWFrame *vtb_frame;
    1888             :         GF_FilterPacket *dst_pck;
    1889             : 
    1890             :         vtb_frame = gf_list_pop_front(ctx->frames);
    1891             :         if (!vtb_frame) return GF_BAD_PARAM;
    1892             : 
    1893             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[VTB] Outputting frame DTS "LLU" CTS "LLU" timescale %d\n", gf_filter_pck_get_dts(vtb_frame->pck_src), gf_filter_pck_get_cts(vtb_frame->pck_src), gf_filter_pck_get_timescale(vtb_frame->pck_src)));
    1894             : 
    1895             :         vtb_frame->frame_ifce.user_data = vtb_frame;
    1896             :         vtb_frame->frame_ifce.get_plane = vtbframe_get_plane;
    1897             : #ifdef VTB_GL_TEXTURE
    1898             :         if (ctx->use_gl_textures)
    1899             :                 vtb_frame->frame_ifce.get_gl_texture = vtbframe_get_gl_texture;
    1900             : #endif
    1901             : 
    1902             :         if (ctx->reconfig_needed)
    1903             :                 vtb_frame->frame_ifce.flags = GF_FRAME_IFCE_BLOCKING;
    1904             : 
    1905             :         safe_int_inc(&ctx->decoded_frames_pending);
    1906             : 
    1907             :         dst_pck = gf_filter_pck_new_frame_interface(ctx->opid, &vtb_frame->frame_ifce, vtbframe_release);
    1908             :         if (!dst_pck) return GF_OUT_OF_MEM;
    1909             : 
    1910             :         gf_filter_pck_merge_properties(vtb_frame->pck_src, dst_pck);
    1911             : 
    1912             :         ctx->last_cts_out = gf_filter_pck_get_cts(vtb_frame->pck_src);
    1913             :         ctx->last_timescale_out = gf_filter_pck_get_timescale(vtb_frame->pck_src);
    1914             :         gf_filter_pck_unref(vtb_frame->pck_src);
    1915             :         vtb_frame->pck_src = NULL;
    1916             :         ctx->last_frame_sent = vtb_frame;
    1917             :         gf_filter_pck_send(dst_pck);
    1918             :         return GF_OK;
    1919             : }
    1920             : 
    1921             : 
    1922             : #endif
    1923             : 
    1924             : static Bool vtbdec_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
    1925             : {
    1926             :         GF_VTBDecCtx *ctx = (GF_VTBDecCtx *) gf_filter_get_udta(filter);
    1927             :         if (evt->base.type==GF_FEVT_PLAY) {
    1928             :                 while (gf_list_count(ctx->frames) ) {
    1929             :                         GF_VTBHWFrame *f = gf_list_pop_back(ctx->frames);
    1930             :                         if (f->pck_src) gf_filter_pck_unref(f->pck_src);
    1931             :                         f->pck_src = NULL;
    1932             :                         gf_list_add(ctx->frames_res, f);
    1933             :                 }
    1934             :                 ctx->drop_non_refs = evt->play.drop_non_ref;
    1935             :         }
    1936             :         else if ((evt->base.type==GF_FEVT_SET_SPEED) || (evt->base.type==GF_FEVT_RESUME)) {
    1937             :                 ctx->drop_non_refs = evt->play.drop_non_ref;
    1938             :         }
    1939             :         return GF_FALSE;
    1940             : }
    1941             : 
    1942             : static GF_Err vtbdec_initialize(GF_Filter *filter)
    1943             : {
    1944             :         GF_VTBDecCtx *ctx = (GF_VTBDecCtx *) gf_filter_get_udta(filter);
    1945             : #ifdef VTB_GL_TEXTURE
    1946             :         if (ctx->no_copy)
    1947             :                 ctx->use_gl_textures = GF_TRUE;
    1948             : #endif
    1949             : 
    1950             :         ctx->frames_res = gf_list_new();
    1951             :         ctx->frames = gf_list_new();
    1952             :         ctx->streams = gf_list_new();
    1953             :         return GF_OK;
    1954             : }
    1955             : 
    1956             : static void vtbdec_finalize(GF_Filter *filter)
    1957             : {
    1958             :         GF_VTBDecCtx *ctx = (GF_VTBDecCtx *) gf_filter_get_udta(filter);
    1959             :         vtbdec_delete_decoder(ctx);
    1960             : 
    1961             : #ifdef VTB_GL_TEXTURE
    1962             :         if (ctx->cache_texture) {
    1963             :                 CFRelease(ctx->cache_texture);
    1964             :     }
    1965             : #endif
    1966             : 
    1967             :         if (ctx->frames) {
    1968             :                 while (gf_list_count(ctx->frames) ) {
    1969             :                         GF_VTBHWFrame *f = gf_list_pop_back(ctx->frames);
    1970             :                         if (f->pck_src) gf_filter_pck_unref(f->pck_src);
    1971             :                         gf_free(f);
    1972             :                 }
    1973             :                 gf_list_del(ctx->frames);
    1974             :         }
    1975             : 
    1976             :         if (ctx->frames_res) {
    1977             :                 while (gf_list_count(ctx->frames_res) ) {
    1978             :                         GF_VTBHWFrame *f = gf_list_pop_back(ctx->frames_res);
    1979             :                         if (f->pck_src) gf_filter_pck_unref(f->pck_src);
    1980             :                         gf_free(f);
    1981             :                 }
    1982             :                 gf_list_del(ctx->frames_res);
    1983             :         }
    1984             :         gf_list_del(ctx->streams);
    1985             : 
    1986             :         if (ctx->nal_bs) gf_bs_del(ctx->nal_bs);
    1987             :         if (ctx->ps_bs) gf_bs_del(ctx->ps_bs);
    1988             :         if (ctx->nalu_rewrite_bs) gf_bs_del(ctx->nalu_rewrite_bs);
    1989             :         if (ctx->nalu_buffer) gf_free(ctx->nalu_buffer);
    1990             : }
    1991             : 
    1992             : 
    1993             : static const GF_FilterCapability VTBDecCaps[] =
    1994             : {
    1995             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    1996             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    1997             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG4_PART2),
    1998             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AVC),
    1999             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_HEVC),
    2000             :         { .code=GF_PROP_PID_SCALABLE, .val={.type=GF_PROP_BOOL, .value.boolean = GF_TRUE}, .flags=(GF_CAPS_INPUT_OPT), .priority=255 },
    2001             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_TILE_BASE, GF_TRUE),
    2002             : 
    2003             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_SIMPLE),
    2004             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_MAIN),
    2005             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_SNR),
    2006             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_SPATIAL),
    2007             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_HIGH),
    2008             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_422),
    2009             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_H263),
    2010             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_S263),
    2011             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4X),
    2012             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AP4H),
    2013             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCH),
    2014             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCN),
    2015             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCS),
    2016             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_APCO),
    2017             : 
    2018             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
    2019             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    2020             : };
    2021             : 
    2022             : #define OFFS(_n)        #_n, offsetof(GF_VTBDecCtx, _n)
    2023             : 
    2024             : static const GF_FilterArgs VTBDecArgs[] =
    2025             : {
    2026             :         { OFFS(reorder), "number of frames to wait for temporal re-ordering", GF_PROP_UINT, "6", NULL, GF_FS_ARG_HINT_ADVANCED},
    2027             :         { OFFS(no_copy), "dispatch VTB frames into filter chain (no copy)", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED},
    2028             :         { OFFS(ofmt), "set default pixel format for decoded video. If not matched default to nv12", GF_PROP_PIXFMT, "nv12", NULL, GF_FS_ARG_HINT_ADVANCED},
    2029             :         { OFFS(disable_hw), "disable hardware decoding", GF_PROP_BOOL, "false", NULL, 0},
    2030             :         {}
    2031             : };
    2032             : 
    2033             : GF_FilterRegister GF_VTBDecCtxRegister = {
    2034             :         .name = "vtbdec",
    2035             :         GF_FS_SET_DESCRIPTION("VideoToolBox decoder")
    2036             :         GF_FS_SET_HELP("This filter decodes video streams through OSX/iOS VideoToolBox (MPEG-2, H263, AVC|H264, HEVC, ProRes). It allows GPU frame dispatch or direct frame copy.")
    2037             :         .private_size = sizeof(GF_VTBDecCtx),
    2038             :         .args = VTBDecArgs,
    2039             :         .priority = 1,
    2040             :         SETCAPS(VTBDecCaps),
    2041             :         .initialize = vtbdec_initialize,
    2042             :         .finalize = vtbdec_finalize,
    2043             :         .configure_pid = vtbdec_configure_pid,
    2044             :         .process = vtbdec_process,
    2045             :         .process_event = vtbdec_process_event,
    2046             : };
    2047             : 
    2048             : #else
    2049             : #undef _GF_MATH_H_
    2050             : #include <gpac/maths.h>
    2051             : #include <gpac/filters.h>
    2052             : 
    2053             : #endif // !defined(GPAC_DISABLE_AV_PARSERS) && ( defined(GPAC_CONFIG_DARWIN) || defined(GPAC_CONFIG_IOS) ) && defined(GPAC_HAS_VTB)
    2054             : 
    2055        2877 : const GF_FilterRegister *vtbdec_register(GF_FilterSession *session)
    2056             : {
    2057             : #if !defined(GPAC_DISABLE_AV_PARSERS) && ( defined(GPAC_CONFIG_DARWIN) || defined(GPAC_CONFIG_IOS) ) && defined(GPAC_HAS_VTB)
    2058             :         return &GF_VTBDecCtxRegister;
    2059             : #else
    2060        2877 :         return NULL;
    2061             : #endif
    2062             : }

Generated by: LCOV version 1.13