1 /* This is a DEPRECATED code used only to maintain */
2 /* compatibility with libavresample for installations */
3 /* that don't have access to libswresample. Upgrading */
4 /* to swresample is HIGHLY recommended, as this code */
5 /* is most likely to lead to imprecise results */
6 
7 #include <libavresample/avresample.h>
8 #include <libavutil/opt.h>
9 
10 #include "bliss.h"
11 
12 #define NB_BYTES_PER_SAMPLE 2
13 #define SAMPLE_RATE 22050
14 
av_calloc(size_t nmemb,size_t size)15 void *av_calloc(size_t nmemb, size_t size) {
16   if (size <= 0 || nmemb >= INT_MAX / size)
17     return NULL;
18   return av_mallocz(nmemb * size);
19 }
20 
av_samples_fill_arrays_fixed(uint8_t ** audio_data,int * linesize,const uint8_t * buf,int nb_channels,int nb_samples,enum AVSampleFormat sample_fmt,int align)21 int av_samples_fill_arrays_fixed(uint8_t **audio_data, int *linesize,
22                                  const uint8_t *buf, int nb_channels,
23                                  int nb_samples, enum AVSampleFormat sample_fmt,
24                                  int align) {
25   int ch, planar, buf_size, line_size;
26 
27   planar = av_sample_fmt_is_planar(sample_fmt);
28   buf_size = av_samples_get_buffer_size(&line_size, nb_channels, nb_samples,
29                                         sample_fmt, align);
30   if (buf_size < 0)
31     return buf_size;
32 
33   audio_data[0] = (uint8_t *)buf;
34   for (ch = 1; planar && ch < nb_channels; ch++)
35     audio_data[ch] = audio_data[ch - 1] + line_size;
36 
37   if (linesize)
38     *linesize = line_size;
39 
40   return buf_size;
41 }
42 
av_samples_alloc_fixed(uint8_t ** audio_data,int * linesize,int nb_channels,int nb_samples,enum AVSampleFormat sample_fmt,int align)43 int av_samples_alloc_fixed(uint8_t **audio_data, int *linesize, int nb_channels,
44                            int nb_samples, enum AVSampleFormat sample_fmt,
45                            int align) {
46   uint8_t *buf;
47   int size = av_samples_get_buffer_size(NULL, nb_channels, nb_samples,
48                                         sample_fmt, align);
49   if (size < 0)
50     return size;
51 
52   buf = av_malloc(size);
53   if (!buf)
54     return AVERROR(ENOMEM);
55 
56   size = av_samples_fill_arrays_fixed(audio_data, linesize, buf, nb_channels,
57                                       nb_samples, sample_fmt, align);
58   if (size < 0) {
59     av_free(buf);
60     return size;
61   }
62 
63   av_samples_set_silence(audio_data, 0, nb_samples, nb_channels, sample_fmt);
64 
65   return size;
66 }
67 
av_samples_alloc_array_and_samples_fixed(uint8_t *** audio_data,int * linesize,int nb_channels,int nb_samples,enum AVSampleFormat sample_fmt,int align)68 int av_samples_alloc_array_and_samples_fixed(uint8_t ***audio_data,
69                                              int *linesize, int nb_channels,
70                                              int nb_samples,
71                                              enum AVSampleFormat sample_fmt,
72                                              int align) {
73   int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1;
74 
75   *audio_data = av_calloc(nb_planes, sizeof(**audio_data));
76   if (!*audio_data)
77     return AVERROR(ENOMEM);
78   ret = av_samples_alloc_fixed(*audio_data, linesize, nb_channels, nb_samples,
79                                sample_fmt, align);
80   if (ret < 0)
81     av_freep(audio_data);
82   return ret;
83 }
84 
bl_audio_decode(char const * const filename,struct bl_song * const song)85 int bl_audio_decode(char const *const filename, struct bl_song *const song) {
86   int ret;
87   // Contexts and libav variables
88   AVPacket avpkt;
89   AVFormatContext *context;
90   int audio_stream;
91   AVCodecContext *codec_context = NULL;
92   AVCodec *codec = NULL;
93   AVFrame *decoded_frame = NULL;
94   AVAudioResampleContext *avr_ctx;
95 
96   // Size of the samples
97   uint64_t size = 0;
98 
99   // Dictionary to fetch tags
100   AVDictionaryEntry *tags_dictionary;
101 
102   // Pointer to beginning of music data
103   int8_t *beginning;
104   // Received frame holder
105   int got_frame;
106   // Position in the data buffer
107   int index;
108   // Initialize AV lib
109   av_register_all();
110   context = avformat_alloc_context();
111 
112   av_log_set_level(AV_LOG_QUIET);
113 
114   // Open input file
115   if (avformat_open_input(&context, filename, NULL, NULL) < 0) {
116     fprintf(stderr, "Couldn't open file: %s. Error %d encountered.\n", filename,
117             errno);
118     return BL_UNEXPECTED;
119   }
120 
121   // Search for a valid stream
122   if (avformat_find_stream_info(context, NULL) < 0) {
123     fprintf(stderr, "Couldn't find stream information\n");
124     return BL_UNEXPECTED;
125   }
126 
127   // Get audio stream
128   audio_stream =
129       av_find_best_stream(context, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
130   if (audio_stream < 0) {
131     fprintf(stderr, "Couldn't find a suitable audio stream\n");
132     return BL_UNEXPECTED;
133   }
134 
135   // Find associated codec
136   codec_context = context->streams[audio_stream]->codec;
137   if (!codec_context) {
138     fprintf(stderr, "Codec not found!\n");
139     return BL_UNEXPECTED;
140   }
141   if (avcodec_open2(codec_context, codec, NULL) < 0) {
142     fprintf(stderr, "Could not open codec\n");
143     return BL_UNEXPECTED;
144   }
145   // Fill song properties
146   song->filename = malloc(strlen(filename) + 1);
147   strcpy(song->filename, filename);
148 
149   song->sample_rate = codec_context->sample_rate;
150   song->duration = (uint64_t)(context->duration) / ((uint64_t)AV_TIME_BASE);
151   song->bitrate = context->bit_rate;
152   song->resampled = 0;
153   song->nb_bytes_per_sample =
154       av_get_bytes_per_sample(codec_context->sample_fmt);
155   song->channels = codec_context->channels;
156 
157   // Get number of samples
158   size = (((uint64_t)(context->duration) * (uint64_t)SAMPLE_RATE) /
159           ((uint64_t)AV_TIME_BASE)) *
160          song->channels * NB_BYTES_PER_SAMPLE;
161 
162   // Estimated number of samples
163   song->nSamples = ((((uint64_t)(context->duration) * (uint64_t)SAMPLE_RATE) /
164                      ((uint64_t)AV_TIME_BASE)) *
165                     song->channels);
166 
167   // Allocate sample_array
168   if ((song->sample_array = calloc(size, 1)) == NULL) {
169     fprintf(stderr, "Could not allocate enough memory\n");
170     return BL_UNEXPECTED;
171   }
172 
173   beginning = song->sample_array;
174   index = 0;
175 
176   song->resampled = 0;
177   song->nb_bytes_per_sample =
178       av_get_bytes_per_sample(codec_context->sample_fmt);
179   song->channels = codec_context->channels;
180 
181   // If the song is in a floating-point format, prepare the conversion to int16
182   if (codec_context->sample_fmt != AV_SAMPLE_FMT_S16 ||
183       (codec_context->sample_rate != SAMPLE_RATE)) {
184     song->resampled = 1;
185     song->nb_bytes_per_sample = 2;
186     song->sample_rate = SAMPLE_RATE;
187 
188     avr_ctx = avresample_alloc_context();
189     if (codec_context->channel_layout <= 0) {
190       fprintf(stderr,
191               "Impossible to find channel layout; assuming stereo...\n");
192       av_opt_set_int(avr_ctx, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
193       av_opt_set_int(avr_ctx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
194     } else {
195       av_opt_set_int(avr_ctx, "in_channel_layout",
196                      codec_context->channel_layout, 0);
197       av_opt_set_int(avr_ctx, "out_channel_layout",
198                      codec_context->channel_layout, 0);
199     }
200     av_opt_set_int(avr_ctx, "in_sample_rate", codec_context->sample_rate, 0);
201     av_opt_set_int(avr_ctx, "in_sample_fmt", codec_context->sample_fmt, 0);
202 
203     av_opt_set_int(avr_ctx, "out_sample_rate", song->sample_rate, 0);
204     av_opt_set_int(avr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
205     if ((ret = avresample_open(avr_ctx)) < 0) {
206       fprintf(stderr, "Could not allocate resampler context\n");
207       return BL_UNEXPECTED;
208     }
209   }
210 
211   // Zero initialize tags
212   song->artist = NULL;
213   song->title = NULL;
214   song->album = NULL;
215   song->tracknumber = NULL;
216 
217   // Initialize tracknumber tag
218   tags_dictionary = av_dict_get(context->metadata, "track", NULL, 0);
219   if (tags_dictionary != NULL) {
220     song->tracknumber = malloc(strlen(tags_dictionary->value) + 1);
221     strcpy(song->tracknumber, tags_dictionary->value);
222     song->tracknumber[strcspn(song->tracknumber, "/")] = '\0';
223   } else {
224     song->tracknumber = malloc(1 * sizeof(char));
225     strcpy(song->tracknumber, "");
226   }
227 
228   // Initialize title tag
229   tags_dictionary = av_dict_get(context->metadata, "title", NULL, 0);
230   if (tags_dictionary != NULL) {
231     song->title = malloc(strlen(tags_dictionary->value) + 1);
232     strcpy(song->title, tags_dictionary->value);
233   } else {
234     song->title = malloc(12 * sizeof(char));
235     strcpy(song->title, "<no title>");
236   }
237 
238   // Initialize artist tag
239   tags_dictionary = av_dict_get(context->metadata, "ARTIST", NULL, 0);
240   if (tags_dictionary != NULL) {
241     song->artist = malloc(strlen(tags_dictionary->value) + 1);
242     strcpy(song->artist, tags_dictionary->value);
243   } else {
244     song->artist = malloc(12 * sizeof(char));
245     strcpy(song->artist, "<no artist>");
246   }
247 
248   // Initialize album tag
249   tags_dictionary = av_dict_get(context->metadata, "ALBUM", NULL, 0);
250   if (tags_dictionary != NULL) {
251     song->album = malloc(strlen(tags_dictionary->value) + 1);
252     strcpy(song->album, tags_dictionary->value);
253   } else {
254     song->album = malloc(11 * sizeof(char));
255     strcpy(song->album, "<no album>");
256   }
257 
258   // Initialize genre tag
259   tags_dictionary = av_dict_get(context->metadata, "genre", NULL, 0);
260   if (tags_dictionary != NULL) {
261     song->genre = malloc(strlen(tags_dictionary->value) + 1);
262     strcpy(song->genre, tags_dictionary->value);
263   } else {
264     song->genre = malloc(11 * sizeof(char));
265     strcpy(song->genre, "<no genre>");
266   }
267 
268   // Read the whole data and copy them into a huge buffer
269   av_init_packet(&avpkt);
270   while (av_read_frame(context, &avpkt) >= 0) {
271     if (avpkt.stream_index == audio_stream) {
272       got_frame = 0;
273 
274       // If decoded frame has not been allocated yet
275       if (!decoded_frame) {
276         // Try to allocate it
277         decoded_frame = av_frame_alloc();
278         if (!decoded_frame) {
279           fprintf(stderr, "Could not allocate audio frame\n");
280           return BL_UNEXPECTED;
281         }
282       } else {
283         // Else, unreference it and reset fields
284         av_frame_unref(decoded_frame);
285       }
286 
287       int length = avcodec_decode_audio4(codec_context, decoded_frame,
288                                          &got_frame, &avpkt);
289       if (length < 0) {
290         avpkt.size = 0;
291       }
292 
293       av_free_packet(&avpkt);
294 
295       // Copy decoded data into a huge array
296       if (got_frame) {
297         size_t data_size = av_samples_get_buffer_size(
298             NULL, codec_context->channels, decoded_frame->nb_samples,
299             codec_context->sample_fmt, 1);
300 
301         if ((index * song->nb_bytes_per_sample + data_size) > size) {
302           int8_t *ptr;
303           ptr = realloc(beginning, size + data_size);
304           if (ptr != NULL) {
305             beginning = ptr;
306             size += data_size;
307             song->nSamples += data_size / song->nb_bytes_per_sample;
308           } else
309             break;
310         }
311 
312         // If the song is in a floating-point format, convert it to int16
313         if (song->resampled == 1) {
314           uint8_t **out_buffer;
315           size_t dst_bufsize;
316           // Approximate the resampled buffer size
317           int dst_nb_samples = av_rescale_rnd(
318               avresample_get_delay(avr_ctx) + decoded_frame->nb_samples,
319               SAMPLE_RATE, codec_context->sample_rate, AV_ROUND_UP);
320 
321           dst_bufsize = av_samples_alloc_array_and_samples_fixed(
322               &out_buffer, decoded_frame->linesize, song->channels,
323               dst_nb_samples, AV_SAMPLE_FMT_S16, 0);
324 
325           ret = avresample_convert(avr_ctx, out_buffer, 0, dst_bufsize,
326                                    (uint8_t **)decoded_frame->extended_data, 0,
327                                    decoded_frame->nb_samples);
328 
329           if (ret < 0) {
330             fprintf(stderr,
331                     "Error while converting from floating-point to int\n");
332             return BL_UNEXPECTED;
333           }
334           if (ret != 0) {
335             // Get the real resampled buffer size
336             dst_bufsize = av_samples_get_buffer_size(NULL, song->channels, ret,
337                                                      AV_SAMPLE_FMT_S16, 1);
338             memcpy((index * song->nb_bytes_per_sample) + beginning,
339                    out_buffer[0], dst_bufsize);
340             index += dst_bufsize / (float)song->nb_bytes_per_sample;
341           }
342           av_freep(&out_buffer[0]);
343           free(out_buffer);
344         } else {
345           memcpy((index * song->nb_bytes_per_sample) + beginning,
346                  decoded_frame->extended_data[0], data_size);
347           index += data_size / song->nb_bytes_per_sample;
348         }
349       }
350     } else {
351       // Dropping packets that do not belong to the audio stream
352       // (such as album cover)
353       av_free_packet(&avpkt);
354     }
355   }
356   song->sample_array = beginning;
357 
358   // Free memory
359   avpkt.data = NULL;
360   avpkt.size = 0;
361 
362   // Use correct number of samples after decoding
363   song->nSamples = index;
364 
365   // Read the end of audio, as precognized in
366   // http://ffmpeg.org/pipermail/libav-user/2015-August/008433.html
367   do {
368     avcodec_decode_audio4(codec_context, decoded_frame, &got_frame, &avpkt);
369   } while (got_frame);
370 
371   // Free memory
372   if (song->resampled)
373     avresample_free(&avr_ctx);
374   avcodec_close(codec_context);
375   av_frame_unref(decoded_frame);
376 #if LIBAVUTIL_VERSION_MAJOR > 51
377   av_frame_free(&decoded_frame);
378 #endif
379   av_free_packet(&avpkt);
380   avformat_close_input(&context);
381 
382   return BL_OK;
383 }
384