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 : }
|