summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libffmpeg/xine_decoder.c343
1 files changed, 309 insertions, 34 deletions
diff --git a/src/libffmpeg/xine_decoder.c b/src/libffmpeg/xine_decoder.c
index 32aee95e4..af4af2552 100644
--- a/src/libffmpeg/xine_decoder.c
+++ b/src/libffmpeg/xine_decoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_decoder.c,v 1.61 2002/10/29 16:30:53 miguelfreitas Exp $
+ * $Id: xine_decoder.c,v 1.62 2002/10/31 05:26:46 tmmm Exp $
*
* xine decoder plugin using ffmpeg
*
@@ -51,12 +51,12 @@
typedef struct {
video_decoder_class_t decoder_class;
int illegal_vlc;
-} ff_class_t;
+} ff_video_class_t;
typedef struct ff_decoder_s {
video_decoder_t video_decoder;
- ff_class_t *class;
+ ff_video_class_t *class;
xine_stream_t *stream;
int video_step;
@@ -80,12 +80,38 @@ typedef struct ff_decoder_s {
int is_continous;
-} ff_decoder_t;
+} ff_video_decoder_t;
+
+typedef struct {
+ audio_decoder_class_t decoder_class;
+} ff_audio_class_t;
+
+typedef struct ff_audio_decoder_s {
+ audio_decoder_t audio_decoder;
+
+ xine_stream_t *stream;
+
+ int output_open;
+ int audio_channels;
+ int audio_bits;
+ int audio_sample_rate;
+
+ unsigned char *buf;
+ int bufsize;
+ int size;
+
+ AVCodecContext context;
+ char *decode_buffer;
+ int decoder_ok;
+
+} ff_audio_decoder_t;
+
#define VIDEOBUFSIZE 128*1024
+#define AUDIOBUFSIZE VIDEOBUFSIZE
-static void init_codec (ff_decoder_t *this, AVCodec *codec) {
+static void init_codec (ff_video_decoder_t *this, AVCodec *codec) {
/* force (width % 8 == 0), otherwise there will be
* display problems with Xv.
@@ -121,7 +147,7 @@ static void init_codec (ff_decoder_t *this, AVCodec *codec) {
this->skipframes = 0;
}
-static void find_sequence_header (ff_decoder_t *this,
+static void find_sequence_header (ff_video_decoder_t *this,
uint8_t * current, uint8_t * end){
uint8_t code;
@@ -256,11 +282,11 @@ static void find_sequence_header (ff_decoder_t *this,
}
static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
- ff_decoder_t *this = (ff_decoder_t *) this_gen;
+ ff_video_decoder_t *this = (ff_video_decoder_t *) this_gen;
int ratio;
#ifdef LOG
- printf ("ffmpeg: processing packet type = %08x, buf : %d, buf->decoder_flags=%08x\n",
+ printf ("ffmpeg: processing packet type = %08x, buf : %p, buf->decoder_flags=%08x\n",
buf->type, buf, buf->decoder_flags);
#endif
@@ -319,6 +345,11 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
this->stream->meta_info[XINE_META_INFO_VIDEOCODEC]
= strdup ("ms wmv 7 (ffmpeg)");
break;
+ case BUF_VIDEO_WMV8:
+ codec = avcodec_find_decoder (CODEC_ID_WMV2);
+ this->stream->meta_info[XINE_META_INFO_VIDEOCODEC]
+ = strdup ("ms wmv 8 (ffmpeg)");
+ break;
case BUF_VIDEO_MPEG4 :
case BUF_VIDEO_XVID :
case BUF_VIDEO_DIVX5 :
@@ -623,7 +654,7 @@ void avcodec_register_all(void)
}
static void ff_dispose (video_decoder_t *this_gen) {
- ff_decoder_t *this = (ff_decoder_t *) this_gen;
+ ff_video_decoder_t *this = (ff_video_decoder_t *) this_gen;
#ifdef LOG
printf ("ffmpeg: ff_dispose\n");
@@ -643,15 +674,15 @@ static void ff_dispose (video_decoder_t *this_gen) {
free (this_gen);
}
-static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
+static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
- ff_decoder_t *this ;
+ ff_video_decoder_t *this ;
#ifdef LOG
printf ("ffmpeg: open_plugin\n");
#endif
- this = (ff_decoder_t *) malloc (sizeof (ff_decoder_t));
+ this = (ff_video_decoder_t *) malloc (sizeof (ff_video_decoder_t));
this->video_decoder.decode_data = ff_decode_data;
this->video_decoder.flush = ff_flush;
@@ -660,7 +691,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
this->size = 0;
this->stream = stream;
- this->class = (ff_class_t *) class_gen;
+ this->class = (ff_video_class_t *) class_gen;
this->chunk_buffer = xine_xmalloc (SLICE_BUFFER_SIZE + 4);
@@ -680,15 +711,15 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
* ffmpeg plugin class
*/
-static char *get_identifier (video_decoder_class_t *this) {
- return "ffmpeg";
+static char *ff_video_get_identifier (video_decoder_class_t *this) {
+ return "ffmpeg video";
}
-static char *get_description (video_decoder_class_t *this) {
+static char *ff_video_get_description (video_decoder_class_t *this) {
return "ffmpeg based video decoder plugin";
}
-static void dispose_class (video_decoder_class_t *this) {
+static void ff_video_dispose_class (video_decoder_class_t *this) {
free (this);
}
@@ -697,17 +728,17 @@ static void init_once_routine(void) {
avcodec_register_all();
}
-static void *init_plugin (xine_t *xine, void *data) {
+static void *init_video_plugin (xine_t *xine, void *data) {
- ff_class_t *this;
+ ff_video_class_t *this;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
- this = (ff_class_t *) malloc (sizeof (ff_class_t));
+ this = (ff_video_class_t *) malloc (sizeof (ff_video_class_t));
- this->decoder_class.open_plugin = open_plugin;
- this->decoder_class.get_identifier = get_identifier;
- this->decoder_class.get_description = get_description;
- this->decoder_class.dispose = dispose_class;
+ this->decoder_class.open_plugin = ff_video_open_plugin;
+ this->decoder_class.get_identifier = ff_video_get_identifier;
+ this->decoder_class.get_description = ff_video_get_description;
+ this->decoder_class.dispose = ff_video_dispose_class;
this->illegal_vlc = xine->config->register_bool (xine->config, "codec.ffmpeg_illegal_vlc", 1,
_("allow illegal vlc codes in mpeg4 streams"), NULL,
@@ -718,28 +749,272 @@ static void *init_plugin (xine_t *xine, void *data) {
return this;
}
+
+static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
+
+ ff_audio_decoder_t *this = (ff_audio_decoder_t *) this_gen;
+ int bytes_consumed;
+ int decode_buffer_size;
+ int offset;
+ int out;
+ audio_buffer_t *audio_buffer;
+ int bytes_to_send;
+
+ if (buf->decoder_flags & BUF_FLAG_HEADER) {
+
+ AVCodec *codec = NULL;
+ int codec_type;
+ xine_waveformatex *audio_header = (xine_waveformatex *)buf->content;
+
+ codec_type = buf->type & 0xFFFF0000;
+
+ switch (codec_type) {
+ case BUF_AUDIO_WMAV1:
+ codec = avcodec_find_decoder (CODEC_ID_WMAV1);
+ this->stream->meta_info[XINE_META_INFO_VIDEOCODEC]
+ = strdup ("Windows Media Audio v1");
+ break;
+ case BUF_AUDIO_WMAV2:
+ codec = avcodec_find_decoder (CODEC_ID_WMAV2);
+ this->stream->meta_info[XINE_META_INFO_VIDEOCODEC]
+ = strdup ("Windows Media Audio v2");
+ break;
+ }
+
+ if (!codec) {
+ printf (" could not open ffmpeg decoder for buf type 0x%X\n",
+ codec_type);
+ return;
+ }
+
+ memset(&this->context, 0, sizeof(this->context));
+
+ this->context.sample_rate = this->audio_sample_rate = buf->decoder_info[1];
+ this->audio_bits = buf->decoder_info[2];
+ this->context.channels = this->audio_channels = buf->decoder_info[3];
+ this->context.block_align = audio_header->nBlockAlign;
+ this->buf = xine_xmalloc(AUDIOBUFSIZE);
+ this->bufsize = AUDIOBUFSIZE;
+ this->size = 0;
+
+printf ("decode buffer (before) = %p\n", this->decode_buffer);
+ this->decode_buffer = xine_xmalloc(50000);
+printf ("decode buffer (after) = %p\n", this->decode_buffer);
+
+ if (avcodec_open (&this->context, codec) < 0) {
+ printf ("ffmpeg: couldn't open decoder\n");
+ return;
+ }
+
+ this->decoder_ok = 1;
+
+ return;
+ } else if (this->decoder_ok) {
+
+ if (!this->output_open) {
+ this->output_open = this->stream->audio_out->open(this->stream->audio_out,
+ this->audio_bits, this->audio_sample_rate,
+ (this->audio_channels == 2) ? AO_CAP_MODE_STEREO : AO_CAP_MODE_MONO);
+ }
+
+ /* if the audio still isn't open, bail */
+ if (!this->output_open)
+ return;
+
+ if( this->size + buf->size > this->bufsize ) {
+ this->bufsize = this->size + 2 * buf->size;
+ printf("ffmpeg: increasing source buffer to %d to avoid overflow.\n",
+ this->bufsize);
+ this->buf = realloc( this->buf, this->bufsize );
+ }
+
+printf (" *** accumulating audio data\n");
+ xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size);
+ this->size += buf->size;
+
+ if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* time to decode a frame */
+printf (" *** time to decode audio\n");
+
+ offset = 0;
+ while (this->size>0) {
+printf (" size = %d\n", this->size);
+ bytes_consumed = avcodec_decode_audio (&this->context,
+ (INT16 *)this->decode_buffer,
+ &decode_buffer_size,
+ &this->buf[offset],
+ this->size);
+printf (" bytes consumed = %d, decode buffer size = %d\n",
+ bytes_consumed, decode_buffer_size);
+
+ if (bytes_consumed<0) {
+ printf ("ffmpeg: error decompressing audio frame\n");
+ this->size=0;
+ return;
+ }
+
+ /* dispatch the decoded audio */
+ out = 0;
+printf (" preparing to dispatch...\n");
+ while (out < decode_buffer_size) {
+printf (" dispatching audio buffer, out = %d, decoder buffer size = %d\n",
+ out, decode_buffer_size);
+ audio_buffer =
+ this->stream->audio_out->get_buffer (this->stream->audio_out);
+ if (audio_buffer->mem_size == 0) {
+ printf ("ffmpeg: Help! Allocated audio buffer with nothing in it!\n");
+ return;
+ }
+
+ if ((decode_buffer_size - out) > audio_buffer->mem_size)
+{
+ bytes_to_send = audio_buffer->mem_size;
+printf(" 1) bytes/send = %d\n", bytes_to_send);
+}
+ else
+{
+ bytes_to_send = decode_buffer_size - out;
+printf(" 2) bytes/send = %d\n", bytes_to_send);
+}
+
+ /* fill up this buffer */
+ xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out],
+ bytes_to_send);
+ /* byte count / 2 (bytes / sample) / channels */
+ audio_buffer->num_frames = bytes_to_send / 2 / this->audio_channels;
+
+ audio_buffer->vpts = buf->pts;
+ buf->pts = 0; /* only first buffer gets the real pts */
+ this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer);
+
+ out += bytes_to_send;
+ }
+
+ this->size -= bytes_consumed;
+ offset += bytes_consumed;
+
+ if (!decode_buffer_size) {
+ printf ("ffmpeg: didn't get an audio frame, got %d bytes left\n",
+ this->size);
+
+ if (this->size>0)
+ memmove (this->buf, &this->buf[offset], this->size);
+
+ return;
+ }
+
+ }
+
+ /* reset internal accumulation buffer */
+ this->size = 0;
+ }
+ }
+}
+
+static void ff_audio_reset (audio_decoder_t *this_gen) {
+}
+
+static void ff_audio_dispose (audio_decoder_t *this_gen) {
+
+ ff_audio_decoder_t *this = (ff_audio_decoder_t *) this_gen;
+
+ if (this->output_open)
+ this->stream->audio_out->close (this->stream->audio_out);
+ this->output_open = 0;
+
+ free(this->buf);
+ free(this->decode_buffer);
+
+ free (this_gen);
+}
+
+static audio_decoder_t *ff_audio_open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) {
+
+ ff_audio_decoder_t *this ;
+
+ this = (ff_audio_decoder_t *) malloc (sizeof (ff_audio_decoder_t));
+
+ this->audio_decoder.decode_data = ff_audio_decode_data;
+ this->audio_decoder.reset = ff_audio_reset;
+ this->audio_decoder.dispose = ff_audio_dispose;
+
+ this->output_open = 0;
+ this->audio_channels = 0;
+ this->stream = stream;
+ this->buf = NULL;
+ this->size = 0;
+ this->decoder_ok = 0;
+
+ return &this->audio_decoder;
+}
+
+static char *ff_audio_get_identifier (audio_decoder_class_t *this) {
+ return "ffmpeg audio";
+}
+
+static char *ff_audio_get_description (audio_decoder_class_t *this) {
+ return "ffmpeg based audio decoder plugin";
+}
+
+static void ff_audio_dispose_class (audio_decoder_class_t *this) {
+ free (this);
+}
+
+static void *init_audio_plugin (xine_t *xine, void *data) {
+
+ ff_audio_class_t *this ;
+
+ this = (ff_audio_class_t *) malloc (sizeof (ff_audio_class_t));
+
+ this->decoder_class.open_plugin = ff_audio_open_plugin;
+ this->decoder_class.get_identifier = ff_audio_get_identifier;
+ this->decoder_class.get_description = ff_audio_get_description;
+ this->decoder_class.dispose = ff_audio_dispose_class;
+
+ return this;
+}
+
/*
* exported plugin catalog entry
*/
-static uint32_t supported_types[] = {
- BUF_VIDEO_MSMPEG4_V3, BUF_VIDEO_MSMPEG4_V2,
- BUF_VIDEO_MSMPEG4_V1, BUF_VIDEO_WMV7, BUF_VIDEO_MPEG4,
- BUF_VIDEO_XVID, BUF_VIDEO_DIVX5, BUF_VIDEO_MJPEG,
- BUF_VIDEO_H263, BUF_VIDEO_RV10,
+static uint32_t supported_video_types[] = {
+ BUF_VIDEO_MSMPEG4_V1,
+ BUF_VIDEO_MSMPEG4_V2,
+ BUF_VIDEO_MSMPEG4_V3,
+ BUF_VIDEO_WMV7,
+ /*BUF_VIDEO_WMV8,*/
+ BUF_VIDEO_MPEG4,
+ BUF_VIDEO_XVID,
+ BUF_VIDEO_DIVX5,
+ BUF_VIDEO_MJPEG,
+ BUF_VIDEO_H263,
+ BUF_VIDEO_RV10,
/* PIX_FMT_YUV410P must be supported to enable svq1 */
/* BUF_VIDEO_SORENSON_V1 */
- BUF_VIDEO_JPEG, BUF_VIDEO_MPEG, 0
+ BUF_VIDEO_JPEG,
+ BUF_VIDEO_MPEG,
+ 0
};
-static decoder_info_t dec_info_ffmpeg = {
- supported_types, /* supported types */
- 5 /* priority */
+static uint32_t supported_audio_types[] = {
+ BUF_AUDIO_WMAV1,
+ BUF_AUDIO_WMAV2,
+ 0
};
+static decoder_info_t dec_info_ffmpeg_video = {
+ supported_video_types, /* supported types */
+ 9 /* priority */
+};
+
+static decoder_info_t dec_info_ffmpeg_audio = {
+ supported_audio_types, /* supported types */
+ 9 /* priority */
+};
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_VIDEO_DECODER, 11, "ffmpeg", XINE_VERSION_CODE, &dec_info_ffmpeg, init_plugin },
+ { PLUGIN_VIDEO_DECODER, 11, "ffmpegvideo", XINE_VERSION_CODE, &dec_info_ffmpeg_video, init_video_plugin },
+/* { PLUGIN_AUDIO_DECODER, 10, "ffmpegaudio", XINE_VERSION_CODE, &dec_info_ffmpeg_audio, init_audio_plugin },*/
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};