2 * Copyright (c) 2015 Ludmila Glinskih
3 * Copyright (c) 2001 Fabrice Bellard
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * Encodes raw data to FLAC format and decodes it back to raw. Compares raw-data
30 #include "libavcodec/avcodec.h"
31 #include "libavutil/channel_layout.h"
32 #include "libavutil/common.h"
33 #include "libavutil/mem.h"
34 #include "libavutil/samplefmt.h"
36 #define NUMBER_OF_AUDIO_FRAMES 200
37 #define NAME_BUFF_SIZE 100
39 /* generate i-th frame of test audio */
40 static int generate_raw_frame(uint16_t *frame_data
, int i
, int sample_rate
,
41 int channels
, int frame_size
)
45 for (j
= 0; j
< frame_size
; j
++) {
46 frame_data
[channels
* j
] = 10000 * ((j
/ 10 * i
) % 2);
47 for (k
= 1; k
< channels
; k
++)
48 frame_data
[channels
* j
+ k
] = frame_data
[channels
* j
] * (k
+ 1);
53 static int init_encoder(const AVCodec
*enc
, AVCodecContext
**enc_ctx
,
54 const AVChannelLayout
*ch_layout
, int sample_rate
)
58 char name_buff
[NAME_BUFF_SIZE
];
60 av_channel_layout_describe(ch_layout
, name_buff
, NAME_BUFF_SIZE
);
61 av_log(NULL
, AV_LOG_INFO
, "channel layout: %s, sample rate: %i\n", name_buff
, sample_rate
);
63 ctx
= avcodec_alloc_context3(enc
);
65 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate encoder context\n");
66 return AVERROR(ENOMEM
);
69 ctx
->sample_fmt
= AV_SAMPLE_FMT_S16
;
70 ctx
->sample_rate
= sample_rate
;
71 av_channel_layout_copy(&ctx
->ch_layout
, ch_layout
);
73 result
= avcodec_open2(ctx
, enc
, NULL
);
75 av_log(ctx
, AV_LOG_ERROR
, "Can't open encoder\n");
83 static int init_decoder(const AVCodec
*dec
, AVCodecContext
**dec_ctx
,
84 const AVChannelLayout
*ch_layout
)
89 ctx
= avcodec_alloc_context3(dec
);
91 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate decoder context\n");
92 return AVERROR(ENOMEM
);
95 ctx
->request_sample_fmt
= AV_SAMPLE_FMT_S16
;
96 av_channel_layout_copy(&ctx
->ch_layout
, ch_layout
);
98 result
= avcodec_open2(ctx
, dec
, NULL
);
100 av_log(ctx
, AV_LOG_ERROR
, "Can't open decoder\n");
108 static int run_test(const AVCodec
*enc
, const AVCodec
*dec
,
109 AVCodecContext
*enc_ctx
, AVCodecContext
*dec_ctx
)
112 AVFrame
*in_frame
, *out_frame
;
113 uint8_t *raw_in
= NULL
, *raw_out
= NULL
;
114 int in_offset
= 0, out_offset
= 0;
117 int in_frame_bytes
, out_frame_bytes
;
119 enc_pkt
= av_packet_alloc();
121 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate output packet\n");
122 return AVERROR(ENOMEM
);
125 in_frame
= av_frame_alloc();
127 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate input frame\n");
128 return AVERROR(ENOMEM
);
131 in_frame
->nb_samples
= enc_ctx
->frame_size
;
132 in_frame
->format
= enc_ctx
->sample_fmt
;
133 result
= av_channel_layout_copy(&in_frame
->ch_layout
, &enc_ctx
->ch_layout
);
136 if (av_frame_get_buffer(in_frame
, 0) != 0) {
137 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate a buffer for input frame\n");
138 return AVERROR(ENOMEM
);
141 out_frame
= av_frame_alloc();
143 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate output frame\n");
144 return AVERROR(ENOMEM
);
147 raw_in
= av_malloc(in_frame
->linesize
[0] * NUMBER_OF_AUDIO_FRAMES
);
149 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate memory for raw_in\n");
150 return AVERROR(ENOMEM
);
153 raw_out
= av_malloc(in_frame
->linesize
[0] * NUMBER_OF_AUDIO_FRAMES
);
155 av_log(NULL
, AV_LOG_ERROR
, "Can't allocate memory for raw_out\n");
156 return AVERROR(ENOMEM
);
159 for (i
= 0; i
< NUMBER_OF_AUDIO_FRAMES
; i
++) {
160 result
= av_frame_make_writable(in_frame
);
164 generate_raw_frame((uint16_t*)(in_frame
->data
[0]), i
, enc_ctx
->sample_rate
,
165 enc_ctx
->ch_layout
.nb_channels
, enc_ctx
->frame_size
);
166 in_frame_bytes
= in_frame
->nb_samples
* in_frame
->ch_layout
.nb_channels
* sizeof(uint16_t);
167 if (in_frame_bytes
> in_frame
->linesize
[0]) {
168 av_log(NULL
, AV_LOG_ERROR
, "Incorrect value of input frame linesize\n");
171 memcpy(raw_in
+ in_offset
, in_frame
->data
[0], in_frame_bytes
);
172 in_offset
+= in_frame_bytes
;
173 result
= avcodec_send_frame(enc_ctx
, in_frame
);
175 av_log(NULL
, AV_LOG_ERROR
, "Error submitting a frame for encoding\n");
179 while (result
>= 0) {
180 result
= avcodec_receive_packet(enc_ctx
, enc_pkt
);
181 if (result
== AVERROR(EAGAIN
))
183 else if (result
< 0 && result
!= AVERROR_EOF
) {
184 av_log(NULL
, AV_LOG_ERROR
, "Error encoding audio frame\n");
188 /* if we get an encoded packet, feed it straight to the decoder */
189 result
= avcodec_send_packet(dec_ctx
, enc_pkt
);
190 av_packet_unref(enc_pkt
);
192 av_log(NULL
, AV_LOG_ERROR
, "Error submitting a packet for decoding\n");
196 result
= avcodec_receive_frame(dec_ctx
, out_frame
);
197 if (result
== AVERROR(EAGAIN
)) {
200 } else if (result
== AVERROR(EOF
)) {
203 } else if (result
< 0) {
204 av_log(NULL
, AV_LOG_ERROR
, "Error decoding audio packet\n");
208 if (in_frame
->nb_samples
!= out_frame
->nb_samples
) {
209 av_log(NULL
, AV_LOG_ERROR
, "Error frames before and after decoding has different number of samples\n");
210 return AVERROR_UNKNOWN
;
213 if (av_channel_layout_compare(&in_frame
->ch_layout
, &out_frame
->ch_layout
)) {
214 av_log(NULL
, AV_LOG_ERROR
, "Error frames before and after decoding has different channel layout\n");
215 return AVERROR_UNKNOWN
;
218 if (in_frame
->format
!= out_frame
->format
) {
219 av_log(NULL
, AV_LOG_ERROR
, "Error frames before and after decoding has different sample format\n");
220 return AVERROR_UNKNOWN
;
222 out_frame_bytes
= out_frame
->nb_samples
* out_frame
->ch_layout
.nb_channels
* sizeof(uint16_t);
223 if (out_frame_bytes
> out_frame
->linesize
[0]) {
224 av_log(NULL
, AV_LOG_ERROR
, "Incorrect value of output frame linesize\n");
227 memcpy(raw_out
+ out_offset
, out_frame
->data
[0], out_frame_bytes
);
228 out_offset
+= out_frame_bytes
;
232 if (memcmp(raw_in
, raw_out
, out_frame_bytes
* NUMBER_OF_AUDIO_FRAMES
) != 0) {
233 av_log(NULL
, AV_LOG_ERROR
, "Output differs\n");
237 av_log(NULL
, AV_LOG_INFO
, "OK\n");
241 av_packet_free(&enc_pkt
);
242 av_frame_free(&in_frame
);
243 av_frame_free(&out_frame
);
249 const AVCodec
*enc
= NULL
, *dec
= NULL
;
250 AVCodecContext
*enc_ctx
= NULL
, *dec_ctx
= NULL
;
251 const AVChannelLayout channel_layouts
[] = { AV_CHANNEL_LAYOUT_STEREO
,
252 AV_CHANNEL_LAYOUT_5POINT1_BACK
,
253 AV_CHANNEL_LAYOUT_SURROUND
,
254 AV_CHANNEL_LAYOUT_STEREO_DOWNMIX
};
255 int sample_rates
[] = {8000, 44100, 48000, 192000};
258 enc
= avcodec_find_encoder(AV_CODEC_ID_FLAC
);
260 av_log(NULL
, AV_LOG_ERROR
, "Can't find encoder\n");
264 dec
= avcodec_find_decoder(AV_CODEC_ID_FLAC
);
266 av_log(NULL
, AV_LOG_ERROR
, "Can't find decoder\n");
270 for (cl
= 0; cl
< FF_ARRAY_ELEMS(channel_layouts
); cl
++) {
271 for (sr
= 0; sr
< FF_ARRAY_ELEMS(sample_rates
); sr
++) {
272 if (init_encoder(enc
, &enc_ctx
, &channel_layouts
[cl
], sample_rates
[sr
]) != 0)
274 if (init_decoder(dec
, &dec_ctx
, &channel_layouts
[cl
]) != 0)
276 if (run_test(enc
, dec
, enc_ctx
, dec_ctx
) != 0)
278 avcodec_free_context(&enc_ctx
);
279 avcodec_free_context(&dec_ctx
);