<commit_before>/** @file avformat.c
 *  Avformat decoder plugin
 *
 *  Copyright (C) 2006-2007 XMMS2 Team
 *
 *  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.
 */

#include "xmms/xmms_defs.h"
#include "xmms/xmms_xformplugin.h"
#include "xmms/xmms_sample.h"
#include "xmms/xmms_log.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>

#undef ABS
#include "avformat.h"

#define AVFORMAT_BUFFER_SIZE 4096

typedef struct {
	gint track;

	AVFormatContext *fmtctx;
	AVCodecContext *codecctx;
	offset_t offset;

	guchar buffer[AVFORMAT_BUFFER_SIZE];
	guint buffer_size;

	GString *outbuf;
} xmms_avformat_data_t;

typedef struct {
	guint32 v1;
	guint16 v2;
	guint16 v3;
	guint8 v4[8];
} xmms_asf_GUID_t;

xmms_asf_GUID_t xmms_asf_GUIDs[] = {
	/* header */
	{ 0x75B22630, 0x668E, 0x11CF,
	  { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C } },
	/* content description */
	{ 0x75b22633, 0x668e, 0x11cf,
	  { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c } },
	/* extended content description */
	{ 0xD2D0A440, 0xE307, 0x11D2,
	  { 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 } },
};

static gboolean xmms_avformat_plugin_setup (xmms_xform_plugin_t *xform_plugin);
static gboolean xmms_avformat_init (xmms_xform_t *xform);
static void xmms_avformat_destroy (xmms_xform_t *xform);
static gint xmms_avformat_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
                                xmms_error_t *err);
static void xmms_avformat_get_mediainfo (xmms_xform_t *xform);
int xmms_avformat_get_track (AVFormatContext *fmtctx);

static void xmms_asf_metahack (xmms_xform_t *xform);

int xmms_avformat_read_callback (void *user_data, uint8_t *buffer,
                                 int length);
offset_t xmms_avformat_seek_callback (void *user_data, offset_t offset, int whence);

/*
 * Plugin header
 */

XMMS_XFORM_PLUGIN ("avformat",
                   "AVFormat Demuxer", XMMS_VERSION,
                   "ffmpeg libavformat demuxer",
                   xmms_avformat_plugin_setup);

static gboolean
xmms_avformat_plugin_setup (xmms_xform_plugin_t *xform_plugin)
{
	xmms_xform_methods_t methods;

	XMMS_XFORM_METHODS_INIT (methods);
	methods.init = xmms_avformat_init;
	methods.destroy = xmms_avformat_destroy;
	methods.read = xmms_avformat_read;

	xmms_xform_plugin_methods_set (xform_plugin, &methods);

	xmms_xform_plugin_indata_add (xform_plugin,
	                              XMMS_STREAM_TYPE_MIMETYPE,
	                              "video/x-ms-asf",
	                              NULL);

	xmms_magic_add ("asf header", "video/x-ms-asf",
	                "0 belong 0x3026b275", NULL);

	return TRUE;
}

static void
xmms_avformat_destroy (xmms_xform_t *xform)
{
	xmms_avformat_data_t *data;

	g_return_if_fail (xform);

	data = xmms_xform_private_data_get (xform);
	g_return_if_fail (data);

	av_close_input_file (data->fmtctx);

	g_string_free (data->outbuf, TRUE);
	g_free (data);
}

