~ubuntu-branches/debian/experimental/gpac/experimental

« back to all changes in this revision

Viewing changes to modules/rvc_dec/rvc_dec.c

  • Committer: Package Import Robot
  • Author(s): Andres Mejia
  • Date: 2012-02-04 00:12:54 UTC
  • Revision ID: package-import@ubuntu.com-20120204001254-l7v7u4kc4m7cxcqn
Tags: upstream-0.4.5+svn3450~dfsg3
ImportĀ upstreamĀ versionĀ 0.4.5+svn3450~dfsg3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *                      GPAC - Multimedia Framework C SDK
 
3
 *
 
4
 *                      Copyright (c) Telecom ParisTech 2010-
 
5
 *                              Author(s):      Jean Le Feuvre
 
6
 *                                      All rights reserved
 
7
 *
 
8
 *  This file is part of GPAC / OpenSVC Decoder module
 
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/modules/codec.h>
 
28
#include <gpac/avparse.h>
 
29
#include <gpac/constants.h>
 
30
 
 
31
#ifdef WIN32
 
32
#define DllImport __declspec( dllimport )
 
33
 
 
34
 
 
35
#if !defined(__GNUC__)
 
36
#  pragma comment(lib, "RVCDecoder")
 
37
#endif
 
38
 
 
39
#else
 
40
#define DllImport
 
41
#endif
 
42
 
 
43
 
 
44
 
 
45
typedef struct{
 
46
        int Width;
 
47
        int Height;
 
48
        unsigned char* pY[1];
 
49
        unsigned char* pU[1]; 
 
50
        unsigned char* pV[1];
 
51
} RVCFRAME;
 
52
 
 
53
 
 
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();
 
57
 
 
58
 
 
59
typedef struct
 
60
{
 
61
        u16 ES_ID;
 
62
        u32 width, stride, height, out_size, pixel_ar, layer;
 
63
        Bool first_frame;
 
64
 
 
65
        u32 nalu_size_length;
 
66
 
 
67
        void *codec;
 
68
} RVCDec;
 
69
 
 
70
 
 
71
static GF_Err RVCD_AttachStream(GF_BaseDecoder *ifcg, GF_ESD *esd)
 
72
{
 
73
        u32 i, count;
 
74
        s32 res;
 
75
        char Picture;
 
76
        RVCDec *ctx = (RVCDec*) ifcg->privateStack;
 
77
        char* VTLFolder; 
 
78
        char *XDF_doc = NULL; 
 
79
        int isAVCFile;
 
80
 
 
81
        /*not supported in this version*/
 
82
        if (esd->dependsOnESID) return GF_NOT_SUPPORTED;
 
83
        
 
84
        ctx->ES_ID = esd->ESID;
 
85
        ctx->width = ctx->height = ctx->out_size = 0;
 
86
 
 
87
        VTLFolder = (char *)gf_modules_get_option((GF_BaseInterface *)ifcg, "RVCDecoder", "VTLPath");
 
88
        if (!VTLFolder) {
 
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;
 
91
        } else {
 
92
                GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[RVC_Dec] Using VTL in %s\n", VTLFolder));
 
93
        }
 
94
 
 
95
        /*initialize RVC*/
 
96
        if (esd->decoderConfig->predefined_rvc_config) {
 
97
                char opt[100], *path;
 
98
                FILE *f;
 
99
                u32 size;
 
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);
 
106
                size = ftell(f);
 
107
                fseek(f, 0, SEEK_SET);
 
108
                XDF_doc = gf_malloc(sizeof(char)*(size+1));
 
109
                if (!XDF_doc) {
 
110
                        fclose(f);
 
111
                        return GF_OUT_OF_MEM;
 
112
                }
 
113
                fread(XDF_doc, 1, size, f);
 
114
                fclose(f);
 
115
                XDF_doc[size]=0;
 
116
        } else {
 
117
                if (!esd->decoderConfig->rvc_config) 
 
118
                        return GF_NOT_SUPPORTED;
 
119
                XDF_doc = esd->decoderConfig->rvc_config->data;
 
120
        }
 
121
 
 
122
 
 
123
        if(esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_AVC) isAVCFile = 1;
 
124
        else isAVCFile = 0;
 
125
 
 
126
        rvc_init(XDF_doc, VTLFolder, isAVCFile); //->data contains the uncompressed XDF
 
127
 
 
128
        /*free data*/
 
129
        gf_free(XDF_doc);
 
130
        if (esd->decoderConfig->rvc_config) {
 
131
                esd->decoderConfig->rvc_config->data = NULL;
 
132
                esd->decoderConfig->rvc_config->dataLength = 0;
 
133
        }
 
134
                
 
135
        /*decoder config not known, output buffers will be reconfigured at run-time*/
 
136
        if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) 
 
137
                return GF_OK;
 
138
 
 
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;
 
144
                
 
145
                /*decode all NALUs*/
 
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);
 
150
 
 
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*/
 
