| 1 | #include <stdio.h>
|
|---|
| 2 | #include <stddef.h>
|
|---|
| 3 | #include <stdint.h>
|
|---|
| 4 | #include <string.h>
|
|---|
| 5 | #include <errno.h>
|
|---|
| 6 | #include <libavcodec/avcodec.h>
|
|---|
| 7 | #include <libavutil/samplefmt.h>
|
|---|
| 8 | #include <libavutil/channel_layout.h>
|
|---|
| 9 | #include <libavutil/avutil.h>
|
|---|
| 10 | #include <libavutil/frame.h>
|
|---|
| 11 |
|
|---|
| 12 | int main()
|
|---|
| 13 | {
|
|---|
| 14 | AVCodec *codec = NULL;
|
|---|
| 15 | AVCodecContext *ctx = NULL;
|
|---|
| 16 | AVFrame frame = {};
|
|---|
| 17 | AVPacket packet = {};
|
|---|
| 18 | size_t sample_size = 0;
|
|---|
| 19 | int64_t in_pts = 0;
|
|---|
| 20 | int res, final_result = -1;
|
|---|
| 21 |
|
|---|
| 22 | /* First, see if ffmpeg was built with libfdk-aac. It provides better quality. */
|
|---|
| 23 | codec = avcodec_find_encoder_by_name("libfdk_aac");
|
|---|
| 24 | if (!codec)
|
|---|
| 25 | {
|
|---|
| 26 | puts("Failed to find encoder");
|
|---|
| 27 | return -1;
|
|---|
| 28 | }
|
|---|
| 29 |
|
|---|
| 30 | ctx = avcodec_alloc_context3(codec);
|
|---|
| 31 | if (!ctx)
|
|---|
| 32 | {
|
|---|
| 33 | puts("Failed to allocate encoder context");
|
|---|
| 34 | return -1;
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
|---|
| 38 |
|
|---|
| 39 | ctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
|---|
| 40 | ctx->sample_rate = 48000;
|
|---|
| 41 | ctx->channels = 1;
|
|---|
| 42 | ctx->channel_layout = AV_CH_LAYOUT_MONO;
|
|---|
| 43 |
|
|---|
| 44 | ctx->time_base.num = 1;
|
|---|
| 45 | ctx->time_base.den = ctx->sample_rate;
|
|---|
| 46 |
|
|---|
| 47 | ctx->bit_rate = 320000;
|
|---|
| 48 |
|
|---|
| 49 | ctx->profile = FF_PROFILE_AAC_LOW;
|
|---|
| 50 |
|
|---|
| 51 | res = avcodec_open2(ctx, codec, (AVDictionary **)NULL);
|
|---|
| 52 | if (res < 0)
|
|---|
| 53 | {
|
|---|
| 54 | puts("Failed to open encoder context");
|
|---|
| 55 | goto finish;
|
|---|
| 56 | }
|
|---|
| 57 |
|
|---|
| 58 | av_frame_unref(&frame);
|
|---|
| 59 | av_init_packet(&packet);
|
|---|
| 60 |
|
|---|
| 61 | frame.format = ctx->sample_fmt;
|
|---|
| 62 | frame.sample_rate = ctx->sample_rate;
|
|---|
| 63 | frame.channel_layout = ctx->channel_layout;
|
|---|
| 64 | frame.channels = ctx->channels;
|
|---|
| 65 |
|
|---|
| 66 | sample_size = av_get_bytes_per_sample(ctx->sample_fmt);
|
|---|
| 67 |
|
|---|
| 68 | frame.nb_samples = ctx->frame_size;
|
|---|
| 69 |
|
|---|
| 70 | res = av_frame_get_buffer(&frame, 0);
|
|---|
| 71 | if (res < 0)
|
|---|
| 72 | {
|
|---|
| 73 | puts("Failed to allocate input frame");
|
|---|
| 74 | goto finish;
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | memset(frame.data[0], 0, sample_size * frame.nb_samples);
|
|---|
| 78 |
|
|---|
| 79 | for (unsigned int i = 0; i < 5; ++i)
|
|---|
| 80 | {
|
|---|
| 81 | frame.pts = in_pts;
|
|---|
| 82 | printf("Input pts: %lld", (long long)in_pts);
|
|---|
| 83 |
|
|---|
| 84 | in_pts += frame.nb_samples;
|
|---|
| 85 |
|
|---|
| 86 | res = avcodec_send_frame(ctx, &frame);
|
|---|
| 87 | if (res < 0)
|
|---|
| 88 | {
|
|---|
| 89 | puts("Failed to send input frame to the encoder");
|
|---|
| 90 | goto finish;
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 | res = avcodec_receive_packet(ctx, &packet);
|
|---|
| 94 | if (res < 0)
|
|---|
| 95 | {
|
|---|
| 96 | if (res != AVERROR(EAGAIN))
|
|---|
| 97 | {
|
|---|
| 98 | puts("Failed to receive encoded frame from the encoder");
|
|---|
| 99 | goto finish;
|
|---|
| 100 | }
|
|---|
| 101 |
|
|---|
| 102 | printf(", output pts: -");
|
|---|
| 103 | }
|
|---|
| 104 | else
|
|---|
| 105 | {
|
|---|
| 106 | printf(", output pts: %lld", (long long)packet.pts);
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | printf("\n");
|
|---|
| 110 | }
|
|---|
| 111 |
|
|---|
| 112 | final_result = 0;
|
|---|
| 113 |
|
|---|
| 114 | finish:
|
|---|
| 115 | av_frame_unref(&frame);
|
|---|
| 116 | av_packet_unref(&packet);
|
|---|
| 117 | avcodec_free_context(&ctx);
|
|---|
| 118 |
|
|---|
| 119 | return final_result;
|
|---|
| 120 | }
|
|---|