static gboolean
xmms_avformat_init (xmms_xform_t *xform)
{
	xmms_avformat_data_t *data;
	AVInputFormat *format;
	ByteIOContext byteio;
	AVCodec *codec;
	const gchar *mimetype;
	gint temp;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_avformat_data_t, 1);
	data->outbuf = g_string_new (NULL);
	data->buffer_size = AVFORMAT_BUFFER_SIZE;
	data->offset = 0;

	xmms_xform_private_data_set (xform, data);

	av_register_all ();

	mimetype = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_MIMETYPE);
	if (!strcmp (mimetype, "video/x-ms-asf")) {
		xmms_asf_metahack (xform);

		format = av_find_input_format ("asf");
		if (!format) {
			XMMS_DBG ("ASF format not registered to library, this is strange");
			goto err;
		}
	} else {
		/* Unknown mimetype, init failed */
		return FALSE;
	}

	format->flags |= AVFMT_NOFILE;
	if ((temp = init_put_byte (&byteio, data->buffer, data->buffer_size, 0,
	                           xform, xmms_avformat_read_callback, NULL,
	                           xmms_avformat_seek_callback)) < 0) {
		XMMS_DBG ("Could not initialize ByteIOContext structure: %d", temp);
		goto err;
	}
	if ((temp = av_open_input_stream (&data->fmtctx, &byteio, "", format,
	                                  NULL)) < 0) {
		XMMS_DBG ("Could not open input stream for ASF format: %d", temp);
		goto err;
	}
	data->track = xmms_avformat_get_track (data->fmtctx);
	if (data->track < 0) {
		XMMS_DBG ("Could not find WMA data track from file");
		goto err;
	}

	data->codecctx = data->fmtctx->streams[data->track]->codec;
	codec = avcodec_find_decoder (data->codecctx->codec_id);

	if (!strcmp(codec->name, "wmav1")) {
		mimetype = "audio/x-ffmpeg-wmav1";
	} else if (!strcmp(codec->name, "wmav2")) {
		mimetype = "audio/x-ffmpeg-wmav2";
	} else {
		xmms_log_error ("Unknown codec %s inside asf stream",
		                codec->name);
		goto err;
	}

	XMMS_DBG ("mimetype set to '%s'", mimetype);

	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_SAMPLERATE,
	                             data->codecctx->sample_rate);
	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE,
	                             data->codecctx->bit_rate);

	xmms_xform_privdata_set_bin (xform,
	                             "decoder_config",
	                             data->codecctx->extradata,
	                             data->codecctx->extradata_size);

	xmms_avformat_get_mediainfo (xform);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             mimetype,<commit_msg>OTHER: Add AMR support to avformat codec (needs AMR support in ffmpeg)<commit_after>/** @file avformat.c
 *  Avformat decoder plugin
 *
 *  Copyright (C) 2006-2007 XMMS2 Team
 *
 *  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.
 */

#include "xmms/xmms_defs.h"
#include "xmms/xmms_xformplugin.h"
#include "xmms/xmms_sample.h"
#include "xmms/xmms_log.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>

#undef ABS
#include "avformat.h"

#define AVFORMAT_BUFFER_SIZE 4096

typedef struct {
	gint track;

	AVFormatContext *fmtctx;
	AVCodecContext *codecctx;
	offset_t offset;

	guchar buffer[AVFORMAT_BUFFER_SIZE];
	guint buffer_size;

	GString *outbuf;
} xmms_avformat_data_t;

typedef struct {
	guint32 v1;
	guint16 v2;
	guint16 v3;
	guint8 v4[8];
} xmms_asf_GUID_t;

xmms_asf_GUID_t xmms_asf_GUIDs[] = {
	/* header */
	{ 0x75B22630, 0x668E, 0x11CF,
	  { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C } },
	/* content description */
	{ 0x75b22633, 0x668e, 0x11cf,
	  { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c } },
	/* extended content description */
	{ 0xD2D0A440, 0xE307, 0x11D2,
	  { 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 } },
};

static gboolean xmms_avformat_plugin_setup (xmms_xform_plugin_t *xform_plugin);
static gboolean xmms_avformat_init (xmms_xform_t *xform);
static void xmms_avformat_destroy (xmms_xform_t *xform);
static gint xmms_avformat_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
                                xmms_error_t *err);
static void xmms_avformat_get_mediainfo (xmms_xform_t *xform);
int xmms_avformat_get_track (AVFormatContext *fmtctx);

static void xmms_asf_metahack (xmms_xform_t *xform);

int xmms_avformat_read_callback (void *user_data, uint8_t *buffer,
                                 int length);
offset_t xmms_avformat_seek_callback (void *user_data, offset_t offset, int whence);

/*
 * Plugin header
 */

XMMS_XFORM_PLUGIN ("avformat",
                   "AVFormat Demuxer", XMMS_VERSION,
                   "ffmpeg libavformat demuxer",
                   xmms_avformat_plugin_setup);

