12024
|
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 }
|