1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2015 Ludmila Glinskih 3cabdff1aSopenharmony_ci * Copyright (c) 2001 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 6cabdff1aSopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 7cabdff1aSopenharmony_ci * in the Software without restriction, including without limitation the rights 8cabdff1aSopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9cabdff1aSopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 10cabdff1aSopenharmony_ci * furnished to do so, subject to the following conditions: 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * The above copyright notice and this permission notice shall be included in 13cabdff1aSopenharmony_ci * all copies or substantial portions of the Software. 14cabdff1aSopenharmony_ci * 15cabdff1aSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16cabdff1aSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17cabdff1aSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18cabdff1aSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19cabdff1aSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20cabdff1aSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21cabdff1aSopenharmony_ci * THE SOFTWARE. 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci/* 25cabdff1aSopenharmony_ci * FLAC codec test. 26cabdff1aSopenharmony_ci * Encodes raw data to FLAC format and decodes it back to raw. Compares raw-data 27cabdff1aSopenharmony_ci * after that. 28cabdff1aSopenharmony_ci */ 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavcodec/avcodec.h" 31cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 32cabdff1aSopenharmony_ci#include "libavutil/common.h" 33cabdff1aSopenharmony_ci#include "libavutil/samplefmt.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci#define NUMBER_OF_AUDIO_FRAMES 200 36cabdff1aSopenharmony_ci#define NAME_BUFF_SIZE 100 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci/* generate i-th frame of test audio */ 39cabdff1aSopenharmony_cistatic int generate_raw_frame(uint16_t *frame_data, int i, int sample_rate, 40cabdff1aSopenharmony_ci int channels, int frame_size) 41cabdff1aSopenharmony_ci{ 42cabdff1aSopenharmony_ci int j, k; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci for (j = 0; j < frame_size; j++) { 45cabdff1aSopenharmony_ci frame_data[channels * j] = 10000 * ((j / 10 * i) % 2); 46cabdff1aSopenharmony_ci for (k = 1; k < channels; k++) 47cabdff1aSopenharmony_ci frame_data[channels * j + k] = frame_data[channels * j] * (k + 1); 48cabdff1aSopenharmony_ci } 49cabdff1aSopenharmony_ci return 0; 50cabdff1aSopenharmony_ci} 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_cistatic int init_encoder(const AVCodec *enc, AVCodecContext **enc_ctx, 53cabdff1aSopenharmony_ci const AVChannelLayout *ch_layout, int sample_rate) 54cabdff1aSopenharmony_ci{ 55cabdff1aSopenharmony_ci AVCodecContext *ctx; 56cabdff1aSopenharmony_ci int result; 57cabdff1aSopenharmony_ci char name_buff[NAME_BUFF_SIZE]; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci av_channel_layout_describe(ch_layout, name_buff, NAME_BUFF_SIZE); 60cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_INFO, "channel layout: %s, sample rate: %i\n", name_buff, sample_rate); 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci ctx = avcodec_alloc_context3(enc); 63cabdff1aSopenharmony_ci if (!ctx) { 64cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate encoder context\n"); 65cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 66cabdff1aSopenharmony_ci } 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci ctx->sample_fmt = AV_SAMPLE_FMT_S16; 69cabdff1aSopenharmony_ci ctx->sample_rate = sample_rate; 70cabdff1aSopenharmony_ci av_channel_layout_copy(&ctx->ch_layout, ch_layout); 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci result = avcodec_open2(ctx, enc, NULL); 73cabdff1aSopenharmony_ci if (result < 0) { 74cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Can't open encoder\n"); 75cabdff1aSopenharmony_ci return result; 76cabdff1aSopenharmony_ci } 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci *enc_ctx = ctx; 79cabdff1aSopenharmony_ci return 0; 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cistatic int init_decoder(const AVCodec *dec, AVCodecContext **dec_ctx, 83cabdff1aSopenharmony_ci const AVChannelLayout *ch_layout) 84cabdff1aSopenharmony_ci{ 85cabdff1aSopenharmony_ci AVCodecContext *ctx; 86cabdff1aSopenharmony_ci int result; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci ctx = avcodec_alloc_context3(dec); 89cabdff1aSopenharmony_ci if (!ctx) { 90cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR , "Can't allocate decoder context\n"); 91cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci ctx->request_sample_fmt = AV_SAMPLE_FMT_S16; 95cabdff1aSopenharmony_ci av_channel_layout_copy(&ctx->ch_layout, ch_layout); 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci result = avcodec_open2(ctx, dec, NULL); 98cabdff1aSopenharmony_ci if (result < 0) { 99cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Can't open decoder\n"); 100cabdff1aSopenharmony_ci return result; 101cabdff1aSopenharmony_ci } 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci *dec_ctx = ctx; 104cabdff1aSopenharmony_ci return 0; 105cabdff1aSopenharmony_ci} 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_cistatic int run_test(const AVCodec *enc, const AVCodec *dec, 108cabdff1aSopenharmony_ci AVCodecContext *enc_ctx, AVCodecContext *dec_ctx) 109cabdff1aSopenharmony_ci{ 110cabdff1aSopenharmony_ci AVPacket *enc_pkt; 111cabdff1aSopenharmony_ci AVFrame *in_frame, *out_frame; 112cabdff1aSopenharmony_ci uint8_t *raw_in = NULL, *raw_out = NULL; 113cabdff1aSopenharmony_ci int in_offset = 0, out_offset = 0; 114cabdff1aSopenharmony_ci int result = 0; 115cabdff1aSopenharmony_ci int i = 0; 116cabdff1aSopenharmony_ci int in_frame_bytes, out_frame_bytes; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci enc_pkt = av_packet_alloc(); 119cabdff1aSopenharmony_ci if (!enc_pkt) { 120cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate output packet\n"); 121cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci in_frame = av_frame_alloc(); 125cabdff1aSopenharmony_ci if (!in_frame) { 126cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate input frame\n"); 127cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 128cabdff1aSopenharmony_ci } 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci in_frame->nb_samples = enc_ctx->frame_size; 131cabdff1aSopenharmony_ci in_frame->format = enc_ctx->sample_fmt; 132cabdff1aSopenharmony_ci result = av_channel_layout_copy(&in_frame->ch_layout, &enc_ctx->ch_layout); 133cabdff1aSopenharmony_ci if (result < 0) 134cabdff1aSopenharmony_ci return result; 135cabdff1aSopenharmony_ci if (av_frame_get_buffer(in_frame, 0) != 0) { 136cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate a buffer for input frame\n"); 137cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci out_frame = av_frame_alloc(); 141cabdff1aSopenharmony_ci if (!out_frame) { 142cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate output frame\n"); 143cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci raw_in = av_malloc(in_frame->linesize[0] * NUMBER_OF_AUDIO_FRAMES); 147cabdff1aSopenharmony_ci if (!raw_in) { 148cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for raw_in\n"); 149cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci raw_out = av_malloc(in_frame->linesize[0] * NUMBER_OF_AUDIO_FRAMES); 153cabdff1aSopenharmony_ci if (!raw_out) { 154cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for raw_out\n"); 155cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 156cabdff1aSopenharmony_ci } 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci for (i = 0; i < NUMBER_OF_AUDIO_FRAMES; i++) { 159cabdff1aSopenharmony_ci result = av_frame_make_writable(in_frame); 160cabdff1aSopenharmony_ci if (result < 0) 161cabdff1aSopenharmony_ci return result; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci generate_raw_frame((uint16_t*)(in_frame->data[0]), i, enc_ctx->sample_rate, 164cabdff1aSopenharmony_ci enc_ctx->ch_layout.nb_channels, enc_ctx->frame_size); 165cabdff1aSopenharmony_ci in_frame_bytes = in_frame->nb_samples * in_frame->ch_layout.nb_channels * sizeof(uint16_t); 166cabdff1aSopenharmony_ci if (in_frame_bytes > in_frame->linesize[0]) { 167cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Incorrect value of input frame linesize\n"); 168cabdff1aSopenharmony_ci return 1; 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci memcpy(raw_in + in_offset, in_frame->data[0], in_frame_bytes); 171cabdff1aSopenharmony_ci in_offset += in_frame_bytes; 172cabdff1aSopenharmony_ci result = avcodec_send_frame(enc_ctx, in_frame); 173cabdff1aSopenharmony_ci if (result < 0) { 174cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error submitting a frame for encoding\n"); 175cabdff1aSopenharmony_ci return result; 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci while (result >= 0) { 179cabdff1aSopenharmony_ci result = avcodec_receive_packet(enc_ctx, enc_pkt); 180cabdff1aSopenharmony_ci if (result == AVERROR(EAGAIN)) 181cabdff1aSopenharmony_ci break; 182cabdff1aSopenharmony_ci else if (result < 0 && result != AVERROR_EOF) { 183cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error encoding audio frame\n"); 184cabdff1aSopenharmony_ci return result; 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci /* if we get an encoded packet, feed it straight to the decoder */ 188cabdff1aSopenharmony_ci result = avcodec_send_packet(dec_ctx, enc_pkt); 189cabdff1aSopenharmony_ci av_packet_unref(enc_pkt); 190cabdff1aSopenharmony_ci if (result < 0) { 191cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); 192cabdff1aSopenharmony_ci return result; 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci result = avcodec_receive_frame(dec_ctx, out_frame); 196cabdff1aSopenharmony_ci if (result == AVERROR(EAGAIN)) { 197cabdff1aSopenharmony_ci result = 0; 198cabdff1aSopenharmony_ci continue; 199cabdff1aSopenharmony_ci } else if (result == AVERROR(EOF)) { 200cabdff1aSopenharmony_ci result = 0; 201cabdff1aSopenharmony_ci break; 202cabdff1aSopenharmony_ci } else if (result < 0) { 203cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error decoding audio packet\n"); 204cabdff1aSopenharmony_ci return result; 205cabdff1aSopenharmony_ci } 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci if (in_frame->nb_samples != out_frame->nb_samples) { 208cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different number of samples\n"); 209cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci if (av_channel_layout_compare(&in_frame->ch_layout, &out_frame->ch_layout)) { 213cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different channel layout\n"); 214cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 215cabdff1aSopenharmony_ci } 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci if (in_frame->format != out_frame->format) { 218cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different sample format\n"); 219cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 220cabdff1aSopenharmony_ci } 221cabdff1aSopenharmony_ci out_frame_bytes = out_frame->nb_samples * out_frame->ch_layout.nb_channels * sizeof(uint16_t); 222cabdff1aSopenharmony_ci if (out_frame_bytes > out_frame->linesize[0]) { 223cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Incorrect value of output frame linesize\n"); 224cabdff1aSopenharmony_ci return 1; 225cabdff1aSopenharmony_ci } 226cabdff1aSopenharmony_ci memcpy(raw_out + out_offset, out_frame->data[0], out_frame_bytes); 227cabdff1aSopenharmony_ci out_offset += out_frame_bytes; 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_ci if (memcmp(raw_in, raw_out, out_frame_bytes * NUMBER_OF_AUDIO_FRAMES) != 0) { 232cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Output differs\n"); 233cabdff1aSopenharmony_ci return 1; 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_INFO, "OK\n"); 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci av_freep(&raw_in); 239cabdff1aSopenharmony_ci av_freep(&raw_out); 240cabdff1aSopenharmony_ci av_packet_free(&enc_pkt); 241cabdff1aSopenharmony_ci av_frame_free(&in_frame); 242cabdff1aSopenharmony_ci av_frame_free(&out_frame); 243cabdff1aSopenharmony_ci return 0; 244cabdff1aSopenharmony_ci} 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ciint main(void) 247cabdff1aSopenharmony_ci{ 248cabdff1aSopenharmony_ci const AVCodec *enc = NULL, *dec = NULL; 249cabdff1aSopenharmony_ci AVCodecContext *enc_ctx = NULL, *dec_ctx = NULL; 250cabdff1aSopenharmony_ci const AVChannelLayout channel_layouts[] = { AV_CHANNEL_LAYOUT_STEREO, 251cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_5POINT1_BACK, 252cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_SURROUND, 253cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_STEREO_DOWNMIX }; 254cabdff1aSopenharmony_ci int sample_rates[] = {8000, 44100, 48000, 192000}; 255cabdff1aSopenharmony_ci int cl, sr; 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci enc = avcodec_find_encoder(AV_CODEC_ID_FLAC); 258cabdff1aSopenharmony_ci if (!enc) { 259cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't find encoder\n"); 260cabdff1aSopenharmony_ci return 1; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci dec = avcodec_find_decoder(AV_CODEC_ID_FLAC); 264cabdff1aSopenharmony_ci if (!dec) { 265cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Can't find decoder\n"); 266cabdff1aSopenharmony_ci return 1; 267cabdff1aSopenharmony_ci } 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci for (cl = 0; cl < FF_ARRAY_ELEMS(channel_layouts); cl++) { 270cabdff1aSopenharmony_ci for (sr = 0; sr < FF_ARRAY_ELEMS(sample_rates); sr++) { 271cabdff1aSopenharmony_ci if (init_encoder(enc, &enc_ctx, &channel_layouts[cl], sample_rates[sr]) != 0) 272cabdff1aSopenharmony_ci return 1; 273cabdff1aSopenharmony_ci if (init_decoder(dec, &dec_ctx, &channel_layouts[cl]) != 0) 274cabdff1aSopenharmony_ci return 1; 275cabdff1aSopenharmony_ci if (run_test(enc, dec, enc_ctx, dec_ctx) != 0) 276cabdff1aSopenharmony_ci return 1; 277cabdff1aSopenharmony_ci avcodec_free_context(&enc_ctx); 278cabdff1aSopenharmony_ci avcodec_free_context(&dec_ctx); 279cabdff1aSopenharmony_ci } 280cabdff1aSopenharmony_ci } 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci return 0; 283cabdff1aSopenharmony_ci} 284