static gboolean
xmms_avformat_plugin_setup (xmms_xform_plugin_t *xform_plugin)
{
	xmms_xform_methods_t methods;

	XMMS_XFORM_METHODS_INIT (methods);
	methods.init = xmms_avformat_init;
	methods.destroy = xmms_avformat_destroy;
	methods.read = xmms_avformat_read;

	xmms_xform_plugin_methods_set (xform_plugin, &methods);

	xmms_xform_plugin_indata_add (xform_plugin,
	                              XMMS_STREAM_TYPE_MIMETYPE,
	                              "video/x-ms-asf",
	                              NULL);

	xmms_xform_plugin_indata_add (xform_plugin,
	                              XMMS_STREAM_TYPE_MIMETYPE,
	                              "audio/3gpp",
	                              NULL);

	xmms_magic_add ("asf header", "video/x-ms-asf",
	                "0 belong 0x3026b275", NULL);

	xmms_magic_add ("amr header", "audio/3gpp",
	                "0 string #!AMR", NULL);

	return TRUE;
}

static void
xmms_avformat_destroy (xmms_xform_t *xform)
{
	xmms_avformat_data_t *data;

	g_return_if_fail (xform);

	data = xmms_xform_private_data_get (xform);
	g_return_if_fail (data);

	av_close_input_file (data->fmtctx);

	g_string_free (data->outbuf, TRUE);
	g_free (data);
}

static gboolean
xmms_avformat_init (xmms_xform_t *xform)
{
	xmms_avformat_data_t *data;
	AVInputFormat *format;
	ByteIOContext byteio;
	AVCodec *codec;
	const gchar *mimetype;
	gint temp;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_avformat_data_t, 1);
	data->outbuf = g_string_new (NULL);
	data->buffer_size = AVFORMAT_BUFFER_SIZE;
	data->offset = 0;

	xmms_xform_private_data_set (xform, data);

	av_register_all ();

	mimetype = xmms_xform_indata_get_str (xform, XMMS_STREAM_TYPE_MIMETYPE);
	if (!strcmp (mimetype, "video/x-ms-asf")) {
		xmms_asf_metahack (xform);

		format = av_find_input_format ("asf");
		if (!format) {
			XMMS_DBG ("ASF format not registered to library");
			goto err;
		}
	} else if (!strcmp (mimetype, "audio/3gpp")) {
		format = av_find_input_format ("amr");
		if (!format) {
			XMMS_DBG ("AMR format not registered to library");
			goto err;
		}
	} else {
		/* Unknown mimetype, init failed */
		return FALSE;
	}

	format->flags |= AVFMT_NOFILE;
	if ((temp = init_put_byte (&byteio, data->buffer, data->buffer_size, 0,
	                           xform, xmms_avformat_read_callback, NULL,
	                           xmms_avformat_seek_callback)) < 0) {
		XMMS_DBG ("Could not initialize ByteIOContext structure: %d", temp);
		goto err;
	}
	if ((temp = av_open_input_stream (&data->fmtctx, &byteio, "", format,
	                                  NULL)) < 0) {
		XMMS_DBG ("Could not open input stream for ASF format: %d", temp);
		goto err;
	}
	data->track = xmms_avformat_get_track (data->fmtctx);
	if (data->track < 0) {
		XMMS_DBG ("Could not find WMA data track from file");
		goto err;
	}

	data->codecctx = data->fmtctx->streams[data->track]->codec;
	codec = avcodec_find_decoder (data->codecctx->codec_id);

	if (!strcmp (codec->name, "wmav1")) {
		mimetype = "audio/x-ffmpeg-wmav1";
	} else if (!strcmp (codec->name, "wmav2")) {
		mimetype = "audio/x-ffmpeg-wmav2";
	} else if (!strcmp (codec->name, "amr_nb")) {
		mimetype = "audio/x-ffmpeg-amr_nb";
	} else if (!strcmp (codec->name, "amr_wb")) {
		mimetype = "audio/x-ffmpeg-amr_wb";
	} else {
		xmms_log_error ("Unknown codec %s inside asf stream",
		                codec->name);
		goto err;
	}

	XMMS_DBG ("mimetype set to '%s'", mimetype);

	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_SAMPLERATE,
	                             data->codecctx->sample_rate);
	xmms_xform_metadata_set_int (xform,
	                             XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE,
	                             data->codecctx->bit_rate);

	xmms_xform_privdata_set_bin (xform,
	                             "decoder_config",
	                             data->codecctx->extradata,
	                             data->codecctx->extradata_size);

	xmms_avformat_get_mediainfo (xform);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             mimetype,
{'fraction_non_alphanumeric': 0.10305882352941176, 'fraction_numerical': 0.023058823529411764, 'mean_word_length': 3.0868589743589743, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1056148', 'n_tokens_mistral': 5171, 'n_tokens_neox': 4814, 'n_words': 1033}