153
                        if (!i) {
 
154
                                if ((ctx->width<w) || (ctx->height<h)) {
 
155
                                        ctx->width = w;
 
156
                                        ctx->height = h;
 
157
                                        if ( ((s32)par_n>0) && ((s32)par_d>0) )
 
158
                                                ctx->pixel_ar = (par_n<<16) || par_d;
 
159
                                }
 
160
                        }
 
161
                        /* call decode - warning for AVC: the data blocks do not contain startcode prefixes (00000001), you may need to add them) */
 
162
                        
 
163
                        res = rvc_decode(slc->data, slc->size, &Picture, 1);
 
164
                        if (res<0) {
 
165
                                GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding SPS %d\n", res));
 
166
                        }
 
167
                        
 
168
                }
 
169
 
 
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*/
 
174
 
 
175
                        
 
176
                        res = rvc_decode(slc->data, slc->size, &Picture, 1);
 
177
                        if (res<0) {
 
178
                                GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
 
179
                        }
 
180
                        
 
181
                }
 
182
 
 
183
                gf_odf_avc_cfg_del(cfg);
 
184
        } else if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) {
 
185
                GF_M4VDecSpecInfo dsi;
 
186
                GF_Err e;
 
187
                /*decode DSI*/
 
188
                e = gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
 
189
                if (e) return e;
 
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;
 
194
                
 
195
                
 
196
                res = rvc_decode(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &Picture, 1);
 
197
                if (res<0) {
 
198
                        GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
 
199
                }
 
200
                
 
201
 
 
202
        } else {
 
203
                /*unknown type, do what you want*/
 
204
                
 
205
                res = rvc_decode(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &Picture, 1);
 
206
                if (res<0) {
 
207
                        GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[SVC Decoder] Error decoding PPS %d\n", res));
 
208
                }
 
209
                
 
210
        }
 
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;
 
215
        return GF_OK;
 
216
}
 
217
static GF_Err RVCD_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID)
 
218
{
 
219
        RVCDec *ctx = (RVCDec*) ifcg->privateStack;
 
220
 
 
221
        //close RVC decoder
 
222
        rvc_close();
 
223
        ctx->codec = NULL;
 
224
        ctx->width = ctx->height = ctx->out_size = 0;
 
225
        return GF_OK;
 
226
}
 
227
static GF_Err RVCD_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability)
 
228
{
 
229
        RVCDec *ctx = (RVCDec*) ifcg->privateStack;
 
230
 
 
231
        switch (capability->CapCode) {
 
232
        case GF_CODEC_RESILIENT:
 
233
                capability->cap.valueInt = 1;
 
234
                break;
 
235
        case GF_CODEC_WIDTH:
 
236
                capability->cap.valueInt = ctx->width;
 
237
                break;
 
238
        case GF_CODEC_HEIGHT:
 
239
                capability->cap.valueInt = ctx->height;
 
240
                break;
 
241
        case GF_CODEC_STRIDE:
 
242
                capability->cap.valueInt = ctx->stride;
 
243
                break;
 
244
        case GF_CODEC_PAR:
 
245
                capability->cap.valueInt = ctx->pixel_ar;
 
246
                break;
 
247
        case GF_CODEC_OUTPUT_SIZE:
 
248
                capability->cap.valueInt = ctx->out_size;
 
249
                break;
 
250
        case GF_CODEC_PIXEL_FORMAT:
 
251
                capability->cap.valueInt = GF_PIXEL_YV12;
 
252
                break;
 
253
        case GF_CODEC_BUFFER_MIN:
 
254
                capability->cap.valueInt = 1;
 
255
                break;
 
256
        case GF_CODEC_BUFFER_MAX:
 
257
                capability->cap.valueInt = 2;
 
258
                break;
 
259
        case GF_CODEC_PADDING_BYTES:
 
260
                capability->cap.valueInt = 32;
 
261
                break;
 
262
        case GF_CODEC_REORDER:
 
263
                capability->cap.valueInt = 1;
 
264
                break;
 
265
        /*not known at our level...*/
 
266
        case GF_CODEC_CU_DURATION:
 
267
        default:
 
268
                capability->cap.valueInt = 0;
 
269
                break;
 
270
        }
 
271
        return GF_OK;
 
272
}
 
273
static GF_Err RVCD_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability)
 
274
{
 
275
        return GF_NOT_SUPPORTED;
 
276
}
 
277
 
 
278
 
 
279
int bookmark = 0;
 
280
 
 
281
static GF_Err RVCD_ProcessData(GF_MediaDecoder *ifcg, 
 
282
                char *inBuffer, u32 inBufferLength,
 
283
                u16 ES_ID,
 
284
                char *outBuffer, u32 *outBufferLength,
 
285
                u8 PaddingBits, u32 mmlevel)
 
