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