2
* GPAC - Multimedia Framework C SDK
4
* Copyright (c) Telecom ParisTech 2010-
5
* Author(s): Jean Le Feuvre
8
* This file is part of GPAC / OpenSVC Decoder module
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)
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.
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.
27
#include <gpac/modules/codec.h>
28
#include <gpac/avparse.h>
29
#include <gpac/constants.h>
32
#define DllImport __declspec( dllimport )
35
#if !defined(__GNUC__)
36
# pragma comment(lib, "RVCDecoder")
54
DllImport int rvc_init(char* XDF, char* VTLFolder, int isAVCFile);
55
DllImport int rvc_decode(unsigned char* nal, int nal_length, char *outBuffer, int newBuffer);
56
DllImport void rvc_close();
62
u32 width, stride, height, out_size, pixel_ar, layer;
71
static GF_Err RVCD_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd)
76
RVCDec *ctx = (RVCDec*) ifcg->privateStack;
81
/*not supported in this version*/
82
if (esd->dependsOnESID) return GF_NOT_SUPPORTED;
84
ctx->ES_ID = esd->ESID;
85
ctx->width = ctx->height = ctx->out_size = 0;
87
VTLFolder = (char *)gf_modules_get_option((GF_BaseInterface *)ifcg, "RVCDecoder", "VTLPath");
89
GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[RVC_Dec] Cannot locate VTL: path is unknown. Please indicate path in GPAC config file:\n[RVCDecoder]\nVTLPath=PATH\n"));
90
return GF_SERVICE_ERROR;
92
GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[RVC_Dec] Using VTL in %s\n", VTLFolder));
96
if (esd->decoderConfig->predefined_rvc_config) {
100
sprintf(opt, "Predefined_%d", esd->decoderConfig->predefined_rvc_config);
101
path = gf_modules_get_option((GF_BaseInterface *)ifcg, "RVCDecoder", (const char *)opt);
102
if (!opt) return GF_NOT_SUPPORTED;
103
f = fopen(path, "rt");
104
if (!f) return GF_NOT_SUPPORTED;
105
fseek(f, 0, SEEK_END);
107
fseek(f, 0, SEEK_SET);
108
XDF_doc = gf_malloc(sizeof(char)*(size+1));
111
return GF_OUT_OF_MEM;
113
fread(XDF_doc, 1, size, f);
117
if (!esd->decoderConfig->rvc_config)
118
return GF_NOT_SUPPORTED;
119
XDF_doc = esd->decoderConfig->rvc_config->data;
123
if(esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) isAVCFile = 1;
126
rvc_init(XDF_doc, VTLFolder, isAVCFile); //->data contains the uncompressed XDF
130
if (esd->decoderConfig->rvc_config) {
131
esd->decoderConfig->rvc_config->data = NULL;
132
esd->decoderConfig->rvc_config->dataLength = 0;
135
/*decoder config not known, output buffers will be reconfigured at run-time*/
136
if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data)
139
/*initialize the decoder */
140
if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) {
141
GF_AVCConfig *cfg = gf_odf_avc_cfg_read(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
142
if (!cfg) return GF_NON_COMPLIANT_BITSTREAM;
143
ctx->nalu_size_length = cfg->nal_unit_size;
146
count = gf_list_count(cfg->sequenceParameterSets);
147
for (i=0; i<count; i++) {
148
u32 w, h, par_n, par_d;
149
GF_AVCConfigSlot *slc = gf_list_get(cfg->sequenceParameterSets, i);
151
gf_avc_get_sps_info(slc->data, slc->size, &slc->id, &w, &h, &par_n, &par_d);
152
/*by default use the base layer*/
154
if ((ctx->width<w) || (ctx->height<h)) {
157
if ( ((s32)par_n>0) && ((s32)par_d>0) )
158
ctx->pixel_ar = (par_n<<16) || par_d;
161
/* call decode - warning for AVC: the data blocks do not contain startcode prefixes (00000001), you may need to add them) */
163
res = rvc_decode(slc->data, slc->size, &Picture, 1);
165
GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding SPS %d\n", res));
170
count = gf_list_count(cfg->pictureParameterSets);
171
for (i=0; i<count; i++) {
172
GF_AVCConfigSlot *slc = gf_list_get(cfg->pictureParameterSets, i);
173
/*same remark as above*/
176
res = rvc_decode(slc->data, slc->size, &Picture, 1);
178
GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
183
gf_odf_avc_cfg_del(cfg);
184
} else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) {
185
GF_M4VDecSpecInfo dsi;
188
e = gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
190
if (!dsi.width || !dsi.height) return GF_NON_COMPLIANT_BITSTREAM;
191
ctx->width = dsi.width;
192
ctx->height = dsi.height;
193
ctx->pixel_ar = (dsi.par_num<<16) | dsi.par_den;
196
res = rvc_decode(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &Picture, 1);
198
GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
203
/*unknown type, do what you want*/
205
res = rvc_decode(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &Picture, 1);
207
GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
211
/*adjust stride to what you decoder uses*/
212
ctx->stride = ctx->width;
213
/*precompute output buffer size*/
214
ctx->out_size = ctx->stride * ctx->height * 3 / 2;
217
static GF_Err RVCD_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID)
219
RVCDec *ctx = (RVCDec*) ifcg->privateStack;
224
ctx->width = ctx->height = ctx->out_size = 0;
227
static GF_Err RVCD_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability)
229
RVCDec *ctx = (RVCDec*) ifcg->privateStack;
231
switch (capability->CapCode) {
232
case GF_CODEC_RESILIENT:
233
capability->cap.valueInt = 1;
236
capability->cap.valueInt = ctx->width;
238
case GF_CODEC_HEIGHT:
239
capability->cap.valueInt = ctx->height;
241
case GF_CODEC_STRIDE:
242
capability->cap.valueInt = ctx->stride;
245
capability->cap.valueInt = ctx->pixel_ar;
247
case GF_CODEC_OUTPUT_SIZE:
248
capability->cap.valueInt = ctx->out_size;
250
case GF_CODEC_PIXEL_FORMAT:
251
capability->cap.valueInt = GF_PIXEL_YV12;
253
case GF_CODEC_BUFFER_MIN:
254
capability->cap.valueInt = 1;
256
case GF_CODEC_BUFFER_MAX:
257
capability->cap.valueInt = 2;
259
case GF_CODEC_PADDING_BYTES:
260
capability->cap.valueInt = 32;
262
case GF_CODEC_REORDER:
263
capability->cap.valueInt = 1;
265
/*not known at our level...*/
266
case GF_CODEC_CU_DURATION:
268
capability->cap.valueInt = 0;
273
static GF_Err RVCD_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability)
275
return GF_NOT_SUPPORTED;
281
static GF_Err RVCD_ProcessData(GF_MediaDecoder *ifcg,
282
char *inBuffer, u32 inBufferLength,
284
char *outBuffer, u32 *outBufferLength,
285
u8 PaddingBits, u32 mmlevel)
288
RVCDec *ctx = (RVCDec*) ifcg->privateStack;
290
if (!ES_ID || (ES_ID!=ctx->ES_ID) /*|| !ctx->codec*/) {
291
*outBufferLength = 0;
294
if (*outBufferLength < ctx->out_size) {
295
*outBufferLength = ctx->out_size;
296
return GF_BUFFER_TOO_SMALL;
299
//if your decoder outputs directly in the memory passed, setup pointers for your decoder output picture
303
if (ctx->nalu_size_length) {
304
u32 i, nalu_size = 0;
308
while (inBufferLength) {
309
for (i=0; i<ctx->nalu_size_length; i++) {
310
nalu_size = (nalu_size<<8) + ptr[i];
312
ptr += ctx->nalu_size_length;
314
//same remark as above regardin start codes
316
if(nalNumber > bookmark){
317
got_pic = rvc_decode(ptr, nalu_size, outBuffer, !got_pic);
320
return GF_PACKED_FRAMES;
322
}else if(nalNumber == bookmark){
323
got_pic = rvc_decode(NULL, 0, outBuffer, !got_pic);
325
return GF_PACKED_FRAMES;
331
if (inBufferLength < nalu_size + ctx->nalu_size_length)
334
inBufferLength -= nalu_size + ctx->nalu_size_length;
343
got_pic = rvc_decode(ptr, inBufferLength, outBuffer, 1);
346
//if (got_pic!=1) return GF_OK;
348
/*if size changed during the decoding, resize the composition buffer*/
349
/*if ((pic.Width != ctx->width) || (pic.Height!=ctx->height))
351
ctx->width = pic.Width;
352
ctx->stride = pic.Width;
353
ctx->height = pic.Height;
354
ctx->out_size = ctx->stride * ctx->height * 3 / 2;
355
*outBufferLength = ctx->out_size;
356
return GF_BUFFER_TOO_SMALL;
359
*outBufferLength = ctx->out_size;*/
361
/*if your decoder does not output directly in the memory passed, copy over the data*/
363
/*memcpy(outBuffer, pic.pY[0], ctx->stride*ctx->height);
364
memcpy(outBuffer + ctx->stride * ctx->height, pic.pU[0], ctx->stride*ctx->height/4);
365
memcpy(outBuffer + 5*ctx->stride * ctx->height/4, pic.pV[0], ctx->stride*ctx->height/4);*/
367
if(got_pic>1) return GF_PACKED_FRAMES;
371
static u32 RVCD_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, GF_ESD *esd, u8 PL)
373
if (StreamType != GF_STREAM_VISUAL) return GF_CODEC_NOT_SUPPORTED;
375
if (!esd) return GF_CODEC_STREAM_TYPE_SUPPORTED;
376
switch (esd->decoderConfig->objectTypeIndication) {
377
case GPAC_OTI_VIDEO_AVC:
378
case GPAC_OTI_VIDEO_MPEG4_PART2:
379
if (!esd->decoderConfig->rvc_config && !esd->decoderConfig->predefined_rvc_config) return GF_CODEC_NOT_SUPPORTED;
380
return GF_CODEC_SUPPORTED+1;
382
return GF_CODEC_NOT_SUPPORTED;
385
static const char *RVCD_GetCodecName(GF_BaseDecoder *dec)
387
return "RVC Decoder";
390
GF_BaseDecoder *NewRVCDec()
392
GF_MediaDecoder *ifcd;
395
GF_SAFEALLOC(ifcd, GF_MediaDecoder);
396
GF_SAFEALLOC(dec, RVCDec);
397
GF_REGISTER_MODULE_INTERFACE(ifcd, GF_MEDIA_DECODER_INTERFACE, "RVC Decoder", "gpac distribution")
399
ifcd->privateStack = dec;
401
/*setup our own interface*/
402
ifcd->AttachStream = RVCD_AttachStream;
403
ifcd->DetachStream = RVCD_DetachStream;
404
ifcd->GetCapabilities = RVCD_GetCapabilities;
405
ifcd->SetCapabilities = RVCD_SetCapabilities;
406
ifcd->GetName = RVCD_GetCodecName;
407
ifcd->CanHandleStream = RVCD_CanHandleStream;
408
ifcd->ProcessData = RVCD_ProcessData;
409
return (GF_BaseDecoder *) ifcd;
412
void DeleteRVCDec(GF_BaseDecoder *ifcg)
414
RVCDec *ctx = (RVCDec*) ifcg->privateStack;
419
const u32 *QueryInterfaces()
422
#ifndef GPAC_DISABLE_AV_PARSERS
423
GF_MEDIA_DECODER_INTERFACE,
430
GF_BaseInterface *LoadInterface(u32 InterfaceType)
432
#ifndef GPAC_DISABLE_AV_PARSERS
433
if (InterfaceType == GF_MEDIA_DECODER_INTERFACE) return (GF_BaseInterface *)NewRVCDec();
438
void ShutdownInterface(GF_BaseInterface *ifce)
440
switch (ifce->InterfaceType) {
441
#ifndef GPAC_DISABLE_AV_PARSERS
442
case GF_MEDIA_DECODER_INTERFACE:
443
DeleteRVCDec((GF_BaseDecoder*)ifce);