vdr/xine-lib-vdr/src/libffmpeg Makefile.am Makefile.in audio_decoder.c diff_to_ffmpeg_cvs.txt dvaudio_decoder.c mpeg_parser.c mpeg_parser.h video_decoder.c xine_decoder.c xine_decoder.h xine_encoder.c
Darren Salt
pkg-vdr-dvb-changes@lists.alioth.debian.org
Mon, 04 Apr 2005 22:29:54 +0000
Update of /cvsroot/pkg-vdr-dvb/vdr/xine-lib-vdr/src/libffmpeg
In directory haydn:/tmp/cvs-serv2129/src/libffmpeg
Added Files:
Makefile.am Makefile.in audio_decoder.c diff_to_ffmpeg_cvs.txt
dvaudio_decoder.c mpeg_parser.c mpeg_parser.h video_decoder.c
xine_decoder.c xine_decoder.h xine_encoder.c
Log Message:
Import of VDR-patched xine-lib.
--- NEW FILE: mpeg_parser.c ---
/*
* Copyright (C) 2001-2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Simple MPEG-ES parser/framer by Thibaut Mattern (tmattern@noos.fr)
* based on libmpeg2 decoder.
*
* $Id: mpeg_parser.c,v 1.1 2005/04/04 22:29:51 dsalt-guest Exp $
*/
#define LOG_MODULE "mpeg_parser"
#define LOG_VERBOSE
/*
#define LOG
*/
#include "mpeg_parser.h"
/* mpeg frame rate table from lavc */
static const int frame_rate_tab[][2] = {
{ 0, 0},
{24000, 1001},
{ 24, 1},
{ 25, 1},
{30000, 1001},
{ 30, 1},
{ 50, 1},
{60000, 1001},
{ 60, 1},
/* Xing's 15fps: (9) */
{ 15, 1},
/* libmpeg3's "Unofficial economy rates": (10-13) */
{ 5, 1},
{ 10, 1},
{ 12, 1},
{ 15, 1},
{ 0, 0},
};
void mpeg_parser_init (mpeg_parser_t *parser)
{
mpeg_parser_reset(parser);
}
void mpeg_parser_reset (mpeg_parser_t *parser)
{
parser->shift = 0xffffff00;
parser->is_sequence_needed = 1;
parser->in_slice = 0;
parser->chunk_ptr = parser->chunk_buffer;
parser->chunk_start = parser->chunk_buffer;
parser->buffer_size = 0;
parser->code = 0xb4;
parser->picture_coding_type = 0;
parser->width = 0;
parser->height = 0;
parser->rate_code = 0;
parser->aspect_ratio_info = 0;
parser->frame_duration = 0;
parser->is_mpeg1 = 0;
parser->has_sequence = 0;
parser->frame_aspect_ratio = 0.0;
}
static void parse_header_picture (mpeg_parser_t *parser, uint8_t * buffer)
{
parser->picture_coding_type = (buffer [1] >> 3) & 7;
}
static double get_aspect_ratio(mpeg_parser_t *parser)
{
double ratio;
double mpeg1_pel_ratio[16] = {1.0 /* forbidden */,
1.0, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157,
0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 1.0 /*reserved*/ };
if( !parser->is_mpeg1 ) {
/* these hardcoded values are defined on mpeg2 standard for
* aspect ratio. other values are reserved or forbidden. */
switch (parser->aspect_ratio_info) {
case 2:
ratio = 4.0 / 3.0;
break;
case 3:
ratio = 16.0 / 9.0;
break;
case 4:
ratio = 2.11 / 1.0;
break;
case 1:
default:
ratio = (double)parser->width / (double)parser->height;
break;
}
} else {
/* mpeg1 constants refer to pixel aspect ratio */
ratio = (double)parser->width / (double)parser->height;
ratio /= mpeg1_pel_ratio[parser->aspect_ratio_info];
}
return ratio;
}
static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int len)
{
int is_frame_done;
int next_code = parser->code;
/* wait for sequence_header_code */
if (parser->is_sequence_needed) {
if (code != 0xb3) {
lprintf("waiting for sequence header\n");
parser->chunk_ptr = parser->chunk_buffer;
return 0;
}
}
is_frame_done = parser->in_slice && ((!next_code) || (next_code == 0xb7));
if (is_frame_done)
parser->in_slice = 0;
switch (code) {
case 0x00: /* picture_start_code */
parse_header_picture (parser, buffer);
parser->in_slice = 1;
switch (parser->picture_coding_type) {
case B_TYPE:
lprintf ("B-Frame\n");
break;
case P_TYPE:
lprintf ("P-Frame\n");
break;
case I_TYPE:
lprintf ("I-Frame\n");
break;
}
break;
case 0xb2: /* user data code */
/* process_userdata(mpeg2dec, buffer); */
break;
case 0xb3: /* sequence_header_code */
{
int value;
int width;
int height;
if (parser->is_sequence_needed) {
parser->is_sequence_needed = 0;
}
if ((buffer[6] & 0x20) != 0x20) {
lprintf("Invalid sequence: missing marker_bit\n");
parser->has_sequence = 0;
break; /* missing marker_bit */
}
value = (buffer[0] << 16) |
(buffer[1] << 8) |
buffer[2];
width = ((value >> 12) + 15) & ~15;
height = ((value & 0xfff) + 15) & ~15;
if ((width > 1920) || (height > 1152)) {
lprintf("Invalid sequence: width=%d, height=%d\n", width, height);
parser->has_sequence = 0;
break; /* size restrictions for MP@HL */
}
parser->width = width;
parser->height = height;
parser->rate_code = buffer[3] & 15;
parser->aspect_ratio_info = buffer[3] >> 4;
if (parser->rate_code < sizeof(frame_rate_tab)) {
parser->frame_duration = 90000;
parser->frame_duration *= frame_rate_tab[parser->rate_code][1];
parser->frame_duration /= frame_rate_tab[parser->rate_code][0];
} else {
printf ("invalid/unknown frame rate code : %d \n",
parser->rate_code);
parser->frame_duration = 0;
}
parser->has_sequence = 1;
parser->is_mpeg1 = 1;
}
break;
case 0xb5: /* extension_start_code */
switch (buffer[0] & 0xf0) {
case 0x10: /* sequence extension */
parser->is_mpeg1 = 0;
}
default:
if (code >= 0xb9)
lprintf ("stream not demultiplexed ?\n");
if (code >= 0xb0)
break;
}
return is_frame_done;
}
static inline uint8_t *copy_chunk (mpeg_parser_t *parser,
uint8_t *current, uint8_t *end)
{
uint32_t shift;
uint8_t *chunk_ptr;
uint8_t *limit;
uint8_t byte;
shift = parser->shift;
chunk_ptr = parser->chunk_ptr;
limit = current + (parser->chunk_buffer + BUFFER_SIZE - chunk_ptr);
if (limit > end)
limit = end;
while (1) {
byte = *current++;
*chunk_ptr++ = byte;
if (shift != 0x00000100) {
shift = (shift | byte) << 8;
if (current < limit)
continue;
if (current == end) {
parser->chunk_ptr = chunk_ptr;
parser->shift = shift;
lprintf("Need more bytes\n");
return NULL;
} else {
/* we filled the chunk buffer without finding a start code */
lprintf("Buffer full\n");
parser->code = 0xb4; /* sequence_error_code */
parser->chunk_ptr = parser->chunk_buffer;
return current;
}
}
lprintf("New chunk: 0x%2X\n", byte);
parser->chunk_ptr = chunk_ptr;
parser->shift = 0xffffff00;
parser->code = byte;
return current;
}
}
uint8_t *mpeg_parser_decode_data (mpeg_parser_t *parser,
uint8_t *current, uint8_t *end,
int *flush)
{
int ret;
uint8_t code;
ret = 0;
*flush = 0;
while (current != end) {
if (parser->chunk_ptr == parser->chunk_buffer) {
/* write the beginning of the chunk */
parser->chunk_buffer[0] = 0x00;
parser->chunk_buffer[1] = 0x00;
parser->chunk_buffer[2] = 0x01;
parser->chunk_buffer[3] = parser->code;
parser->chunk_ptr += 4;
parser->chunk_start = parser->chunk_ptr;
parser->has_sequence = 0;
}
code = parser->code;
current = copy_chunk (parser, current, end);
if (current == NULL)
return NULL;
ret = parse_chunk (parser, code, parser->chunk_start,
parser->chunk_ptr - parser->chunk_start - 4);
parser->chunk_start = parser->chunk_ptr;
if (ret == 1) {
if (parser->has_sequence) {
parser->frame_aspect_ratio = get_aspect_ratio(parser);
}
parser->buffer_size = parser->chunk_ptr - parser->chunk_buffer - 4;
parser->chunk_ptr = parser->chunk_buffer;
if (parser->code == 0xb7) /* sequence end, maybe a still menu */
*flush = 1;
return current;
}
}
return NULL;
}
--- NEW FILE: dvaudio_decoder.c ---
/*
* Copyright (C) 2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: dvaudio_decoder.c,v 1.1 2005/04/04 22:29:51 dsalt-guest Exp $
*
* dv audio decoder based on patch by Dan Dennedy <dan@dennedy.org>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#define LOG_MODULE "dvaudio"
#define LOG_VERBOSE
/*
#define LOG
*/
#include "xine_internal.h"
#include "buffer.h"
#include "xineutils.h"
#ifdef _MSC_VER
/* ffmpeg has own definitions of those types */
# undef int8_t
# undef uint8_t
# undef int16_t
# undef uint16_t
# undef int32_t
# undef uint32_t
# undef int64_t
# undef uint64_t
#endif
#ifdef HAVE_FFMPEG
# include <avcodec.h>
# include "libavcodec/dvdata.h"
#else
# include "libavcodec/avcodec.h"
# include "libavcodec/dvdata.h"
#endif
#ifdef _MSC_VER
# undef malloc
# undef free
# undef realloc
#endif
#define AUDIOBUFSIZE 128*1024
#define MAXFRAMESIZE 131072
typedef struct {
audio_decoder_class_t decoder_class;
} dvaudio_class_t;
typedef struct dvaudio_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;
char *decode_buffer;
int decoder_ok;
} dvaudio_decoder_t;
enum dv_pack_type {
dv_header525 = 0x3f, /* see dv_write_pack for important details on */
dv_header625 = 0xbf, /* these two packs */
dv_timecode = 0x13,
dv_audio_source = 0x50,
dv_audio_control = 0x51,
dv_audio_recdate = 0x52,
dv_audio_rectime = 0x53,
dv_video_source = 0x60,
dv_video_control = 0x61,
dv_viedo_recdate = 0x62,
dv_video_rectime = 0x63,
dv_unknown_pack = 0xff,
};
/*
* This is the dumbest implementation of all -- it simply looks at
* a fixed offset and if pack isn't there -- fails. We might want
* to have a fallback mechanism for complete search of missing packs.
*/
static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t)
{
int offs;
switch (t) {
case dv_audio_source:
offs = (80*6 + 80*16*3 + 3);
break;
case dv_audio_control:
offs = (80*6 + 80*16*4 + 3);
break;
case dv_video_control:
offs = (80*5 + 48 + 5);
break;
default:
return NULL;
}
return (frame[offs] == t ? &frame[offs] : NULL);
}
static inline uint16_t dv_audio_12to16(uint16_t sample)
{
uint16_t shift, result;
sample = (sample < 0x800) ? sample : sample | 0xf000;
shift = (sample & 0xf00) >> 8;
if (shift < 0x2 || shift > 0xd) {
result = sample;
} else if (shift < 0x8) {
shift--;
result = (sample - (256 * shift)) << shift;
} else {
shift = 0xe - shift;
result = ((sample + ((256 * shift) + 1)) << shift) - 1;
}
return result;
}
/*
* There's a couple of assumptions being made here:
* 1. By default we silence erroneous (0x8000/16bit 0x800/12bit) audio samples.
* We can pass them upwards when ffmpeg will be ready to deal with them.
* 2. We don't do software emphasis.
* 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples
* are converted into 16bit linear ones.
*/
static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2)
{
int size, i, j, d, of, smpls, freq, quant, half_ch;
uint16_t lc, rc;
const DVprofile* sys;
const uint8_t* as_pack;
as_pack = dv_extract_pack(frame, dv_audio_source);
if (!as_pack) /* No audio ? */
return 0;
sys = dv_frame_profile(frame);
smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */
freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48KHz, 1 - 44,1kHz, 2 - 32 kHz */
quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
if (quant > 1)
return -1; /* Unsupported quantization */
size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */
half_ch = sys->difseg_size/2;
/* for each DIF segment */
for (i = 0; i < sys->difseg_size; i++) {
frame += 6 * 80; /* skip DIF segment header */
if (quant == 1 && i == half_ch) {
if (!pcm2)
break;
else
pcm = pcm2;
}
for (j = 0; j < 9; j++) {
for (d = 8; d < 80; d += 2) {
if (quant == 0) { /* 16bit quantization */
of = sys->audio_shuffle[i][j] + (d - 8)/2 * sys->audio_stride;
if (of*2 >= size)
continue;
#ifdef WORDS_BIGENDIAN
pcm[of*2] = frame[d];
pcm[of*2+1] = frame[d+1];
#else
pcm[of*2] = frame[d+1];
pcm[of*2+1] = frame[d];
#endif
if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)
pcm[of*2+1] = 0;
} else { /* 12bit quantization */
lc = ((uint16_t)frame[d] << 4) |
((uint16_t)frame[d+2] >> 4);
rc = ((uint16_t)frame[d+1] << 4) |
((uint16_t)frame[d+2] & 0x0f);
lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
of = sys->audio_shuffle[i%half_ch][j] + (d - 8)/3 * sys->audio_stride;
if (of*2 >= size)
continue;
#ifdef WORDS_BIGENDIAN
pcm[of*2] = lc >> 8;
pcm[of*2+1] = lc & 0xff;
#else
pcm[of*2] = lc & 0xff;
pcm[of*2+1] = lc >> 8;
#endif
of = sys->audio_shuffle[i%half_ch+half_ch][j] +
(d - 8)/3 * sys->audio_stride;
#ifdef WORDS_BIGENDIAN
pcm[of*2] = rc >> 8;
pcm[of*2+1] = rc & 0xff;
#else
pcm[of*2] = rc & 0xff;
pcm[of*2+1] = rc >> 8;
#endif
++d;
}
}
frame += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
}
}
return size;
}
static void dvaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
dvaudio_decoder_t *this = (dvaudio_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_PREVIEW)
return;
if (buf->decoder_flags & BUF_FLAG_STDHEADER) {
this->buf = xine_xmalloc(AUDIOBUFSIZE);
this->bufsize = AUDIOBUFSIZE;
this->size = 0;
this->decode_buffer = xine_xmalloc(MAXFRAMESIZE);
this->audio_sample_rate = buf->decoder_info[1];
this->audio_bits = buf->decoder_info[2];
this->audio_channels = buf->decoder_info[3];
_x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "DV Audio");
this->decoder_ok = 1;
return;
}
if (this->decoder_ok && !(buf->decoder_flags & (BUF_FLAG_HEADER|BUF_FLAG_SPECIAL))) {
if (!this->output_open) {
this->output_open = this->stream->audio_out->open(this->stream->audio_out,
this->stream, 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;
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("dvaudio: increasing buffer to %d to avoid overflow.\n"),
this->bufsize);
this->buf = realloc( this->buf, this->bufsize );
}
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 */
offset = 0;
while (this->size>0) {
decode_buffer_size = dv_extract_audio(&this->buf[offset], this->decode_buffer, NULL);
if (decode_buffer_size > -1)
bytes_consumed = dv_frame_profile(&this->buf[offset])->frame_size;
else
bytes_consumed = decode_buffer_size;
/* dispatch the decoded audio */
out = 0;
while (out < decode_buffer_size) {
audio_buffer =
this->stream->audio_out->get_buffer (this->stream->audio_out);
if (audio_buffer->mem_size == 0) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"dvaudio: 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;
else
bytes_to_send = decode_buffer_size - out;
/* 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, this->stream);
out += bytes_to_send;
}
this->size -= bytes_consumed;
offset += bytes_consumed;
}
/* reset internal accumulation buffer */
this->size = 0;
}
}
}
static void dvaudio_reset (audio_decoder_t *this_gen) {
dvaudio_decoder_t *this = (dvaudio_decoder_t *) this_gen;
this->size = 0;
}
static void dvaudio_discontinuity (audio_decoder_t *this_gen) {
}
static void dvaudio_dispose (audio_decoder_t *this_gen) {
dvaudio_decoder_t *this = (dvaudio_decoder_t *) this_gen;
if (this->output_open)
this->stream->audio_out->close (this->stream->audio_out, this->stream);
this->output_open = 0;
free(this->buf);
free(this->decode_buffer);
free (this_gen);
}
static audio_decoder_t *dvaudio_open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) {
dvaudio_decoder_t *this ;
this = (dvaudio_decoder_t *) xine_xmalloc (sizeof (dvaudio_decoder_t));
this->audio_decoder.decode_data = dvaudio_decode_data;
this->audio_decoder.reset = dvaudio_reset;
this->audio_decoder.discontinuity = dvaudio_discontinuity;
this->audio_decoder.dispose = dvaudio_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 *dvaudio_get_identifier (audio_decoder_class_t *this) {
return "dv audio";
}
static char *dvaudio_get_description (audio_decoder_class_t *this) {
return "dv audio decoder plugin";
}
static void dvaudio_dispose_class (audio_decoder_class_t *this) {
free (this);
}
static void *init_dvaudio_plugin (xine_t *xine, void *data) {
dvaudio_class_t *this ;
this = (dvaudio_class_t *) xine_xmalloc (sizeof (dvaudio_class_t));
this->decoder_class.open_plugin = dvaudio_open_plugin;
this->decoder_class.get_identifier = dvaudio_get_identifier;
this->decoder_class.get_description = dvaudio_get_description;
this->decoder_class.dispose = dvaudio_dispose_class;
return this;
}
static uint32_t supported_audio_types[] = {
BUF_AUDIO_DV,
0
};
decoder_info_t dec_info_dvaudio = {
supported_audio_types, /* supported types */
5 /* priority */
};
/*
* exported plugin catalog entry
*/
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_DECODER, 15, "dvaudio", XINE_VERSION_CODE, &dec_info_dvaudio, init_dvaudio_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
--- NEW FILE: video_decoder.c ---
/*
* Copyright (C) 2001-2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
[...1308 lines suppressed...]
BUF_VIDEO_FLV1,
BUF_VIDEO_QTRLE,
BUF_VIDEO_H264,
0
};
static uint32_t wmv8_video_types[] = {
BUF_VIDEO_WMV8,
0
};
decoder_info_t dec_info_ffmpeg_video = {
supported_video_types, /* supported types */
6 /* priority */
};
decoder_info_t dec_info_ffmpeg_wmv8 = {
wmv8_video_types, /* supported types */
0 /* priority */
};
--- NEW FILE: mpeg_parser.h ---
/*
* Copyright (C) 2001-2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Simple MPEG-ES parser/framer by Thibaut Mattern (tmattern@noos.fr)
* based on libmpeg2 decoder.
*
* $Id: mpeg_parser.h,v 1.1 2005/04/04 22:29:51 dsalt-guest Exp $
*/
#ifndef HAVE_MPEG_PARSER_H
#define HAVE_MPEG_PARSER_H
#include "xine_internal.h"
#include "xine_decoder.h"
#define BUFFER_SIZE (1194 * 1024) /* libmpeg2's buffer size */
/* picture coding type (mpeg2 header) */
#define I_TYPE 1
#define P_TYPE 2
#define B_TYPE 3
#define D_TYPE 4
typedef struct mpeg_parser_s {
uint32_t shift;
int is_sequence_needed;
uint8_t chunk_buffer[BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
uint8_t *chunk_ptr;
uint8_t *chunk_start;
int buffer_size;
uint8_t code;
uint8_t picture_coding_type;
int rate_code;
int aspect_ratio_info;
int in_slice;
/* public properties */
int is_mpeg1;
int has_sequence;
int width;
int height;
int frame_duration;
double frame_aspect_ratio;
} mpeg_parser_t;
/* parser initialization */
void mpeg_parser_init (mpeg_parser_t *parser);
/* read a frame
* return a pointer to the first byte of the next frame
* or NULL if more bytes are needed
* *flush is set to 1 if the decoder must be flushed (needed for still menus)
*/
uint8_t *mpeg_parser_decode_data (mpeg_parser_t *parser,
uint8_t *current, uint8_t *end,
int *flush);
/* reset the parser */
void mpeg_parser_reset (mpeg_parser_t *parser);
#endif /* HAVE_MPEG_PARSER_H */
--- NEW FILE: Makefile.am ---
include $(top_srcdir)/misc/Makefile.common
if HAVE_FFMPEG
FF_CPPFLAGS = $(FFMPEG_CPPFLAGS)
link_ffmpeg = $(FFMPEG_LIBS)
else
link_ffmpeg = \
$(top_builddir)/src/libffmpeg/libavcodec/libavcodec.la \
$(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la
SUBDIRS = libavcodec
endif
# this must always be included, even if the current machine has no DXR3...
EXTRA_DIST = xine_encoder.c diff_to_ffmpeg_cvs.txt
INTERNAL_DOCS = diff_to_ffmpeg_cvs.txt
libdir = $(XINE_PLUGINDIR)
lib_LTLIBRARIES = xineplug_decode_ff.la xineplug_decode_dvaudio.la
if HAVE_DXR3
AM_CPPFLAGS = -I$(top_srcdir)/src/dxr3 $(X_CFLAGS) $(FF_CPPFLAGS)
xineplug_decode_ff_la_SOURCES = xine_decoder.c audio_decoder.c video_decoder.c \
xine_encoder.c mpeg_parser.c
# The dxr3 uses ffmpegs MPEG encoder by dlopen()ing the ffmpeg plugin and
# dlsym()ing the necessary function. Therefore we must allow more exported
# symbols and cannot use @XINE_PLUGIN_MIN_SYMS@
xineplug_decode_ff_la_LDFLAGS = -avoid-version -module
else
AM_CPPFLAGS = $(FF_CPPFLAGS)
xineplug_decode_ff_la_SOURCES = xine_decoder.c audio_decoder.c video_decoder.c \
mpeg_parser.c
xineplug_decode_ff_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
endif
xineplug_decode_ff_la_LIBADD = $(MLIB_LIBS) $(XINE_LIB) -lm $(ZLIB_LIBS) \
$(link_ffmpeg)
xineplug_decode_dvaudio_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
xineplug_decode_dvaudio_la_SOURCES = dvaudio_decoder.c
xineplug_decode_dvaudio_la_LIBADD = $(XINE_LIB)
noinst_HEADERS = xine_decoder.h mpeg_parser.h
--- NEW FILE: diff_to_ffmpeg_cvs.txt ---
--- avcodec.h 2004-05-28 18:20:57.000000000 +0200
+++ avcodec.h 2004-05-28 18:25:10.000000000 +0200
@@ -15,6 +15,13 @@
#include "rational.h"
#include <sys/types.h> /* size_t */
+/* FIXME: We cannot use ffmpeg's XvMC capabilities, since that would require
+ * linking the ffmpeg plugin against XvMC libraries, which is a bad thing,
+ * since they are output dependend.
+ * The correct fix would be to reimplement the XvMC functions libavcodec uses
+ * and do the necessary talking with our XvMC output plugin there. */
+#undef HAVE_XVMC
+
#define FFMPEG_VERSION_INT 0x000408
#define FFMPEG_VERSION "0.4.8"
#define LIBAVCODEC_BUILD 4715
@@ -2177,6 +2184,13 @@
((uint8_t*)(x))[0])
#endif
+/* unused static macro */
+#if defined(__GNUC__) && !defined(DEBUG)
+/* since we do not compile the encoder part of ffmpeg, some static
+ * functions will be unused; this is ok, the compiler will take care */
+# define static static __attribute__((__unused__))
+#endif
+
#ifdef __cplusplus
}
#endif
--- common.h 2004-05-28 18:20:57.000000000 +0200
+++ common.h 2004-05-28 18:22:54.000000000 +0200
@@ -6,6 +6,11 @@
#ifndef COMMON_H
#define COMMON_H
+/* xine: disable DEBUG for ffmpeg (too noisy) */
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# define CONFIG_WIN32
#endif
@@ -213,7 +218,9 @@
/* debug stuff */
# ifndef DEBUG
+# ifndef NDEBUG
# define NDEBUG
+# endif
# endif
# include <assert.h>
--- dsputil.h 2004-05-28 18:20:57.000000000 +0200
+++ dsputil.h 2004-05-28 18:22:54.000000000 +0200
@@ -31,6 +31,9 @@
#include "common.h"
#include "avcodec.h"
+#if defined(ARCH_X86)
+#define HAVE_MMX 1
+#endif
//#define DEBUG
/* dct code */
--- mlib/dsputil_mlib.c 2004-05-28 18:20:57.000000000 +0200
+++ mlib/dsputil_mlib.c 2004-05-28 18:22:54.000000000 +0200
@@ -20,6 +20,8 @@
#include "../dsputil.h"
#include "../mpegvideo.h"
+#include "../../../xine-utils/xineutils.h"
+
#include <mlib_types.h>
#include <mlib_status.h>
#include <mlib_sys.h>
@@ -419,6 +421,7 @@
void dsputil_init_mlib(DSPContext* c, AVCodecContext *avctx)
{
+ if (xine_mm_accel() & MM_ACCEL_MLIB) {
c->get_pixels = get_pixels_mlib;
c->diff_pixels = diff_pixels_mlib;
c->add_pixels_clamped = add_pixels_clamped_mlib;
@@ -445,10 +448,12 @@
c->put_no_rnd_pixels_tab[1][0] = put_pixels8_mlib;
c->bswap_buf = bswap_buf_mlib;
+ }
}
void MPV_common_init_mlib(MpegEncContext *s)
{
+ if (xine_mm_accel() & MM_ACCEL_MLIB) {
if(s->avctx->dct_algo==FF_DCT_AUTO || s->avctx->dct_algo==FF_DCT_MLIB){
s->dsp.fdct = ff_fdct_mlib;
}
@@ -459,4 +464,5 @@
s->dsp.idct = ff_idct_mlib;
s->dsp.idct_permutation_type= FF_NO_IDCT_PERM;
}
+ }
}
--- motion_est.c 2004-05-30 20:16:44.000000000 +0200
+++ motion_est.c 2004-05-10 23:21:24.000000000 +0200
@@ -20,6 +20,9 @@
*
* new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
*/
+
+/* motion estimation only needed for encoders */
+#ifdef CONFIG_ENCODERS
/**
* @file motion_est.c
@@ -1998,3 +2001,5 @@
}
}
}
+
+#endif /* CONFIG_ENCODERS */
--- mpeg12.c 2004-05-28 18:20:57.000000000 +0200
+++ mpeg12.c 2004-05-28 18:22:54.000000000 +0200
@@ -34,6 +34,13 @@
//#include <assert.h>
+/* if xine's MPEG encoder is enabled, enable the encoding features in
+ * this particular module */
+#if defined(XINE_MPEG_ENCODER) && !defined(CONFIG_ENCODERS)
+#define CONFIG_ENCODERS
+#endif
+
+
/* Start codes. */
#define SEQ_END_CODE 0x000001b7
#define SEQ_START_CODE 0x000001b3
--- mpegvideo.c 2004-08-04 18:17:52.000000000 +0200
+++ mpegvideo.c 2004-08-04 18:19:08.000000000 +0200
@@ -38,6 +38,14 @@
//#undef NDEBUG
//#include <assert.h>
+
+/* if xine's MPEG encoder is enabled, enable the encoding features in
+ * this particular module */
+#if defined(XINE_MPEG_ENCODER) && !defined(CONFIG_ENCODERS)
+#define CONFIG_ENCODERS
+#endif
+
+
#ifdef CONFIG_ENCODERS
static void encode_picture(MpegEncContext *s, int picture_number);
#endif //CONFIG_ENCODERS
@@ -1032,6 +1040,8 @@
s->low_delay= 0; //s->max_b_frames ? 0 : 1;
avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1);
break;
+/* xine: this is never used in either decode or MPEG-1 encode mode */
+#if 0
case CODEC_ID_MPEG2VIDEO:
s->out_format = FMT_MPEG1;
s->low_delay= 0; //s->max_b_frames ? 0 : 1;
@@ -1153,6 +1163,7 @@
s->low_delay=1;
break;
#endif
+#endif /* #if 0 */
default:
return -1;
}
@@ -1171,13 +1182,22 @@
ff_set_cmp(&s->dsp, s->dsp.ildct_cmp, s->avctx->ildct_cmp);
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
+ ff_init_me(s);
+#endif /* #if 0 */
+
#ifdef CONFIG_ENCODERS
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
if (s->out_format == FMT_H263)
h263_encode_init(s);
if(s->msmpeg4_version)
ff_msmpeg4_encode_init(s);
#endif
+#endif /* #if 0 */
+/* xine: we do want this for MPEG-1 encoding */
if (s->out_format == FMT_MPEG1)
ff_mpeg1_encode_init(s);
#endif
@@ -1229,9 +1249,12 @@
ff_rate_control_uninit(s);
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
MPV_common_end(s);
if (s->out_format == FMT_MJPEG)
mjpeg_close(s);
+#endif /* #if 0 */
av_freep(&avctx->extradata);
@@ -2135,8 +2158,11 @@
MPV_frame_end(s);
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
if (s->out_format == FMT_MJPEG)
mjpeg_picture_trailer(s);
+#endif /* #if 0 */
if(s->flags&CODEC_FLAG_PASS1)
ff_write_pass1_stats(s);
@@ -3673,6 +3699,8 @@
case CODEC_ID_MPEG1VIDEO:
case CODEC_ID_MPEG2VIDEO:
mpeg1_encode_mb(s, s->block, motion_x, motion_y); break;
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
case CODEC_ID_MPEG4:
mpeg4_encode_mb(s, s->block, motion_x, motion_y); break;
@@ -3690,6 +3718,7 @@
#endif
case CODEC_ID_MJPEG:
mjpeg_encode_mb(s, s->block); break;
+#endif /* #if 0 */
default:
assert(0);
}
@@ -3897,6 +3926,8 @@
+sse(s, s->new_picture.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], w>>1, h>>1, s->uvlinesize);
}
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
static int pre_estimate_motion_thread(AVCodecContext *c, void *arg){
MpegEncContext *s= arg;
@@ -3940,6 +3971,7 @@
}
return 0;
}
+#endif
static int mb_var_thread(AVCodecContext *c, void *arg){
MpegEncContext *s= arg;
@@ -3964,6 +3996,8 @@
}
static void write_slice_end(MpegEncContext *s){
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
if(s->codec_id==CODEC_ID_MPEG4){
if(s->partitioned_frame){
ff_mpeg4_merge_partitions(s);
@@ -3973,6 +4007,7 @@
}else if(s->out_format == FMT_MJPEG){
ff_mjpeg_stuffing(&s->pb);
}
+#endif /* #if 0 */
align_put_bits(&s->pb);
flush_put_bits(&s->pb);
@@ -4024,10 +4059,13 @@
case CODEC_ID_FLV1:
s->gob_index = ff_h263_get_gob_height(s);
break;
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
case CODEC_ID_MPEG4:
if(s->partitioned_frame)
ff_mpeg4_init_partitions(s);
break;
+#endif /* #if 0 */
}
#endif
@@ -4081,9 +4119,12 @@
if(s->start_mb_y != mb_y || mb_x!=0){
write_slice_end(s);
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame){
ff_mpeg4_init_partitions(s);
}
+#endif /* #if 0 */
}
assert((put_bits_count(&s->pb)&7) == 0);
@@ -4105,19 +4146,25 @@
s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, current_packet_size, 0);
switch(s->codec_id){
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
case CODEC_ID_MPEG4:
ff_mpeg4_encode_video_packet_header(s);
ff_mpeg4_clean_buffers(s);
break;
+#endif /* #if 0 */
case CODEC_ID_MPEG1VIDEO:
case CODEC_ID_MPEG2VIDEO:
ff_mpeg1_encode_slice_header(s);
ff_mpeg1_clean_buffers(s);
break;
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
case CODEC_ID_H263:
case CODEC_ID_H263P:
h263_encode_gob_header(s, mb_y);
break;
+#endif /* #if 0 */
}
if(s->flags&CODEC_FLAG_PASS1){
@@ -4231,9 +4278,12 @@
s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT;
s->mb_intra= 0;
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
ff_mpeg4_set_direct_mv(s, mx, my);
#endif
+#endif /* #if 0 */
encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb,
&dmin, &next_block, mx, my);
}
@@ -4421,9 +4471,12 @@
s->mb_intra= 0;
motion_x=s->b_direct_mv_table[xy][0];
motion_y=s->b_direct_mv_table[xy][1];
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
ff_mpeg4_set_direct_mv(s, motion_x, motion_y);
#endif
+#endif /* #if 0 */
break;
case CANDIDATE_MB_TYPE_BIDIR:
s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;
@@ -4530,11 +4583,14 @@
}
}
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
//not beautifull here but we must write it before flushing so it has to be here
if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == I_TYPE)
msmpeg4_encode_ext_header(s);
#endif
+#endif /* #if 0 */
write_slice_end(s);
@@ -4597,12 +4653,15 @@
s->me.mb_var_sum_temp =
s->me.mc_mb_var_sum_temp = 0;
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
/* we need to initialize some time vars before we can encode b-frames */
// RAL: Condition added for MPEG1VIDEO
if (s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->h263_msmpeg4))
ff_set_mpeg4_time(s, s->picture_number); //FIXME rename and use has_b_frames or similar
#endif
+#endif /* #if 0 */
s->me.scene_change_score=0;
@@ -4621,6 +4680,8 @@
ff_update_duplicate_context(s->thread_context[i], s);
}
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
ff_init_me(s);
/* Estimate motion for every MB */
@@ -4633,6 +4694,8 @@
s->avctx->execute(s->avctx, estimate_motion_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count);
}else /* if(s->pict_type == I_TYPE) */{
+#endif /* #if 0 */
+ {
/* I-Frame */
for(i=0; i<s->mb_stride*s->mb_height; i++)
s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA;
@@ -4656,6 +4719,8 @@
//printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum);
}
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
if(!s->umvplus){
if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) {
s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER);
@@ -4709,11 +4774,14 @@
}
}
}
+#endif /* #if 0 */
if (!s->fixed_qscale)
s->current_picture.quality = ff_rate_estimate_qscale(s); //FIXME pic_ptr
if(s->adaptive_quant){
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
#ifdef CONFIG_RISKY
switch(s->codec_id){
case CODEC_ID_MPEG4:
@@ -4726,6 +4794,7 @@
break;
}
#endif
+#endif /* #if 0 */
s->lambda= s->lambda_table[0];
//FIXME broken
@@ -4759,6 +4828,8 @@
s->last_bits= put_bits_count(&s->pb);
switch(s->out_format) {
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
case FMT_MJPEG:
mjpeg_picture_header(s);
break;
@@ -4778,11 +4849,15 @@
h263_encode_picture_header(s, picture_number);
break;
#endif
+#endif /* #if 0 */
case FMT_MPEG1:
mpeg1_encode_picture_header(s, picture_number);
break;
+/* xine: do not need this for decode or MPEG-1 encoding modes */
+#if 0
case FMT_H264:
break;
+#endif /* #if 0 */
default:
assert(0);
}
--- NEW FILE: audio_decoder.c ---
/*
* Copyright (C) 2001-2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: audio_decoder.c,v 1.1 2005/04/04 22:29:51 dsalt-guest Exp $
*
* xine audio decoder plugin using ffmpeg
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#define LOG_MODULE "ffmpeg_audio_dec"
#define LOG_VERBOSE
/*
#define LOG
*/
#include "xine_internal.h"
#include "buffer.h"
#include "xineutils.h"
#include "bswap.h"
#include "xine_decoder.h"
#define AUDIOBUFSIZE (64 * 1024)
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;
AVCodec *codec;
char *decode_buffer;
int decoder_ok;
} ff_audio_decoder_t;
static const ff_codec_t ff_audio_lookup[] = {
{BUF_AUDIO_WMAV1, CODEC_ID_WMAV1, "MS Windows Media Audio 1 (ffmpeg)"},
{BUF_AUDIO_WMAV2, CODEC_ID_WMAV2, "MS Windows Media Audio 2 (ffmpeg)"},
{BUF_AUDIO_14_4, CODEC_ID_RA_144, "Real 14.4 (ffmpeg)"},
{BUF_AUDIO_28_8, CODEC_ID_RA_288, "Real 28.8 (ffmpeg)"},
{BUF_AUDIO_MPEG, CODEC_ID_MP3, "MP3 (ffmpeg)"},
{BUF_AUDIO_MSADPCM, CODEC_ID_ADPCM_MS, "MS ADPCM (ffmpeg)"},
{BUF_AUDIO_QTIMAADPCM, CODEC_ID_ADPCM_IMA_QT, "QT IMA ADPCM (ffmpeg)"},
{BUF_AUDIO_MSIMAADPCM, CODEC_ID_ADPCM_IMA_WAV, "MS IMA ADPCM (ffmpeg)"},
{BUF_AUDIO_DK3ADPCM, CODEC_ID_ADPCM_IMA_DK3, "Duck DK3 ADPCM (ffmpeg)"},
{BUF_AUDIO_DK4ADPCM, CODEC_ID_ADPCM_IMA_DK4, "Duck DK4 ADPCM (ffmpeg)"},
{BUF_AUDIO_VQA_IMA, CODEC_ID_ADPCM_IMA_WS, "Westwood Studios IMA (ffmpeg)"},
{BUF_AUDIO_SMJPEG_IMA, CODEC_ID_ADPCM_IMA_SMJPEG, "SMJPEG IMA (ffmpeg)"},
{BUF_AUDIO_XA_ADPCM, CODEC_ID_ADPCM_XA, "CD-ROM/XA ADPCM (ffmpeg)"},
{BUF_AUDIO_4X_ADPCM, CODEC_ID_ADPCM_4XM, "4X ADPCM (ffmpeg)"},
{BUF_AUDIO_EA_ADPCM, CODEC_ID_ADPCM_EA, "Electronic Arts ADPCM (ffmpeg)"},
{BUF_AUDIO_MULAW, CODEC_ID_PCM_MULAW, "mu-law logarithmic PCM (ffmpeg)"},
{BUF_AUDIO_ALAW, CODEC_ID_PCM_ALAW, "A-law logarithmic PCM (ffmpeg)"},
{BUF_AUDIO_ROQ, CODEC_ID_ROQ_DPCM, "RoQ DPCM (ffmpeg)"},
{BUF_AUDIO_INTERPLAY, CODEC_ID_INTERPLAY_DPCM, "Interplay DPCM (ffmpeg)"},
{BUF_AUDIO_MAC3, CODEC_ID_MACE3, "MACE 3:1 (ffmpeg)"},
{BUF_AUDIO_MAC6, CODEC_ID_MACE6, "MACE 6:1 (ffmpeg)"},
{BUF_AUDIO_XAN_DPCM, CODEC_ID_XAN_DPCM, "Origin Xan DPCM (ffmpeg)"},
{BUF_AUDIO_VMD, CODEC_ID_VMDAUDIO, "Sierra VMD Audio (ffmpeg)"},
{BUF_AUDIO_FLAC, CODEC_ID_FLAC, "FLAC (ffmpeg)"} };
static void ff_audio_ensure_buffer_size(ff_audio_decoder_t *this, int size) {
if (size > this->bufsize) {
this->bufsize = size + size / 2;
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("ffmpeg_audio_dec: increasing buffer to %d to avoid overflow.\n"),
this->bufsize);
this->buf = realloc( this->buf, this->bufsize );
}
}
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) {
/* accumulate init data */
ff_audio_ensure_buffer_size(this, this->size + buf->size);
memcpy(this->buf + this->size, buf->content, buf->size);
this->size += buf->size;
if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
int i, codec_type;
xine_waveformatex *audio_header;
codec_type = buf->type & 0xFFFF0000;
this->codec = NULL;
for(i = 0; i < sizeof(ff_audio_lookup)/sizeof(ff_codec_t); i++)
if(ff_audio_lookup[i].type == codec_type) {
this->codec = avcodec_find_decoder(ff_audio_lookup[i].id);
_x_meta_info_set(this->stream, XINE_META_INFO_AUDIOCODEC,
ff_audio_lookup[i].name);
break;
}
if (!this->codec) {
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
_("ffmpeg_audio_dec: couldn't find ffmpeg decoder for buf type 0x%X\n"),
codec_type);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0);
return;
}
this->context = avcodec_alloc_context();
if(buf->decoder_flags & BUF_FLAG_STDHEADER) {
this->audio_sample_rate = buf->decoder_info[1];
this->audio_channels = buf->decoder_info[3];
if(this->size) {
audio_header = (xine_waveformatex *)this->buf;
this->context->block_align = audio_header->nBlockAlign;
this->context->bit_rate = audio_header->nAvgBytesPerSec * 8;
if(audio_header->cbSize > 0) {
this->context->extradata = xine_xmalloc(audio_header->cbSize);
this->context->extradata_size = audio_header->cbSize;
memcpy( this->context->extradata,
(uint8_t *)audio_header + sizeof(xine_waveformatex),
audio_header->cbSize );
}
}
} else {
short *ptr;
switch(codec_type) {
case BUF_AUDIO_14_4:
this->audio_sample_rate = 8000;
this->audio_channels = 1;
this->context->block_align = 240;
break;
case BUF_AUDIO_28_8:
this->audio_sample_rate = BE_16(&this->buf[0x30]);
this->audio_channels = this->buf[0x37];
/* this->audio_bits = buf->content[0x35] */
this->context->block_align = BE_16(&this->buf[0x2A]);
this->context->extradata_size = 5*sizeof(short);
this->context->extradata = xine_xmalloc(this->context->extradata_size);
ptr = (short *) this->context->extradata;
ptr[0] = BE_16(&this->buf[0x2C]); /* subpacket size */
ptr[1] = BE_16(&this->buf[0x28]); /* subpacket height */
ptr[2] = BE_16(&this->buf[0x16]); /* subpacket flavour */
ptr[3] = BE_32(&this->buf[0x18]); /* coded frame size */
ptr[4] = 0; /* codec's data length */
break;
default:
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"ffmpeg_audio_dec: unknown header with buf type 0x%X\n", codec_type);
break;
}
}
/* Current ffmpeg audio decoders always use 16 bits/sample
* buf->decoder_info[2] can't be used as it doesn't refer to the output
* bits/sample for some codecs (e.g. MS ADPCM) */
this->audio_bits = 16;
this->context->sample_rate = this->audio_sample_rate;
this->context->channels = this->audio_channels;
this->context->codec_id = this->codec->id;
this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC);
this->size = 0;
this->decode_buffer = xine_xmalloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
if (avcodec_open (this->context, this->codec) < 0) {
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
_("ffmpeg_audio_dec: couldn't open decoder\n"));
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0);
return;
}
this->decoder_ok = 1;
return;
}
} else if ((buf->decoder_flags & BUF_FLAG_SPECIAL) &&
(buf->decoder_info[1] == BUF_SPECIAL_STSD_ATOM)) {
this->context->extradata_size = buf->decoder_info[2];
this->context->extradata = xine_xmalloc(buf->decoder_info[2]);
memcpy(this->context->extradata, buf->decoder_info_ptr[2],
buf->decoder_info[2]);
} else if (this->decoder_ok && !(buf->decoder_flags & BUF_FLAG_SPECIAL)) {
if (!this->output_open) {
this->output_open = this->stream->audio_out->open(this->stream->audio_out,
this->stream, 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( buf->decoder_flags & BUF_FLAG_PREVIEW )
return;
ff_audio_ensure_buffer_size(this, this->size + buf->size);
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 */
offset = 0;
while (this->size>0) {
bytes_consumed = avcodec_decode_audio (this->context,
(int16_t *)this->decode_buffer,
&decode_buffer_size,
&this->buf[offset],
this->size);
if (bytes_consumed<0) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"ffmpeg_audio_dec: error decompressing audio frame\n");
this->size=0;
return;
} else if (bytes_consumed == 0)
return;
/* dispatch the decoded audio */
out = 0;
while (out < decode_buffer_size) {
audio_buffer =
this->stream->audio_out->get_buffer (this->stream->audio_out);
if (audio_buffer->mem_size == 0) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"ffmpeg_audio_dec: 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;
else
bytes_to_send = decode_buffer_size - out;
/* 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, this->stream);
out += bytes_to_send;
}
this->size -= bytes_consumed;
offset += bytes_consumed;
}
/* reset internal accumulation buffer */
this->size = 0;
}
}
}
static void ff_audio_reset (audio_decoder_t *this_gen) {
ff_audio_decoder_t *this = (ff_audio_decoder_t *) this_gen;
this->size = 0;
/* try to reset the wma decoder */
if( this->context ) {
avcodec_close (this->context);
avcodec_open (this->context, this->codec);
}
}
static void ff_audio_discontinuity (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->context )
avcodec_close (this->context);
if (this->output_open)
this->stream->audio_out->close (this->stream->audio_out, this->stream);
this->output_open = 0;
free(this->buf);
free(this->decode_buffer);
if(this->context && this->context->extradata)
free(this->context->extradata);
if(this->context)
free(this->context);
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 *) xine_xmalloc (sizeof (ff_audio_decoder_t));
this->audio_decoder.decode_data = ff_audio_decode_data;
this->audio_decoder.reset = ff_audio_reset;
this->audio_decoder.discontinuity = ff_audio_discontinuity;
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->bufsize = 0;
this->decoder_ok = 0;
ff_audio_ensure_buffer_size(this, AUDIOBUFSIZE);
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);
}
void *init_audio_plugin (xine_t *xine, void *data) {
ff_audio_class_t *this ;
this = (ff_audio_class_t *) xine_xmalloc (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;
pthread_once( &once_control, init_once_routine );
return this;
}
static uint32_t supported_audio_types[] = {
BUF_AUDIO_WMAV1,
BUF_AUDIO_WMAV2,
BUF_AUDIO_14_4,
BUF_AUDIO_28_8,
BUF_AUDIO_MULAW,
BUF_AUDIO_ALAW,
BUF_AUDIO_MSADPCM,
BUF_AUDIO_QTIMAADPCM,
BUF_AUDIO_MSIMAADPCM,
BUF_AUDIO_DK3ADPCM,
BUF_AUDIO_DK4ADPCM,
BUF_AUDIO_XA_ADPCM,
BUF_AUDIO_ROQ,
BUF_AUDIO_INTERPLAY,
BUF_AUDIO_VQA_IMA,
BUF_AUDIO_4X_ADPCM,
BUF_AUDIO_MAC3,
BUF_AUDIO_MAC6,
BUF_AUDIO_XAN_DPCM,
BUF_AUDIO_VMD,
BUF_AUDIO_EA_ADPCM,
BUF_AUDIO_SMJPEG_IMA,
BUF_AUDIO_FLAC,
/* BUF_AUDIO_MPEG, */
0
};
decoder_info_t dec_info_ffmpeg_audio = {
supported_audio_types, /* supported types */
6 /* priority */
};
--- NEW FILE: xine_encoder.c ---
/*
* Copyright (C) 2000-2004 the xine project
*
* This file is part of xine, a unix video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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_encoder.c,v 1.1 2005/04/04 22:29:51 dsalt-guest Exp $
*/
/* mpeg encoders for the dxr3 video out plugin. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#define LOG_MODULE "dxr3_mpeg_encoder"
/* #define LOG_VERBOSE */
/* #define LOG */
#include "video_out_dxr3.h"
#ifdef HAVE_FFMPEG
# include <avcodec.h>
#else
# include "libavcodec/avcodec.h"
#endif
/* buffer size for encoded mpeg1 stream; will hold one intra frame
* at 640x480 typical sizes are <50 kB. 512 kB should be plenty */
#define DEFAULT_BUFFER_SIZE 512*1024
/*initialisation function*/
int dxr3_encoder_init(dxr3_driver_t *drv);
/* functions required by encoder api */
static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame);
static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame);
static int lavc_on_unneeded(dxr3_driver_t *drv);
/*encoder structure*/
typedef struct lavc_data_s {
encoder_data_t encoder_data;
AVCodecContext *context; /* handle for encoding */
int width, height; /* width and height of the video frame */
uint8_t *ffmpeg_buffer; /* lavc buffer */
AVFrame *picture; /* picture to be encoded */
uint8_t *out[3]; /* aligned buffer for YV12 data */
uint8_t *buf; /* unaligned YV12 buffer */
} lavc_data_t;
int dxr3_encoder_init(dxr3_driver_t *drv)
{
lavc_data_t* this;
avcodec_init();
register_avcodec(&mpeg1video_encoder);
lprintf("lavc init , version %x\n", avcodec_version());
this = xine_xmalloc(sizeof(lavc_data_t));
if (!this) return 0;
this->encoder_data.type = ENC_LAVC;
this->encoder_data.on_update_format = lavc_on_update_format;
this->encoder_data.on_frame_copy = NULL;
this->encoder_data.on_display_frame = lavc_on_display_frame;
this->encoder_data.on_unneeded = lavc_on_unneeded;
this->context = 0;
drv->enc = &this->encoder_data;
return 1;
}
/* helper function */
static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame);
static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame)
{
lavc_data_t *this = (lavc_data_t *)drv->enc;
AVCodec *codec;
unsigned char use_quantizer;
if (this->context) {
avcodec_close(this->context);
free(this->context);
free(this->picture);
this->context = NULL;
this->picture = NULL;
}
/* if YUY2 and dimensions changed, we need to re-allocate the
* internal YV12 buffer */
if (frame->vo_frame.format == XINE_IMGFMT_YUY2) {
int image_size = frame->vo_frame.pitches[0] * frame->oheight;
this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2,
(void *)&this->buf);
this->out[1] = this->out[0] + image_size;
this->out[2] = this->out[1] + image_size/4;
/* fill with black (yuv 16,128,128) */
memset(this->out[0], 16, image_size);
memset(this->out[1], 128, image_size/4);
memset(this->out[2], 128, image_size/4);
lprintf("Using YUY2->YV12 conversion\n");
}
/* resolution must be a multiple of two */
if ((frame->vo_frame.pitches[0] % 2 != 0) || (frame->oheight % 2 != 0)) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: lavc only handles video dimensions which are multiples of 2\n");
return 0;
}
/* get mpeg codec handle */
codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
if (!codec) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: lavc MPEG1 codec not found\n");
return 0;
}
lprintf("lavc MPEG1 encoder found.\n");
this->width = frame->vo_frame.pitches[0];
this->height = frame->oheight;
this->context = avcodec_alloc_context();
if (!this->context) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: Couldn't start the ffmpeg library\n");
return 0;
}
this->picture = avcodec_alloc_frame();
if (!this->picture) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: Couldn't allocate ffmpeg frame\n");
return 0;
}
/* put sample parameters */
this->context->bit_rate = drv->class->xine->config->register_range(drv->class->xine->config,
"dxr3.encoding.lavc_bitrate", 10000, 1000, 20000,
_("libavcodec mpeg output bitrate (kbit/s)"),
_("The bitrate the libavcodec mpeg encoder should use for DXR3's encoding mode. "
"Higher values will increase quality and CPU usage.\n"
"This setting is only considered, when constant quality mode is disabled."), 10, NULL, NULL);
this->context->bit_rate *= 1000; /* config in kbit/s, libavcodec wants bit/s */
use_quantizer = drv->class->xine->config->register_bool(drv->class->xine->config,
"dxr3.encoding.lavc_quantizer", 1,
_("constant quality mode"),
_("When enabled, libavcodec will use a constant quality mode by dynamically "
"compressing the images based on their complexity. When disabled, libavcodec "
"will use constant bitrate mode."), 10, NULL, NULL);
if (use_quantizer) {
this->context->qmin = drv->class->xine->config->register_range(drv->class->xine->config,
"dxr3.encoding.lavc_qmin", 1, 1, 10,
_("minimum compression"),
_("The minimum compression to apply to an image in constant quality mode."),
10, NULL, NULL);
this->context->qmax = drv->class->xine->config->register_range(drv->class->xine->config,
"dxr3.encoding.lavc_qmax", 2, 1, 20,
_("maximum quantizer"),
_("The maximum compression to apply to an image in constant quality mode."),
10, NULL, NULL);
}
lprintf("lavc -> bitrate %d \n", this->context->bit_rate);
this->context->width = frame->vo_frame.pitches[0];
this->context->height = frame->oheight;
this->context->gop_size = 0; /*intra frames only */
this->context->me_method = ME_ZERO; /*motion estimation type*/
this->context->frame_rate = 90000;
if (frame->vo_frame.duration > 90000 / 24)
this->context->frame_rate_base = 90000 / 24;
else if (frame->vo_frame.duration < 90000 / 60)
this->context->frame_rate_base = 90000 / 60;
else
this->context->frame_rate_base = frame->vo_frame.duration;
/* ffmpeg can complain about illegal framerates, but since this seems no
* problem for the DXR3, we just tell ffmpeg to be more lax with */
this->context->strict_std_compliance = -1;
/* open avcodec */
if (avcodec_open(this->context, codec) < 0) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG, "dxr3_mpeg_encoder: could not open codec\n");
return 0;
}
lprintf("dxr3_mpeg_encoder: lavc MPEG1 codec opened.\n");
if (!this->ffmpeg_buffer)
this->ffmpeg_buffer = (unsigned char *)malloc(DEFAULT_BUFFER_SIZE); /* why allocate more than needed ?! */
if (!this->ffmpeg_buffer) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: Couldn't allocate temp buffer for mpeg data\n");
return 0;
}
return 1;
}
static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame)
{
int size;
lavc_data_t* this = (lavc_data_t *)drv->enc;
ssize_t written;
if (frame->vo_frame.bad_frame) return 1;
/* ignore old frames */
if ((frame->vo_frame.pitches[0] != this->context->width) || (frame->oheight != this->context->height)) {
frame->vo_frame.free(&frame->vo_frame);
lprintf("LAVC ignoring frame !!!\n");
return 1;
}
/* prepare frame for conversion, handles YUY2 -> YV12 conversion when necessary */
lavc_prepare_frame(this, drv, frame);
/* do the encoding */
size = avcodec_encode_video(this->context, this->ffmpeg_buffer, DEFAULT_BUFFER_SIZE, this->picture);
frame->vo_frame.free(&frame->vo_frame);
written = write(drv->fd_video, this->ffmpeg_buffer, size);
if (written < 0) {
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: video device write failed (%s)\n", strerror(errno));
return 0;
}
if (written != size)
xprintf(drv->class->xine, XINE_VERBOSITY_LOG,
"dxr3_mpeg_encoder: Could only write %d of %d mpeg bytes.\n", written, size);
return 1;
}
static int lavc_on_unneeded(dxr3_driver_t *drv)
{
lavc_data_t *this = (lavc_data_t *)drv->enc;
lprintf("flushing buffers\n");
if (this->context) {
avcodec_close(this->context);
free(this->context);
free(this->picture);
this->context = NULL;
this->picture = NULL;
}
return 1;
}
static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame)
{
int i, j, w2;
uint8_t *yuy2;
if (frame->vo_frame.bad_frame) return 1;
if (frame->vo_frame.format == XINE_IMGFMT_YUY2) {
/* need YUY2->YV12 conversion */
if (!(this->out[0] && this->out[1] && this->out[2]) ) {
lprintf("Internal YV12 buffer not created.\n");
return 0;
}
this->picture->data[0] = this->out[0] + frame->vo_frame.pitches[0] * drv->top_bar; /* y */
this->picture->data[1] = this->out[1] + (frame->vo_frame.pitches[0] / 2) * (drv->top_bar / 2); /* u */
this->picture->data[2] = this->out[2] + (frame->vo_frame.pitches[0] / 2) * (drv->top_bar / 2); /* v */
yuy2 = frame->vo_frame.base[0];
w2 = frame->vo_frame.pitches[0] / 2;
for (i = 0; i < frame->vo_frame.height; i += 2) {
for (j = 0; j < w2; j++) {
/* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
*(this->picture->data[0]++) = *(yuy2++);
*(this->picture->data[1]++) = *(yuy2++);
*(this->picture->data[0]++) = *(yuy2++);
*(this->picture->data[2]++) = *(yuy2++);
}
/* down sampling */
for (j = 0; j < w2; j++) {
/* skip every second line for U and V */
*(this->picture->data[0]++) = *(yuy2++);
yuy2++;
*(this->picture->data[0]++) = *(yuy2++);
yuy2++;
}
}
/* reset for encoder */
this->picture->data[0] = this->out[0];
this->picture->data[1] = this->out[1];
this->picture->data[2] = this->out[2];
}
else { /* YV12 **/
this->picture->data[0] = frame->real_base[0];
this->picture->data[1] = frame->real_base[1];
this->picture->data[2] = frame->real_base[2];
}
this->picture->linesize[0] = this->context->width;
this->picture->linesize[1] = this->context->width / 2;
this->picture->linesize[2] = this->context->width / 2;
return 1;
}
--- NEW FILE: xine_decoder.h ---
/*
* Copyright (C) 2001-2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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.h,v 1.1 2005/04/04 22:29:51 dsalt-guest Exp $
*
*/
#ifndef HAVE_XINE_DECODER_H
#define HAVE_XINE_DECODER_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_FFMPEG
# include <avcodec.h>
#else
# include "libavcodec/avcodec.h"
#endif
#ifdef _MSC_VER
# undef malloc
# undef free
# undef realloc
# undef printf
# undef fprintf
#endif
typedef struct ff_codec_s {
uint32_t type;
enum CodecID id;
const char *name;
} ff_codec_t;
void *init_audio_plugin (xine_t *xine, void *data);
void *init_video_plugin (xine_t *xine, void *data);
extern decoder_info_t dec_info_ffmpeg_video;
extern decoder_info_t dec_info_ffmpeg_wmv8;
extern decoder_info_t dec_info_ffmpeg_audio;
extern pthread_once_t once_control;
void init_once_routine(void);
#endif
--- NEW FILE: Makefile.in ---
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SOURCES = $(xineplug_decode_dvaudio_la_SOURCES) $(xineplug_decode_ff_la_SOURCES)
[...961 lines suppressed...]
uninstall-hook:
@if echo '$(libdir)' | egrep ^'$(XINE_PLUGINDIR)' >/dev/null; then \
list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(libdir)/$$p"; \
rm -f $(DESTDIR)$(libdir)/$$p; \
done; \
fi
mostlyclean-generic:
-rm -f *~ \#* .*~ .\#*
maintainer-clean-generic:
-@echo "This command is intended for maintainers to use;"
-@echo "it deletes files that may require special tools to rebuild."
-rm -f Makefile.in
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
--- NEW FILE: xine_decoder.c ---
/*
* Copyright (C) 2001-2004 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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.1 2005/04/04 22:29:51 dsalt-guest Exp $
*
* xine decoder plugin using ffmpeg
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xine_internal.h"
#include "xine_decoder.h"
/*
* common initialisation
*/
pthread_once_t once_control = PTHREAD_ONCE_INIT;
void avcodec_register_all(void)
{
static int inited = 0;
if (inited != 0)
return;
inited = 1;
/* decoders */
register_avcodec(&h263_decoder);
register_avcodec(&mpeg4_decoder);
register_avcodec(&msmpeg4v1_decoder);
register_avcodec(&msmpeg4v2_decoder);
register_avcodec(&msmpeg4v3_decoder);
register_avcodec(&wmv1_decoder);
register_avcodec(&wmv2_decoder);
register_avcodec(&h263i_decoder);
register_avcodec(&rv10_decoder);
register_avcodec(&rv20_decoder);
register_avcodec(&svq1_decoder);
register_avcodec(&svq3_decoder);
register_avcodec(&wmav1_decoder);
register_avcodec(&wmav2_decoder);
register_avcodec(&indeo3_decoder);
register_avcodec(&mpeg1video_decoder);
register_avcodec(&dvvideo_decoder);
register_avcodec(&pcm_s16le_decoder);
register_avcodec(&mjpeg_decoder);
register_avcodec(&mjpegb_decoder);
register_avcodec(&mp2_decoder);
register_avcodec(&mp3_decoder);
register_avcodec(&mace3_decoder);
register_avcodec(&mace6_decoder);
register_avcodec(&huffyuv_decoder);
register_avcodec(&cyuv_decoder);
register_avcodec(&h264_decoder);
register_avcodec(&vp3_decoder);
register_avcodec(&fourxm_decoder);
register_avcodec(&ra_144_decoder);
register_avcodec(&ra_288_decoder);
register_avcodec(&adpcm_ms_decoder);
register_avcodec(&adpcm_ima_qt_decoder);
register_avcodec(&adpcm_ima_wav_decoder);
register_avcodec(&adpcm_ima_dk3_decoder);
register_avcodec(&adpcm_ima_dk4_decoder);
register_avcodec(&adpcm_ima_ws_decoder);
register_avcodec(&adpcm_ima_smjpeg_decoder);
register_avcodec(&adpcm_xa_decoder);
register_avcodec(&adpcm_4xm_decoder);
register_avcodec(&adpcm_ea_decoder);
register_avcodec(&pcm_alaw_decoder);
register_avcodec(&pcm_mulaw_decoder);
register_avcodec(&roq_dpcm_decoder);
register_avcodec(&interplay_dpcm_decoder);
register_avcodec(&cinepak_decoder);
register_avcodec(&msvideo1_decoder);
register_avcodec(&msrle_decoder);
register_avcodec(&rpza_decoder);
register_avcodec(&roq_decoder);
register_avcodec(&idcin_decoder);
register_avcodec(&xan_wc3_decoder);
register_avcodec(&vqa_decoder);
register_avcodec(&interplay_video_decoder);
register_avcodec(&flic_decoder);
register_avcodec(&smc_decoder);
register_avcodec(&eightbps_decoder);
register_avcodec(&vmdvideo_decoder);
register_avcodec(&vmdaudio_decoder);
register_avcodec(&truemotion1_decoder);
register_avcodec(&mszh_decoder);
register_avcodec(&zlib_decoder);
register_avcodec(&xan_dpcm_decoder);
register_avcodec(&asv1_decoder);
register_avcodec(&asv2_decoder);
register_avcodec(&vcr1_decoder);
register_avcodec(&flv_decoder);
register_avcodec(&qtrle_decoder);
register_avcodec(&flac_decoder);
}
void init_once_routine(void) {
avcodec_init();
avcodec_register_all();
}
/*
* exported plugin catalog entry
*/
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
{ PLUGIN_VIDEO_DECODER | PLUGIN_MUST_PRELOAD, 18, "ffmpegvideo", XINE_VERSION_CODE, &dec_info_ffmpeg_video, init_video_plugin },
{ PLUGIN_VIDEO_DECODER, 18, "ffmpeg-wmv8", XINE_VERSION_CODE, &dec_info_ffmpeg_wmv8, init_video_plugin },
{ PLUGIN_AUDIO_DECODER, 15, "ffmpegaudio", XINE_VERSION_CODE, &dec_info_ffmpeg_audio, init_audio_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};