⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_codec_ffmpeg.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
字号:
/* Swfdec * Copyright (C) 2006 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor,  * Boston, MA  02110-1301  USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include <avcodec.h>#include <swscale.h>#include "swfdec_codec_audio.h"#include "swfdec_codec_video.h"#include "swfdec_debug.h"#include "swfdec_internal.h"/*** GENERAL ***/static AVCodecContext *swfdec_codec_ffmpeg_init (enum CodecID id){  AVCodec *codec;  AVCodecContext *ctx;  static gboolean initialized = FALSE;  if (!initialized) {    avcodec_init();    avcodec_register_all ();    initialized = TRUE;  }  codec = avcodec_find_decoder (id);  if (!codec)    return NULL;  ctx = avcodec_alloc_context ();  if (avcodec_open (ctx, codec) < 0)    goto fail;  return ctx;fail:  SWFDEC_ERROR ("failed to initialize playback via ffmpeg");  avcodec_close (ctx);  av_free (ctx);  return NULL;}/*** AUDIO ***/typedef struct {  SwfdecAudioDecoder	decoder;  AVCodecContext *	ctx;  SwfdecBufferQueue *	queue;} SwfdecAudioDecoderFFMpeg;static SwfdecBuffer *swfdec_codec_ffmpeg_convert (AVCodecContext *ctx, SwfdecBuffer *buffer){  SwfdecBuffer *ret;  guint count, i, j, rate;  gint16 *out, *in;  /* do the common case fast */  if (ctx->channels == 2 && ctx->sample_rate == 44100) {    ret = swfdec_buffer_new_and_alloc (buffer->length);    memcpy (ret->data, buffer->data, buffer->length);    return ret;  }  switch (ctx->sample_rate) {    case 44100:      rate = 1;      break;    case 22050:      rate = 2;      break;    case 11025:      rate = 4;      break;    default:      SWFDEC_ERROR ("unsupported sample rate %u", ctx->sample_rate);      return NULL;  }  if (ctx->channels == 1)    rate *= 2;  ret = swfdec_buffer_new_and_alloc (buffer->length * rate);  out = (gint16 *) ret->data;  in = (gint16 *) buffer->data;  count = buffer->length / 2;  for (i = 0; i < count; i++) {    for (j = 0; j < rate; j++) {      *out++ = *in;    }    in++;  }  return ret;}static voidswfdec_audio_decoder_ffmpeg_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer){  SwfdecAudioDecoderFFMpeg *ffmpeg = (SwfdecAudioDecoderFFMpeg *) dec;  int out_size;  int len;  guint amount;  SwfdecBuffer *outbuf = NULL;  if (buffer == NULL)    return;  outbuf = swfdec_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);  for (amount = 0; amount < buffer->length; amount += len) {        len = avcodec_decode_audio2 (ffmpeg->ctx, (short *) outbuf->data, &out_size, buffer->data + amount, buffer->length - amount);    if (len < 0) {      SWFDEC_ERROR ("Error %d while decoding", len);      swfdec_buffer_unref (outbuf);      return;    }    if (out_size > 0) {      SwfdecBuffer *convert;      outbuf->length = out_size;      convert = swfdec_codec_ffmpeg_convert (ffmpeg->ctx, outbuf);      if (convert == NULL) {	swfdec_buffer_unref (outbuf);	return;      }      swfdec_buffer_queue_push (ffmpeg->queue, convert);      outbuf->length = AVCODEC_MAX_AUDIO_FRAME_SIZE;    }  }  swfdec_buffer_unref (outbuf);}static SwfdecBuffer *swfdec_audio_decoder_ffmpeg_pull (SwfdecAudioDecoder *dec){  SwfdecAudioDecoderFFMpeg *ffmpeg = (SwfdecAudioDecoderFFMpeg *) dec;  return swfdec_buffer_queue_pull_buffer (ffmpeg->queue);}static voidswfdec_audio_decoder_ffmpeg_free (SwfdecAudioDecoder *dec){  SwfdecAudioDecoderFFMpeg *ffmpeg = (SwfdecAudioDecoderFFMpeg *) dec;  avcodec_close (ffmpeg->ctx);  av_free (ffmpeg->ctx);  swfdec_buffer_queue_unref (ffmpeg->queue);  g_slice_free (SwfdecAudioDecoderFFMpeg, ffmpeg);}SwfdecAudioDecoder *swfdec_audio_decoder_ffmpeg_new (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format){  SwfdecAudioDecoderFFMpeg *ffmpeg;  AVCodecContext *ctx;  enum CodecID id;  switch (type) {    case SWFDEC_AUDIO_FORMAT_ADPCM:      id = CODEC_ID_ADPCM_SWF;      break;    case SWFDEC_AUDIO_FORMAT_MP3:      id = CODEC_ID_MP3;      break;    default:      return NULL;  }  ctx = swfdec_codec_ffmpeg_init (id);  if (ctx == NULL)    return NULL;  ffmpeg = g_slice_new (SwfdecAudioDecoderFFMpeg);  ffmpeg->ctx = ctx;  ffmpeg->queue = swfdec_buffer_queue_new ();  ffmpeg->decoder.out_format = SWFDEC_AUDIO_OUT_STEREO_44100;  ffmpeg->decoder.pull = swfdec_audio_decoder_ffmpeg_pull;  ffmpeg->decoder.push = swfdec_audio_decoder_ffmpeg_push;  ffmpeg->decoder.free = swfdec_audio_decoder_ffmpeg_free;  ctx->sample_rate = SWFDEC_AUDIO_OUT_RATE (format);  ctx->channels = SWFDEC_AUDIO_OUT_N_CHANNELS (format);  return &ffmpeg->decoder;}/*** VIDEO ***/typedef struct {  SwfdecVideoDecoder	decoder;  AVCodecContext *	ctx;		/* out context (d'oh) */  AVFrame *		frame;		/* the frame we use for decoding */  struct SwsContext *	sws;		/* the format conversion */} SwfdecVideoDecoderFFMpeg;static SwfdecBuffer *swfdec_video_decoder_ffmpeg_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer,    guint *width, guint *height, guint *rowstride){  SwfdecVideoDecoderFFMpeg *codec = (SwfdecVideoDecoderFFMpeg *) dec;  int got_image;  SwfdecBuffer *ret;  AVPicture picture;  if (avcodec_decode_video (codec->ctx, codec->frame, &got_image, 	buffer->data, buffer->length) < 0) {    SWFDEC_WARNING ("error decoding frame");    return NULL;  }  if (got_image == 0) {    SWFDEC_WARNING ("error: did not get an image from decoding");    return NULL;  }  if (codec->sws == NULL) {    codec->sws = sws_getContext (codec->ctx->width, codec->ctx->height, codec->ctx->pix_fmt,	codec->ctx->width, codec->ctx->height, PIX_FMT_RGB32, 0, NULL, NULL, NULL);    if (codec->sws == NULL) {      SWFDEC_ERROR ("Could not get conversion context");      return NULL;    }  }  ret = swfdec_buffer_new_and_alloc (codec->ctx->width * codec->ctx->height * 4);  avpicture_fill (&picture, ret->data, PIX_FMT_RGB32, codec->ctx->width,      codec->ctx->height);  sws_scale (codec->sws, codec->frame->data, codec->frame->linesize, 0, codec->ctx->height,      picture.data, picture.linesize);  *width = codec->ctx->width;  *height = codec->ctx->height;  *rowstride = codec->ctx->width * 4;  return ret;}static voidswfdec_video_decoder_ffmpeg_free (SwfdecVideoDecoder *dec){  SwfdecVideoDecoderFFMpeg *codec = (SwfdecVideoDecoderFFMpeg *) dec;  if (codec->sws) {    sws_freeContext (codec->sws);  };  avcodec_close (codec->ctx);  av_free (codec->ctx);  av_free (codec->frame);  g_free (codec);}SwfdecVideoDecoder *swfdec_video_decoder_ffmpeg_new (SwfdecVideoFormat type){  SwfdecVideoDecoderFFMpeg *codec;  AVCodecContext *ctx;  enum CodecID id;  switch (type) {    case SWFDEC_VIDEO_FORMAT_H263:      id = CODEC_ID_FLV1;      break;    case SWFDEC_VIDEO_FORMAT_SCREEN:      id = CODEC_ID_FLASHSV;      break;    case SWFDEC_VIDEO_FORMAT_VP6:      id = CODEC_ID_VP6F;      break;    default:      return NULL;  }  ctx = swfdec_codec_ffmpeg_init (id);  if (ctx == NULL)    return NULL;  codec = g_new0 (SwfdecVideoDecoderFFMpeg, 1);  codec->decoder.decode = swfdec_video_decoder_ffmpeg_decode;  codec->decoder.free = swfdec_video_decoder_ffmpeg_free;  codec->ctx = ctx;  codec->frame = avcodec_alloc_frame ();  return &codec->decoder;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -