~ubuntu-branches/ubuntu/trusty/linphone/trusty-proposed

« back to all changes in this revision

Viewing changes to mediastreamer2/src/videofilters/theora.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell, Felix Lechner, Mark Purcell
  • Date: 2013-07-31 20:25:44 UTC
  • mfrom: (1.3.9) (15.1.6 experimental)
  • Revision ID: package-import@ubuntu.com-20130731202544-365xxf1ovlgwcexc
Tags: 3.6.1-1
* New upstream release
 - NEW packages liblinphone5, libmediastreamer-base3, libortp9 - match soname

[ Felix Lechner ]
* New upstream version
* Update Standards-Version: 3.9.4
* Port Linphone to the new libeXosip API v4
  - Fixes "FTBFS: sal_eXosip2.c:49:2: error: too few arguments to function
  'eXosip_guess_localip'" (Closes: #710638)
  - Fixes "FTBFS for libexosip2-4 API" (Closes: #709860)
* Add dh_autoreconf (while upstream patch is pending)
* Enable IPv6
* Install documentation README.Debian about 'cv_addr_book.pl'
* Update package names to reflect library SONAMEs
* Drop Build-Depends: libsdl1.2-dev, libsamplerate0-dev, libglib2.0-dev
* Add Build-Depends: automake, quilt, libudev-dev, libpcap-dev, libsoup2.4,
  libupnp-dev, libssl-dev, libxext-dev, mesa-common-dev, libcunit1-dev,
  libspandsp-dev, vim-common, sgmltools-lite, libsqlite3-dev, libpulse-dev,
  libopus-dev

[ Mark Purcell ]
* Add additional Build-Dpends:
 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
mediastreamer2 library - modular sound and video processing and streaming
 
3
Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
 
4
 
 
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.
 
9
 
 
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.
 
14
 
 
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.
 
18
*/
 
19
 
 
20
 
 
21
#include "mediastreamer2/msfilter.h"
 
22
#include "mediastreamer2/msticker.h"
 
23
#include "mediastreamer2/msvideo.h"
 
24
 
 
25
#include <theora/theora.h>
 
26
 
 
27
typedef struct EncState{
 
28
        theora_state tstate;
 
29
        theora_info tinfo;
 
30
        yuv_buffer yuv;
 
31
        mblk_t *packed_conf;
 
32
        uint64_t start_time;
 
33
        uint64_t conf_time;
 
34
        unsigned int mtu;
 
35
        unsigned int nframes;
 
36
} EncState;
 
37
 
 
38
static void enc_init(MSFilter *f){
 
39
        EncState *s=(EncState *)ms_new(EncState,1);
 
40
        theora_info_init(&s->tinfo);
 
41
        s->tinfo.width=MS_VIDEO_SIZE_CIF_W;
 
42
        s->tinfo.height=MS_VIDEO_SIZE_CIF_H;
 
43
        s->tinfo.frame_width=MS_VIDEO_SIZE_CIF_W;
 
44
        s->tinfo.frame_height=MS_VIDEO_SIZE_CIF_H;
 
45
        s->tinfo.offset_x=0;
 
46
        s->tinfo.offset_y=0;
 
47
        s->tinfo.target_bitrate=500000;
 
48
        s->tinfo.pixelformat=OC_PF_420;
 
49
        s->tinfo.fps_numerator=15;
 
50
        s->tinfo.fps_denominator=1;
 
51
        s->tinfo.aspect_numerator=1;
 
52
        s->tinfo.aspect_denominator=1;
 
53
        s->tinfo.colorspace=OC_CS_UNSPECIFIED;
 
54
        s->tinfo.dropframes_p=0;
 
55
        s->tinfo.quick_p=1;
 
56
        s->tinfo.quality=63;
 
57
        s->tinfo.keyframe_auto_p=1;
 
58
        s->tinfo.keyframe_frequency=64;
 
59
        s->tinfo.keyframe_frequency_force=64;
 
60
        s->tinfo.keyframe_data_target_bitrate=s->tinfo.target_bitrate*1.2;
 
61
        s->tinfo.keyframe_auto_threshold=80;
 
62
        s->tinfo.keyframe_mindistance=8;
 
63
        s->tinfo.noise_sensitivity=1;
 
64
        s->packed_conf=NULL;
 
65
        s->start_time=0;
 
66
        s->conf_time=0;
 
67
        s->mtu=ms_get_payload_max_size()-6;
 
68
        s->nframes=0;
 
69
        f->data=s;
 
70
}
 
71
 
 
72
static void enc_uninit(MSFilter *f){
 
73
        EncState *s=(EncState*)f->data;
 
74
        theora_info_clear(&s->tinfo);
 
75
        ms_free(s);
 
76
}
 
77
 
 
78
static int enc_set_vsize(MSFilter *f, void*data){
 
79
        MSVideoSize *vs=(MSVideoSize*)data;
 
80
        EncState *s=(EncState*)f->data;
 
81
        s->tinfo.width=vs->width;
 
82
        s->tinfo.height=vs->height;
 
83
        s->tinfo.frame_width=vs->width;
 
84
        s->tinfo.frame_height=vs->height;
 
85
        return 0;
 
86
}
 
87
 
 
88
static int enc_get_vsize(MSFilter *f, void *data){
 
89
        EncState *s=(EncState*)f->data;
 
90
        MSVideoSize *vs=(MSVideoSize*)data;
 
91
        vs->width=s->tinfo.width;
 
92
        vs->height=s->tinfo.height;
 
93
        return 0;
 
94
}
 
95
 
 
96
static int enc_add_attr(MSFilter *f, void*data){
 
97
        /*const char *attr=(const char*)data;
 
98
        EncState *s=(EncState*)f->data;*/
 
99
        return 0;
 
100
}
 
101
 
 
102
static int enc_set_fps(MSFilter *f, void *data){
 
103
        float *fps=(float*)data;
 
104
        EncState *s=(EncState*)f->data;
 
105
        s->tinfo.fps_numerator=*fps;
 
106
        s->tinfo.keyframe_frequency=(*fps)*5;
 
107
        s->tinfo.keyframe_frequency_force=(*fps)*5;
 
108
        return 0;
 
109
}
 
110
 
 
111
static int enc_get_fps(MSFilter *f, void *data){
 
112
        EncState *s=(EncState*)f->data;
 
113
        float *fps=(float*)data;
 
114
        *fps=s->tinfo.fps_numerator;
 
115
        return 0;
 
116
}
 
117
 
 
118
static int enc_set_br(MSFilter *f, void*data){
 
119
        int br=*(int*)data;
 
120
        EncState *s=(EncState*)f->data;
 
121
        MSVideoSize vsize;
 
122
        float fps;
 
123
        float codecbr=(float)br;
 
124
        vsize.width=s->tinfo.width;
 
125
        vsize.height=s->tinfo.height;
 
126
        fps=s->tinfo.fps_numerator;
 
127
        s->tinfo.target_bitrate=codecbr*0.9;
 
128
        s->tinfo.keyframe_data_target_bitrate=codecbr;
 
129
        /*those default settings would need to be affined*/
 
130
        if (br>=1024000){
 
131
                vsize.width = MS_VIDEO_SIZE_4CIF_W;
 
132
                vsize.height = MS_VIDEO_SIZE_4CIF_H;
 
133
                s->tinfo.quality=15;
 
134
                fps=30;
 
135
        }else if (br>=512000){
 
136
                vsize.width = MS_VIDEO_SIZE_CIF_W;
 
137
                vsize.height = MS_VIDEO_SIZE_CIF_H;
 
138
                s->tinfo.quality=15;
 
139
                fps=15;
 
140
        }else if (br>=256000){
 
141
                vsize.width = MS_VIDEO_SIZE_CIF_W;
 
142
                vsize.height = MS_VIDEO_SIZE_CIF_H;
 
143
                s->tinfo.quality=5;
 
144
                fps=15;
 
145
        }else if(br>=128000){
 
146
                vsize.width=MS_VIDEO_SIZE_QCIF_W;
 
147
                vsize.height=MS_VIDEO_SIZE_QCIF_H;
 
148
                s->tinfo.quality=20;
 
149
                fps=10;
 
150
        }else if(br>=64000){
 
151
                vsize.width=MS_VIDEO_SIZE_QCIF_W;
 
152
                vsize.height=MS_VIDEO_SIZE_QCIF_H;
 
153
                s->tinfo.quality=7;
 
154
                fps=7;
 
155
        }
 
156
        enc_set_vsize(f,&vsize);
 
157
        enc_set_fps(f,&fps);
 
158
        return 0;
 
159
}
 
160
 
 
161
static int enc_set_mtu(MSFilter *f, void*data){
 
162
        EncState *s=(EncState*)f->data;
 
163
        s->mtu=*(int*)data;
 
164
        return 0;
 
165
}
 
166
 
 
167
#define THEORA_RAW_DATA 0
 
168
#define THEORA_PACKED_CONF 1
 
169
#define THEORA_COMMENT 2
 
170
#define THEORA_RESERVED 3
 
171
 
 
172
#define NOT_FRAGMENTED 0
 
173
#define START_FRAGMENT 1
 
174
#define CONT_FRAGMENT 2
 
175
#define END_FRAGMENT 3
 
176
 
 
177
 
 
178
static inline void payload_header_set(uint8_t *buf, uint32_t ident, uint8_t ft, uint8_t tdt, uint8_t pkts){
 
179
        uint32_t tmp;
 
180
        tmp=((ident&0xFFFFFF)<<8) | ((ft&0x3)<<6) | ((tdt&0x3)<<4) | (pkts&0xf);
 
181
        *((uint32_t*)buf)=htonl(tmp);
 
182
}
 
183
 
 
184
static inline uint32_t payload_header_get_ident(uint8_t *buf){
 
185
        uint32_t *tmp=(uint32_t*)buf;
 
186
        return (ntohl(*tmp)>>8) & 0xFFFFFF;
 
187
}
 
188
 
 
189
static inline uint32_t payload_header_get_tdt(uint8_t *buf){
 
190
        uint32_t *tmp=(uint32_t*)buf;
 
191
        return ((ntohl(*tmp))>>4) & 0x3;
 
192
}
 
193
 
 
194
static inline uint32_t payload_header_get_ft(uint8_t *buf){
 
195
        uint32_t *tmp=(uint32_t*)buf;
 
196
        return ((ntohl(*tmp))>>6) & 0x3;
 
197
}
 
198
 
 
199
static inline uint32_t payload_header_get_pkts(uint8_t *buf){
 
200
        uint32_t *tmp=(uint32_t*)buf;
 
201
        return ntohl(*tmp) & 0xf;
 
202
}
 
203
 
 
204
static int create_packed_conf(EncState *s){
 
205
        ogg_packet p;
 
206
        theora_state *tstate=&s->tstate;
 
207
        mblk_t *h,*t;
 
208
        if (theora_encode_header(tstate,&p)!=0){
 
209
                ms_error("theora_encode_header() error.");
 
210
                return -1;
 
211
        }
 
212
        h=allocb(p.bytes,0);
 
213
        memcpy(h->b_wptr,p.packet,p.bytes);
 
214
        h->b_wptr+=p.bytes;
 
215
        if (theora_encode_tables(tstate,&p)!=0){
 
216
                ms_error("theora_encode_tables error.");
 
217
                freemsg(h);
 
218
                return -1;
 
219
        }
 
220
        t=allocb(p.bytes,0);
 
221
        memcpy(t->b_wptr,p.packet,p.bytes);
 
222
        t->b_wptr+=p.bytes;
 
223
        h->b_cont=t;
 
224
        msgpullup(h,-1);
 
225
        s->packed_conf=h;
 
226
        return 0;
 
227
}
 
228
 
 
229
static void enc_preprocess(MSFilter *f){
 
230
        EncState *s=(EncState*)f->data;
 
231
        int err;
 
232
        if ((err=theora_encode_init(&s->tstate,&s->tinfo))!=0){
 
233
                ms_error("error in theora_encode_init() : %i !",err);
 
234
        }
 
235
        s->yuv.y_width=s->tinfo.width;
 
236
        s->yuv.y_height=s->tinfo.height;
 
237
        s->yuv.y_stride=s->tinfo.width;
 
238
        s->yuv.uv_width=s->tinfo.width/2;
 
239
        s->yuv.uv_height=s->tinfo.height/2;
 
240
        s->yuv.uv_stride=s->tinfo.width/2;
 
241
        create_packed_conf(s);
 
242
        s->conf_time=0;
 
243
        s->nframes=0;
 
244
}
 
245
 
 
246
static void enc_postprocess(MSFilter *f){
 
247
        EncState *s=(EncState*)f->data;
 
248
        theora_clear(&s->tstate);
 
249
        
 
250
        //If preprocess is called after postprocess,
 
251
        //then we loose all info...
 
252
        //theora_info_clear(&s->tinfo);
 
253
        
 
254
        if (s->packed_conf) {
 
255
                freemsg(s->packed_conf);
 
256
                s->packed_conf=NULL;
 
257
        }
 
258
}
 
259
 
 
260
static void enc_fill_yuv(yuv_buffer *yuv, mblk_t *im){
 
261
        yuv->y=(uint8_t*)im->b_rptr;
 
262
        yuv->u=(uint8_t*)im->b_rptr+(yuv->y_stride*yuv->y_height);
 
263
        yuv->v=(uint8_t*)yuv->u+(yuv->uv_stride*yuv->uv_height);
 
264
}
 
265
 
 
266
 
 
267
static void packetize_and_send(MSFilter *f, EncState *s, mblk_t *om, uint32_t timestamp, uint8_t tdt){
 
268
        mblk_t *packet;
 
269
        mblk_t *h;
 
270
        int npackets=0;
 
271
        static const int ident=0xdede;
 
272
        while(om!=NULL){
 
273
                if (om->b_wptr-om->b_rptr>=s->mtu){
 
274
                        packet=dupb(om);
 
275
                        packet->b_wptr=packet->b_rptr+s->mtu;
 
276
                        om->b_rptr=packet->b_wptr;
 
277
                }else {
 
278
                        packet=om;
 
279
                        om=NULL;
 
280
                }
 
281
                ++npackets;
 
282
                h=allocb(6,0);
 
283
                if (npackets==1){
 
284
                        if (om==NULL)
 
285
                                payload_header_set(h->b_wptr,ident,NOT_FRAGMENTED,tdt,1);
 
286
                        else
 
287
                                payload_header_set(h->b_wptr,ident,START_FRAGMENT,tdt,1);
 
288
                }else{
 
289
                        if (om==NULL)
 
290
                                payload_header_set(h->b_wptr,ident,END_FRAGMENT,tdt,1);
 
291
                        else
 
292
                                payload_header_set(h->b_wptr,ident,CONT_FRAGMENT,tdt,1);
 
293
                }
 
294
                h->b_wptr+=4;
 
295
                *((uint16_t*)h->b_wptr)=htons(msgdsize(packet));
 
296
                h->b_wptr+=2;
 
297
                h->b_cont=packet;
 
298
                mblk_set_timestamp_info(h,timestamp);
 
299
                ms_debug("sending theora frame of size %i",msgdsize(h));
 
300
                ms_queue_put(f->outputs[0],h);
 
301
        }
 
302
}
 
303
 
 
304
bool_t need_send_conf(EncState *s, uint64_t elapsed){
 
305
        /*send immediately then 10 seconds later */
 
306
        if ( (elapsed==0 && s->conf_time==0)
 
307
                || (elapsed>=3000 && s->conf_time==1)
 
308
                || (elapsed>=10000 && s->conf_time==2)){
 
309
                s->conf_time++;
 
310
                return TRUE;
 
311
        }
 
312
        return FALSE;
 
313
}
 
314
 
 
315
static void enc_process(MSFilter *f){
 
316
        mblk_t *im,*om;
 
317
        ogg_packet op;
 
318
        EncState *s=(EncState*)f->data;
 
319
        uint64_t timems=f->ticker->time;
 
320
        uint32_t timestamp=timems*90;
 
321
        uint64_t elapsed;
 
322
 
 
323
        
 
324
        while((im=ms_queue_get(f->inputs[0]))!=NULL){
 
325
                /*for the firsts frames only send theora packed conf*/
 
326
                om=NULL;
 
327
                if (s->nframes==0){
 
328
                        s->start_time=timems;
 
329
                }
 
330
                elapsed=timems-s->start_time;
 
331
 
 
332
                if (need_send_conf(s,elapsed)){
 
333
                        if (s->packed_conf) {
 
334
                                om=dupmsg(s->packed_conf);
 
335
                                ms_message("sending theora packed conf (%i bytes)",msgdsize(om));
 
336
                                packetize_and_send(f,s,om,timestamp,THEORA_PACKED_CONF);
 
337
                        }else {
 
338
                                ms_error("No packed conf to send.");
 
339
                        }
 
340
                }else{
 
341
                        enc_fill_yuv(&s->yuv,im);
 
342
                        ms_debug("subtmitting yuv frame to theora encoder...");
 
343
                        if (theora_encode_YUVin(&s->tstate,&s->yuv)!=0){
 
344
                                ms_error("theora_encode_YUVin error.");
 
345
                        }else{
 
346
                                if (theora_encode_packetout(&s->tstate,0,&op)==1){
 
347
                                        ms_debug("Got theora coded frame");
 
348
                                        om=allocb(op.bytes,0);
 
349
                                        memcpy(om->b_wptr,op.packet,op.bytes);
 
350
                                        om->b_wptr+=op.bytes;
 
351
                                        packetize_and_send(f,s,om,timestamp,THEORA_RAW_DATA);
 
352
                                }
 
353
                        }
 
354
                }
 
355
                freemsg(im);
 
356
                s->nframes++;
 
357
        }
 
358
}
 
359
 
 
360
static MSFilterMethod enc_methods[]={
 
361
        {       MS_FILTER_SET_VIDEO_SIZE, enc_set_vsize },
 
362
        {       MS_FILTER_SET_FPS,      enc_set_fps     },
 
363
        {       MS_FILTER_GET_VIDEO_SIZE, enc_get_vsize },
 
364
        {       MS_FILTER_GET_FPS,      enc_get_fps     },
 
365
        {       MS_FILTER_ADD_ATTR, enc_add_attr        },
 
366
        {       MS_FILTER_SET_BITRATE, enc_set_br       },
 
367
        {       MS_FILTER_SET_MTU, enc_set_mtu  },
 
368
        {       0                       , NULL }
 
369
};
 
370
 
 
371
#ifdef _MSC_VER
 
372
 
 
373
MSFilterDesc ms_theora_enc_desc={
 
374
        MS_THEORA_ENC_ID,
 
375
        "MSTheoraEnc",
 
376
        N_("The theora video encoder from xiph.org"),
 
377
        MS_FILTER_ENCODER,
 
378
        "theora",
 
379
        1,
 
380
        1,
 
381
        enc_init,
 
382
        enc_preprocess,
 
383
        enc_process,
 
384
        enc_postprocess,
 
385
        enc_uninit,
 
386
        enc_methods
 
387
};
 
388
 
 
389
#else
 
390
 
 
391
MSFilterDesc ms_theora_enc_desc={
 
392
        .id=MS_THEORA_ENC_ID,
 
393
        .name="MSTheoraEnc",
 
394
        .text=N_("The open-source and royalty-free 'theora' video codec from xiph.org"),
 
395
        .category=MS_FILTER_ENCODER,
 
396
        .enc_fmt="theora",
 
397
        .ninputs=1,
 
398
        .noutputs=1,
 
399
        .init=enc_init,
 
400
        .preprocess=enc_preprocess,
 
401
        .process=enc_process,
 
402
        .postprocess=enc_postprocess,
 
403
        .uninit=enc_uninit,
 
404
        .methods=enc_methods
 
405
};
 
406
 
 
407
#endif
 
408
 
 
409
MS_FILTER_DESC_EXPORT(ms_theora_enc_desc)
 
410
 
 
411
typedef struct DecState{
 
412
        theora_state tstate;
 
413
        theora_info tinfo;
 
414
        mblk_t *yuv;
 
415
        mblk_t *curframe;
 
416
        bool_t ready;
 
417
}DecState;
 
418
 
 
419
static void dec_init(MSFilter *f){
 
420
        DecState *s=(DecState *)ms_new(DecState,1);
 
421
        s->ready=FALSE;
 
422
        theora_info_init(&s->tinfo);
 
423
        s->yuv=NULL;
 
424
        s->curframe=NULL;
 
425
        f->data=s;
 
426
}
 
427
 
 
428
static void dec_uninit(MSFilter *f){
 
429
        DecState *s=(DecState*)f->data;
 
430
        if (s->yuv!=NULL) freemsg(s->yuv);
 
431
        if (s->curframe!=NULL) freemsg(s->curframe);
 
432
        theora_info_clear(&s->tinfo);
 
433
        ms_free(s);
 
434
}
 
435
 
 
436
static bool_t dec_init_theora(DecState *s, ogg_packet *op){
 
437
        theora_comment tcom;
 
438
        static const int ident_packet_size=42; 
 
439
        theora_comment_init(&tcom);
 
440
        tcom.vendor="dummy";
 
441
        op->b_o_s=1;
 
442
        if (theora_decode_header(&s->tinfo,&tcom,op)==0){
 
443
                op->packet+=ident_packet_size;
 
444
                op->bytes-=ident_packet_size;
 
445
                /*recall once to decode tables*/
 
446
                if (theora_decode_header(&s->tinfo,&tcom,op)==0){
 
447
                        if (theora_decode_init(&s->tstate,&s->tinfo)==0){
 
448
                                ms_debug("theora decoder ready, pixfmt=%i",
 
449
                                        s->tinfo.pixelformat);
 
450
                                return TRUE;    
 
451
                        }
 
452
                }else{
 
453
                        ms_warning("error decoding theora tables");
 
454
                }
 
455
        }else{
 
456
                ms_warning("error decoding theora header");
 
457
        }
 
458
        return FALSE;
 
459
}
 
460
/* remove payload header and agregates fragmented packets */
 
461
static mblk_t *dec_unpacketize(MSFilter *f, DecState *s, mblk_t *im, int *tdt){
 
462
        uint8_t ft;
 
463
        *tdt=payload_header_get_tdt((uint8_t*)im->b_rptr);
 
464
        ft=payload_header_get_ft((uint8_t*)im->b_rptr);
 
465
        im->b_rptr+=6;
 
466
        
 
467
        if (ft==NOT_FRAGMENTED) return im;
 
468
        if (ft==START_FRAGMENT){
 
469
                if (s->curframe!=NULL)
 
470
                        freemsg(s->curframe);
 
471
                s->curframe=im;
 
472
        }else if (ft==CONT_FRAGMENT){
 
473
                if (s->curframe!=NULL)
 
474
                        concatb(s->curframe,im);
 
475
                else
 
476
                        freemsg(im);
 
477
        }else{/*end fragment*/
 
478
                if (s->curframe!=NULL){
 
479
                        mblk_t *ret;
 
480
                        concatb(s->curframe,im);
 
481
                        msgpullup(s->curframe,-1);
 
482
                        ret=s->curframe;
 
483
                        s->curframe=NULL;
 
484
                        return ret;
 
485
                }else
 
486
                        freemsg(im);
 
487
        }
 
488
        return NULL;
 
489
}
 
490
 
 
491
static void dec_process_frame(MSFilter *f, DecState *s, ogg_packet *op){
 
492
        yuv_buffer yuv;
 
493
        if (theora_decode_packetin(&s->tstate,op)==0){
 
494
                if (theora_decode_YUVout(&s->tstate,&yuv)==0){
 
495
                        mblk_t *om;
 
496
                        int i;
 
497
                        int ylen=yuv.y_width*yuv.y_height;
 
498
                        int uvlen=yuv.uv_width*yuv.uv_height;
 
499
                        ms_debug("Got yuv buffer from theora decoder");
 
500
                        if (s->yuv==NULL){
 
501
                                int len=(ylen)+(2*uvlen);
 
502
                                s->yuv=allocb(len,0);
 
503
                        }
 
504
                        om=dupb(s->yuv);
 
505
                        for(i=0;i<yuv.y_height;++i){
 
506
                                memcpy(om->b_wptr,yuv.y+yuv.y_stride*i,yuv.y_width);
 
507
                                om->b_wptr+=yuv.y_width;
 
508
                        }
 
509
                        for(i=0;i<yuv.uv_height;++i){
 
510
                                memcpy(om->b_wptr,yuv.u+yuv.uv_stride*i,yuv.uv_width);
 
511
                                om->b_wptr+=yuv.uv_width;
 
512
                        }
 
513
                        for(i=0;i<yuv.uv_height;++i){
 
514
                                memcpy(om->b_wptr,yuv.v+yuv.uv_stride*i,yuv.uv_width);
 
515
                                om->b_wptr+=yuv.uv_width;
 
516
                        }
 
517
                        ms_queue_put(f->outputs[0],om);
 
518
                }
 
519
        }else{
 
520
                ms_warning("theora decoding error");
 
521
        }
 
522
}
 
523
 
 
524
static void dec_process(MSFilter *f){
 
525
        mblk_t *im;
 
526
        mblk_t *m;
 
527
        ogg_packet op;
 
528
        int tdt;
 
529
        DecState *s=(DecState*)f->data;
 
530
        while( (im=ms_queue_get(f->inputs[0]))!=0) {
 
531
                m=dec_unpacketize(f,s,im,&tdt);
 
532
                if (m!=NULL){
 
533
                        /* now in im we have only the theora data*/
 
534
                        op.packet=(uint8_t*)m->b_rptr;
 
535
                        op.bytes=m->b_wptr-m->b_rptr;
 
536
                        op.b_o_s=0;
 
537
                        op.e_o_s=0;
 
538
                        op.granulepos=0;
 
539
                        op.packetno=0;
 
540
                        if (tdt!=THEORA_RAW_DATA) /*packed conf*/ {
 
541
                                if (!s->ready){
 
542
                                        if (dec_init_theora(s,&op))
 
543
                                                s->ready=TRUE;
 
544
                                }
 
545
                        }else{
 
546
                                if (s->ready){
 
547
                                        dec_process_frame(f,s,&op);
 
548
                                }else{
 
549
                                        ms_warning("skipping theora packet because decoder was not initialized yet with theora header and tables");
 
550
                                }
 
551
                        }
 
552
                        freemsg(m);
 
553
                }
 
554
        }
 
555
}
 
556
 
 
557
#ifdef _MSC_VER
 
558
 
 
559
MSFilterDesc ms_theora_dec_desc={
 
560
        MS_THEORA_DEC_ID,
 
561
        "MSTheoraDec",
 
562
        N_("The theora video decoder from xiph.org"),
 
563
        MS_FILTER_DECODER,
 
564
        "theora",
 
565
        1,
 
566
        1,
 
567
        dec_init,
 
568
        NULL,
 
569
        dec_process,
 
570
        NULL,
 
571
        dec_uninit,
 
572
        NULL
 
573
};
 
574
 
 
575
#else
 
576
 
 
577
MSFilterDesc ms_theora_dec_desc={
 
578
        .id=MS_THEORA_DEC_ID,
 
579
        .name="MSTheoraDec",
 
580
        .text=N_("The theora video decoder from xiph.org"),
 
581
        .category=MS_FILTER_DECODER,
 
582
        .enc_fmt="theora",
 
583
        .ninputs=1,
 
584
        .noutputs=1,
 
585
        .init=dec_init,
 
586
        .process=dec_process,
 
587
        .uninit=dec_uninit
 
588
};
 
589
 
 
590
#endif
 
591
MS_FILTER_DESC_EXPORT(ms_theora_dec_desc)