2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "mediastreamer-config.h"
24 #include "ffmpeg-priv.h"
26 #include "mediastreamer2/msfilter.h"
27 #include "mediastreamer2/msvideo.h"
31 extern void ms_ffmpeg_check_init();
33 typedef struct DecState{
34 AVCodecContext av_context;
40 struct SwsContext *sws_ctx;
41 enum PixelFormat output_pix_fmt;
44 bool_t snow_initialized;
48 static void dec_init(MSFilter *f, enum CodecID cid){
49 DecState *s=(DecState *)ms_new0(DecState,1);
50 ms_ffmpeg_check_init();
52 avcodec_get_context_defaults(&s->av_context);
57 s->output_pix_fmt=PIX_FMT_YUV420P;
58 s->snow_initialized=FALSE;
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);
69 s->av_context.width=MS_VIDEO_SIZE_QCIF_W;
70 s->av_context.height=MS_VIDEO_SIZE_QCIF_H;
74 static void dec_h263_init(MSFilter *f){
75 dec_init(f,CODEC_ID_H263);
78 static void dec_mpeg4_init(MSFilter *f){
79 dec_init(f,CODEC_ID_MPEG4);
82 static void dec_mjpeg_init(MSFilter *f){
83 dec_init(f,CODEC_ID_MJPEG);
86 static void dec_snow_init(MSFilter *f){
87 dec_init(f,CODEC_ID_SNOW);
90 static 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);
101 static int dec_add_fmtp(MSFilter *f, void *data){
102 const char *fmtp=(const char*)data;
103 DecState *s=(DecState*)f->data;
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);
110 for(i=0,j=0;i<max;i+=2,++j){
112 octet[1]=config[i+1];
113 s->dci[j]=(uint8_t)strtol(octet,NULL,16);
116 ms_message("Got mpeg4 config string: %s",config);
121 static void dec_preprocess(MSFilter *f){
122 DecState *s=(DecState*)f->data;
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;
135 static 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;
143 static 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
158 static 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;
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));
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]));*/
174 /* remove H.263 Payload Header */
176 /* we ignore the redundant picture header and
177 directly go to the bitstream */
181 inm->b_rptr[0]=inm->b_rptr[1]=0;
191 static 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){
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);
201 s->snow_initialized=TRUE;
202 ms_message("Snow decoder initialized,size=%ix%i",
204 s->av_context.height);
216 //unsigned int tspec:8; /* type-specific field */
217 unsigned int off:32; /* fragment byte offset */
218 uint8_t type; /* id of jpeg decoder params */
219 uint8_t q; /* quantization factor (or table id) */
220 uint8_t width; /* frame width in 8 pixel blocks */
221 uint8_t height; /* frame height in 8 pixel blocks */
228 unsigned int count:14;
231 struct jpeghdr_qtable {
238 static u_char lum_dc_codelens[] = {
239 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
242 static u_char lum_dc_symbols[] = {
243 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
246 static u_char lum_ac_codelens[] = {
247 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d,
250 static u_char lum_ac_symbols[] = {
251 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
252 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
253 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
254 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
255 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
256 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
257 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
258 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
259 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
260 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
261 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
262 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
263 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
264 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
265 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
266 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
267 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
268 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
269 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
270 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
274 static u_char chm_dc_codelens[] = {
275 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
278 static u_char chm_dc_symbols[] = {
279 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
282 static u_char chm_ac_codelens[] = {
283 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77,
286 static u_char chm_ac_symbols[] = {
287 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
288 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
289 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
290 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
291 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
292 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
293 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
294 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
295 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
296 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
297 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
298 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
299 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
300 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
301 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
302 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
303 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
304 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
305 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
306 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
311 MakeQuantHeader(u_char *p, u_char *qt, int tableNo, int table_len)
314 *p++ = 0xdb; /* DQT */
315 *p++ = 0; /* length msb */
316 *p++ = table_len+3; /* length lsb */
318 memcpy(p, qt, table_len);
319 return (p + table_len);
323 MakeHuffmanHeader(u_char *p, u_char *codelens, int ncodes,
324 u_char *symbols, int nsymbols, int tableNo,
328 *p++ = 0xc4; /* DHT */
329 *p++ = 0; /* length msb */
330 *p++ = 3 + ncodes + nsymbols; /* length lsb */
331 *p++ = (tableClass << 4) | tableNo;
332 memcpy(p, codelens, ncodes);
334 memcpy(p, symbols, nsymbols);
340 MakeDRIHeader(u_char *p, u_short dri) {
342 *p++ = 0xdd; /* DRI */
343 *p++ = 0x0; /* length msb */
344 *p++ = 4; /* length lsb */
345 *p++ = dri >> 8; /* dri msb */
346 *p++ = dri & 0xff; /* dri lsb */
352 * type, width, height: as supplied in RTP/JPEG header
353 * lqt, cqt: quantization tables as either derived from
354 * the Q field using MakeTables() or as specified
356 * dri: restart interval in MCUs, or 0 if no restarts.
358 * p: pointer to return area
361 * The length of the generated headers.
363 * Generate a frame and scan headers that can be prepended to the
364 * RTP/JPEG data payload to produce a JPEG compressed image in
365 * interchange format (except for possible trailing garbage and
366 * absence of an EOI marker to terminate the scan).
368 static int MakeHeaders(u_char *p, int type, int w, int h, u_char *lqt,
369 u_char *cqt, unsigned table_len, u_short dri)
373 /* convert from blocks to pixels */
378 *p++ = 0xd8; /* SOI */
382 p = MakeQuantHeader(p, lqt, 0, table_len/2);
383 p = MakeQuantHeader(p, cqt, 1, table_len/2);
387 p = MakeQuantHeader(p, lqt, 0, table_len);
388 //p = MakeQuantHeader(p, lqt, 1, table_len);
391 p = MakeDRIHeader(p, dri);
394 *p++ = 0xc0; /* SOF */
395 *p++ = 0; /* length msb */
396 *p++ = 17; /* length lsb */
397 *p++ = 8; /* 8-bit precision */
398 *p++ = h >> 8; /* height msb */
399 *p++ = h; /* height lsb */
400 *p++ = w >> 8; /* width msb */
401 *p++ = w; /* wudth lsb */
402 *p++ = 3; /* number of components */
403 *p++ = 0; /* comp 0 */
405 *p++ = 0x21; /* hsamp = 2, vsamp = 1 */
407 *p++ = 0x22; /* hsamp = 2, vsamp = 2 */
408 *p++ = 0; /* quant table 0 */
409 *p++ = 1; /* comp 1 */
410 *p++ = 0x11; /* hsamp = 1, vsamp = 1 */
411 *p++ = table_len <= 64 ? 0x00 : 0x01; //1 /* quant table 1 */
412 *p++ = 2; /* comp 2 */
413 *p++ = 0x11; /* hsamp = 1, vsamp = 1 */
414 *p++ = table_len <= 64 ? 0x00 : 0x01; //1; /* quant table 1 */
415 p = MakeHuffmanHeader(p, lum_dc_codelens,
416 sizeof(lum_dc_codelens),
418 sizeof(lum_dc_symbols), 0, 0);
419 p = MakeHuffmanHeader(p, lum_ac_codelens,
420 sizeof(lum_ac_codelens),
422 sizeof(lum_ac_symbols), 0, 1);
423 p = MakeHuffmanHeader(p, chm_dc_codelens,
424 sizeof(chm_dc_codelens),
426 sizeof(chm_dc_symbols), 1, 0);
427 p = MakeHuffmanHeader(p, chm_ac_codelens,
428 sizeof(chm_ac_codelens),
430 sizeof(chm_ac_symbols), 1, 1);
433 *p++ = 0xda; /* SOS */
434 *p++ = 0; /* length msb */
435 *p++ = 12; /* length lsb */
436 *p++ = 3; /* 3 components */
437 *p++ = 0; /* comp 0 */
438 *p++ = 0; /* huffman table 0 */
439 *p++ = 1; /* comp 1 */
440 *p++ = 0x11; /* huffman table 1 */
441 *p++ = 2; /* comp 2 */
442 *p++ = 0x11; /* huffman table 1 */
443 *p++ = 0; /* first DCT coeff */
444 *p++ = 63; /* last DCT coeff */
445 *p++ = 0; /* sucessive approx. */
452 * Table K.1 from JPEG spec.
454 static const int jpeg_luma_quantizer[64] = {
455 16, 11, 10, 16, 24, 40, 51, 61,
456 12, 12, 14, 19, 26, 58, 60, 55,
457 14, 13, 16, 24, 40, 57, 69, 56,
458 14, 17, 22, 29, 51, 87, 80, 62,
459 18, 22, 37, 56, 68, 109, 103, 77,
460 24, 35, 55, 64, 81, 104, 113, 92,
461 49, 64, 78, 87, 103, 121, 120, 101,
462 72, 92, 95, 98, 112, 100, 103, 99
466 * Table K.2 from JPEG spec.
468 static const int jpeg_chroma_quantizer[64] = {
469 17, 18, 24, 47, 99, 99, 99, 99,
470 18, 21, 26, 66, 99, 99, 99, 99,
471 24, 26, 56, 99, 99, 99, 99, 99,
472 47, 66, 99, 99, 99, 99, 99, 99,
473 99, 99, 99, 99, 99, 99, 99, 99,
474 99, 99, 99, 99, 99, 99, 99, 99,
475 99, 99, 99, 99, 99, 99, 99, 99,
476 99, 99, 99, 99, 99, 99, 99, 99
480 * Call MakeTables with the Q factor and two u_char[64] return arrays
482 static void MakeTables(int q, u_char *lqt, u_char *cqt)
487 if (q < 1) factor = 1;
488 if (q > 99) factor = 99;
494 for (i=0; i < 64; i++) {
495 int lq = (jpeg_luma_quantizer[i] * q + 50) / 100;
496 int cq = (jpeg_chroma_quantizer[i] * q + 50) / 100;
498 /* Limit the quantizers to 1 <= q <= 255 */
500 else if (lq > 255) lq = 255;
504 else if (cq > 255) cq = 255;
510 read_rfc2435_header(DecState *s,mblk_t *inm)
512 if (msgdsize(inm) >= sizeof(struct jpeghdr)) {
513 struct jpeghdr *hdr = (struct jpeghdr *)inm->b_rptr;
514 uint32_t off = ntohl(*(uint32_t*)inm->b_rptr);
516 uint16_t table_len=0;
519 mblk_t *headers=NULL;
521 inm->b_rptr += sizeof(struct jpeghdr);
523 struct jpeghdr_rst *rsthdr = (struct jpeghdr_rst *)inm->b_rptr;
524 dri = ntohs(rsthdr->dri);
525 inm->b_rptr += sizeof(struct jpeghdr_rst);
530 inm->b_rptr++; /* MBZ */
531 inm->b_rptr++; /* Precision */
532 table_len = ntohs(*((uint16_t*)(inm->b_rptr)));
533 inm->b_rptr++; /* len */
534 inm->b_rptr++; /* len */
535 headers = allocb(495 + table_len*2 + (dri > 0 ? 6 : 0), 0);
536 len = MakeHeaders(headers->b_rptr, hdr->type, hdr->width, hdr->height,
537 inm->b_rptr, inm->b_rptr+table_len/2, table_len, dri);
538 inm->b_rptr += table_len;
539 headers->b_wptr += len;
541 uint8_t lqt_cqt[128];
542 MakeTables(hdr->q, lqt_cqt, lqt_cqt+64);
544 headers = allocb(495 + table_len + (dri > 0 ? 6 : 0), 0);
545 len = MakeHeaders(headers->b_rptr, hdr->type, hdr->width, hdr->height,
546 lqt_cqt, lqt_cqt+64, table_len, dri);
547 headers->b_wptr += len;
553 /* prepend headers to JPEG RTP data */
554 if (mblk_get_marker_info(inm))
555 mblk_set_marker_info(headers, TRUE);
557 msgpullup(headers, -1);
567 static mblk_t *get_as_yuvmsg(MSFilter *f, DecState *s, AVFrame *orig){
568 AVCodecContext *ctx=&s->av_context;
570 if (s->outbuf.w!=ctx->width || s->outbuf.h!=ctx->height){
571 if (s->sws_ctx!=NULL){
572 sws_freeContext(s->sws_ctx);
575 s->yuv_msg=yuv_buf_alloc(&s->outbuf,ctx->width,ctx->height);
576 s->outbuf.w=ctx->width;
577 s->outbuf.h=ctx->height;
578 s->sws_ctx=sws_getContext(ctx->width,ctx->height,ctx->pix_fmt,
579 ctx->width,ctx->height,s->output_pix_fmt,SWS_FAST_BILINEAR,
582 if (sws_scale(s->sws_ctx,orig->data,orig->linesize, 0,
583 ctx->height, s->outbuf.planes, s->outbuf.strides)<0){
584 ms_error("%s: error in sws_scale().",f->desc->name);
586 return dupmsg(s->yuv_msg);
589 static void dec_process_frame(MSFilter *f, mblk_t *inm){
590 DecState *s=(DecState*)f->data;
593 /* get a picture from the input queue */
595 if (f->desc->id==MS_H263_DEC_ID) inm=skip_rfc2429_header(inm);
596 else if (f->desc->id==MS_H263_OLD_DEC_ID) inm=skip_rfc2190_header(inm);
597 else if (s->codec==CODEC_ID_SNOW && s->input==NULL) inm=parse_snow_header(s,inm);
598 else if (s->codec==CODEC_ID_MJPEG && f->desc->id==MS_JPEG_DEC_ID) inm=read_rfc2435_header(s,inm);
600 /* accumulate the video packet until we have the rtp markbit*/
604 concatb(s->input,inm);
607 if (mblk_get_marker_info(inm)){
610 /*ms_message("got marker bit !");*/
611 /*append some padding bytes for ffmpeg to safely
612 read extra bytes...*/
613 msgpullup(s->input,msgdsize(s->input)+8);
616 while ( (remain=frame->b_wptr-frame->b_rptr)> 0) {
618 av_init_packet(&pkt);
619 pkt.data = frame->b_rptr;
621 len=avcodec_decode_video2(&s->av_context,&orig,&got_picture,&pkt);
622 /*len=avcodec_decode_video(&s->av_context,&orig,&got_picture,(uint8_t*)frame->b_rptr,remain );*/
624 ms_warning("ms_AVdecoder_process: error %i.",len);
628 ms_queue_put(f->outputs[0],get_as_yuvmsg(f,s,&orig));
637 static void dec_process(MSFilter *f){
639 while((inm=ms_queue_get(f->inputs[0]))!=0){
640 dec_process_frame(f,inm);
645 static MSFilterMethod methods[]={
646 { MS_FILTER_ADD_FMTP , dec_add_fmtp },
652 MSFilterDesc ms_h263_dec_desc={
655 N_("A H.263 decoder using ffmpeg library"),
668 MSFilterDesc ms_h263_old_dec_desc={
671 N_("A H.263 decoder using ffmpeg library"),
685 MSFilterDesc ms_mpeg4_dec_desc={
688 N_("A MPEG4 decoder using ffmpeg library"),
701 MSFilterDesc ms_jpeg_dec_desc={
704 N_("A RTP/JPEG decoder using ffmpeg library"),
717 MSFilterDesc ms_mjpeg_dec_desc={
720 N_("A MJPEG decoder using ffmpeg library"),
733 MSFilterDesc ms_snow_dec_desc={
736 N_("A snow decoder using ffmpeg library"),
751 MSFilterDesc ms_h263_dec_desc={
754 .text=N_("A H.263 decoder using ffmpeg library"),
755 .category=MS_FILTER_DECODER,
756 .enc_fmt="H263-1998",
760 .preprocess=dec_preprocess,
761 .process=dec_process,
762 .postprocess=dec_postprocess,
767 MSFilterDesc ms_h263_old_dec_desc={
768 .id=MS_H263_OLD_DEC_ID,
769 .name="MSH263OldDec",
770 .text=N_("A H.263 decoder using ffmpeg library"),
771 .category=MS_FILTER_DECODER,
776 .preprocess=dec_preprocess,
777 .process=dec_process,
778 .postprocess=dec_postprocess,
784 MSFilterDesc ms_mpeg4_dec_desc={
787 .text="A MPEG4 decoder using ffmpeg library",
788 .category=MS_FILTER_DECODER,
792 .init=dec_mpeg4_init,
793 .preprocess=dec_preprocess,
794 .process=dec_process,
795 .postprocess=dec_postprocess,
800 MSFilterDesc ms_jpeg_dec_desc={
803 .text="A RTP/MJEPG decoder using ffmpeg library",
804 .category=MS_FILTER_DECODER,
808 .init=dec_mjpeg_init,
809 .preprocess=dec_preprocess,
810 .process=dec_process,
811 .postprocess=dec_postprocess,
816 MSFilterDesc ms_mjpeg_dec_desc={
819 .text="A MJEPG decoder using ffmpeg library",
820 .category=MS_FILTER_DECODER,
824 .init=dec_mjpeg_init,
825 .preprocess=dec_preprocess,
826 .process=dec_process,
827 .postprocess=dec_postprocess,
832 MSFilterDesc ms_snow_dec_desc={
835 .text="A snow decoder using ffmpeg library",
836 .category=MS_FILTER_DECODER,
841 .preprocess=dec_preprocess,
842 .process=dec_process,
843 .postprocess=dec_postprocess,
850 MS_FILTER_DESC_EXPORT(ms_mpeg4_dec_desc)
851 MS_FILTER_DESC_EXPORT(ms_h263_dec_desc)
852 MS_FILTER_DESC_EXPORT(ms_h263_old_dec_desc)
853 MS_FILTER_DESC_EXPORT(ms_snow_dec_desc)
855 /* decode JPEG image with RTP/jpeg headers */
856 MS_FILTER_DESC_EXPORT(ms_jpeg_dec_desc)
857 /* decode JPEG image with jpeg headers */
858 MS_FILTER_DESC_EXPORT(ms_mjpeg_dec_desc)