aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2020-06-09 17:37:40 +0100
committerSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2020-06-09 17:37:40 +0100
commitf25f654d6ca981efdbc9aa2c11f11422c9fe6c01 (patch)
tree582cbf948c6fba11ffe8f9bae4ef7089fc50d512
parent31a0a4c57026cd4ee682e4c5eccfaba153cd8f03 (diff)
add gapless supportHEADmaster
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-rw-r--r--src/utils-lgpl/fcplay.c228
1 files changed, 221 insertions, 7 deletions
diff --git a/src/utils-lgpl/fcplay.c b/src/utils-lgpl/fcplay.c
index 83d48a0..991ca43 100644
--- a/src/utils-lgpl/fcplay.c
+++ b/src/utils-lgpl/fcplay.c
@@ -77,6 +77,10 @@ static void usage(void)
void play_samples(char *name, unsigned int card, unsigned int device,
unsigned long buffer_size, unsigned int frag,
unsigned long codec_id);
+void play_gapless_samples(char **names, int start_idx, int fcount, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id);
+
static int print_time(struct compress *compress)
{
@@ -96,7 +100,7 @@ int main(int argc, char **argv)
{
char *file;
unsigned long buffer_size = 0;
- int c, i;
+ int c, i, gapless = 0;
unsigned int card = 0, device = 0, frag = 0;
unsigned int codec_id = SND_AUDIOCODEC_MP3;
@@ -104,7 +108,7 @@ int main(int argc, char **argv)
usage();
verbose = 0;
- while ((c = getopt(argc, argv, "hvb:f:c:d:I:")) != -1) {
+ while ((c = getopt(argc, argv, "hvg:b:f:c:d:I:")) != -1) {
switch (c) {
case 'h':
usage();
@@ -143,6 +147,9 @@ int main(int argc, char **argv)
case 'v':
verbose = 1;
break;
+ case 'g':
+ gapless = 1;
+ break;
default:
exit(EXIT_FAILURE);
}
@@ -150,9 +157,13 @@ int main(int argc, char **argv)
if (optind >= argc)
usage();
- file = argv[optind];
-
- play_samples(file, card, device, buffer_size, frag, codec_id);
+ if (gapless) {
+ play_gapless_samples(argv, optind, argc - optind, card,
+ device, buffer_size, frag, codec_id);
+ } else {
+ file = argv[optind];
+ play_samples(file, card, device, buffer_size, frag, codec_id);
+ }
fprintf(stderr, "Finish Playing.... Close Normally\n");
exit(EXIT_SUCCESS);
@@ -187,7 +198,8 @@ static int get_codec_id(int codec_id)
}
}
-static int parse_file(char *file, struct snd_codec *codec)
+static int parse_file(char *file, struct snd_codec *codec,
+ struct compr_gapless_mdata *mdata)
{
AVFormatContext *ctx = NULL;
AVStream *stream;
@@ -238,6 +250,17 @@ static int parse_file(char *file, struct snd_codec *codec)
codec->level = 0;
codec->rate_control = 0;
codec->ch_mode = 0;
+
+ if (mdata) {
+ // mdata->encoder_delay = ctx->initial_padding;
+ mdata->encoder_padding = stream->first_discard_sample;//#codec->trailing_padding;
+ printf("DEBUG:: %s: %d\n", __func__, mdata->encoder_padding);
+ printf("DEBUG:: %s: %ld\n", __func__, stream->start_skip_samples);
+ printf("DEBUG:: %s: %ld\n", __func__, stream->last_discard_sample);
+ printf("DEBUG:: %s: %ld\n", __func__, stream->start_skip_samples);
+ printf("DEBUG:: %s: %ld\n", __func__, stream->start_skip_samples);
+ }
+
filled = 1;
if (codec->id == SND_AUDIOCODEC_FLAC) {
@@ -311,7 +334,7 @@ void play_samples(char *name, unsigned int card, unsigned int device,
memset(&codec, 0, sizeof(codec));
memset(&config, 0, sizeof(config));
- parse_file(name, &codec);
+ parse_file(name, &codec, NULL);
config.codec = &codec;
@@ -394,3 +417,194 @@ FILE_EXIT:
printf("%s: exit failure\n", __func__);
exit(EXIT_FAILURE);
}
+
+void play_gapless_samples(char **names, int start_idx, int fcount, unsigned int card, unsigned int device,
+ unsigned long buffer_size, unsigned int frag,
+ unsigned long codec_id)
+{
+ struct compr_config config;
+ struct compr_gapless_mdata mdata;
+ struct snd_codec codec;
+ struct compress *compress;
+ FILE *file;
+ char *buffer;
+ int size, num_read, wrote;
+ int test_loop = 10;
+ int file_idx = 0;
+ int rc = 0;
+ char *name;
+
+
+ if (verbose)
+ printf("%s: Playing Gapless for %d files\n", __func__, fcount);
+
+ memset(&codec, 0, sizeof(codec));
+ memset(&config, 0, sizeof(config));
+
+ name = names[start_idx + file_idx];
+ printf("DEBUG:%s: %d %s file \n", __func__, __LINE__, name);
+ parse_file(name, &codec, &mdata);
+ file = fopen(name, "rb");
+ if (!file) {
+ fprintf(stderr, "Unable to open file '%s'\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+
+ config.codec = &codec;
+
+ compress = compress_open(card, device, COMPRESS_IN, &config);
+ if (!compress || !is_compress_ready(compress)) {
+ fprintf(stderr, "Unable to open Compress device %d:%d\n",
+ card, device);
+ fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
+ goto FILE_EXIT;
+ };
+ if (verbose)
+ printf("%s: Opened compress device\n", __func__);
+
+ size = config.fragment_size;
+ buffer = malloc(size * config.fragments);
+ if (!buffer) {
+ fprintf(stderr, "Unable to allocate %d bytes\n", size);
+ goto COMP_EXIT;
+ }
+ mdata.encoder_delay = 20* 2048;
+ mdata.encoder_padding = 10* 1024;
+
+ compress_set_gapless_metadata(compress, &mdata);
+
+
+ /* we will write frag fragment_size and then start */
+ num_read = fread(buffer, 1, size * config.fragments, file);
+ if (num_read > 0) {
+ if (verbose)
+ printf("%s: Doing first buffer write of %d\n", __func__, num_read);
+ wrote = compress_write(compress, buffer, num_read);
+ if (wrote < 0) {
+ fprintf(stderr, "Error %d playing sample\n", wrote);
+ fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
+ goto BUF_EXIT;
+ }
+ if (wrote != num_read) {
+ /* TODO: Buufer pointer needs to be set here */
+ fprintf(stderr, "We wrote %d, DSP accepted %d\n", num_read, wrote);
+ }
+ }
+
+ compress_start(compress);
+ if (verbose)
+ printf("%s: You should hear audio NOW!!!\n", __func__);
+
+
+ do {
+ if (verbose)
+ printf("%s: gapless loop %d\n", __func__, test_loop);
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ if (file_idx != 0) {
+ name = names[start_idx + file_idx];
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ file = fopen(name, "rb");
+ if (!file) {
+ fprintf(stderr, "Unable to open file '%s'\n", name);
+ goto TRACK_EXIT;
+ }
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ parse_file(name, &codec, &mdata);
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ rc = compress_next_track(compress);
+ if (rc) {
+ fprintf(stderr, "Failed to set next track (%d)\n", rc);
+ goto TRACK_EXIT;
+ }
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ //FIXME
+ mdata.encoder_delay = 2048;
+ mdata.encoder_padding = 1024;
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ rc = compress_set_gapless_metadata(compress, &mdata);
+ if (rc) {
+ fprintf(stderr, "Failed to set gapless metadata (%d)\n", rc);
+ goto TRACK_EXIT;
+ }
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ rc = compress_set_codec_params(compress, &codec);
+ if (rc) {
+ fprintf(stderr, "Failed to set codec params (%d)\n", rc);
+ goto TRACK_EXIT;
+ }
+
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ rc = compress_partial_drain(compress);
+ if (rc) {
+ fprintf(stderr, "Failed to partial drain (%d)\n", rc);
+ goto TRACK_EXIT;
+ }
+ printf("DEBUG: %s: %d \n", __func__, __LINE__);
+ }
+
+ printf("Playing file %s On Card %u device %u, with buffer of %lu bytes\n",
+ name, card, device, buffer_size);
+ printf("Format %u Channels %u, %u Hz, Bit Rate %d\n",
+ codec.id, codec.ch_in, codec.sample_rate, codec.bit_rate);
+
+ do {
+ num_read = fread(buffer, 1, size, file);
+ if (num_read > 0) {
+ wrote = compress_write(compress, buffer, num_read);
+ if (wrote < 0) {
+ fprintf(stderr, "Error playing sample\n");
+ fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
+ goto BUF_EXIT;
+ }
+ if (wrote != num_read) {
+ /* TODO: Buffer pointer needs to be set here */
+ fprintf(stderr, "We wrote %d, DSP accepted %d\n", num_read, wrote);
+ }
+ if (verbose) {
+ print_time(compress);
+ printf("%s: wrote %d\n", __func__, wrote);
+ }
+ }
+ } while (num_read > 0);
+
+ file_idx++;
+
+ if (file_idx == fcount) {
+ /* Finished playing all the files.*/
+ rc = compress_drain(compress);
+ if (rc) {
+ fprintf(stderr, "Failed to drain (%d)\n", rc);
+ goto TRACK_EXIT;
+ }
+ }
+
+ fclose(file);
+ printf("File idx vs fcount %d vs %d \n", file_idx, fcount);
+
+ } while (file_idx < fcount);
+
+ if (verbose)
+ printf("%s: exit success\n", __func__);
+
+ free(buffer);
+ compress_close(compress);
+ return;
+
+TRACK_EXIT:
+ fclose(file);
+BUF_EXIT:
+ free(buffer);
+COMP_EXIT:
+ compress_close(compress);
+FILE_EXIT:
+ if (verbose)
+ printf("%s: exit failure\n", __func__);
+ exit(EXIT_FAILURE);
+}