transcode_aac.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2018 Andreas Unterweger
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
31 #include <stdio.h>
32 
33 #include "libavformat/avformat.h"
34 #include "libavformat/avio.h"
35 
36 #include "libavcodec/avcodec.h"
37 
38 #include "libavutil/audio_fifo.h"
39 #include "libavutil/avstring.h"
40 #include "libavutil/frame.h"
41 #include "libavutil/opt.h"
42 
44 
45 /* The output bit rate in bit/s */
46 #define OUTPUT_BIT_RATE 96000
47 /* The number of output channels */
48 #define OUTPUT_CHANNELS 2
49 
55 static char *get_error_text(const int error)
56 {
57  static char error_buffer[255];
58  av_strerror(error, error_buffer, sizeof(error_buffer));
59  return error_buffer;
60 }
61 
69 static int open_input_file(const char *filename,
70  AVFormatContext **input_format_context,
71  AVCodecContext **input_codec_context)
72 {
73  AVCodecContext *avctx;
74  AVCodec *input_codec;
75  int error;
76 
77  /* Open the input file to read from it. */
78  if ((error = avformat_open_input(input_format_context, filename, NULL,
79  NULL)) < 0) {
80  fprintf(stderr, "Could not open input file '%s' (error '%s')\n",
81  filename, get_error_text(error));
82  *input_format_context = NULL;
83  return error;
84  }
85 
86  /* Get information on the input file (number of streams etc.). */
87  if ((error = avformat_find_stream_info(*input_format_context, NULL)) < 0) {
88  fprintf(stderr, "Could not open find stream info (error '%s')\n",
89  get_error_text(error));
90  avformat_close_input(input_format_context);
91  return error;
92  }
93 
94  /* Make sure that there is only one stream in the input file. */
95  if ((*input_format_context)->nb_streams != 1) {
96  fprintf(stderr, "Expected one audio input stream, but found %d\n",
97  (*input_format_context)->nb_streams);
98  avformat_close_input(input_format_context);
99  return AVERROR_EXIT;
100  }
101 
102  /* Find a decoder for the audio stream. */
103  if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) {
104  fprintf(stderr, "Could not find input codec\n");
105  avformat_close_input(input_format_context);
106  return AVERROR_EXIT;
107  }
108 
109  /* Allocate a new decoding context. */
110  avctx = avcodec_alloc_context3(input_codec);
111  if (!avctx) {
112  fprintf(stderr, "Could not allocate a decoding context\n");
113  avformat_close_input(input_format_context);
114  return AVERROR(ENOMEM);
115  }
116 
117  /* Initialize the stream parameters with demuxer information. */
118  error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar);
119  if (error < 0) {
120  avformat_close_input(input_format_context);
121  avcodec_free_context(&avctx);
122  return error;
123  }
124 
125  /* Open the decoder for the audio stream to use it later. */
126  if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) {
127  fprintf(stderr, "Could not open input codec (error '%s')\n",
128  get_error_text(error));
129  avcodec_free_context(&avctx);
130  avformat_close_input(input_format_context);
131  return error;
132  }
133 
134  /* Save the decoder context for easier access later. */
135  *input_codec_context = avctx;
136 
137  return 0;
138 }
139 
150 static int open_output_file(const char *filename,
151  AVCodecContext *input_codec_context,
152  AVFormatContext **output_format_context,
153  AVCodecContext **output_codec_context)
154 {
155  AVCodecContext *avctx = NULL;
156  AVIOContext *output_io_context = NULL;
157  AVStream *stream = NULL;
158  AVCodec *output_codec = NULL;
159  int error;
160 
161  /* Open the output file to write to it. */
162  if ((error = avio_open(&output_io_context, filename,
163  AVIO_FLAG_WRITE)) < 0) {
164  fprintf(stderr, "Could not open output file '%s' (error '%s')\n",
165  filename, get_error_text(error));
166  return error;
167  }
168 
169  /* Create a new format context for the output container format. */
170  if (!(*output_format_context = avformat_alloc_context())) {
171  fprintf(stderr, "Could not allocate output format context\n");
172  return AVERROR(ENOMEM);
173  }
174 
175  /* Associate the output file (pointer) with the container format context. */
176  (*output_format_context)->pb = output_io_context;
177 
178  /* Guess the desired container format based on the file extension. */
179  if (!((*output_format_context)->oformat = av_guess_format(NULL, filename,
180  NULL))) {
181  fprintf(stderr, "Could not find output file format\n");
182  goto cleanup;
183  }
184 
185  av_strlcpy((*output_format_context)->filename, filename,
186  sizeof((*output_format_context)->filename));
187 
188  /* Find the encoder to be used by its name. */
189  if (!(output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC))) {
190  fprintf(stderr, "Could not find an AAC encoder.\n");
191  goto cleanup;
192  }
193 
194  /* Create a new audio stream in the output file container. */
195  if (!(stream = avformat_new_stream(*output_format_context, NULL))) {
196  fprintf(stderr, "Could not create new stream\n");
197  error = AVERROR(ENOMEM);
198  goto cleanup;
199  }
200 
201  avctx = avcodec_alloc_context3(output_codec);
202  if (!avctx) {
203  fprintf(stderr, "Could not allocate an encoding context\n");
204  error = AVERROR(ENOMEM);
205  goto cleanup;
206  }
207 
208  /* Set the basic encoder parameters.
209  * The input file's sample rate is used to avoid a sample rate conversion. */
210  avctx->channels = OUTPUT_CHANNELS;
212  avctx->sample_rate = input_codec_context->sample_rate;
213  avctx->sample_fmt = output_codec->sample_fmts[0];
214  avctx->bit_rate = OUTPUT_BIT_RATE;
215 
216  /* Allow the use of the experimental AAC encoder. */
218 
219  /* Set the sample rate for the container. */
220  stream->time_base.den = input_codec_context->sample_rate;
221  stream->time_base.num = 1;
222 
223  /* Some container formats (like MP4) require global headers to be present.
224  * Mark the encoder so that it behaves accordingly. */
225  if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER)
227 
228  /* Open the encoder for the audio stream to use it later. */
229  if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) {
230  fprintf(stderr, "Could not open output codec (error '%s')\n",
231  get_error_text(error));
232  goto cleanup;
233  }
234 
235  error = avcodec_parameters_from_context(stream->codecpar, avctx);
236  if (error < 0) {
237  fprintf(stderr, "Could not initialize stream parameters\n");
238  goto cleanup;
239  }
240 
241  /* Save the encoder context for easier access later. */
242  *output_codec_context = avctx;
243 
244  return 0;
245 
246 cleanup:
247  avcodec_free_context(&avctx);
248  avio_close((*output_format_context)->pb);
249  avformat_free_context(*output_format_context);
250  *output_format_context = NULL;
251  return error < 0 ? error : AVERROR_EXIT;
252 }
253 
258 static void init_packet(AVPacket *packet)
259 {
260  av_init_packet(packet);
261  /* Set the packet data and size so that it is recognized as being empty. */
262  packet->data = NULL;
263  packet->size = 0;
264 }
265 
271 static int init_input_frame(AVFrame **frame)
272 {
273  if (!(*frame = av_frame_alloc())) {
274  fprintf(stderr, "Could not allocate input frame\n");
275  return AVERROR(ENOMEM);
276  }
277  return 0;
278 }
279 
289 static int init_resampler(AVCodecContext *input_codec_context,
290  AVCodecContext *output_codec_context,
291  AVAudioResampleContext **resample_context)
292 {
293  /* Only initialize the resampler if it is necessary, i.e.,
294  * if and only if the sample formats differ. */
295  if (input_codec_context->sample_fmt != output_codec_context->sample_fmt ||
296  input_codec_context->channels != output_codec_context->channels) {
297  int error;
298 
299  /* Create a resampler context for the conversion. */
300  if (!(*resample_context = avresample_alloc_context())) {
301  fprintf(stderr, "Could not allocate resample context\n");
302  return AVERROR(ENOMEM);
303  }
304 
305  /* Set the conversion parameters.
306  * Default channel layouts based on the number of channels
307  * are assumed for simplicity (they are sometimes not detected
308  * properly by the demuxer and/or decoder).
309  */
310  av_opt_set_int(*resample_context, "in_channel_layout",
311  av_get_default_channel_layout(input_codec_context->channels), 0);
312  av_opt_set_int(*resample_context, "out_channel_layout",
313  av_get_default_channel_layout(output_codec_context->channels), 0);
314  av_opt_set_int(*resample_context, "in_sample_rate",
315  input_codec_context->sample_rate, 0);
316  av_opt_set_int(*resample_context, "out_sample_rate",
317  output_codec_context->sample_rate, 0);
318  av_opt_set_int(*resample_context, "in_sample_fmt",
319  input_codec_context->sample_fmt, 0);
320  av_opt_set_int(*resample_context, "out_sample_fmt",
321  output_codec_context->sample_fmt, 0);
322 
323  /* Open the resampler with the specified parameters. */
324  if ((error = avresample_open(*resample_context)) < 0) {
325  fprintf(stderr, "Could not open resample context\n");
326  avresample_free(resample_context);
327  return error;
328  }
329  }
330  return 0;
331 }
332 
339 static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
340 {
341  /* Create the FIFO buffer based on the specified output sample format. */
342  if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt,
343  output_codec_context->channels, 1))) {
344  fprintf(stderr, "Could not allocate FIFO\n");
345  return AVERROR(ENOMEM);
346  }
347  return 0;
348 }
349 
355 static int write_output_file_header(AVFormatContext *output_format_context)
356 {
357  int error;
358  if ((error = avformat_write_header(output_format_context, NULL)) < 0) {
359  fprintf(stderr, "Could not write output file header (error '%s')\n",
360  get_error_text(error));
361  return error;
362  }
363  return 0;
364 }
365 
379 static int decode_audio_frame(AVFrame *frame,
380  AVFormatContext *input_format_context,
381  AVCodecContext *input_codec_context,
382  int *data_present, int *finished)
383 {
384  /* Packet used for temporary storage. */
385  AVPacket input_packet;
386  int error;
387  init_packet(&input_packet);
388 
389  /* Read one audio frame from the input file into a temporary packet. */
390  if ((error = av_read_frame(input_format_context, &input_packet)) < 0) {
391  /* If we are the the end of the file, flush the decoder below. */
392  if (error == AVERROR_EOF)
393  *finished = 1;
394  else {
395  fprintf(stderr, "Could not read frame (error '%s')\n",
396  get_error_text(error));
397  return error;
398  }
399  }
400 
401  /* Send the audio frame stored in the temporary packet to the decoder.
402  * The input audio stream decoder is used to do this. */
403  if ((error = avcodec_send_packet(input_codec_context, &input_packet)) < 0) {
404  fprintf(stderr, "Could not send packet for decoding (error '%s')\n",
405  get_error_text(error));
406  return error;
407  }
408 
409  /* Receive one frame from the decoder. */
410  error = avcodec_receive_frame(input_codec_context, frame);
411  /* If the decoder asks for more data to be able to decode a frame,
412  * return indicating that no data is present. */
413  if (error == AVERROR(EAGAIN)) {
414  error = 0;
415  goto cleanup;
416  /* If the end of the input file is reached, stop decoding. */
417  } else if (error == AVERROR_EOF) {
418  *finished = 1;
419  error = 0;
420  goto cleanup;
421  } else if (error < 0) {
422  fprintf(stderr, "Could not decode frame (error '%s')\n",
423  get_error_text(error));
424  goto cleanup;
425  /* Default case: Return decoded data. */
426  } else {
427  *data_present = 1;
428  goto cleanup;
429  }
430 
431 cleanup:
432  av_packet_unref(&input_packet);
433  return error;
434 }
435 
448 static int init_converted_samples(uint8_t ***converted_input_samples,
449  AVCodecContext *output_codec_context,
450  int frame_size)
451 {
452  int error;
453 
454  /* Allocate as many pointers as there are audio channels.
455  * Each pointer will later point to the audio samples of the corresponding
456  * channels (although it may be NULL for interleaved formats).
457  */
458  if (!(*converted_input_samples = calloc(output_codec_context->channels,
459  sizeof(**converted_input_samples)))) {
460  fprintf(stderr, "Could not allocate converted input sample pointers\n");
461  return AVERROR(ENOMEM);
462  }
463 
464  /* Allocate memory for the samples of all channels in one consecutive
465  * block for convenience. */
466  if ((error = av_samples_alloc(*converted_input_samples, NULL,
467  output_codec_context->channels,
468  frame_size,
469  output_codec_context->sample_fmt, 0)) < 0) {
470  fprintf(stderr,
471  "Could not allocate converted input samples (error '%s')\n",
472  get_error_text(error));
473  av_freep(&(*converted_input_samples)[0]);
474  free(*converted_input_samples);
475  return error;
476  }
477  return 0;
478 }
479 
492 static int convert_samples(uint8_t **input_data,
493  uint8_t **converted_data, const int frame_size,
494  AVAudioResampleContext *resample_context)
495 {
496  int error;
497 
498  /* Convert the samples using the resampler. */
499  if ((error = avresample_convert(resample_context, converted_data, 0,
500  frame_size, input_data, 0, frame_size)) < 0) {
501  fprintf(stderr, "Could not convert input samples (error '%s')\n",
502  get_error_text(error));
503  return error;
504  }
505 
506  /* Perform a sanity check so that the number of converted samples is
507  * not greater than the number of samples to be converted.
508  * If the sample rates differ, this case has to be handled differently. */
509  if (avresample_available(resample_context)) {
510  fprintf(stderr, "Converted samples left over\n");
511  return AVERROR_EXIT;
512  }
513 
514  return 0;
515 }
516 
526  uint8_t **converted_input_samples,
527  const int frame_size)
528 {
529  int error;
530 
531  /* Make the FIFO as large as it needs to be to hold both,
532  * the old and the new samples. */
533  if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
534  fprintf(stderr, "Could not reallocate FIFO\n");
535  return error;
536  }
537 
538  /* Store the new samples in the FIFO buffer. */
539  if (av_audio_fifo_write(fifo, (void **)converted_input_samples,
540  frame_size) < frame_size) {
541  fprintf(stderr, "Could not write data to FIFO\n");
542  return AVERROR_EXIT;
543  }
544  return 0;
545 }
546 
564  AVFormatContext *input_format_context,
565  AVCodecContext *input_codec_context,
566  AVCodecContext *output_codec_context,
567  AVAudioResampleContext *resample_context,
568  int *finished)
569 {
570  /* Temporary storage of the input samples of the frame read from the file. */
571  AVFrame *input_frame = NULL;
572  /* Temporary storage for the converted input samples. */
573  uint8_t **converted_input_samples = NULL;
574  int data_present = 0;
575  int ret = AVERROR_EXIT;
576 
577  /* Initialize temporary storage for one input frame. */
578  if (init_input_frame(&input_frame))
579  goto cleanup;
580  /* Decode one frame worth of audio samples. */
581  if (decode_audio_frame(input_frame, input_format_context,
582  input_codec_context, &data_present, finished))
583  goto cleanup;
584  /* If we are at the end of the file and there are no more samples
585  * in the decoder which are delayed, we are actually finished.
586  * This must not be treated as an error. */
587  if (*finished) {
588  ret = 0;
589  goto cleanup;
590  }
591  /* If there is decoded data, convert and store it. */
592  if (data_present) {
593  /* Initialize the temporary storage for the converted input samples. */
594  if (init_converted_samples(&converted_input_samples, output_codec_context,
595  input_frame->nb_samples))
596  goto cleanup;
597 
598  /* Convert the input samples to the desired output sample format.
599  * This requires a temporary storage provided by converted_input_samples. */
600  if (convert_samples(input_frame->extended_data, converted_input_samples,
601  input_frame->nb_samples, resample_context))
602  goto cleanup;
603 
604  /* Add the converted input samples to the FIFO buffer for later processing. */
605  if (add_samples_to_fifo(fifo, converted_input_samples,
606  input_frame->nb_samples))
607  goto cleanup;
608  ret = 0;
609  }
610  ret = 0;
611 
612 cleanup:
613  if (converted_input_samples) {
614  av_freep(&converted_input_samples[0]);
615  free(converted_input_samples);
616  }
617  av_frame_free(&input_frame);
618 
619  return ret;
620 }
621 
630 static int init_output_frame(AVFrame **frame,
631  AVCodecContext *output_codec_context,
632  int frame_size)
633 {
634  int error;
635 
636  /* Create a new frame to store the audio samples. */
637  if (!(*frame = av_frame_alloc())) {
638  fprintf(stderr, "Could not allocate output frame\n");
639  return AVERROR_EXIT;
640  }
641 
642  /* Set the frame's parameters, especially its size and format.
643  * av_frame_get_buffer needs this to allocate memory for the
644  * audio samples of the frame.
645  * Default channel layouts based on the number of channels
646  * are assumed for simplicity. */
647  (*frame)->nb_samples = frame_size;
648  (*frame)->channel_layout = output_codec_context->channel_layout;
649  (*frame)->format = output_codec_context->sample_fmt;
650  (*frame)->sample_rate = output_codec_context->sample_rate;
651 
652  /* Allocate the samples of the created frame. This call will make
653  * sure that the audio frame can hold as many samples as specified. */
654  if ((error = av_frame_get_buffer(*frame, 0)) < 0) {
655  fprintf(stderr, "Could not allocate output frame samples (error '%s')\n",
656  get_error_text(error));
657  av_frame_free(frame);
658  return error;
659  }
660 
661  return 0;
662 }
663 
664 /* Global timestamp for the audio frames. */
665 static int64_t pts = 0;
666 
676 static int encode_audio_frame(AVFrame *frame,
677  AVFormatContext *output_format_context,
678  AVCodecContext *output_codec_context,
679  int *data_present)
680 {
681  /* Packet used for temporary storage. */
682  AVPacket output_packet;
683  int error;
684  init_packet(&output_packet);
685 
686  /* Set a timestamp based on the sample rate for the container. */
687  if (frame) {
688  frame->pts = pts;
689  pts += frame->nb_samples;
690  }
691 
692  /* Send the audio frame stored in the temporary packet to the encoder.
693  * The output audio stream encoder is used to do this. */
694  error = avcodec_send_frame(output_codec_context, frame);
695  /* The encoder signals that it has nothing more to encode. */
696  if (error == AVERROR_EOF) {
697  error = 0;
698  goto cleanup;
699  } else if (error < 0) {
700  fprintf(stderr, "Could not send packet for encoding (error '%s')\n",
701  get_error_text(error));
702  return error;
703  }
704 
705  /* Receive one encoded frame from the encoder. */
706  error = avcodec_receive_packet(output_codec_context, &output_packet);
707  /* If the encoder asks for more data to be able to provide an
708  * encoded frame, return indicating that no data is present. */
709  if (error == AVERROR(EAGAIN)) {
710  error = 0;
711  goto cleanup;
712  /* If the last frame has been encoded, stop encoding. */
713  } else if (error == AVERROR_EOF) {
714  error = 0;
715  goto cleanup;
716  } else if (error < 0) {
717  fprintf(stderr, "Could not encode frame (error '%s')\n",
718  get_error_text(error));
719  goto cleanup;
720  /* Default case: Return encoded data. */
721  } else {
722  *data_present = 1;
723  }
724 
725  /* Write one audio frame from the temporary packet to the output file. */
726  if (*data_present &&
727  (error = av_write_frame(output_format_context, &output_packet)) < 0) {
728  fprintf(stderr, "Could not write frame (error '%s')\n",
729  get_error_text(error));
730  goto cleanup;
731  }
732 
733 cleanup:
734  av_packet_unref(&output_packet);
735  return error;
736 }
737 
747  AVFormatContext *output_format_context,
748  AVCodecContext *output_codec_context)
749 {
750  /* Temporary storage of the output samples of the frame written to the file. */
751  AVFrame *output_frame;
752  /* Use the maximum number of possible samples per frame.
753  * If there is less than the maximum possible frame size in the FIFO
754  * buffer use this number. Otherwise, use the maximum possible frame size. */
755  const int frame_size = FFMIN(av_audio_fifo_size(fifo),
756  output_codec_context->frame_size);
757  int data_written;
758 
759  /* Initialize temporary storage for one output frame. */
760  if (init_output_frame(&output_frame, output_codec_context, frame_size))
761  return AVERROR_EXIT;
762 
763  /* Read as many samples from the FIFO buffer as required to fill the frame.
764  * The samples are stored in the frame temporarily. */
765  if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) {
766  fprintf(stderr, "Could not read data from FIFO\n");
767  av_frame_free(&output_frame);
768  return AVERROR_EXIT;
769  }
770 
771  /* Encode one frame worth of audio samples. */
772  if (encode_audio_frame(output_frame, output_format_context,
773  output_codec_context, &data_written)) {
774  av_frame_free(&output_frame);
775  return AVERROR_EXIT;
776  }
777  av_frame_free(&output_frame);
778  return 0;
779 }
780 
786 static int write_output_file_trailer(AVFormatContext *output_format_context)
787 {
788  int error;
789  if ((error = av_write_trailer(output_format_context)) < 0) {
790  fprintf(stderr, "Could not write output file trailer (error '%s')\n",
791  get_error_text(error));
792  return error;
793  }
794  return 0;
795 }
796 
797 int main(int argc, char **argv)
798 {
799  AVFormatContext *input_format_context = NULL, *output_format_context = NULL;
800  AVCodecContext *input_codec_context = NULL, *output_codec_context = NULL;
801  AVAudioResampleContext *resample_context = NULL;
802  AVAudioFifo *fifo = NULL;
803  int ret = AVERROR_EXIT;
804 
805  if (argc != 3) {
806  fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);
807  exit(1);
808  }
809 
810  /* Register all codecs and formats so that they can be used. */
811  av_register_all();
812  /* Open the input file for reading. */
813  if (open_input_file(argv[1], &input_format_context,
814  &input_codec_context))
815  goto cleanup;
816  /* Open the output file for writing. */
817  if (open_output_file(argv[2], input_codec_context,
818  &output_format_context, &output_codec_context))
819  goto cleanup;
820  /* Initialize the resampler to be able to convert audio sample formats. */
821  if (init_resampler(input_codec_context, output_codec_context,
822  &resample_context))
823  goto cleanup;
824  /* Initialize the FIFO buffer to store audio samples to be encoded. */
825  if (init_fifo(&fifo, output_codec_context))
826  goto cleanup;
827  /* Write the header of the output file container. */
828  if (write_output_file_header(output_format_context))
829  goto cleanup;
830 
831  /* Loop as long as we have input samples to read or output samples
832  * to write; abort as soon as we have neither. */
833  while (1) {
834  /* Use the encoder's desired frame size for processing. */
835  const int output_frame_size = output_codec_context->frame_size;
836  int finished = 0;
837 
838  /* Make sure that there is one frame worth of samples in the FIFO
839  * buffer so that the encoder can do its work.
840  * Since the decoder's and the encoder's frame size may differ, we
841  * need to FIFO buffer to store as many frames worth of input samples
842  * that they make up at least one frame worth of output samples. */
843  while (av_audio_fifo_size(fifo) < output_frame_size) {
844  /* Decode one frame worth of audio samples, convert it to the
845  * output sample format and put it into the FIFO buffer. */
846  if (read_decode_convert_and_store(fifo, input_format_context,
847  input_codec_context,
848  output_codec_context,
849  resample_context, &finished))
850  goto cleanup;
851 
852  /* If we are at the end of the input file, we continue
853  * encoding the remaining audio samples to the output file. */
854  if (finished)
855  break;
856  }
857 
858  /* If we have enough samples for the encoder, we encode them.
859  * At the end of the file, we pass the remaining samples to
860  * the encoder. */
861  while (av_audio_fifo_size(fifo) >= output_frame_size ||
862  (finished && av_audio_fifo_size(fifo) > 0))
863  /* Take one frame worth of audio samples from the FIFO buffer,
864  * encode it and write it to the output file. */
865  if (load_encode_and_write(fifo, output_format_context,
866  output_codec_context))
867  goto cleanup;
868 
869  /* If we are at the end of the input file and have encoded
870  * all remaining samples, we can exit this loop and finish. */
871  if (finished) {
872  int data_written;
873  /* Flush the encoder as it may have delayed frames. */
874  do {
875  data_written = 0;
876  if (encode_audio_frame(NULL, output_format_context,
877  output_codec_context, &data_written))
878  goto cleanup;
879  } while (data_written);
880  break;
881  }
882  }
883 
884  /* Write the trailer of the output file container. */
885  if (write_output_file_trailer(output_format_context))
886  goto cleanup;
887  ret = 0;
888 
889 cleanup:
890  if (fifo)
891  av_audio_fifo_free(fifo);
892  if (resample_context) {
893  avresample_close(resample_context);
894  avresample_free(&resample_context);
895  }
896  if (output_codec_context)
897  avcodec_free_context(&output_codec_context);
898  if (output_format_context) {
899  avio_close(output_format_context->pb);
900  avformat_free_context(output_format_context);
901  }
902  if (input_codec_context)
903  avcodec_free_context(&input_codec_context);
904  if (input_format_context)
905  avformat_close_input(&input_format_context);
906 
907  return ret;
908 }
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition: avcodec.h:2255
uint64_t av_get_default_channel_layout(int nb_channels)
Return default channel layout for a given number of channels.
Bytestream IO Context.
Definition: avio.h:111
AVAudioFifo * av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, int nb_samples)
Allocate an AVAudioFifo.
Buffered I/O operations.
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
Read data from an AVAudioFifo.
This structure describes decoded (raw) audio or video data.
Definition: frame.h:147
AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
int main(int argc, char **argv)
int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
int avresample_convert(AVAudioResampleContext *avr, uint8_t **output, int out_plane_size, int out_samples, uint8_t *const *input, int in_plane_size, int in_samples)
Convert input samples and write them to the output FIFO.
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Read encoded data from the encoder.
void av_audio_fifo_free(AVAudioFifo *af)
Free an AVAudioFifo.
int num
numerator
Definition: rational.h:44
int size
Definition: avcodec.h:1154
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:394
AVCodec.
Definition: avcodec.h:2842
static void init_packet(AVPacket *packet)
Initialize one data packet for reading or writing.
void avresample_free(AVAudioResampleContext **avr)
Free AVAudioResampleContext and associated AVOption values.
void av_freep(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
static int open_input_file(const char *filename, AVFormatContext **input_format_context, AVCodecContext **input_codec_context)
Open an input file and the required decoder.
Definition: transcode_aac.c:69
Format I/O context.
Definition: avformat.h:920
static int encode_audio_frame(AVFrame *frame, AVFormatContext *output_format_context, AVCodecContext *output_codec_context, int *data_present)
Encode one frame worth of audio to the output file.
static int read_decode_convert_and_store(AVAudioFifo *fifo, AVFormatContext *input_format_context, AVCodecContext *input_codec_context, AVCodecContext *output_codec_context, AVAudioResampleContext *resample_context, int *finished)
Read one audio frame from the input file, decode, convert and store it in the FIFO buffer...
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1860
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:227
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Fill the codec context based on the values from the supplied codec parameters.
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
uint8_t * data
Definition: avcodec.h:1153
#define AVERROR_EOF
End of file.
Definition: error.h:51
static int init_input_frame(AVFrame **frame)
Initialize one audio frame for reading from the input file.
void avresample_close(AVAudioResampleContext *avr)
Close AVAudioResampleContext.
static int write_output_file_header(AVFormatContext *output_format_context)
Write the header of the output file container.
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Return decoded output data from a decoder.
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:1295
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
struct AVAudioFifo AVAudioFifo
Context for an Audio FIFO Buffer.
Definition: audio_fifo.h:49
static int load_encode_and_write(AVAudioFifo *fifo, AVFormatContext *output_format_context, AVCodecContext *output_codec_context)
Load one audio frame from the FIFO buffer, encode and write it to the output file.
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
reference-counted frame API
uint64_t channel_layout
Audio channel layout.
Definition: avcodec.h:1903
int av_audio_fifo_size(AVAudioFifo *af)
Get the current number of samples in the AVAudioFifo available for reading.
int bit_rate
the average bitrate
Definition: avcodec.h:1265
external API header
#define FFMIN(a, b)
Definition: common.h:66
static int open_output_file(const char *filename, AVCodecContext *input_codec_context, AVFormatContext **output_format_context, AVCodecContext **output_codec_context)
Open an output file and the required encoder.
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
static int decode_audio_frame(AVFrame *frame, AVFormatContext *input_format_context, AVCodecContext *input_codec_context, int *data_present, int *finished)
Decode one audio frame from the input file.
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:407
AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
static int add_samples_to_fifo(AVAudioFifo *fifo, uint8_t **converted_input_samples, const int frame_size)
Add converted input audio samples to the FIFO buffer for later processing.
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:52
Stream structure.
Definition: avformat.h:693
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
int frame_size
Number of samples per channel in an audio frame.
Definition: avcodec.h:1872
int avresample_available(AVAudioResampleContext *avr)
Return the number of available samples in the output FIFO.
int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)
Allocate a samples buffer for nb_samples samples, and fill data pointers and linesize accordingly...
static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
Initialize a FIFO buffer for the audio samples to be encoded.
Libavcodec external API header.
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer...
#define OUTPUT_BIT_RATE
Definition: transcode_aac.c:46
int sample_rate
samples per second
Definition: avcodec.h:1852
struct AVAudioResampleContext AVAudioResampleContext
Definition: avresample.h:106
main external API structure.
Definition: avcodec.h:1216
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Supply a raw video or audio frame to the encoder.
static int convert_samples(uint8_t **input_data, uint8_t **converted_data, const int frame_size, AVAudioResampleContext *resample_context)
Convert the input audio samples into the output sample format.
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Fill the parameters struct based on the values from the supplied codec context.
static int init_resampler(AVCodecContext *input_codec_context, AVCodecContext *output_codec_context, AVAudioResampleContext **resample_context)
Initialize the audio resampler based on the input and output codec settings.
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
static int64_t pts
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:153
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
#define OUTPUT_CHANNELS
Definition: transcode_aac.c:48
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: avcodec.h:762
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
Reallocate an AVAudioFifo.
AVAudioResampleContext * avresample_alloc_context(void)
Allocate AVAudioResampleContext and set options.
Main libavformat public API header.
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
static int write_output_file_trailer(AVFormatContext *output_format_context)
Write the trailer of the output file container.
static char * get_error_text(const int error)
Convert an error code into a text message.
Definition: transcode_aac.c:55
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
int den
denominator
Definition: rational.h:45
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Audio FIFO Buffer.
int channels
number of audio channels
Definition: avcodec.h:1853
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
static int init_converted_samples(uint8_t ***converted_input_samples, AVCodecContext *output_codec_context, int frame_size)
Initialize a temporary storage for the specified number of audio samples.
AVCodecParameters * codecpar
Definition: avformat.h:811
enum AVSampleFormat * sample_fmts
array of supported sample formats, or NULL if unknown, array is terminated by -1
Definition: avcodec.h:2865
static int init_output_frame(AVFrame **frame, AVCodecContext *output_codec_context, int frame_size)
Initialize one input frame for writing to the output file.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:722
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:181
This structure stores compressed data.
Definition: avcodec.h:1130
void av_register_all(void)
Initialize libavformat and register all the muxers, demuxers and protocols.
int avresample_open(AVAudioResampleContext *avr)
Initialize AVAudioResampleContext.
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:200
int strict_std_compliance
strictly follow the standard (MPEG-4, ...).
Definition: avcodec.h:2250