rendered paste body#include "xmms/xmms_xformplugin.h"
#include "xmms/xmms_log.h"
#include "xmms/xmms_medialib.h"
#include <glib.h>
#include <string.h>
/*
* Defines
*/
#define MIN_FLV_SIZE 24
#define MIN_FLV_HEADER 13
#define BUFFERSIZE 4096
/* Private Data Type
*/
typedef struct _flv_tag_St {
guchar tag_type;
guchar data_size[3];
guchar timestamp[3];
guchar timestamp_ext;
guchar stream_id[3];
} flv_tag_t ;
typedef struct xmms_flv_data_St {
guchar stream_type;
flv_tag_t tag_header;
} xmms_flv_data_t;
/*
* Function prototypes
*/
static gboolean xmms_flv_plugin_setup (xmms_xform_plugin_t *xform_plugin);
static gint xmms_flv_read (xmms_xform_t *xform, gpointer buf, gint len,
xmms_error_t *error);
static void xmms_flv_destroy (xmms_xform_t *xform);
static gboolean xmms_flv_init (xmms_xform_t *xform);
static gint64 xmms_flv_seek (xmms_xform_t *xform, gint64 samples,
xmms_xform_seek_mode_t whence,
xmms_error_t *error);
/*
* Plugin header
*/
XMMS_XFORM_PLUGIN ("FLV",
"FLV Demuxer", XMMS_VERSION,
"FLV Demuxer",
xmms_flv_plugin_setup);
static gboolean
xmms_flv_plugin_setup (xmms_xform_plugin_t *xform_plugin)
{
xmms_xform_methods_t methods;
XMMS_XFORM_METHODS_INIT (methods);
methods.init = xmms_flv_init;
methods.destroy = xmms_flv_destroy;
methods.read = xmms_flv_read;
methods.seek = xmms_flv_seek;
xmms_xform_plugin_methods_set (xform_plugin, &methods);
xmms_xform_plugin_indata_add (xform_plugin,
XMMS_STREAM_TYPE_MIMETYPE,
"video/x-flv",
NULL);
xmms_magic_add ("FLV Header", "video/x-flv",
"0 string FLV", NULL);
xmms_magic_extension_add ("video/x-flv", "*.flv");
return TRUE;
}
static gboolean
xmms_flv_init (xmms_xform_t *xform)
{
xmms_error_t error;
xmms_flv_data_t *data = NULL;
gint ret = 0;
guchar header[MIN_FLV_HEADER+1];
g_return_val_if_fail (xform, FALSE);
data = g_new0 (xmms_flv_data_t, 1);
xmms_xform_private_data_set (xform, data);
/* Read header */
ret = xmms_xform_read (xform, header, MIN_FLV_HEADER, &error);
if( ret < MIN_FLV_HEADER )
return FALSE;
data->stream_type = header[4];
if( !((data->stream_type & 0x05) || (data->stream_type & 0x04)) )
{
xmms_log_error(" Only video stream.......no audio stream found.....!! ");
return FALSE;
}
/* TODO: read in metadata tag and also peek at 1st audio tag to get stream format
As of now just skip the headers and let read method analyse each tag including metadata and video
skipping them as and when encountered */
xmms_xform_outdata_type_add (xform,
XMMS_STREAM_TYPE_MIMETYPE,
"audio/mpeg",
NULL);
return TRUE;
}
static gint
xmms_flv_read (xmms_xform_t *xform, gpointer buf, gint len,
xmms_error_t *error)
{
gint ret;
xmms_flv_data_t *data;
guchar sound_info;
gboolean done = FALSE;
gint dsize = 0;
g_return_val_if_fail (xform, -1);
data = xmms_xform_private_data_get (xform);
g_return_val_if_fail (data, -1);
while (!done) {
ret = xmms_xform_read (xform, &data->tag_header, sizeof(flv_tag_t), error);
if (ret <= 0)
return ret;
if (ret < sizeof(flv_tag_t)) {
xmms_log_error("Couldn't read FLV tag header......");
return -1;
}
dsize = ( ( data->tag_header.data_size[0] << 16 ) +
(data->tag_header.data_size[1] << 8 ) + data->tag_header.data_size[2] );
printf("\n size %d \n",dsize);
if (data->tag_header.tag_type == 0x08) {
ret = xmms_xform_read (xform, &sound_info, 1, error);
if (ret <= 0)
return ret;
dsize--;
g_assert(dsize < len);
ret = xmms_xform_read (xform, buf, dsize, error);
done = 1;
if (ret <= 0)
return ret;
}
else xmms_xform_seek (xform, dsize, XMMS_XFORM_SEEK_CUR, error);
xmms_xform_seek (xform, 4, XMMS_XFORM_SEEK_CUR, error);
}
return dsize;
}
static gint64
xmms_flv_seek (xmms_xform_t *xform, gint64 samples,
xmms_xform_seek_mode_t whence, xmms_error_t *error)
{
return (xmms_xform_seek (xform, samples, whence, error));
}
static void
xmms_flv_destroy (xmms_xform_t *xform)
{
g_return_if_fail (xform);
g_free (xmms_xform_private_data_get (xform));
}