286
{
 
287
        s32 got_pic;
 
288
        RVCDec *ctx = (RVCDec*) ifcg->privateStack;
 
289
 
 
290
        if (!ES_ID || (ES_ID!=ctx->ES_ID) /*|| !ctx->codec*/) {
 
291
                *outBufferLength = 0;
 
292
                return GF_OK;
 
293
        }
 
294
        if (*outBufferLength < ctx->out_size) {
 
295
                *outBufferLength = ctx->out_size;
 
296
                return GF_BUFFER_TOO_SMALL;
 
297
        }
 
298
 
 
299
        //if your decoder outputs directly in the memory passed, setup pointers for your decoder output picture
 
300
 
 
301
        got_pic = 0;
 
302
        
 
303
        if (ctx->nalu_size_length) {
 
304
                u32 i, nalu_size = 0;
 
305
                u8 *ptr = inBuffer;
 
306
                int nalNumber = 1;
 
307
                
 
308
                while (inBufferLength) {
 
309
                        for (i=0; i<ctx->nalu_size_length; i++) {
 
310
                                nalu_size = (nalu_size<<8) + ptr[i];
 
311
                        }
 
312
                        ptr += ctx->nalu_size_length;
 
313
 
 
314
                        //same remark as above regardin start codes
 
315
                        
 
316
                        if(nalNumber > bookmark){
 
317
                                got_pic = rvc_decode(ptr, nalu_size, outBuffer, !got_pic);
 
318
                                bookmark ++;
 
319
                                if(got_pic>1){
 
320
                                        return GF_PACKED_FRAMES;
 
321
                                }
 
322
                        }else if(nalNumber == bookmark){
 
323
                                got_pic = rvc_decode(NULL, 0, outBuffer, !got_pic);
 
324
                                if(got_pic>1){
 
325
                                        return GF_PACKED_FRAMES;
 
326
                                }
 
327
                        }
 
328
                        nalNumber ++;
 
329
 
 
330
                        ptr += nalu_size;
 
331
                        if (inBufferLength < nalu_size + ctx->nalu_size_length) 
 
332
                                break;
 
333
 
 
334
                        inBufferLength -= nalu_size + ctx->nalu_size_length;
 
335
                }
 
336
                bookmark = 0;
 
337
 
 
338
        } else {
 
339
                u32 nalu_size = 0;
 
340
                u8 *ptr = inBuffer;
 
341
                
 
342
 
 
343
                got_pic = rvc_decode(ptr, inBufferLength, outBuffer, 1);
 
344
        }
 
345
 
 
346
        //if (got_pic!=1) return GF_OK;
 
347
 
 
348
        /*if size changed during the decoding, resize the composition buffer*/
 
349
        /*if ((pic.Width != ctx->width) || (pic.Height!=ctx->height)) 
 
350
        {
 
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;
 
357
        }
 
358
        
 
359
        *outBufferLength = ctx->out_size;*/
 
360
 
 
361
        /*if your decoder does not output directly in the memory passed, copy over the data*/
 
362
        
 
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);*/      
 
366
 
 
367
        if(got_pic>1) return GF_PACKED_FRAMES;
 
368
        return GF_OK;
 
369
}
 
370
 
 
371
static u32 RVCD_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, GF_ESD *esd, u8 PL)
 
372
{
 
373
        if (StreamType != GF_STREAM_VISUAL) return GF_CODEC_NOT_SUPPORTED;
 
374
        /*media type query*/
 
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;
 
381
        }
 
382
        return GF_CODEC_NOT_SUPPORTED;
 
383
}
 
384
 
 
385
static const char *RVCD_GetCodecName(GF_BaseDecoder *dec)
 
386
{
 
387
        return "RVC Decoder";
 
388
}
 
389
 
 
390
GF_BaseDecoder *NewRVCDec()
 
391
{
 
392
        GF_MediaDecoder *ifcd;
 
393
        RVCDec *dec;
 
394
        
 
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")
 
398
 
 
399
        ifcd->privateStack = dec;
 
400
 
 
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;
 
410
}
 
411
 
 
412
void DeleteRVCDec(GF_BaseDecoder *ifcg)
 
413
{
 
414
        RVCDec *ctx = (RVCDec*) ifcg->privateStack;
 
415
        gf_free(ctx);
 
416
        gf_free(ifcg);
 
417
}
 
418
 
 
419
const u32 *QueryInterfaces() 
 
420
{
 
421
        static u32 si [] = {
 
422
#ifndef GPAC_DISABLE_AV_PARSERS
 
423
                GF_MEDIA_DECODER_INTERFACE,
 
424
#endif
 
425
                0
 
426
        };
 
427
        return si; 
 
428
}
 
429
 
 
430
GF_BaseInterface *LoadInterface(u32 InterfaceType) 
 
431
{
 
432
#ifndef GPAC_DISABLE_AV_PARSERS
 
433
        if (InterfaceType == GF_MEDIA_DECODER_INTERFACE) return (GF_BaseInterface *)NewRVCDec();
 
434
#endif
 
435
        return NULL;
 
436
}
 
437
 
 
438
void ShutdownInterface(GF_BaseInterface *ifce)
 
439
{
 
440
        switch (ifce->InterfaceType) {
 
441
#ifndef GPAC_DISABLE_AV_PARSERS
 
442
        case GF_MEDIA_DECODER_INTERFACE: 
 
443
                DeleteRVCDec((GF_BaseDecoder*)ifce);
 
444
                break;
 
445
#endif
 
446
        }
 
447
}