<commit_before>/*
 * Copyright (C) 2009-2012 <NAME>
 * Copyright (C) 2005 <NAME>, <NAME>
 *
 * Author: <NAME> <<EMAIL>>
 *
 * This file may be used under the terms of the GNU Lesser General Public
 * License version 2.1.
 */

#include "gstav_adec.h"
#include "plugin.h"

#include <libavcodec/avcodec.h>
#include <gst/tag/tag.h>

#include <stdlib.h>
#include <string.h> /* for memcpy */
#include <stdbool.h>

#define GST_CAT_DEFAULT gstav_debug

static GstElementClass *parent_class;

#define BUFFER_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE

struct oggvorbis_private {
	unsigned int len[3];
	unsigned char *packet[3];
};

struct ring {
	size_t in, out;
};

struct obj {
	GstElement element;
	GstPad *sinkpad, *srcpad;
	AVCodec *codec;
	AVCodecContext *av_ctx;
	bool got_header;
	struct oggvorbis_private priv;
	uint64_t timestamp;
	AVPacket pkt;
	uint8_t *buffer_data;
	size_t buffer_size;
	struct ring ring;
	int (*header_func)(struct obj *self, GstBuffer *buf);
	uint64_t next_timestamp;
	int bps;
	GMutex *mutex;
};

struct obj_class {
	GstElementClass parent_class;
};

static inline uint8_t get_byte(const uint8_t **b)
{
	return *((*b)++);
}

static inline uint32_t get_le32(const uint8_t **b)
{
	struct unaligned_32 { uint32_t l; } __attribute__((packed));
	*b += sizeof(uint32_t);
	return ((const struct unaligned_32 *)(*b - sizeof(uint32_t)))->l;
}

static int
default_header(struct obj *self, GstBuffer *buf)
{
	return 0;
}

static unsigned int
fixup_vorbis_headers(struct oggvorbis_private *priv, uint8_t **buf)
{
	int i, offset, len;
	unsigned char *ptr;

	len = priv->len[0] + priv->len[1] + priv->len[2];
	ptr = *buf = g_malloc0(len + len / 255 + 64);

	ptr[0] = 2;
	offset = 1;
	offset += av_xiphlacing(&ptr[offset], priv->len[0]);
	offset += av_xiphlacing(&ptr[offset], priv->len[1]);
	for (i = 0; i < 3; i++) {
		memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
		offset += priv->len[i];
		g_free(priv->packet[i]);
	}
	*buf = g_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
	return offset;
}

static int
vorbis_header(struct obj *self, GstBuffer *buf)
{
	const uint8_t *p = buf->data;
	struct oggvorbis_private *priv = &self->priv;
	int pkt_type = *p;

	if (!(pkt_type & 1))
		return 0;

	if (buf->size < 1 || pkt_type > 5)
		return -1;

	priv->len[pkt_type >> 1] = buf->size;
	priv->packet[pkt_type >> 1] = g_malloc0(buf->size);
	memcpy(priv->packet[pkt_type >> 1], buf->data, buf->size);

	if (pkt_type == 1) {
		/* tag */
		unsigned blocksize, bs0, bs1;
		p += 7; /* skip "\001vorbis" tag */

		if (buf->size != 30)
			return -1;

		if (get_le32(&p) != 0)
			return -1;

		self->av_ctx->channels = get_byte(&p);
		self->av_ctx->sample_rate = get_le32(&p);
		p += 4; /* max bitrate */
		self->av_ctx->bit_rate = get_le32(&p);
		p += 4; /* min bitrate */

		blocksize = get_byte(&p);
		bs0 = blocksize & 15;
		bs1 = blocksize >> 4;

		if (bs0 > bs1)
			return -1;
		if (bs0 < 6 || bs1 > 13)
			return -1;

		if (get_byte(&p) != 1)
			return -1;
	}
	else if (pkt_type == 3) {
		/* comment */
	}
	else {
		/* extradata */
		self->av_ctx->extradata_size =
			fixup_vorbis_headers(&self->priv, &self->av_ctx->extradata);
	}

	return 1;
}

static int
flac_header(struct obj *self, GstBuffer *buf)
{
	unsigned type = (buf->data[0] & 0x7F);
	/* frame sync code */
	if (type == 127)
		return 0;
	return 1;
}

static inline void
calculate_timestamp(struct obj *self, GstBuffer *out_buf)
{
	uint32_t samples;

	samples = out_buf->size / (self->av_ctx->channels * (self->bps >> 3));

	out_buf->timestamp = self->timestamp;
	out_buf->duration = gst_util_uint64_scale_int(samples, GST_SECOND, self->av_ctx->sample_rate);

	self->timestamp += out_buf->duration;
}

