Ticket #9764: transcode_v4_ffmpeg_1.c

File transcode_v4_ffmpeg_1.c, 32.4 KB (added by David Fletcher, 4 years ago)

Transcode (based in example in source tree), modified from previously uploated to fetch the example MP3 insrtead of an internet radio stream

Line 
1/*
2 * This file is for investigation of MP3 decoding issues on older Arm hardware
3 *
4 */
5
6//Static compile on Raspberry Pi (Armv7):
7// gcc transcode_v4_ffmpeg.c libavformat.a libavcodec.a libswresample.a libavutil.a -Wno-format -Wno-deprecated-declarations -I/usr/local/include/:/usr/include/arm-linux-gnueabihf/sys/:/usr/lib/arm-linux-gnueabihf/li -lm -lpthread -o transcode
8
9//Static compile for Reciva radio (Armv4):
10// arm-9tdmi-linux-gnu-gcc -lm -lpthread transcode_v4_ffmpeg.c libavformat.a libavcodec.a libswresample.a libavutil.a -Wno-format -Wno-deprecated-declarations -I/tmp/reciva/root/include/ -I/tmp/reciva/root/usr/include/ -o transcode_v4_ffmpeg
11
12
13
14/**
15 * @file
16 * simple audio converter
17 *
18 * @example transcode_aac.c
19 * Convert an input audio file to AAC in an MP4 container using FFmpeg.
20 * @author Andreas Unterweger (dustsigns@gmail.com)
21 */
22
23#include <stdio.h>
24#include <time.h>
25
26#include "libavformat/avformat.h"
27#include "libavformat/avio.h"
28
29#include "libavcodec/avcodec.h"
30
31#include "libavutil/audio_fifo.h"
32#include "libavutil/avassert.h"
33#include "libavutil/avstring.h"
34#include "libavutil/frame.h"
35#include "libavutil/opt.h"
36
37#include "libswresample/swresample.h"
38
39#include "fdk-aac/FDK_audio.h"
40#include "fdk-aac/aacdecoder_lib.h"
41#include "fdk-aac/aacenc_lib.h"
42#include "fdk-aac/genericStds.h"
43#include "fdk-aac/machine_type.h"
44#include "fdk-aac/syslib_channelMapDescr.h"
45
46
47/** The output bit rate in kbit/s (96000) */
48#define OUTPUT_BIT_RATE 128000
49/** The number of output channels */
50#define OUTPUT_CHANNELS 2
51
52/** Open an input file and the required decoder. */
53static int open_input_file(const char *filename,
54 AVFormatContext **input_format_context,
55 AVCodecContext **input_codec_context)
56{
57 AVCodecContext *avctx;
58 AVCodec *input_codec;
59 AVDictionary *opts = NULL;
60 int error;
61
62 av_dict_set(&opts, "user_agent", "Reciva Next Generation", 0);
63 av_dict_set(&opts, "multiple_requests", "1", 0);
64
65 /** Open the input file to read from it. */
66 if ((error = avformat_open_input(input_format_context, filename, NULL, NULL)) < 0) {
67 fprintf(stderr, "Could not open input file '%s' (error '%s')\n",
68 filename, av_err2str(error));
69 *input_format_context = NULL;
70 return error;
71 }
72
73 av_dict_free(&opts);
74
75 /** Get information on the input file (number of streams etc.). */
76 if ((error = avformat_find_stream_info(*input_format_context, NULL)) < 0) {
77 fprintf(stderr, "Could not open find stream info (error '%s')\n",
78 av_err2str(error));
79 avformat_close_input(input_format_context);
80 return error;
81 }
82
83 /** Make sure that there is only one stream in the input file. */
84 if ((*input_format_context)->nb_streams != 1) {
85 fprintf(stderr, "Expected one audio input stream, but found %d\n",
86 (*input_format_context)->nb_streams);
87 avformat_close_input(input_format_context);
88 return AVERROR_EXIT;
89 }
90
91 /** Find a decoder for the audio stream. */
92 if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) {
93 fprintf(stderr, "Could not find input codec\n");
94 avformat_close_input(input_format_context);
95 return AVERROR_EXIT;
96 }
97
98 /** allocate a new decoding context */
99 avctx = avcodec_alloc_context3(input_codec);
100 if (!avctx) {
101 fprintf(stderr, "Could not allocate a decoding context\n");
102 avformat_close_input(input_format_context);
103 return AVERROR(ENOMEM);
104 }
105
106 /** initialize the stream parameters with demuxer information */
107 error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar);
108 if (error < 0) {
109 avformat_close_input(input_format_context);
110 avcodec_free_context(&avctx);
111 return error;
112 }
113
114 /** Open the decoder for the audio stream to use it later. */
115 if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) {
116 fprintf(stderr, "Could not open input codec (error '%s')\n",
117 av_err2str(error));
118 avcodec_free_context(&avctx);
119 avformat_close_input(input_format_context);
120 return error;
121 }
122
123 /** Save the decoder context for easier access later. */
124 *input_codec_context = avctx;
125
126 av_dump_format(*input_format_context, 0, filename, 0);
127
128 return 0;
129}
130
131/**
132 * Open an output file and the required encoder.
133 * Also set some basic encoder parameters.
134 * Some of these parameters are based on the input file's parameters.
135 */
136static int open_output_file(const char *filename,
137 AVCodecContext *input_codec_context,
138 AVFormatContext **output_format_context,
139 AVCodecContext **output_codec_context)
140{
141 AVCodecContext *avctx = NULL;
142 AVIOContext *output_io_context = NULL;
143 AVStream *stream = NULL;
144 AVCodec *output_codec = NULL;
145 int error;
146
147 /** Open the output file to write to it. */
148 if ((error = avio_open(&output_io_context, filename,
149 AVIO_FLAG_WRITE)) < 0) {
150 fprintf(stderr, "Could not open output file '%s' (error '%s')\n",
151 filename, av_err2str(error));
152 return error;
153 }
154
155 /** Create a new format context for the output container format. */
156 if (!(*output_format_context = avformat_alloc_context())) {
157 fprintf(stderr, "Could not allocate output format context\n");
158 return AVERROR(ENOMEM);
159 }
160
161 /** Associate the output file (pointer) with the container format context. */
162 (*output_format_context)->pb = output_io_context;
163
164 /** Set the desired container format */
165 if (!((*output_format_context)->oformat = av_guess_format("au", NULL, NULL))) {
166 fprintf(stderr, "Could not find output file format\n");
167 goto cleanup;
168 }
169
170 //av_strlcpy((*output_format_context)->filename, filename, sizeof((*output_format_context)->filename));
171
172 /** Find the encoder to be used by its name. */
173 if (!(output_codec = avcodec_find_encoder(AV_CODEC_ID_PCM_S16BE))) {
174 fprintf(stderr, "Could not find an PCM_S16BE encoder.\n");
175 goto cleanup;
176 }
177
178 /** Create a new audio stream in the output file container. */
179 if (!(stream = avformat_new_stream(*output_format_context, NULL))) {
180 fprintf(stderr, "Could not create new stream\n");
181 error = AVERROR(ENOMEM);
182 goto cleanup;
183 }
184
185 avctx = avcodec_alloc_context3(output_codec);
186 if (!avctx) {
187 fprintf(stderr, "Could not allocate an encoding context\n");
188 error = AVERROR(ENOMEM);
189 goto cleanup;
190 }
191
192 /**
193 * Set the basic encoder parameters.
194 * The input file's sample rate is used to avoid a sample rate conversion.
195 */
196 avctx->channels = OUTPUT_CHANNELS;
197 avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
198 avctx->sample_rate = input_codec_context->sample_rate;
199 avctx->sample_fmt = output_codec->sample_fmts[0];
200 avctx->bit_rate = OUTPUT_BIT_RATE;
201
202 printf("Incoming bit rate: %i", input_codec_context->bit_rate);
203
204 /** Allow the use of the experimental AAC encoder */
205 avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
206
207 /** Set the sample rate for the container. */
208 stream->time_base.den = input_codec_context->sample_rate;
209 stream->time_base.num = 1;
210
211 /**
212 * Some container formats (like MP4) require global headers to be present
213 * Mark the encoder so that it behaves accordingly.
214 */
215 if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER)
216 avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
217
218 /** Open the encoder for the audio stream to use it later. */
219 if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) {
220 fprintf(stderr, "Could not open output codec (error '%s')\n",
221 av_err2str(error));
222 goto cleanup;
223 }
224
225 error = avcodec_parameters_from_context(stream->codecpar, avctx);
226 if (error < 0) {
227 fprintf(stderr, "Could not initialize stream parameters\n");
228 goto cleanup;
229 }
230
231 /** Save the encoder context for easier access later. */
232 *output_codec_context = avctx;
233
234 return 0;
235
236cleanup:
237 avcodec_free_context(&avctx);
238 avio_closep(&(*output_format_context)->pb);
239 avformat_free_context(*output_format_context);
240 *output_format_context = NULL;
241 return error < 0 ? error : AVERROR_EXIT;
242}
243
244/** Initialize one data packet for reading or writing. */
245//static void init_packet(AVPacket *packet)
246//{
247// av_init_packet(packet);
248// /** Set the packet data and size so that it is recognized as being empty. */
249// packet->data = NULL;
250// packet->size = 0;
251//}
252
253/**
254 * Initialize one data packet for reading or writing.
255 * @param[out] packet Packet to be initialized
256 * @return Error code (0 if successful)
257 */
258static int init_packet(AVPacket **packet)
259{
260 if (!(*packet = av_packet_alloc())) {
261 fprintf(stderr, "Could not allocate packet\n");
262 return AVERROR(ENOMEM);
263 }
264 return 0;
265}
266
267/** Initialize one audio frame for reading from the input file */
268static int init_input_frame(AVFrame **frame)
269{
270 if (!(*frame = av_frame_alloc())) {
271 fprintf(stderr, "Could not allocate input frame\n");
272 return AVERROR(ENOMEM);
273 }
274 return 0;
275}
276
277/**
278 * Initialize the audio resampler based on the input and output codec settings.
279 * If the input and output sample formats differ, a conversion is required
280 * libswresample takes care of this, but requires initialization.
281 */
282static int init_resampler(AVCodecContext *input_codec_context,
283 AVCodecContext *output_codec_context,
284 SwrContext **resample_context)
285{
286
287 int error;
288
289 /**
290 * Create a resampler context for the conversion.
291 * Set the conversion parameters.
292 * Default channel layouts based on the number of channels
293 * are assumed for simplicity (they are sometimes not detected
294 * properly by the demuxer and/or decoder).
295 */
296 *resample_context = swr_alloc_set_opts(NULL,
297 av_get_default_channel_layout(output_codec_context->channels),
298 output_codec_context->sample_fmt,
299 output_codec_context->sample_rate,
300 av_get_default_channel_layout(input_codec_context->channels),
301 input_codec_context->sample_fmt,
302 input_codec_context->sample_rate,
303 0, NULL);
304
305 av_opt_set(*resample_context, "dither_method", "triangular", 0);
306 av_opt_set(*resample_context, "dither_scale", "1", 0);
307
308
309 if (!*resample_context) {
310 fprintf(stderr, "Could not allocate resample context\n");
311 return AVERROR(ENOMEM);
312 }
313 /**
314 * Perform a sanity check so that the number of converted samples is
315 * not greater than the number of samples to be converted.
316 * If the sample rates differ, this case has to be handled differently
317 */
318 av_assert0(output_codec_context->sample_rate == input_codec_context->sample_rate);
319
320 /** Open the resampler with the specified parameters. */
321 if ((error = swr_init(*resample_context)) < 0) {
322 fprintf(stderr, "Could not open resample context\n");
323 swr_free(resample_context);
324 return error;
325 }
326 return 0;
327}
328
329/** Initialize a FIFO buffer for the audio samples to be encoded. */
330static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
331{
332 /** Create the FIFO buffer based on the specified output sample format. */
333 if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt,
334 output_codec_context->channels, 1))) {
335 fprintf(stderr, "Could not allocate FIFO\n");
336 return AVERROR(ENOMEM);
337 }
338 return 0;
339}
340
341/** Write the header of the output file container. */
342static int write_output_file_header(AVFormatContext *output_format_context)
343{
344 int error;
345
346 av_dict_set(&output_format_context->metadata,"title","title", 0);
347 av_dict_set(&output_format_context->metadata,"comment","comment", 0);
348
349 if ((error = avformat_write_header(output_format_context, &output_format_context->metadata)) < 0) {
350 fprintf(stderr, "Could not write output file header (error '%s')\n",av_err2str(error));
351 return error;
352 }
353 return 0;
354}
355
356
357/**
358 * Decode one audio frame from the input file.
359 * @param frame Audio frame to be decoded
360 * @param input_format_context Format context of the input file
361 * @param input_codec_context Codec context of the input file
362 * @param[out] data_present Indicates whether data has been decoded
363 * @param[out] finished Indicates whether the end of file has
364 * been reached and all data has been
365 * decoded. If this flag is false, there
366 * is more data to be decoded, i.e., this
367 * function has to be called again.
368 * @return Error code (0 if successful)
369 */
370static int decode_audio_frame(AVFrame *frame,
371 AVFormatContext *input_format_context,
372 AVCodecContext *input_codec_context,
373 int *data_present, int *finished)
374{
375 /* Packet used for temporary storage. */
376 AVPacket *input_packet;
377 int error;
378
379 error = init_packet(&input_packet);
380 if (error < 0)
381 return error;
382
383 /* Read one audio frame from the input file into a temporary packet. */
384 if ((error = av_read_frame(input_format_context, input_packet)) < 0) {
385 /* If we are at the end of the file, flush the decoder below. */
386 if (error == AVERROR_EOF)
387 *finished = 1;
388 else {
389 fprintf(stderr, "Could not read frame (error '%s')\n",
390 av_err2str(error));
391 goto cleanup;
392 }
393 }
394
395 /* Send the audio frame stored in the temporary packet to the decoder.
396 * The input audio stream decoder is used to do this. */
397 if ((error = avcodec_send_packet(input_codec_context, input_packet)) < 0) {
398 fprintf(stderr, "Could not send packet for decoding (error '%s')\n",
399 av_err2str(error));
400 goto cleanup;
401 }
402
403 /* Receive one frame from the decoder. */
404 error = avcodec_receive_frame(input_codec_context, frame);
405 /* If the decoder asks for more data to be able to decode a frame,
406 * return indicating that no data is present. */
407 if (error == AVERROR(EAGAIN)) {
408 error = 0;
409 goto cleanup;
410 /* If the end of the input file is reached, stop decoding. */
411 } else if (error == AVERROR_EOF) {
412 *finished = 1;
413 error = 0;
414 goto cleanup;
415 } else if (error < 0) {
416 fprintf(stderr, "Could not decode frame (error '%s')\n",
417 av_err2str(error));
418 goto cleanup;
419 /* Default case: Return decoded data. */
420 } else {
421 *data_present = 1;
422 goto cleanup;
423 }
424
425cleanup:
426 av_packet_free(&input_packet);
427 return error;
428}
429
430/**
431 * Initialize a temporary storage for the specified number of audio samples.
432 * The conversion requires temporary storage due to the different format.
433 * The number of audio samples to be allocated is specified in frame_size.
434 */
435static int init_converted_samples(uint8_t ***converted_input_samples,
436 AVCodecContext *output_codec_context,
437 int frame_size)
438{
439 int error;
440
441 /**
442 * Allocate as many pointers as there are audio channels.
443 * Each pointer will later point to the audio samples of the corresponding
444 * channels (although it may be NULL for interleaved formats).
445 */
446 if (!(*converted_input_samples = calloc(output_codec_context->channels,
447 sizeof(**converted_input_samples)))) {
448 fprintf(stderr, "Could not allocate converted input sample pointers\n");
449 return AVERROR(ENOMEM);
450 }
451
452 /**
453 * Allocate memory for the samples of all channels in one consecutive
454 * block for convenience.
455 */
456 if ((error = av_samples_alloc(*converted_input_samples, NULL,
457 output_codec_context->channels,
458 frame_size,
459 output_codec_context->sample_fmt, 0)) < 0) {
460 fprintf(stderr,
461 "Could not allocate converted input samples (error '%s')\n",
462 av_err2str(error));
463 av_freep(&(*converted_input_samples)[0]);
464 free(*converted_input_samples);
465 return error;
466 }
467 return 0;
468}
469
470/**
471 * Convert the input audio samples into the output sample format.
472 * The conversion happens on a per-frame basis, the size of which is specified
473 * by frame_size.
474 */
475static int convert_samples(const uint8_t **input_data,
476 uint8_t **converted_data, const int frame_size,
477 SwrContext *resample_context)
478{
479 int error;
480
481 /** Convert the samples using the resampler. */
482 if ((error = swr_convert(resample_context,converted_data, frame_size,input_data, frame_size)) < 0) {
483 fprintf(stderr, "Could not convert input samples (error '%s')\n",
484 av_err2str(error));
485 return error;
486 }
487
488 return 0;
489}
490
491/** Add converted input audio samples to the FIFO buffer for later processing. */
492static int add_samples_to_fifo(AVAudioFifo *fifo,
493 uint8_t **converted_input_samples,
494 const int frame_size)
495{
496 int error;
497
498 /**
499 * Make the FIFO as large as it needs to be to hold both,
500 * the old and the new samples.
501 */
502 if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
503 fprintf(stderr, "Could not reallocate FIFO\n");
504 return error;
505 }
506
507 /** Store the new samples in the FIFO buffer. */
508 if (av_audio_fifo_write(fifo, (void **)converted_input_samples,
509 frame_size) < frame_size) {
510 fprintf(stderr, "Could not write data to FIFO\n");
511 return AVERROR_EXIT;
512 }
513 return 0;
514}
515
516/**
517 * Read one audio frame from the input file, decodes, converts and stores
518 * it in the FIFO buffer.
519 */
520static int read_decode_convert_and_store(AVAudioFifo *fifo,
521 AVFormatContext *input_format_context,
522 AVCodecContext *input_codec_context,
523 AVCodecContext *output_codec_context,
524 SwrContext *resampler_context,
525 int *finished)
526{
527 /** Temporary storage of the input samples of the frame read from the file. */
528 AVFrame *input_frame = NULL;
529 /** Temporary storage for the converted input samples. */
530 uint8_t **converted_input_samples = NULL;
531 int data_present;
532 int ret = AVERROR_EXIT;
533
534 /** Initialize temporary storage for one input frame. */
535 if (init_input_frame(&input_frame))
536 goto cleanup;
537 /** Decode one frame worth of audio samples. */
538 if (decode_audio_frame(input_frame, input_format_context,
539 input_codec_context, &data_present, finished))
540 goto cleanup;
541 /**
542 * If we are at the end of the file and there are no more samples
543 * in the decoder which are delayed, we are actually finished.
544 * This must not be treated as an error.
545 */
546 if (*finished && !data_present) {
547 ret = 0;
548 goto cleanup;
549 }
550 /** If there is decoded data, convert and store it */
551 if (data_present) {
552 /** Initialize the temporary storage for the converted input samples. */
553 if (init_converted_samples(&converted_input_samples, output_codec_context,
554 input_frame->nb_samples))
555 goto cleanup;
556
557 /**
558 * Convert the input samples to the desired output sample format.
559 * This requires a temporary storage provided by converted_input_samples.
560 */
561 if (convert_samples((const uint8_t**)input_frame->extended_data, converted_input_samples,
562 input_frame->nb_samples, resampler_context))
563 goto cleanup;
564
565 /** Add the converted input samples to the FIFO buffer for later processing. */
566 if (add_samples_to_fifo(fifo, converted_input_samples,
567 input_frame->nb_samples))
568 goto cleanup;
569 ret = 0;
570 }
571 ret = 0;
572
573cleanup:
574 if (converted_input_samples) {
575 av_freep(&converted_input_samples[0]);
576 free(converted_input_samples);
577 }
578 av_frame_free(&input_frame);
579
580 return ret;
581}
582
583/**
584 * Initialize one input frame for writing to the output file.
585 * The frame will be exactly frame_size samples large.
586 */
587static int init_output_frame(AVFrame **frame,
588 AVCodecContext *output_codec_context,
589 int frame_size)
590{
591 int error;
592
593 /** Create a new frame to store the audio samples. */
594 if (!(*frame = av_frame_alloc())) {
595 fprintf(stderr, "Could not allocate output frame\n");
596 return AVERROR_EXIT;
597 }
598
599 /**
600 * Set the frame's parameters, especially its size and format.
601 * av_frame_get_buffer needs this to allocate memory for the
602 * audio samples of the frame.
603 * Default channel layouts based on the number of channels
604 * are assumed for simplicity.
605 */
606 (*frame)->nb_samples = frame_size;
607 (*frame)->channel_layout = output_codec_context->channel_layout;
608 (*frame)->format = output_codec_context->sample_fmt;
609 (*frame)->sample_rate = output_codec_context->sample_rate;
610
611 /**
612 * Allocate the samples of the created frame. This call will make
613 * sure that the audio frame can hold as many samples as specified.
614 */
615 if ((error = av_frame_get_buffer(*frame, 0)) < 0) {
616 fprintf(stderr, "Could not allocate output frame samples (error '%s')\n", av_err2str(error));
617 av_frame_free(frame);
618 return error;
619 }
620
621 return 0;
622}
623
624/** Global timestamp for the audio frames */
625static int64_t pts = 0;
626
627/**
628 * Encode one frame worth of audio to the output file.
629 * @param frame Samples to be encoded
630 * @param output_format_context Format context of the output file
631 * @param output_codec_context Codec context of the output file
632 * @param[out] data_present Indicates whether data has been
633 * encoded
634 * @return Error code (0 if successful)
635 */
636static int encode_audio_frame(AVFrame *frame,
637 AVFormatContext *output_format_context,
638 AVCodecContext *output_codec_context,
639 int *data_present)
640{
641 /* Packet used for temporary storage. */
642 AVPacket *output_packet;
643 int error;
644
645 error = init_packet(&output_packet);
646 if (error < 0)
647 return error;
648
649 /* Set a timestamp based on the sample rate for the container. */
650 if (frame) {
651 frame->pts = pts;
652 pts += frame->nb_samples;
653 }
654
655 /* Send the audio frame stored in the temporary packet to the encoder.
656 * The output audio stream encoder is used to do this. */
657 error = avcodec_send_frame(output_codec_context, frame);
658 /* The encoder signals that it has nothing more to encode. */
659 if (error == AVERROR_EOF) {
660 error = 0;
661 goto cleanup;
662 } else if (error < 0) {
663 fprintf(stderr, "Could not send packet for encoding (error '%s')\n",
664 av_err2str(error));
665 goto cleanup;
666 }
667
668 /* Receive one encoded frame from the encoder. */
669 error = avcodec_receive_packet(output_codec_context, output_packet);
670 /* If the encoder asks for more data to be able to provide an
671 * encoded frame, return indicating that no data is present. */
672 if (error == AVERROR(EAGAIN)) {
673 error = 0;
674 goto cleanup;
675 /* If the last frame has been encoded, stop encoding. */
676 } else if (error == AVERROR_EOF) {
677 error = 0;
678 goto cleanup;
679 } else if (error < 0) {
680 fprintf(stderr, "Could not encode frame (error '%s')\n",
681 av_err2str(error));
682 goto cleanup;
683 /* Default case: Return encoded data. */
684 } else {
685 *data_present = 1;
686 }
687
688 /* Write one audio frame from the temporary packet to the output file. */
689 if (*data_present &&
690 (error = av_write_frame(output_format_context, output_packet)) < 0) {
691 fprintf(stderr, "Could not write frame (error '%s')\n",
692 av_err2str(error));
693 goto cleanup;
694 }
695
696cleanup:
697 av_packet_free(&output_packet);
698 return error;
699}
700
701
702/**
703 * Load one audio frame from the FIFO buffer, encode and write it to the
704 * output file.
705 */
706static int load_encode_and_write(AVAudioFifo *fifo,
707 AVFormatContext *output_format_context,
708 AVCodecContext *output_codec_context)
709{
710 /** Temporary storage of the output samples of the frame written to the file. */
711 AVFrame *output_frame;
712 /**
713 * Use the maximum number of possible samples per frame.
714 * If there is less than the maximum possible frame size in the FIFO
715 * buffer use this number. Otherwise, use the maximum possible frame size
716 */
717
718 const int frame_size = FFMIN(av_audio_fifo_size(fifo), output_codec_context->frame_size);
719 int data_written;
720
721 /** Initialize temporary storage for one output frame. */
722 if (init_output_frame(&output_frame, output_codec_context, frame_size))
723 return AVERROR_EXIT;
724
725 /**
726 * Read as many samples from the FIFO buffer as required to fill the frame.
727 * The samples are stored in the frame temporarily.
728 */
729 if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) {
730 fprintf(stderr, "Could not read data from FIFO\n");
731 av_frame_free(&output_frame);
732 return AVERROR_EXIT;
733 }
734
735 /** Encode one frame worth of audio samples. */
736 if (encode_audio_frame(output_frame, output_format_context,
737 output_codec_context, &data_written)) {
738 av_frame_free(&output_frame);
739 return AVERROR_EXIT;
740 }
741 av_frame_free(&output_frame);
742 return 0;
743}
744
745/** Write the trailer of the output file container. */
746static int write_output_file_trailer(AVFormatContext *output_format_context)
747{
748 int error;
749 if ((error = av_write_trailer(output_format_context)) < 0) {
750 fprintf(stderr, "Could not write output file trailer (error '%s')\n",
751 av_err2str(error));
752 return error;
753 }
754 return 0;
755}
756
757/** Convert an audio file to an AAC file in an MP4 container. */
758int main(int argc, char **argv)
759{
760 AVFormatContext *input_format_context = NULL, *output_format_context = NULL;
761 AVCodecContext *input_codec_context = NULL, *output_codec_context = NULL;
762 SwrContext *resample_context = NULL;
763 AVAudioFifo *fifo = NULL;
764 int ret = AVERROR_EXIT;
765 int iterations = 0;
766
767 av_log_set_level(AV_LOG_DEBUG);
768
769 //const char *inUrl = "http://stream.live.vc.bbcmedia.co.uk/bbc_radio_fourfm";
770 //const char *inUrl = "http://stream.live.vc.bbcmedia.co.uk/bbc_world_service";
771 const char *inUrl = "http://www.megapico.co.uk/sharpfin/s-32-44100.mp3";
772 //const char *inUrl = "http://stream.releaseradio.net/stream";
773 const char *outFile = "output.au";
774
775 //Global network initialization
776 avformat_network_init();
777
778 /** Open the input file for reading. */
779 if (open_input_file(inUrl, &input_format_context, &input_codec_context))
780 goto cleanup;
781
782 printf("Frame rate 1: %i\n", input_codec_context->sample_rate);
783
784 //Assume output has 16 bits per sample
785 if(((input_codec_context->sample_rate * input_codec_context->channels * 16) > 768000) && (input_format_context->streams[0]->codecpar->codec_id == AV_CODEC_ID_MP3)){
786 printf("Too much data!!\n");
787 //Need to go for direct forwarding of data
788 }
789
790 /** Open the output file for writing. */
791 if (open_output_file(outFile, input_codec_context, &output_format_context, &output_codec_context))
792 goto cleanup;
793
794 /** Initialize the resampler to be able to convert audio sample formats. */
795 if (init_resampler(input_codec_context, output_codec_context, &resample_context))
796 goto cleanup;
797
798 /** Initialize the FIFO buffer to store audio samples to be encoded. */
799 if (init_fifo(&fifo, output_codec_context))
800 goto cleanup;
801
802 /** Write the header of the output file container. */
803 if (write_output_file_header(output_format_context))
804 goto cleanup;
805
806 // The frame size is not set automatically for a WAV/AU output, set something manually here
807 // Smaller sizes increase CPU usage, larger ones cause delay in data output
808 // FrameLen = int((144 * BitRate / SampleRate ) + Padding);
809 output_codec_context->frame_size = (int)((72 * OUTPUT_BIT_RATE / output_codec_context->sample_rate ) + 0);
810 printf("Frame rate: %i\n", input_codec_context->sample_rate);
811
812 /**
813 * Loop as long as we have input samples to read or output samples
814 * to write; abort as soon as we have neither.
815 */
816
817 while (iterations < 2000) {
818 iterations++;
819 /** Use the encoder's desired frame size for processing. */
820 const int output_frame_size = output_codec_context->frame_size;
821 int finished = 0;
822
823 /**
824 * Make sure that there is one frame worth of samples in the FIFO
825 * buffer so that the encoder can do its work.
826 * Since the decoder's and the encoder's frame size may differ, we
827 * need to FIFO buffer to store as many frames worth of input samples
828 * that they make up at least one frame worth of output samples.
829 */
830 while (av_audio_fifo_size(fifo) < output_frame_size) {
831 /**
832 * Decode one frame worth of audio samples, convert it to the
833 * output sample format and put it into the FIFO buffer.
834 */
835 if (read_decode_convert_and_store(fifo, input_format_context,
836 input_codec_context,
837 output_codec_context,
838 resample_context, &finished))
839 goto cleanup;
840
841 /**
842 * If we are at the end of the input file, we continue
843 * encoding the remaining audio samples to the output file.
844 */
845 if (finished)
846 break;
847 }
848
849 /**
850 * If we have enough samples for the encoder, we encode them.
851 * At the end of the file, we pass the remaining samples to
852 * the encoder.
853 */
854 while (av_audio_fifo_size(fifo) >= output_frame_size ||
855 (finished && av_audio_fifo_size(fifo) > 0))
856 /**
857 * Take one frame worth of audio samples from the FIFO buffer,
858 * encode it and write it to the output file.
859 */
860 if (load_encode_and_write(fifo, output_format_context,
861 output_codec_context))
862 goto cleanup;
863
864 /**
865 * If we are at the end of the input file and have encoded
866 * all remaining samples, we can exit this loop and finish.
867 */
868 if (finished) {
869 int data_written;
870 /** Flush the encoder as it may have delayed frames. */
871 do {
872 if (encode_audio_frame(NULL, output_format_context,
873 output_codec_context, &data_written))
874 goto cleanup;
875 } while (data_written);
876 break;
877 }
878 }
879
880 /** Write the trailer of the output file container. */
881 if (write_output_file_trailer(output_format_context))
882 goto cleanup;
883 ret = 0;
884
885cleanup:
886 if (fifo)
887 av_audio_fifo_free(fifo);
888 swr_free(&resample_context);
889 if (output_codec_context)
890 avcodec_free_context(&output_codec_context);
891 if (output_format_context) {
892 avio_closep(&output_format_context->pb);
893 avformat_free_context(output_format_context);
894 }
895 if (input_codec_context)
896 avcodec_free_context(&input_codec_context);
897 if (input_format_context)
898 avformat_close_input(&input_format_context);
899
900 return ret;
901}