codec_ffmpeg.c

00001 /*
00002  * iaxclient: a cross-platform IAX softphone library
00003  *
00004  * Copyrights:
00005  * Copyright (C) 2003-2006, Horizon Wimba, Inc.
00006  * Copyright (C) 2007, Wimba, Inc.
00007  *
00008  * Contributors:
00009  * Steve Kann <stevek@stevek.com>
00010  * Peter Grayson <jpgrayson@gmail.com>
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU Lesser (Library) General Public License.
00014  *
00015  * A video codec using the ffmpeg library.
00016  */
00017 
00018 #include <stdlib.h>
00019 
00020 #include "codec_ffmpeg.h"
00021 #include "iaxclient_lib.h"
00022 
00023 #ifdef WIN32
00024 #include "libavcodec/avcodec.h"
00025 #else
00026 #include <ffmpeg/avcodec.h>
00027 #endif
00028 
00029 struct slice_header_t
00030 {
00031         unsigned char version;
00032         unsigned short source_id;
00033         unsigned char frame_index;
00034         unsigned char slice_index;
00035         unsigned char num_slices;
00036 };
00037 
00038 struct encoder_ctx
00039 {
00040         AVCodecContext * avctx;
00041         AVFrame * picture;
00042 
00043         struct slice_header_t slice_header;
00044 
00045         unsigned char *frame_buf;
00046         int frame_buf_len;
00047 };
00048 
00049 struct decoder_ctx
00050 {
00051         AVCodecContext * avctx;
00052         AVFrame * picture;
00053 
00054         struct slice_header_t slice_header;
00055         int frame_size;
00056 
00057         unsigned char * frame_buf;
00058         int frame_buf_len;
00059 };
00060 
00061 static struct slice_set_t * g_slice_set = 0;
00062 
00063 static enum CodecID map_iaxc_codec_to_avcodec(int format)
00064 {
00065         switch (format)
00066         {
00067         case IAXC_FORMAT_H261:
00068                 return CODEC_ID_H261;
00069 
00070         case IAXC_FORMAT_H263:
00071                 return CODEC_ID_H263;
00072 
00073         case IAXC_FORMAT_H263_PLUS:
00074                 return CODEC_ID_H263P;
00075 
00076         case IAXC_FORMAT_MPEG4:
00077                 return CODEC_ID_MPEG4;
00078 
00079         case IAXC_FORMAT_H264:
00080                 return CODEC_ID_H264;
00081 
00082         case IAXC_FORMAT_THEORA:
00083                 return CODEC_ID_THEORA;
00084 
00085         default:
00086                 return CODEC_ID_NONE;
00087         }
00088 }
00089 
00090 static void destroy(struct iaxc_video_codec *c)
00091 {
00092         if (c)
00093         {
00094                 struct encoder_ctx *e = (struct encoder_ctx *) c->encstate;
00095                 struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
00096 
00097                 if (e)
00098                 {
00099                         av_freep(&e->avctx);
00100                         av_freep(&e->picture);
00101                         if (e->frame_buf)
00102                                 free(e->frame_buf);
00103                         free(e);
00104                 }
00105 
00106                 if (d)
00107                 {
00108                         av_freep(&d->avctx);
00109                         av_freep(&d->picture);
00110                         if (d->frame_buf)
00111                                 free(d->frame_buf);
00112                         free(d);
00113                 }
00114 
00115                 free(c);
00116         }
00117 }
00118 
00119 static void reset_decoder_frame_state(struct decoder_ctx * d)
00120 {
00121         memset(d->frame_buf, 0, d->frame_buf_len);
00122         d->frame_size = 0;
00123         d->slice_header.slice_index = 0;
00124 }
00125 
00126 static int frame_to_frame_xlate(AVCodecContext * avctx, AVFrame * picture,
00127                 int * outlen, char * out)
00128 {
00129         int line;
00130 
00131         *outlen = avctx->width * avctx->height * 6 / 4;
00132 
00133         for ( line = 0; line < avctx->height / 2; ++line )
00134         {
00135                 /* y even */
00136                 memcpy(out + avctx->width * (2 * line + 0),
00137                        picture->data[0] + (2 * line + 0) * picture->linesize[0],
00138                        avctx->width);
00139 
00140                 /* y odd */
00141                 memcpy(out + avctx->width * (2 * line + 1),
00142                        picture->data[0] + (2 * line + 1) * picture->linesize[0],
00143                        avctx->width);
00144 
00145                 /* u + v */
00146                 memcpy(out + avctx->width * avctx->height
00147                                 + line * avctx->width / 2,
00148                        picture->data[1] + line * picture->linesize[1],
00149                        avctx->width / 2);
00150 
00151                 memcpy(out + avctx->width * avctx->height * 5 / 4
00152                                 + line * avctx->width / 2,
00153                        picture->data[2] + line * picture->linesize[2],
00154                        avctx->width / 2);
00155         }
00156 
00157         return 0;
00158 }
00159 
00160 static int pass_frame_to_decoder(AVCodecContext * avctx, AVFrame * picture,
00161                 int inlen, unsigned char * in, int * outlen, char * out)
00162 {
00163         int bytes_decoded;
00164         int got_picture;
00165 
00166         bytes_decoded = avcodec_decode_video(avctx, picture, &got_picture,
00167                         in, inlen);
00168 
00169         if ( bytes_decoded != inlen )
00170         {
00171                 fprintf(stderr,
00172                         "codec_ffmpeg: decode: failed to decode whole frame %d / %d\n",
00173                         bytes_decoded, inlen);
00174                 return -1;
00175         }
00176 
00177         if ( !got_picture )
00178         {
00179                 fprintf(stderr,
00180                         "codec_ffmpeg: decode: failed to get picture\n");
00181                 return -1;
00182         }
00183 
00184         frame_to_frame_xlate(avctx, picture, outlen, out);
00185 
00186         return 0;
00187 }
00188 
00189 static char *parse_slice_header(char * in, struct slice_header_t * slice_header)
00190 {
00191         slice_header->version     = in[0];
00192         slice_header->source_id   = (in[1] << 8) | in[2];
00193         slice_header->frame_index = in[3];
00194         slice_header->slice_index = in[4];
00195         slice_header->num_slices  = in[5];
00196 
00197         if ( slice_header->version != 0 )
00198         {
00199                 fprintf(stderr,
00200                         "codec_ffmpeg: decode: unknown slice header version %d\n",
00201                         slice_header->version);
00202                 return 0;
00203         }
00204 
00205         return in + 6;
00206 }
00207 
00208 static int decode_iaxc_slice(struct iaxc_video_codec * c, int inlen,
00209                 char * in, int * outlen, char * out)
00210 {
00211         struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
00212         struct slice_header_t * sh_saved = &d->slice_header;
00213         struct slice_header_t sh_this;
00214         char * inp;
00215         int ret;
00216 
00217         inp = parse_slice_header(in, &sh_this);
00218 
00219         if ( !inp )
00220                 return -1;
00221 
00222         inlen -= inp - in;
00223 
00224         if ( sh_this.source_id == sh_saved->source_id )
00225         {
00226                 unsigned char frame_delta;
00227 
00228                 frame_delta = sh_this.frame_index - sh_saved->frame_index;
00229 
00230                 if ( frame_delta > 20 )
00231                 {
00232                         /* This is an old slice. It's too late, we ignore it. */
00233                         return 1;
00234                 }
00235                 else if ( frame_delta > 0 )
00236                 {
00237                         /* This slice belongs to a future frame */
00238                         if ( sh_saved->slice_index > 0 )
00239                         {
00240                                 /* We have received slices for a previous
00241                                  * frame (e.g. the one we were previously
00242                                  * working on), so we go ahead and send this
00243                                  * partial frame to the decoder and get setup
00244                                  * for the new frame.
00245                                  */
00246 
00247                                 ret = pass_frame_to_decoder(d->avctx, d->picture,
00248                                                 d->frame_size, d->frame_buf,
00249                                                 outlen, out);
00250 
00251                                 reset_decoder_frame_state(d);
00252 
00253                                 if ( ret )
00254                                         return -1;
00255                         }
00256 
00257                         sh_saved->frame_index = sh_this.frame_index;
00258                 }
00259         }
00260         else
00261         {
00262                 sh_saved->source_id = sh_this.source_id;
00263                 sh_saved->frame_index = sh_this.frame_index;
00264                 sh_saved->slice_index = 0;
00265                 d->frame_size = 0;
00266         }
00267 
00268         if ( c->fragsize * sh_this.slice_index + inlen > d->frame_buf_len )
00269         {
00270                 fprintf(stderr,
00271                         "codec_ffmpeg: decode: slice overflows decoder frame buffer\n");
00272                 return -1;
00273         }
00274 
00275         memcpy(d->frame_buf + c->fragsize * sh_this.slice_index,
00276                         inp, inlen);
00277         sh_saved->slice_index++;
00278         d->frame_size = c->fragsize * sh_this.slice_index + inlen;
00279 
00280         if ( sh_saved->slice_index < sh_this.num_slices )
00281         {
00282                 /* Do not decode yet, there are more slices coming for
00283                  * this frame.
00284                  */
00285                 return 1;
00286         }
00287 
00288         ret = pass_frame_to_decoder(d->avctx, d->picture, d->frame_size,
00289                         d->frame_buf, outlen, out);
00290 
00291         reset_decoder_frame_state(d);
00292 
00293         if ( ret )
00294                 return -1;
00295 
00296         return 0;
00297 }
00298 
00299 static int decode_rtp_slice(struct iaxc_video_codec * c,
00300                   int inlen, char * in, int * outlen, char * out)
00301 {
00302         struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
00303         int ret = 1;
00304 
00305         while ( inlen )
00306         {
00307                 int bytes_decoded;
00308                 int got_picture;
00309 
00310                 bytes_decoded = avcodec_decode_video(d->avctx, d->picture,
00311                                 &got_picture, (unsigned char *)in, inlen);
00312 
00313                 if ( bytes_decoded < 0 )
00314                 {
00315                         fprintf(stderr,
00316                                 "codec_ffmpeg: decode: error decoding frame\n");
00317                         return -1;
00318                 }
00319 
00320                 inlen -= bytes_decoded;
00321                 in += bytes_decoded;
00322 
00323                 if ( got_picture && ret == 0)
00324                 {
00325                         fprintf(stderr,
00326                                 "codec_ffmpeg: decode: unexpected second frame\n");
00327                         return -1;
00328                 }
00329 
00330                 if ( got_picture )
00331                 {
00332                         frame_to_frame_xlate(d->avctx, d->picture, outlen, out);
00333                         ret = 0;
00334                 }
00335         }
00336 
00337         return ret;
00338 }
00339 
00340 static void slice_encoded_frame(struct slice_header_t * sh,
00341                 struct slice_set_t * slice_set,
00342                 unsigned char * in, int inlen, int fragsize)
00343 {
00344         sh->num_slices = slice_set->num_slices = (inlen - 1) / fragsize + 1;
00345 
00346         for (sh->slice_index = 0; sh->slice_index < sh->num_slices;
00347                         ++sh->slice_index)
00348         {
00349                 int slice_size = (sh->slice_index == sh->num_slices - 1) ?
00350                         inlen % fragsize : fragsize;
00351 
00352                 slice_set->size[sh->slice_index] = slice_size + 6;
00353                 slice_set->data[sh->slice_index][0] = sh->version;
00354                 slice_set->data[sh->slice_index][1] = sh->source_id >> 8;
00355                 slice_set->data[sh->slice_index][2] = sh->source_id & 0xff;
00356                 slice_set->data[sh->slice_index][3] = sh->frame_index;
00357                 slice_set->data[sh->slice_index][4] = sh->slice_index;
00358                 slice_set->data[sh->slice_index][5] = sh->num_slices;
00359 
00360                 memcpy(&slice_set->data[sh->slice_index][6], in, slice_size);
00361 
00362                 in += slice_size;
00363         }
00364 
00365         sh->frame_index++;
00366 }
00367 
00368 static int encode(struct iaxc_video_codec *c,
00369                 int inlen, char * in, struct slice_set_t * slice_set)
00370 {
00371         struct encoder_ctx *e = (struct encoder_ctx *) c->encstate;
00372         int encoded_size;
00373 
00374         avcodec_get_frame_defaults(e->picture);
00375 
00376         e->picture->data[0] = (unsigned char *)in;
00377         e->picture->data[1] = (unsigned char *)in
00378                 + e->avctx->width * e->avctx->height;
00379         e->picture->data[2] = (unsigned char *)in
00380                 + e->avctx->width * e->avctx->height * 5 / 4;
00381 
00382         e->picture->linesize[0] = e->avctx->width;
00383         e->picture->linesize[1] = e->avctx->width / 2;
00384         e->picture->linesize[2] = e->avctx->width / 2;
00385 
00386         /* TODO: investigate setting a real pts value */
00387         e->picture->pts = AV_NOPTS_VALUE;
00388 
00389         /* TODO: investigate quality */
00390         e->picture->quality = 10;
00391 
00392         g_slice_set = slice_set;
00393         slice_set->num_slices = 0;
00394 
00395         encoded_size = avcodec_encode_video(e->avctx,
00396                         e->frame_buf, e->frame_buf_len, e->picture);
00397 
00398         if (!encoded_size)
00399         {
00400                 fprintf(stderr, "codec_ffmpeg: encode failed\n");
00401                 return -1;
00402         }
00403 
00404         slice_set->key_frame = e->avctx->coded_frame->key_frame;
00405 
00406         /* This is paranoia, of course. */
00407         g_slice_set = 0;
00408 
00409         /* We are in one of two modes here.
00410          *
00411          * The first possibility is that the codec supports rtp
00412          * packetization. In this case, the slice_set has already been
00413          * filled via encode_rtp_callback() calls made during the call
00414          * to avcodec_encode_video().
00415          *
00416          * The second possibility is that we have one big encoded frame
00417          * that we need to slice-up ourselves.
00418          */
00419 
00420         if (!e->avctx->rtp_payload_size)
00421                 slice_encoded_frame(&e->slice_header, slice_set,
00422                                 e->frame_buf, encoded_size, c->fragsize);
00423 
00424         return 0;
00425 }
00426 
00427 void encode_rtp_callback(struct AVCodecContext *avctx, void *data, int size,
00428                      int mb_nb)
00429 {
00430         memcpy(&g_slice_set->data[g_slice_set->num_slices], data, size);
00431         g_slice_set->size[g_slice_set->num_slices] = size;
00432         g_slice_set->num_slices++;
00433 }
00434 
00435 struct iaxc_video_codec *codec_video_ffmpeg_new(int format, int w, int h,
00436                                                      int framerate, int bitrate,
00437                                                      int fragsize)
00438 {
00439         struct encoder_ctx *e;
00440         struct decoder_ctx *d;
00441         AVCodec *codec;
00442         int ff_enc_id, ff_dec_id;
00443         char *name;
00444 
00445         struct iaxc_video_codec *c = calloc(sizeof(struct iaxc_video_codec), 1);
00446 
00447         if (!c)
00448         {
00449                 fprintf(stderr,
00450                         "codec_ffmpeg: failed to allocate video context\n");
00451                 return NULL;
00452         }
00453 
00454         avcodec_init();
00455         avcodec_register_all();
00456 
00457         c->format = format;
00458         c->width = w;
00459         c->height = h;
00460         c->framerate = framerate;
00461         c->bitrate = bitrate;
00462         /* TODO: Is a fragsize of zero valid? If so, there's a divide
00463          * by zero error to contend with.
00464          */
00465         c->fragsize = fragsize;
00466 
00467         c->encode = encode;
00468         c->decode = decode_iaxc_slice;
00469         c->destroy = destroy;
00470 
00471         c->encstate = calloc(sizeof(struct encoder_ctx), 1);
00472         if (!c->encstate)
00473                 goto bail;
00474         e = c->encstate;
00475         e->avctx = avcodec_alloc_context();
00476         if (!e->avctx)
00477                 goto bail;
00478         e->picture = avcodec_alloc_frame();
00479         if (!e->picture)
00480                 goto bail;
00481         /* The idea here is that the encoded frame that will land in this
00482          * buffer will be no larger than the size of an uncompressed 32-bit
00483          * rgb frame.
00484          *
00485          * TODO: Is this assumption really valid?
00486          */
00487         e->frame_buf_len = w * h * 4;
00488         e->frame_buf = malloc(e->frame_buf_len);
00489         if (!e->frame_buf)
00490                 goto bail;
00491 
00492         c->decstate = calloc(sizeof(struct decoder_ctx), 1);
00493         if (!c->decstate)
00494                 goto bail;
00495         d = c->decstate;
00496         d->avctx = avcodec_alloc_context();
00497         if (!d->avctx)
00498                 goto bail;
00499         d->picture = avcodec_alloc_frame();
00500         if (!d->picture)
00501                 goto bail;
00502         d->frame_buf_len = e->frame_buf_len;
00503         d->frame_buf = malloc(d->frame_buf_len);
00504         if (!d->frame_buf)
00505                 goto bail;
00506 
00507         e->slice_header.version = 0;
00508         srandom(time(0));
00509         e->slice_header.source_id = random() & 0xffff;
00510 
00511         e->avctx->time_base.num = 1;
00512         e->avctx->time_base.den = framerate;
00513 
00514         e->avctx->width = w;
00515         e->avctx->height = h;
00516 
00517         e->avctx->bit_rate = bitrate;
00518 
00519         /* This determines how often i-frames are sent */
00520         e->avctx->gop_size = framerate * 3;
00521         e->avctx->pix_fmt = PIX_FMT_YUV420P;
00522         e->avctx->has_b_frames = 0;
00523 
00524         e->avctx->mb_qmin = e->avctx->qmin = 10;
00525         e->avctx->mb_qmax = e->avctx->qmax = 10;
00526 
00527         e->avctx->lmin = 2 * FF_QP2LAMBDA;
00528         e->avctx->lmax = 10 * FF_QP2LAMBDA;
00529         e->avctx->global_quality = FF_QP2LAMBDA * 2;
00530         e->avctx->qblur = 0.5;
00531         e->avctx->global_quality = 10;
00532 
00533         e->avctx->flags |= CODEC_FLAG_PSNR;
00534         e->avctx->flags |= CODEC_FLAG_QSCALE;
00535 
00536         e->avctx->mb_decision = FF_MB_DECISION_SIMPLE;
00537 
00538         ff_enc_id = ff_dec_id = map_iaxc_codec_to_avcodec(format);
00539 
00540         /* Note, when fragsize is used (non-zero) ffmpeg will use a "best
00541          * effort" strategy: the fragment size will be fragsize +/- 20%
00542          */
00543 
00544         switch (format)
00545         {
00546 
00547         case IAXC_FORMAT_H261:
00548                 /* TODO: H261 only works with specific resolutions. */
00549                 name = "H.261";
00550                 break;
00551 
00552         case IAXC_FORMAT_H263:
00553                 /* TODO: H263 only works with specific resolutions. */
00554                 name = "H.263";
00555                 e->avctx->flags |= CODEC_FLAG_AC_PRED;
00556                 if (fragsize)
00557                 {
00558                         c->decode = decode_rtp_slice;
00559                         e->avctx->rtp_payload_size = fragsize;
00560                         e->avctx->flags |=
00561                                 CODEC_FLAG_TRUNCATED | CODEC_FLAG2_STRICT_GOP;
00562                         e->avctx->rtp_callback = encode_rtp_callback;
00563                         d->avctx->flags |= CODEC_FLAG_TRUNCATED;
00564                 }
00565                 break;
00566 
00567         case IAXC_FORMAT_H263_PLUS:
00568                 /* Although the encoder is CODEC_ID_H263P, the decoder
00569                  * is the regular h.263, so we handle this special case
00570                  * here.
00571                  */
00572                 ff_dec_id = CODEC_ID_H263;
00573                 name = "H.263+";
00574                 e->avctx->flags |= CODEC_FLAG_AC_PRED;
00575                 if (fragsize)
00576                 {
00577                         c->decode = decode_rtp_slice;
00578                         e->avctx->rtp_payload_size = fragsize;
00579                         e->avctx->flags |=
00580                                 CODEC_FLAG_TRUNCATED |
00581                                 CODEC_FLAG_H263P_SLICE_STRUCT |
00582                                 CODEC_FLAG2_STRICT_GOP |
00583                                 CODEC_FLAG2_LOCAL_HEADER;
00584                         e->avctx->rtp_callback = encode_rtp_callback;
00585                         d->avctx->flags |= CODEC_FLAG_TRUNCATED;
00586                 }
00587                 break;
00588 
00589         case IAXC_FORMAT_MPEG4:
00590                 name = "MPEG4";
00591                 c->decode = decode_rtp_slice;
00592                 e->avctx->rtp_payload_size = fragsize;
00593                 e->avctx->rtp_callback = encode_rtp_callback;
00594                 e->avctx->flags |=
00595                         CODEC_FLAG_TRUNCATED |
00596                         CODEC_FLAG_H263P_SLICE_STRUCT |
00597                         CODEC_FLAG2_STRICT_GOP |
00598                         CODEC_FLAG2_LOCAL_HEADER;
00599 
00600                 d->avctx->flags |= CODEC_FLAG_TRUNCATED;
00601                 break;
00602 
00603         case IAXC_FORMAT_H264:
00604                 name = "H.264";
00605 
00606                 /*
00607                  * Encoder flags
00608                  */
00609 
00610                 /* Headers are not repeated */
00611                 /* e->avctx->flags |= CODEC_FLAG_GLOBAL_HEADER; */
00612 
00613                 /* Slower, less blocky */
00614                 /* e->avctx->flags |= CODEC_FLAG_LOOP_FILTER; */
00615 
00616                 e->avctx->flags |= CODEC_FLAG_PASS1;
00617                 /* e->avctx->flags |= CODEC_FLAG_PASS2; */
00618 
00619                 /* Compute psnr values at encode-time (avctx->error[]) */
00620                 /* e->avctx->flags |= CODEC_FLAG_PSNR; */
00621 
00622                 /* e->avctx->flags2 |= CODEC_FLAG2_8X8DCT; */
00623 
00624                 /* Access Unit Delimiters */
00625                 e->avctx->flags2 |= CODEC_FLAG2_AUD;
00626 
00627                 /* Allow b-frames to be used as reference */
00628                 /* e->avctx->flags2 |= CODEC_FLAG2_BPYRAMID; */
00629 
00630                 /* b-frame rate distortion optimization */
00631                 /* e->avctx->flags2 |= CODEC_FLAG2_BRDO; */
00632 
00633                 /* e->avctx->flags2 |= CODEC_FLAG2_FASTPSKIP; */
00634 
00635                 /* Multiple references per partition */
00636                 /* e->avctx->flags2 |= CODEC_FLAG2_MIXED_REFS; */
00637 
00638                 /* Weighted biprediction for b-frames */
00639                 /* e->avctx->flags2 |= CODEC_FLAG2_WPRED; */
00640 
00641                 /*
00642                  * Decoder flags
00643                  */
00644 
00645                 /* Do not draw edges */
00646                 /* d->avctx->flags |= CODEC_FLAG_EMU_EDGE; */
00647 
00648                 /* Decode grayscale only */
00649                 /* d->avctx->flags |= CODEC_FLAG_GRAY; */
00650 
00651                 /* d->avctx->flags |= CODEC_FLAG_LOW_DELAY; */
00652 
00653                 /* Allow input bitstream to be randomly truncated */
00654                 /* d->avctx->flags |= CODEC_FLAG_TRUNCATED; */
00655 
00656                 /* Allow out-of-spec speed tricks */
00657                 /* d->avctx->flags2 |= CODEC_FLAG2_FAST; */
00658                 break;
00659 
00660         case IAXC_FORMAT_THEORA:
00661                 /* TODO: ffmpeg only has a theora decoder. Until it has
00662                  * an encoder also, we cannot use ffmpeg for theora.
00663                  */
00664                 name = "Theora";
00665                 break;
00666 
00667         default:
00668                 fprintf(stderr, "codec_ffmpeg: unsupported format (0x%08x)\n",
00669                                 format);
00670                 goto bail;
00671         }
00672 
00673         strcpy(c->name, "ffmpeg-");
00674         strncat(c->name, name, sizeof(c->name));
00675 
00676         /* Get the codecs */
00677         codec = avcodec_find_encoder(ff_enc_id);
00678         if (!codec)
00679         {
00680                 iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
00681                              "codec_ffmpeg: cannot find encoder %d\n",
00682                              ff_enc_id);
00683                 goto bail;
00684         }
00685 
00686         if (avcodec_open(e->avctx, codec))
00687         {
00688                 iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
00689                              "codec_ffmpeg: cannot open encoder %s\n", name);
00690                 goto bail;
00691         }
00692 
00693         codec = avcodec_find_decoder(ff_dec_id);
00694         if (!codec)
00695         {
00696                 iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
00697                              "codec_ffmpeg: cannot find decoder %d\n",
00698                              ff_dec_id);
00699                 goto bail;
00700         }
00701         if (avcodec_open(d->avctx, codec))
00702         {
00703                 iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
00704                              "codec_ffmpeg: cannot open decoder %s\n", name);
00705                 goto bail;
00706         }
00707 
00708         {
00709                 enum PixelFormat fmts[] = { PIX_FMT_YUV420P, -1 };
00710                 if (d->avctx->get_format(d->avctx, fmts) != PIX_FMT_YUV420P)
00711                 {
00712                         iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
00713                                         "codec_ffmpeg: cannot set decode format to YUV420P\n");
00714                         goto bail;
00715                 }
00716         }
00717 
00718         return c;
00719 
00720 bail:
00721         destroy(c);
00722         return 0;
00723 }
00724 
00725 int codec_video_ffmpeg_check_codec(int format)
00726 {
00727         AVCodec *codec;
00728         enum CodecID codec_id;
00729 
00730         /* These functions are idempotent, so it is okay that we
00731          * may call them elsewhere at a different time.
00732          */
00733         avcodec_init();
00734         avcodec_register_all();
00735 
00736         codec_id = map_iaxc_codec_to_avcodec(format);
00737 
00738         if (codec_id == CODEC_ID_NONE)
00739                 return 0;
00740 
00741         codec = avcodec_find_encoder(codec_id);
00742 
00743         return codec ? 1 : 0;
00744 }
00745 

Generated on Mon Sep 24 15:43:29 2007 for IAXClient by  doxygen 1.5.3