source: mediastreamer2/linphone/mediastreamer2/src/videodec.c @ 0:5a6e836a86a3

Last change on this file since 0:5a6e836a86a3 was 0:5a6e836a86a3, checked in by aymeric <aymeric@…>, 5 years ago

Initial import

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@1 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 10.5 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#ifdef HAVE_CONFIG_H
21#include "mediastreamer-config.h"
22#endif
23
24#include "ffmpeg-priv.h"
25
26#include "mediastreamer2/msfilter.h"
27#include "mediastreamer2/msvideo.h"
28#include "rfc2429.h"
29
30
31extern void ms_ffmpeg_check_init();
32
33typedef struct DecState{
34        AVCodecContext av_context;
35        AVCodec *av_codec;
36        enum CodecID codec;
37        mblk_t *input;
38        YuvBuf outbuf;
39        mblk_t *yuv_msg;
40        struct SwsContext *sws_ctx;
41        int output_pix_fmt;
42        uint8_t dci[512];
43        int dci_size;
44        bool_t snow_initialized;
45}DecState;
46
47
48static void dec_init(MSFilter *f, enum CodecID cid){
49        DecState *s=(DecState *)ms_new0(DecState,1);
50        ms_ffmpeg_check_init();
51       
52        avcodec_get_context_defaults(&s->av_context);
53        s->av_codec=NULL;
54        s->codec=cid;
55        s->input=NULL;
56        s->yuv_msg=NULL;
57        s->output_pix_fmt=PIX_FMT_YUV420P;
58        s->snow_initialized=FALSE;
59        s->outbuf.w=0;
60        s->outbuf.h=0;
61        s->sws_ctx=NULL;
62        f->data=s;
63
64        s->av_codec=avcodec_find_decoder(s->codec);
65        if (s->av_codec==NULL){
66                ms_error("Could not find decoder %i!",s->codec);
67        }
68        /*
69        s->av_context.width=MS_VIDEO_SIZE_QCIF_W;
70        s->av_context.height=MS_VIDEO_SIZE_QCIF_H;
71        */
72}
73
74static void dec_h263_init(MSFilter *f){
75        dec_init(f,CODEC_ID_H263);
76}
77
78static void dec_mpeg4_init(MSFilter *f){
79        dec_init(f,CODEC_ID_MPEG4);
80}
81
82static void dec_mjpeg_init(MSFilter *f){
83        dec_init(f,CODEC_ID_MJPEG);
84}
85
86static void dec_snow_init(MSFilter *f){
87        dec_init(f,CODEC_ID_SNOW);
88}
89
90static void dec_uninit(MSFilter *f){
91        DecState *s=(DecState*)f->data;
92        if (s->input!=NULL) freemsg(s->input);
93        if (s->yuv_msg!=NULL) freemsg(s->yuv_msg);
94        if (s->sws_ctx!=NULL){
95                sws_freeContext(s->sws_ctx);
96                s->sws_ctx=NULL;
97        }
98        ms_free(s);
99}
100
101static int dec_add_fmtp(MSFilter *f, void *data){
102        const char *fmtp=(const char*)data;
103        DecState *s=(DecState*)f->data;
104        char config[512];
105        if (fmtp_get_value(fmtp,"config",config,sizeof(config))){
106                /*convert hexa decimal config string into a bitstream */
107                int i,j,max=strlen(config);
108                char octet[3];
109                octet[2]=0;
110                for(i=0,j=0;i<max;i+=2,++j){
111                        octet[0]=config[i];
112                        octet[1]=config[i+1];
113                        s->dci[j]=strtol(octet,NULL,16);
114                }
115                s->dci_size=j;
116                ms_message("Got mpeg4 config string: %s",config);
117        }
118        return 0;
119}
120
121static void dec_preprocess(MSFilter *f){
122        DecState *s=(DecState*)f->data;
123        int error;
124        /* we must know picture size before initializing snow decoder*/
125        if (s->codec!=CODEC_ID_SNOW){
126                error=avcodec_open(&s->av_context, s->av_codec);
127                if (error!=0) ms_error("avcodec_open() failed: %i",error);
128                if (s->codec==CODEC_ID_MPEG4 && s->dci_size>0){
129                        s->av_context.extradata=s->dci;
130                        s->av_context.extradata_size=s->dci_size;
131                }
132        }
133}
134
135static void dec_postprocess(MSFilter *f){
136        DecState *s=(DecState*)f->data;
137        if (s->av_context.codec!=NULL){
138                avcodec_close(&s->av_context);
139                s->av_context.codec=NULL;
140        }
141}
142
143static mblk_t * skip_rfc2190_header(mblk_t *inm){
144        if (msgdsize(inm) >= 4) {
145                uint8_t *ph = inm->b_rptr;
146                int F = (ph[0]>>7) & 0x1;
147                int P = (ph[0]>>6) & 0x1;
148                if (F == 0) inm->b_rptr += 4;  // mode A
149                else if (P == 0) inm->b_rptr += 8; // mode B
150                else inm->b_rptr += 12;   // mode C
151        } else {
152                freemsg(inm);
153                inm=NULL;
154        }
155        return inm;
156}
157
158static mblk_t * skip_rfc2429_header(mblk_t *inm){
159        if (msgdsize(inm) >= 2){
160                uint32_t *p = (uint32_t*)inm->b_rptr;
161                uint8_t *ph=inm->b_rptr;
162                int PLEN;
163                int gob_num;
164                bool_t P;
165               
166                P=rfc2429_get_P(ph);
167                PLEN=rfc2429_get_PLEN(ph);
168                /*printf("receiving new packet; P=%i; V=%i; PLEN=%i; PEBIT=%i\n",P,rfc2429_get_V(ph),PLEN,rfc2429_get_PEBIT(ph));
169                */
170                gob_num = (ntohl(*p) >> 10) & 0x1f;
171                /*ms_message("gob %i, size %i", gob_num, msgdsize(inm));
172                ms_message("ms_AVdecoder_process: received %08x %08x", ntohl(p[0]), ntohl(p[1]));*/
173               
174                /* remove H.263 Payload Header */
175                if (PLEN>0){
176                        /* we ignore the redundant picture header and
177                        directly go to the bitstream */
178                        inm->b_rptr+=PLEN;
179                }
180                if (P){
181                        inm->b_rptr[0]=inm->b_rptr[1]=0;
182                }else{
183                        /* no PSC omitted */
184                        inm->b_rptr+=2;
185                }
186                return inm;
187        }else freemsg(inm);
188        return NULL;
189}
190
191static mblk_t * parse_snow_header(DecState *s,mblk_t *inm){
192        if (msgdsize(inm) >= 4){
193                uint32_t h = ntohl(*(uint32_t*)inm->b_rptr);
194                if (!s->snow_initialized){
195                        int error;
196                        s->av_context.width=h>>16;
197                        s->av_context.height=h&0xffff;
198                        error=avcodec_open(&s->av_context, s->av_codec);
199                        if (error!=0) ms_error("avcodec_open() failed for snow: %i",error);
200                        else {
201                                s->snow_initialized=TRUE;
202                                ms_message("Snow decoder initialized,size=%ix%i",
203                                s->av_context.width,
204                                s->av_context.height);
205                        }
206                }
207                inm->b_rptr+=4;
208                return inm;
209        }else {
210                freemsg(inm);
211                return NULL;
212        }
213}
214
215static mblk_t *get_as_yuvmsg(MSFilter *f, DecState *s, AVFrame *orig){
216        AVCodecContext *ctx=&s->av_context;
217
218        if (s->outbuf.w!=ctx->width || s->outbuf.h!=ctx->height){
219                if (s->sws_ctx!=NULL){
220                        sws_freeContext(s->sws_ctx);
221                        s->sws_ctx=NULL;
222                }
223                s->yuv_msg=yuv_buf_alloc(&s->outbuf,ctx->width,ctx->height);
224                s->outbuf.w=ctx->width;
225                s->outbuf.h=ctx->height;
226                s->sws_ctx=sws_getContext(ctx->width,ctx->height,ctx->pix_fmt,
227                        ctx->width,ctx->height,s->output_pix_fmt,SWS_FAST_BILINEAR,
228                        NULL, NULL, NULL);
229        }
230        if (sws_scale(s->sws_ctx,orig->data,orig->linesize, 0,
231                                        ctx->height, s->outbuf.planes, s->outbuf.strides)<0){
232                ms_error("%s: error in sws_scale().",f->desc->name);
233        }
234        return dupmsg(s->yuv_msg);
235}
236
237static void dec_process_frame(MSFilter *f, mblk_t *inm){
238        DecState *s=(DecState*)f->data;
239        AVFrame orig;
240        int got_picture;
241        /* get a picture from the input queue */
242       
243        if (f->desc->id==MS_H263_DEC_ID) inm=skip_rfc2429_header(inm);
244        else if (f->desc->id==MS_H263_OLD_DEC_ID) inm=skip_rfc2190_header(inm);
245        else if (s->codec==CODEC_ID_SNOW && s->input==NULL) inm=parse_snow_header(s,inm);
246        if (inm){
247                /* accumulate the video packet until we have the rtp markbit*/
248                if (s->input==NULL){
249                        s->input=inm;
250                }else{
251                        concatb(s->input,inm);
252                }
253               
254                if (mblk_get_marker_info(inm)){
255                        mblk_t *frame;
256                        int remain,len;
257                        /*ms_message("got marker bit !");*/
258                        /*append some padding bytes for ffmpeg to safely
259                        read extra bytes...*/
260                        msgpullup(s->input,msgdsize(s->input)+8);
261                        frame=s->input;
262                        s->input=NULL;
263                        while ( (remain=frame->b_wptr-frame->b_rptr)> 0) {
264                                len=avcodec_decode_video(&s->av_context,&orig,&got_picture,(uint8_t*)frame->b_rptr,remain );
265                                if (len<=0) {
266                                        ms_warning("ms_AVdecoder_process: error %i.",len);
267                                        break;
268                                }
269                                if (got_picture) {
270                                        ms_queue_put(f->outputs[0],get_as_yuvmsg(f,s,&orig));
271                                }
272                                frame->b_rptr+=len;
273                        }
274                        freemsg(frame);
275                }
276        }
277}
278
279static void dec_process(MSFilter *f){
280        mblk_t *inm;
281        while((inm=ms_queue_get(f->inputs[0]))!=0){
282                dec_process_frame(f,inm);
283        }
284}
285
286
287static MSFilterMethod methods[]={
288        {               MS_FILTER_ADD_FMTP              ,       dec_add_fmtp    },
289        {               0               ,               NULL                    }
290};
291
292#ifdef _MSC_VER
293
294MSFilterDesc ms_h263_dec_desc={
295        MS_H263_DEC_ID,
296        "MSH263Dec",
297        "A H.263 decoder using ffmpeg library",
298        MS_FILTER_DECODER,
299        "H263-1998",
300        1,
301        1,
302        dec_h263_init,
303        dec_preprocess,
304        dec_process,
305        dec_postprocess,
306        dec_uninit,
307        methods
308};
309
310MSFilterDesc ms_h263_old_dec_desc={
311        MS_H263_DEC_ID,
312        "MSH263OldDec",
313        "A H.263 decoder using ffmpeg library",
314        MS_FILTER_DECODER,
315        "H263",
316        1,
317        1,
318        dec_h263_init,
319        dec_preprocess,
320        dec_process,
321        dec_postprocess,
322        dec_uninit,
323        methods
324};
325
326
327MSFilterDesc ms_mpeg4_dec_desc={
328        MS_MPEG4_DEC_ID,
329        "MSMpeg4Dec",
330        "A MPEG4 decoder using ffmpeg library",
331        MS_FILTER_DECODER,
332        "MP4V-ES",
333        1,
334        1,
335        dec_mpeg4_init,
336        dec_preprocess,
337        dec_process,
338        dec_postprocess,
339        dec_uninit,
340        methods
341};
342
343MSFilterDesc ms_mjpeg_dec_desc={
344        MS_MJPEG_DEC_ID,
345        "MSMJpegDec",
346        "A MJPEG decoder using ffmpeg library",
347        MS_FILTER_DECODER,
348        "MJPEG",
349        1,
350        1,
351        dec_mjpeg_init,
352        dec_preprocess,
353        dec_process,
354        dec_postprocess,
355        dec_uninit,
356        methods
357};
358
359MSFilterDesc ms_snow_dec_desc={
360        MS_SNOW_DEC_ID,
361        "MSSnowDec",
362        "A snow decoder using ffmpeg library",
363        MS_FILTER_DECODER,
364        "snow",
365        1,
366        1,
367        dec_snow_init,
368        dec_preprocess,
369        dec_process,
370        dec_postprocess,
371        dec_uninit,
372        methods
373};
374
375#else
376
377MSFilterDesc ms_h263_dec_desc={
378        .id=MS_H263_DEC_ID,
379        .name="MSH263Dec",
380        .text="A H.263 decoder using ffmpeg library",
381        .category=MS_FILTER_DECODER,
382        .enc_fmt="H263-1998",
383        .ninputs=1,
384        .noutputs=1,
385        .init=dec_h263_init,
386        .preprocess=dec_preprocess,
387        .process=dec_process,
388        .postprocess=dec_postprocess,
389        .uninit=dec_uninit,
390        .methods= methods
391};
392
393MSFilterDesc ms_h263_old_dec_desc={
394        .id=MS_H263_OLD_DEC_ID,
395        .name="MSH263OldDec",
396        .text="A H.263 decoder using ffmpeg library",
397        .category=MS_FILTER_DECODER,
398        .enc_fmt="H263",
399        .ninputs=1,
400        .noutputs=1,
401        .init=dec_h263_init,
402        .preprocess=dec_preprocess,
403        .process=dec_process,
404        .postprocess=dec_postprocess,
405        .uninit=dec_uninit,
406        .methods= methods
407};
408
409
410MSFilterDesc ms_mpeg4_dec_desc={
411        .id=MS_MPEG4_DEC_ID,
412        .name="MSMpeg4Dec",
413        .text="A MPEG4 decoder using ffmpeg library",
414        .category=MS_FILTER_DECODER,
415        .enc_fmt="MP4V-ES",
416        .ninputs=1,
417        .noutputs=1,
418        .init=dec_mpeg4_init,
419        .preprocess=dec_preprocess,
420        .process=dec_process,
421        .postprocess=dec_postprocess,
422        .uninit=dec_uninit,
423        .methods= methods
424};
425
426MSFilterDesc ms_mjpeg_dec_desc={
427        .id=MS_MJPEG_DEC_ID,
428        .name="MSMJpegDec",
429        .text="A MJEPG decoder using ffmpeg library",
430        .category=MS_FILTER_DECODER,
431        .enc_fmt="MJPEG",
432        .ninputs=1,
433        .noutputs=1,
434        .init=dec_mjpeg_init,
435        .preprocess=dec_preprocess,
436        .process=dec_process,
437        .postprocess=dec_postprocess,
438        .uninit=dec_uninit,
439        .methods= methods
440};
441
442MSFilterDesc ms_snow_dec_desc={
443        .id=MS_SNOW_DEC_ID,
444        .name="MSSnowDec",
445        .text="A snow decoder using ffmpeg library",
446        .category=MS_FILTER_DECODER,
447        .enc_fmt="x-snow",
448        .ninputs=1,
449        .noutputs=1,
450        .init=dec_snow_init,
451        .preprocess=dec_preprocess,
452        .process=dec_process,
453        .postprocess=dec_postprocess,
454        .uninit=dec_uninit,
455        .methods= methods
456};
457
458#endif
459
460MS_FILTER_DESC_EXPORT(ms_mpeg4_dec_desc)
461MS_FILTER_DESC_EXPORT(ms_h263_dec_desc)
462MS_FILTER_DESC_EXPORT(ms_h263_old_dec_desc)
463MS_FILTER_DESC_EXPORT(ms_mjpeg_dec_desc)
464MS_FILTER_DESC_EXPORT(ms_snow_dec_desc)
Note: See TracBrowser for help on using the repository browser.