Browse Source

slipshod audio playback testing

master
hex 3 years ago
parent
commit
4ef7a71aa8
2 changed files with 111 additions and 86 deletions
  1. 0
    8
      meson.build
  2. 111
    78
      src/main.c

+ 0
- 8
meson.build View File

@@ -1,8 +0,0 @@
project('hmp', 'c')

ff_avcodec = dependency('libavcodec')
ff_avformat = dependency('libavformat')
ff_avutil = dependency('libavutil')
ff_swresample = dependency('libswresample')

executable('hmp', 'src/main.c', dependencies : [ff_avcodec, ff_avformat, ff_avutil, ff_swresample ])

+ 111
- 78
src/main.c View File

@@ -17,102 +17,125 @@
#include <microhttpd.h>

#define PORT 8888
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096

int decode_audio_file(const char* path, char** data, int* size) {
//initialize things
av_register_all();
int decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, uint8_t* out_data, int* index) {

//get format
AVFormatContext* format = avformat_alloc_context();
if (avformat_open_input(&format, path, NULL, NULL)) {
fprintf(stderr, "Could not open file '%s'\n", path);
return -1;
}
int i, ch;
int ret, data_size;

if (avformat_find_stream_info(format, NULL) < 0) {
fprintf(stderr, "Could not retrieve stream info from file '%s'", path);
return -1;
ret = avcodec_send_packet(dec_ctx, pkt);
if (ret < 0) {
fprintf(stderr, "Error submitting packet to decoder\n");
exit(1);
}

//get stream
int stream_index = -1;
for (int i=0; i<format->nb_streams; ++i) {
if(format->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
stream_index = i;
break;
while (ret >= 0) {
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
}
else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
exit(1);
}

data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);
if (data_size < 0) {
fprintf(stderr, "Failed to calculate data size\n");
exit(1);
}
for (i = 0; i < frame->nb_samples; ++i)
for (ch = 0; ch < dec_ctx->channels; ++ch) {
//printf("%i\n", dec_ctx->channels);
memcpy(out_data + *index, frame->data[0] + (data_size*i*2 + ch*data_size), data_size);
*index += data_size;
}
}
return 0;
}

if (stream_index == -1) {
fprintf(stderr, "Could not retrieve stream from file '%s'", path);
int decode_audio_file(const char* path, uint8_t* out_data, int size) {
const AVCodec *codec;
AVCodecContext *c = NULL;
AVCodecParserContext *parser = NULL;
int len, ret;
FILE *f;
uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
uint8_t *data;
size_t data_size;
AVPacket *pkt;
AVFrame *decoded_frame = NULL;


avcodec_register_all();
pkt = av_packet_alloc();
codec = avcodec_find_decoder(AV_CODEC_ID_FLAC);
if (!codec) {
fprintf(stderr, "Codec not found!\n");
return -1;
}

AVStream* stream = format->streams[stream_index];
//open codec
AVCodecContext* codec = stream->codec;

//initialize resampler
struct SwrContext* swr = swr_alloc();
av_opt_set_int(swr, "in_channel_count", codec->channels, 0);
av_opt_set_int(swr, "out_channel_count", 2, 0);
av_opt_set_int(swr, "in_channel_layout", codec->channel_layout, 0);
av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(swr, "in_sample_rate", codec->sample_rate, 0);
av_opt_set_int(swr, "out_sample_rate", 44100, 0);
av_opt_set_int(swr, "in_sample_fmt", codec->sample_fmt, 0);
av_opt_set_int(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
swr_init(swr);
if (!swr_is_initialized(swr)) {
fprintf(stderr, "Resampler not properly initialized!");
parser = av_parser_init(codec->id);
if (!parser) {
fprintf(stderr, "Parser not found!\n");
return -1;
}
AVPacket packet;
av_init_packet(&packet);
AVFrame* frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Unable to allocate frame");

c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate audio context!\n");
return -1;
}

//iterate through frames
*data = NULL;
*size = 0;
if(avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
f = fopen(path, "rb");
if(!f) {
fprintf(stderr, "Could not open %s\n", path);
exit(1);
}

while(av_read_frame(format, &packet) >= 0) {
int gotFrame;
printf("test");
if (avcodec_decode_audio4(codec, frame, &gotFrame, &packet) < 0) {
break;
data = inbuf;
data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

int index = 0;
while (data_size > 0) {
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "Could not allocate audio frame\n");
exit(1);
}
}

printf("test2");
if (!gotFrame) {
continue;
ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsing\n");
exit(1);
}
data += ret;
data_size -= ret;

if (pkt->size)
decode(c, pkt, decoded_frame, out_data, &index);
if (data_size < AUDIO_REFILL_THRESH) {
memmove(inbuf, data, data_size);
data = inbuf;
len = fread(data + data_size, 1, AUDIO_INBUF_SIZE - data_size, f);
if (len > 0)
data_size += len;
}
}
avcodec_free_context(&c);
av_parser_close(parser);
av_frame_free(&decoded_frame);
av_packet_free(&pkt);

//resample frames
char* buffer;
av_samples_alloc((uint8_t**) &buffer,
NULL,
2,
frame->nb_samples,
AV_SAMPLE_FMT_S16, 0);

int frame_count = swr_convert(swr,
(uint8_t**) &buffer,
frame->nb_samples,
(const uint8_t**) frame->data,
frame->nb_samples);
//append resampled frames to data
*data = (char*) realloc(*data,
(*size + frame->nb_samples) * sizeof(char) * 2);
memcpy(*data + *size, buffer, frame_count * sizeof(char) * 2);
*size += frame_count;
}
return 0;
}

@@ -137,7 +160,7 @@ int play_pcm_data(char* data, int size) {

default_driver = ao_default_driver_id();

memset(&format, 0, sizeof(format));
memset(&format, 0, sizeof(format));
format.bits = 16;
format.channels = 2;
format.rate = 44100;
@@ -163,7 +186,8 @@ int play_pcm_data(char* data, int size) {
buffer[4*i] = buffer[4*i+2] = sample & 0xff;
buffer[4*i+1] = buffer[4*i+3] = (sample >> 8) & 0xff;
}
ao_play(device, buffer, buf_size);
if (ao_play(device, data, size) == 0)
fprintf(stderr, "Failed to playback audio");

/* -- Close and shutdown -- */
ao_close(device);
@@ -193,6 +217,16 @@ int answer_to_connection (void *cls, struct MHD_Connection *connection,

int main(int argc, char **argv)
{
int bsize = 1024*1024*60;
uint8_t* audio_buffer = calloc(bsize, sizeof(uint8_t));
decode_audio_file("testsong.flac", audio_buffer, bsize);
/*
for (int i = 0; i < 1000; ++i)
printf("%02x\n", audio_buffer[i]);
*/
play_pcm_data((char*)audio_buffer, bsize);

/*
struct MHD_Daemon *daemon;

daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
@@ -203,7 +237,6 @@ int main(int argc, char **argv)

MHD_stop_daemon (daemon);
return 0;
/*
char* data;
int size;
decode_audio_file("song.webm", &data, &size);

Loading…
Cancel
Save