mirror of https://github.com/nealey/hdjd.git
Add an AAC player, since this is now my little playground
This commit is contained in:
parent
6476f2838b
commit
aab7e4819c
|
@ -0,0 +1,165 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
#include <neaacdec.h>
|
||||||
|
#include <mp4ff.h>
|
||||||
|
|
||||||
|
/* Some things I use for debugging */
|
||||||
|
#ifdef NODUMP
|
||||||
|
# define DUMPf(fmt, args...)
|
||||||
|
#else
|
||||||
|
# define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
|
||||||
|
#endif
|
||||||
|
#define DUMP() DUMPf("")
|
||||||
|
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
||||||
|
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
||||||
|
#define DUMP_s(v) DUMPf("%s = %s", #v, v)
|
||||||
|
#define DUMP_c(v) DUMPf("%s = '%c' (0x%02x)", #v, v, v)
|
||||||
|
#define DUMP_p(v) DUMPf("%s = %p", #v, v)
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
read_callback(void *user_data, void *buffer, uint32_t length)
|
||||||
|
{
|
||||||
|
return fread(buffer, 1, length, (FILE*)user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
seek_callback(void *user_data, uint64_t position)
|
||||||
|
{
|
||||||
|
return fseek((FILE*)user_data, position, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GetAACTrack(mp4ff_t *infile)
|
||||||
|
{
|
||||||
|
/* find AAC track */
|
||||||
|
int i, rc;
|
||||||
|
int numTracks = mp4ff_total_tracks(infile);
|
||||||
|
|
||||||
|
for (i = 0; i < numTracks; i++)
|
||||||
|
{
|
||||||
|
unsigned char *buff = NULL;
|
||||||
|
int buff_size = 0;
|
||||||
|
mp4AudioSpecificConfig mp4ASC;
|
||||||
|
|
||||||
|
mp4ff_get_decoder_config(infile, i, &buff, &buff_size);
|
||||||
|
|
||||||
|
if (buff)
|
||||||
|
{
|
||||||
|
rc = NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC);
|
||||||
|
free(buff);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
continue;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can't decode this */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
snd_pcm_t *snd;
|
||||||
|
|
||||||
|
int track;
|
||||||
|
|
||||||
|
mp4ff_t *infile;
|
||||||
|
mp4ff_callback_t mp4cb;
|
||||||
|
|
||||||
|
NeAACDecHandle hDecoder;
|
||||||
|
NeAACDecConfigurationPtr config;
|
||||||
|
mp4AudioSpecificConfig mp4ASC;
|
||||||
|
|
||||||
|
unsigned char *buffer;
|
||||||
|
int buffer_size;
|
||||||
|
unsigned long samplerate;
|
||||||
|
unsigned char channels;
|
||||||
|
|
||||||
|
long sampleId, numSamples;
|
||||||
|
void *sample_buffer;
|
||||||
|
|
||||||
|
if (snd_pcm_open(&snd, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
||||||
|
fprintf(stderr, "Opening ALSA\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mp4cb.read = read_callback;
|
||||||
|
mp4cb.seek = seek_callback;
|
||||||
|
mp4cb.user_data = stdin;
|
||||||
|
|
||||||
|
infile = mp4ff_open_read(&mp4cb);
|
||||||
|
if (! infile) {
|
||||||
|
fprintf(stderr, "Opening stdin fail\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((track = GetAACTrack(infile)) < 0) {
|
||||||
|
fprintf(stderr, "GetAACTrack\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hDecoder = NeAACDecOpen();
|
||||||
|
config = NeAACDecGetCurrentConfiguration(hDecoder);
|
||||||
|
config->outputFormat = FAAD_FMT_16BIT;
|
||||||
|
NeAACDecSetConfiguration(hDecoder, config);
|
||||||
|
|
||||||
|
buffer = NULL;
|
||||||
|
buffer_size = 0;
|
||||||
|
mp4ff_get_decoder_config(infile, track, &buffer, &buffer_size);
|
||||||
|
|
||||||
|
if (NeAACDecInit2(hDecoder, buffer, buffer_size, &samplerate, &channels) < 0) {
|
||||||
|
fprintf(stderr, "Initializing decoder\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_set_params(snd,
|
||||||
|
SND_PCM_FORMAT_S16,
|
||||||
|
SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||||
|
channels,
|
||||||
|
samplerate,
|
||||||
|
1,
|
||||||
|
500000) < 0) {
|
||||||
|
fprintf(stderr, "Set ALSA params\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
DUMP_d(channels);
|
||||||
|
DUMP_d(samplerate);
|
||||||
|
|
||||||
|
if (buffer) {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
numSamples = mp4ff_num_samples(infile, track);
|
||||||
|
|
||||||
|
for (sampleId = 0; sampleId < numSamples; sampleId++) {
|
||||||
|
int rc;
|
||||||
|
long dur;
|
||||||
|
unsigned int sample_count;
|
||||||
|
unsigned int delay = 0;
|
||||||
|
NeAACDecFrameInfo frameInfo;
|
||||||
|
|
||||||
|
buffer = NULL;
|
||||||
|
buffer_size = 0;
|
||||||
|
|
||||||
|
dur = mp4ff_get_sample_duration(infile, track, sampleId);
|
||||||
|
rc = mp4ff_read_sample(infile, track, sampleId, &buffer, &buffer_size);
|
||||||
|
if (rc == 0) {
|
||||||
|
fprintf(stderr, "Read failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sample_buffer = NeAACDecDecode(hDecoder, &frameInfo, buffer, buffer_size);
|
||||||
|
sample_count = frameInfo.samples;
|
||||||
|
|
||||||
|
snd_pcm_writei(snd, sample_buffer, sample_count / channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue