Mercurial > pidgin
comparison src/mediastreamer/msavdecoder.c @ 12024:e67993da8a22
[gaim-migrate @ 14317]
I strongly suspect CruiseControl is going to yell at me for this.
A voice chat API, GUI + mediastreamer. This is what I'm using for Google Talk.
This doesn't actually do anything at all. There's no code in the Jabber plugin yet
to use this API (although it Works For Me). All it will do is compile and link.
If you're lucky.
To build this, you should install oRTP from Linphone, Speex and iLBC (also
from linphone, I believe). To not build this, ./configure --disable-vv.
Most of the configure.ac and Makefile.am hackery was lifted right out of
Linphone with a few modifications. It seems to work if you have everything
installed or if you --disable-vv. I haven't really tested not having
everything installed and not --disabling-vv.
It's kinda funky to include all of mediastreamer in the source tree like this,
but linphone doesn't build it as a separate library. I'll probably wind up
writing them a patch to build it as a .so so we can link it dynamically instead.
This code certainly isn't finished. It'll adapt as I progress on the Google code,
but it's certainly of more use here in CVS than in my personal tree.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Wed, 09 Nov 2005 08:07:20 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
12023:80faf1ca5280 | 12024:e67993da8a22 |
---|---|
1 /* | |
2 The mediastreamer library aims at providing modular media processing and I/O | |
3 for linphone, but also for any telephony application. | |
4 Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org | |
5 | |
6 This library is free software; you can redistribute it and/or | |
7 modify it under the terms of the GNU Lesser General Public | |
8 License as published by the Free Software Foundation; either | |
9 version 2.1 of the License, or (at your option) any later version. | |
10 | |
11 This library is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 Lesser General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU Lesser General Public | |
17 License along with this library; if not, write to the Free Software | |
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 */ | |
20 | |
21 #include "msavdecoder.h" | |
22 #include "mscodec.h" | |
23 extern MSFilter *ms_mpeg_encoder_new(); | |
24 extern MSFilter *ms_mpeg4_encoder_new(); | |
25 extern MSFilter *ms_h263_encoder_new(); | |
26 | |
27 | |
28 MSCodecInfo MPEGinfo={ | |
29 { | |
30 "MPEG1 codec", | |
31 0, | |
32 MS_FILTER_VIDEO_CODEC, | |
33 ms_mpeg_encoder_new, | |
34 "This is a MPEG1 codec taken from the ffmpeg project." | |
35 }, | |
36 ms_mpeg_encoder_new, | |
37 ms_mpeg_decoder_new, | |
38 0, | |
39 0, | |
40 0, /*bitrate */ | |
41 0, /*sample freq */ | |
42 0, | |
43 "MPV", | |
44 1, | |
45 1 | |
46 }; | |
47 | |
48 MSCodecInfo h263info={ | |
49 { | |
50 "H263 codec", | |
51 0, | |
52 MS_FILTER_VIDEO_CODEC, | |
53 ms_h263_encoder_new, | |
54 "This is a H263 codec taken from the ffmpeg project." | |
55 }, | |
56 ms_h263_encoder_new, | |
57 ms_h263_decoder_new, | |
58 0, | |
59 0, | |
60 0, /*bitrate */ | |
61 0, /*sample freq */ | |
62 0, | |
63 "H263", | |
64 1, | |
65 1 | |
66 }; | |
67 | |
68 MSCodecInfo MPEG4info={ | |
69 { | |
70 "MPEG4 codec", | |
71 0, | |
72 MS_FILTER_VIDEO_CODEC, | |
73 ms_mpeg4_encoder_new, | |
74 "This is a MPEG4 codec taken from the ffmpeg project." | |
75 }, | |
76 ms_mpeg4_encoder_new, | |
77 ms_mpeg4_decoder_new, | |
78 0, | |
79 0, | |
80 0, /*bitrate */ | |
81 0, /*sample freq */ | |
82 0, | |
83 "MP4V-ES", | |
84 1, | |
85 1 | |
86 }; | |
87 | |
88 | |
89 void ms_AVCodec_init() | |
90 { | |
91 avcodec_init(); | |
92 avcodec_register_all(); | |
93 ms_filter_register((MSFilterInfo*)&h263info); | |
94 //ms_filter_register((MSFilterInfo*)&MPEG4info); | |
95 } | |
96 | |
97 | |
98 static MSAVDecoderClass *ms_avdecoder_class=NULL; | |
99 | |
100 MSFilter *ms_h263decoder_new() | |
101 { | |
102 return ms_AVdecoder_new_with_codec(CODEC_ID_H263); | |
103 } | |
104 | |
105 MSFilter *ms_mpeg_decoder_new() | |
106 { | |
107 return ms_AVdecoder_new_with_codec(CODEC_ID_MPEG1VIDEO); | |
108 } | |
109 | |
110 MSFilter *ms_mpeg4_decoder_new() | |
111 { | |
112 return ms_AVdecoder_new_with_codec(CODEC_ID_MPEG4); | |
113 } | |
114 | |
115 MSFilter *ms_h263_decoder_new(){ | |
116 return ms_AVdecoder_new_with_codec(CODEC_ID_H263); | |
117 } | |
118 | |
119 MSFilter * ms_AVdecoder_new_with_codec(enum CodecID codec_id) | |
120 { | |
121 MSAVDecoder *enc; | |
122 | |
123 enc=g_malloc0(sizeof(MSAVDecoder)); | |
124 if (ms_avdecoder_class==NULL) | |
125 { | |
126 ms_avdecoder_class=g_malloc0(sizeof(MSAVDecoderClass)); | |
127 ms_AVdecoder_class_init(ms_avdecoder_class); | |
128 } | |
129 MS_FILTER(enc)->klass=(MSFilterClass*)ms_avdecoder_class; | |
130 ms_AVdecoder_init(enc,avcodec_find_decoder(codec_id)); | |
131 return MS_FILTER(enc); | |
132 } | |
133 | |
134 | |
135 void ms_AVdecoder_init(MSAVDecoder *dec, AVCodec *codec) | |
136 { | |
137 gint error; | |
138 | |
139 ms_filter_init(MS_FILTER(dec)); | |
140 MS_FILTER(dec)->inqueues=dec->q_inputs; | |
141 MS_FILTER(dec)->outqueues=dec->q_outputs; | |
142 avcodec_get_context_defaults(&dec->av_context); | |
143 dec->av_codec=codec; | |
144 dec->av_opened=0; | |
145 dec->skip_gob=1; | |
146 dec->obufwrap=NULL; | |
147 } | |
148 | |
149 void ms_AVdecoder_class_init(MSAVDecoderClass *klass) | |
150 { | |
151 ms_filter_class_init(MS_FILTER_CLASS(klass)); | |
152 ms_filter_class_set_name( MS_FILTER_CLASS(klass),"AVdecoder"); | |
153 MS_FILTER_CLASS(klass)->max_qinputs=MSAVDECODER_MAX_INPUTS; | |
154 MS_FILTER_CLASS(klass)->max_qoutputs=MSAVDECODER_MAX_INPUTS; | |
155 MS_FILTER_CLASS(klass)->r_maxgran=0; | |
156 MS_FILTER_CLASS(klass)->w_maxgran=0; | |
157 MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_AVdecoder_destroy; | |
158 MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_AVdecoder_process; | |
159 } | |
160 | |
161 void ms_AVdecoder_uninit(MSAVDecoder *dec) | |
162 { | |
163 if (dec->obufwrap!=NULL) ms_buffer_destroy(dec->obufwrap); | |
164 if (dec->av_opened) avcodec_close(&dec->av_context); | |
165 } | |
166 void ms_AVdecoder_destroy( MSAVDecoder *obj) | |
167 { | |
168 ms_AVdecoder_uninit(obj); | |
169 g_free(obj); | |
170 } | |
171 | |
172 gint ms_AVdecoder_set_format(MSAVDecoder *dec, gchar *fmt) | |
173 { | |
174 gint format; | |
175 if (strcmp(fmt,"YUV420P")==0) format=PIX_FMT_YUV420P; | |
176 else if (strcmp(fmt,"YUV422")==0) format=PIX_FMT_YUV422; | |
177 else if (strcmp(fmt,"RGB24")==0) format=PIX_FMT_RGB24; | |
178 else if (strcmp(fmt,"BGR24")==0) format=PIX_FMT_BGR24; | |
179 else if (strcmp(fmt,"YUV422P")==0) format=PIX_FMT_YUV422P; | |
180 else if (strcmp(fmt,"YUV444P")==0) format=PIX_FMT_YUV444P; | |
181 else { | |
182 g_warning("ms_AVdecoder_set_format: unsupported format %s.",fmt); | |
183 return -1; | |
184 } | |
185 dec->output_pix_fmt=format; | |
186 return 0; | |
187 } | |
188 | |
189 void ms_AVdecoder_process(MSAVDecoder *r) | |
190 { | |
191 AVFrame orig; | |
192 AVFrame transformed; | |
193 MSQueue *inq,*outq; | |
194 MSMessage *inm,*outm; | |
195 gint error; | |
196 gint got_picture; | |
197 gint len; | |
198 unsigned char *data; | |
199 AVCodecContext *ctx=&r->av_context; | |
200 gint gob_num; | |
201 | |
202 inq=r->q_inputs[0]; | |
203 outq=r->q_outputs[0]; | |
204 | |
205 /* get a picture from the input queue */ | |
206 inm=ms_queue_get(inq); | |
207 g_return_if_fail(inm!=NULL); | |
208 if (inm->size > 0) | |
209 { | |
210 guint32 *p = inm->data; | |
211 | |
212 if (!r->av_opened){ | |
213 error=avcodec_open(&r->av_context, r->av_codec); | |
214 if (error!=0) g_warning("avcodec_open() failed: %i",error); | |
215 else r->av_opened=1; | |
216 } | |
217 | |
218 gob_num = (ntohl(*p) >> 10) & 0x1f; | |
219 ms_trace("gob %i, size %i", gob_num, inm->size); | |
220 ms_trace("ms_AVdecoder_process: received %08x %08x", ntohl(p[0]), ntohl(p[1])); | |
221 | |
222 /* remove H.263 Payload Header */ | |
223 p[0] = htonl( ntohl(p[0]) & 0x0000ffff ); | |
224 | |
225 if (gob_num == 0){ | |
226 if (r->skip_gob == 0) | |
227 { | |
228 unsigned char *data = r->buf_compressed; | |
229 ms_trace("ms_AVdecoder_process: decoding %08x %08x %08x", ntohl(((unsigned int *)data)[0]), ntohl(((unsigned int *)data)[1]), ntohl(((unsigned int *)data)[2])); | |
230 while (r->buf_size > 0) { | |
231 len=avcodec_decode_video(&r->av_context,&orig,&got_picture,data,r->buf_size /*inm->size*/); | |
232 if (len<0) { | |
233 ms_warning("ms_AVdecoder_process: error %i.",len); | |
234 break; | |
235 } | |
236 if (got_picture) { | |
237 ms_trace("ms_AVdecoder_process: got_picture: width=%i height=%i fmt=%i", | |
238 ctx->width,ctx->height,ctx->pix_fmt); | |
239 /* set the image in the wanted format */ | |
240 outm=ms_message_alloc(); | |
241 if (r->obufwrap==NULL){ | |
242 r->obufwrap=ms_buffer_new(avpicture_get_size(r->output_pix_fmt,ctx->width,ctx->height)); | |
243 r->obufwrap->ref_count++; | |
244 } | |
245 ms_message_set_buf(outm,r->obufwrap); | |
246 avpicture_fill(&transformed,outm->data,r->output_pix_fmt,ctx->width,ctx->height); | |
247 img_convert(&transformed, r->output_pix_fmt, | |
248 &orig,ctx->pix_fmt,ctx->width,ctx->height); | |
249 ms_queue_put(outq,outm); | |
250 } | |
251 r->buf_size -= len; | |
252 data += len; | |
253 } | |
254 } | |
255 else { | |
256 r->skip_gob = 0; | |
257 } | |
258 memcpy(r->buf_compressed, inm->data, inm->size); | |
259 r->buf_size = inm->size; | |
260 } | |
261 else { | |
262 memcpy(r->buf_compressed + r->buf_size, inm->data, inm->size); | |
263 r->buf_size += inm->size; | |
264 } | |
265 } | |
266 ms_message_destroy(inm); | |
267 } | |
268 | |
269 | |
270 void ms_AVdecoder_set_width(MSAVDecoder *av,gint w) | |
271 { | |
272 av->av_context.width=av->width=w; | |
273 } | |
274 | |
275 void ms_AVdecoder_set_height(MSAVDecoder *av,gint h) | |
276 { | |
277 av->av_context.height=av->height=h; | |
278 } |