static GstFlowReturn
pad_chain(GstPad *pad, GstBuffer *buf)
{
	struct obj *self;
	GstFlowReturn ret = GST_FLOW_OK;<commit_msg>adec: refactor calculate_timestamp()<commit_after>/*
 * Copyright (C) 2009-2012 <NAME>
 * Copyright (C) 2005 <NAME>, <NAME>
 *
 * Author: <NAME> <<EMAIL>>
 *
 * This file may be used under the terms of the GNU Lesser General Public
 * License version 2.1.
 */

#include "gstav_adec.h"
#include "plugin.h"

#include <libavcodec/avcodec.h>
#include <gst/tag/tag.h>

#include <stdlib.h>
#include <string.h> /* for memcpy */
#include <stdbool.h>

#define GST_CAT_DEFAULT gstav_debug

static GstElementClass *parent_class;

#define BUFFER_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE

struct oggvorbis_private {
	unsigned int len[3];
	unsigned char *packet[3];
};

struct ring {
	size_t in, out;
};

struct obj {
	GstElement element;
	GstPad *sinkpad, *srcpad;
	AVCodec *codec;
	AVCodecContext *av_ctx;
	bool got_header;
	struct oggvorbis_private priv;
	uint64_t timestamp;
	AVPacket pkt;
	uint8_t *buffer_data;
	size_t buffer_size;
	struct ring ring;
	int (*header_func)(struct obj *self, GstBuffer *buf);
	uint64_t next_timestamp;
	int bps;
	GMutex *mutex;
};

struct obj_class {
	GstElementClass parent_class;
};

static inline uint8_t get_byte(const uint8_t **b)
{
	return *((*b)++);
}

static inline uint32_t get_le32(const uint8_t **b)
{
	struct unaligned_32 { uint32_t l; } __attribute__((packed));
	*b += sizeof(uint32_t);
	return ((const struct unaligned_32 *)(*b - sizeof(uint32_t)))->l;
}

static int
default_header(struct obj *self, GstBuffer *buf)
{
	return 0;
}

static unsigned int
fixup_vorbis_headers(struct oggvorbis_private *priv, uint8_t **buf)
{
	int i, offset, len;
	unsigned char *ptr;

	len = priv->len[0] + priv->len[1] + priv->len[2];
	ptr = *buf = g_malloc0(len + len / 255 + 64);

	ptr[0] = 2;
	offset = 1;
	offset += av_xiphlacing(&ptr[offset], priv->len[0]);
	offset += av_xiphlacing(&ptr[offset], priv->len[1]);
	for (i = 0; i < 3; i++) {
		memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
		offset += priv->len[i];
		g_free(priv->packet[i]);
	}
	*buf = g_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
	return offset;
}

static int
vorbis_header(struct obj *self, GstBuffer *buf)
{
	const uint8_t *p = buf->data;
	struct oggvorbis_private *priv = &self->priv;
	int pkt_type = *p;

	if (!(pkt_type & 1))
		return 0;

	if (buf->size < 1 || pkt_type > 5)
		return -1;

	priv->len[pkt_type >> 1] = buf->size;
	priv->packet[pkt_type >> 1] = g_malloc0(buf->size);
	memcpy(priv->packet[pkt_type >> 1], buf->data, buf->size);

	if (pkt_type == 1) {
		/* tag */
		unsigned blocksize, bs0, bs1;
		p += 7; /* skip "\001vorbis" tag */

		if (buf->size != 30)
			return -1;

		if (get_le32(&p) != 0)
			return -1;

		self->av_ctx->channels = get_byte(&p);
		self->av_ctx->sample_rate = get_le32(&p);
		p += 4; /* max bitrate */
		self->av_ctx->bit_rate = get_le32(&p);
		p += 4; /* min bitrate */

		blocksize = get_byte(&p);
		bs0 = blocksize & 15;
		bs1 = blocksize >> 4;

		if (bs0 > bs1)
			return -1;
		if (bs0 < 6 || bs1 > 13)
			return -1;

		if (get_byte(&p) != 1)
			return -1;
	}
	else if (pkt_type == 3) {
		/* comment */
	}
	else {
		/* extradata */
		self->av_ctx->extradata_size =
			fixup_vorbis_headers(&self->priv, &self->av_ctx->extradata);
	}

	return 1;
}

static int
flac_header(struct obj *self, GstBuffer *buf)
{
	unsigned type = (buf->data[0] & 0x7F);
	/* frame sync code */
	if (type == 127)
		return 0;
	return 1;
}

static inline uint32_t
calculate_duration(struct obj *self, uint64_t size)
{
	uint32_t samples;
	samples = size / (self->av_ctx->channels * (self->bps >> 3));
	return gst_util_uint64_scale_int(samples, GST_SECOND, self->av_ctx->sample_rate);
}

static inline void
calculate_timestamp(struct obj *self, GstBuffer *out_buf)
{
	out_buf->timestamp = self->timestamp;
	out_buf->duration = calculate_duration(self, out_buf->size);
	self->timestamp += out_buf->duration;
}

static GstFlowReturn
pad_chain(GstPad *pad, GstBuffer *buf)
{
	struct obj *self;
	GstFlowReturn ret = GST_FLOW_OK;
{'fraction_non_alphanumeric': 0.16016028955532574, 'fraction_numerical': 0.03076525336091003, 'mean_word_length': 4.134041141340411, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 139, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '447246', 'n_tokens_mistral': 3354, 'n_tokens_neox': 3137, 'n_words': 752}