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 "mediastreamer2/msfilter.h"
22
#include "mediastreamer2/msticker.h"
23
#include "mediastreamer2/msvideo.h"
25
#include <theora/theora.h>
27
typedef struct EncState{
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;
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;
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;
67
s->mtu=ms_get_payload_max_size()-6;
72
static void enc_uninit(MSFilter *f){
73
EncState *s=(EncState*)f->data;
74
theora_info_clear(&s->tinfo);
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;
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;
96
static int enc_add_attr(MSFilter *f, void*data){
97
/*const char *attr=(const char*)data;
98
EncState *s=(EncState*)f->data;*/
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;
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;
118
static int enc_set_br(MSFilter *f, void*data){
120
EncState *s=(EncState*)f->data;
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*/
131
vsize.width = MS_VIDEO_SIZE_4CIF_W;
132
vsize.height = MS_VIDEO_SIZE_4CIF_H;
135
}else if (br>=512000){
136
vsize.width = MS_VIDEO_SIZE_CIF_W;
137
vsize.height = MS_VIDEO_SIZE_CIF_H;
140
}else if (br>=256000){
141
vsize.width = MS_VIDEO_SIZE_CIF_W;
142
vsize.height = MS_VIDEO_SIZE_CIF_H;
145
}else if(br>=128000){
146
vsize.width=MS_VIDEO_SIZE_QCIF_W;
147
vsize.height=MS_VIDEO_SIZE_QCIF_H;
151
vsize.width=MS_VIDEO_SIZE_QCIF_W;
152
vsize.height=MS_VIDEO_SIZE_QCIF_H;
156
enc_set_vsize(f,&vsize);
161
static int enc_set_mtu(MSFilter *f, void*data){
162
EncState *s=(EncState*)f->data;
167
#define THEORA_RAW_DATA 0
168
#define THEORA_PACKED_CONF 1
169
#define THEORA_COMMENT 2
170
#define THEORA_RESERVED 3
172
#define NOT_FRAGMENTED 0
173
#define START_FRAGMENT 1
174
#define CONT_FRAGMENT 2
175
#define END_FRAGMENT 3
178
static inline void payload_header_set(uint8_t *buf, uint32_t ident, uint8_t ft, uint8_t tdt, uint8_t pkts){
180
tmp=((ident&0xFFFFFF)<<8) | ((ft&0x3)<<6) | ((tdt&0x3)<<4) | (pkts&0xf);
181
*((uint32_t*)buf)=htonl(tmp);
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;
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;
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;
199
static inline uint32_t payload_header_get_pkts(uint8_t *buf){
200
uint32_t *tmp=(uint32_t*)buf;
201
return ntohl(*tmp) & 0xf;
204
static int create_packed_conf(EncState *s){
206
theora_state *tstate=&s->tstate;
208
if (theora_encode_header(tstate,&p)!=0){
209
ms_error("theora_encode_header() error.");
213
memcpy(h->b_wptr,p.packet,p.bytes);
215
if (theora_encode_tables(tstate,&p)!=0){
216
ms_error("theora_encode_tables error.");
221
memcpy(t->b_wptr,p.packet,p.bytes);
229
static void enc_preprocess(MSFilter *f){
230
EncState *s=(EncState*)f->data;
232
if ((err=theora_encode_init(&s->tstate,&s->tinfo))!=0){
233
ms_error("error in theora_encode_init() : %i !",err);
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);
246
static void enc_postprocess(MSFilter *f){
247
EncState *s=(EncState*)f->data;
248
theora_clear(&s->tstate);
250
//If preprocess is called after postprocess,
251
//then we loose all info...
252
//theora_info_clear(&s->tinfo);
254
if (s->packed_conf) {
255
freemsg(s->packed_conf);
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);
267
static void packetize_and_send(MSFilter *f, EncState *s, mblk_t *om, uint32_t timestamp, uint8_t tdt){
271
static const int ident=0xdede;
273
if (om->b_wptr-om->b_rptr>=s->mtu){
275
packet->b_wptr=packet->b_rptr+s->mtu;
276
om->b_rptr=packet->b_wptr;
285
payload_header_set(h->b_wptr,ident,NOT_FRAGMENTED,tdt,1);
287
payload_header_set(h->b_wptr,ident,START_FRAGMENT,tdt,1);
290
payload_header_set(h->b_wptr,ident,END_FRAGMENT,tdt,1);
292
payload_header_set(h->b_wptr,ident,CONT_FRAGMENT,tdt,1);
295
*((uint16_t*)h->b_wptr)=htons(msgdsize(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);
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)){
315
static void enc_process(MSFilter *f){
318
EncState *s=(EncState*)f->data;
319
uint64_t timems=f->ticker->time;
320
uint32_t timestamp=timems*90;
324
while((im=ms_queue_get(f->inputs[0]))!=NULL){
325
/*for the firsts frames only send theora packed conf*/
328
s->start_time=timems;
330
elapsed=timems-s->start_time;
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);
338
ms_error("No packed conf to send.");
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.");
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);
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 },
373
MSFilterDesc ms_theora_enc_desc={
376
N_("The theora video encoder from xiph.org"),
391
MSFilterDesc ms_theora_enc_desc={
392
.id=MS_THEORA_ENC_ID,
394
.text=N_("The open-source and royalty-free 'theora' video codec from xiph.org"),
395
.category=MS_FILTER_ENCODER,
400
.preprocess=enc_preprocess,
401
.process=enc_process,
402
.postprocess=enc_postprocess,
409
MS_FILTER_DESC_EXPORT(ms_theora_enc_desc)
411
typedef struct DecState{
419
static void dec_init(MSFilter *f){
420
DecState *s=(DecState *)ms_new(DecState,1);
422
theora_info_init(&s->tinfo);
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);
436
static bool_t dec_init_theora(DecState *s, ogg_packet *op){
438
static const int ident_packet_size=42;
439
theora_comment_init(&tcom);
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);
453
ms_warning("error decoding theora tables");
456
ms_warning("error decoding theora header");
460
/* remove payload header and agregates fragmented packets */
461
static mblk_t *dec_unpacketize(MSFilter *f, DecState *s, mblk_t *im, int *tdt){
463
*tdt=payload_header_get_tdt((uint8_t*)im->b_rptr);
464
ft=payload_header_get_ft((uint8_t*)im->b_rptr);
467
if (ft==NOT_FRAGMENTED) return im;
468
if (ft==START_FRAGMENT){
469
if (s->curframe!=NULL)
470
freemsg(s->curframe);
472
}else if (ft==CONT_FRAGMENT){
473
if (s->curframe!=NULL)
474
concatb(s->curframe,im);
477
}else{/*end fragment*/
478
if (s->curframe!=NULL){
480
concatb(s->curframe,im);
481
msgpullup(s->curframe,-1);
491
static void dec_process_frame(MSFilter *f, DecState *s, ogg_packet *op){
493
if (theora_decode_packetin(&s->tstate,op)==0){
494
if (theora_decode_YUVout(&s->tstate,&yuv)==0){
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");
501
int len=(ylen)+(2*uvlen);
502
s->yuv=allocb(len,0);
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;
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;
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;
517
ms_queue_put(f->outputs[0],om);
520
ms_warning("theora decoding error");
524
static void dec_process(MSFilter *f){
529
DecState *s=(DecState*)f->data;
530
while( (im=ms_queue_get(f->inputs[0]))!=0) {
531
m=dec_unpacketize(f,s,im,&tdt);
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;
540
if (tdt!=THEORA_RAW_DATA) /*packed conf*/ {
542
if (dec_init_theora(s,&op))
547
dec_process_frame(f,s,&op);
549
ms_warning("skipping theora packet because decoder was not initialized yet with theora header and tables");
559
MSFilterDesc ms_theora_dec_desc={
562
N_("The theora video decoder from xiph.org"),
577
MSFilterDesc ms_theora_dec_desc={
578
.id=MS_THEORA_DEC_ID,
580
.text=N_("The theora video decoder from xiph.org"),
581
.category=MS_FILTER_DECODER,
586
.process=dec_process,
591
MS_FILTER_DESC_EXPORT(ms_theora_dec_desc)