Hi Nicolas, Very helpful, thank you. I trimmed this code down to just the essentials of the audio section since video isn't a problem.
What I see is that: - The call to avresample_convert() seems to always succeed, so I think decode and resample are working ok - The first call to avcodec_encode_audio2() succeeds and returns a packet (got_packet_ptr true), which is successfully written to the output - Subsequent calls to avcodec_encode_audio2() return -22 (Illegal argument) and got_packet_ptr false Here is some sample output from the code below: begin input loop src pkt stream 1, pts 125098, dts 125098 got_audio linesize[0]=2304 nb_samples=1152 avr_convert() ret len 1152 destaudio pts 125098 avcodec_encode_audio2() success write audio pkt: stream 0, pts 124617, dts 124617 src pkt stream 1, pts 127258, dts 127258 got_audio linesize[0]=2304 nb_samples=1152 avr_convert() ret len 1152 destaudio pts 127258 avcodec_encode_audio2() error -22 Invalid argument Any ideas? Thanks again! Code: #include <stdio.h> #include <assert.h> #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" #include "libavresample/avresample.h" #include "libavutil/opt.h" int main (int argc, const char * argv[]) { const char *infile = argv[1]; const char *outfile = argv[2]; int r; AVPacket pkt; AVFrame *srcaudio = NULL; AVFormatContext *in = NULL, *out = NULL; AVCodecContext *in_acodec, *out_acodec; AVStream *in_astream, *out_astream; AVAudioResampleContext *avr; AVCodec *acodec; int got_audio; char errbuf[128]; int got_packet_ptr = 0; int audio_bufsize = AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE; int64_t audio_samples = 0; int64_t first_pts = -1; // init LAVF av_register_all(); avformat_network_init(); //av_log_set_level(AV_LOG_VERBOSE); // Open input file printf("Open input file: %s\n", infile); r = avformat_open_input(&in, infile, NULL, NULL); if (r) { printf("open err %x\n", r); return r; } r = avformat_find_stream_info(in, NULL); if (r < 0) { printf("find_stream_info err %x\n", r); return r; } // iterate over input streams for (int i = 0; i < in->nb_streams; i++) { AVStream *inputStream = in->streams[i]; if (inputStream->codec->codec_type == AVMEDIA_TYPE_AUDIO) { inputStream->discard = AVDISCARD_NONE; in_astream = inputStream; in_acodec = inputStream->codec; if (!inputStream->codec->codec) { avcodec_open2(inputStream->codec, avcodec_find_decoder(inputStream->codec->codec_id), NULL); } printf("Input audio %s rate %d channels %d sample_format %d\n", in_acodec->codec->name, in_acodec->sample_rate, in_acodec->channels, in_acodec->sample_fmt); } else { inputStream->discard = AVDISCARD_ALL; } } assert(in_acodec); // Open output file for writing out = avformat_alloc_context(); assert(out); out->oformat = av_guess_format(NULL, outfile, NULL); // Guess output container format based on file extension assert(out->oformat); // Output parameters // Audio codec acodec = avcodec_find_encoder(CODEC_ID_MP2); assert(acodec); out_acodec = avcodec_alloc_context3(acodec); avcodec_get_context_defaults3(out_acodec, acodec); assert(out_acodec); out_acodec->channels = 2; out_acodec->sample_rate = 48000; out_acodec->sample_fmt = AV_SAMPLE_FMT_S16; out_acodec->channel_layout = av_get_channel_layout("stereo"); out_acodec->time_base = in_acodec->time_base; // TODO: set other codec parameters r = avcodec_open2(out_acodec, acodec, NULL); assert(!r); // Audio stream out_astream = avformat_new_stream(out, out_acodec->codec); assert(out_astream); out_astream->codec = out_acodec; // setup audio resample context avr = avresample_alloc_context(); av_opt_set_int(avr, "in_channel_layout", in_acodec ->channel_layout, 0); av_opt_set_int(avr, "out_channel_layout", out_acodec->channel_layout, 0); av_opt_set_int(avr, "in_sample_fmt", in_acodec ->sample_fmt, 0); av_opt_set_int(avr, "out_sample_fmt", out_acodec->sample_fmt, 0); av_opt_set_int(avr, "in_sample_rate", in_acodec ->sample_rate, 0); av_opt_set_int(avr, "out_sample_rate", out_acodec->sample_rate, 0); av_opt_set_int(avr, "in_channels", in_acodec ->channels, 0); av_opt_set_int(avr, "out_channels", out_acodec->channels, 0); r = avresample_open(avr); assert(!r); // print audio params printf("Output audio %s rate %d channels %d sample_format %d\n", out_acodec->codec->name, out_acodec->sample_rate, out_acodec->channels, out_acodec->sample_fmt); // Begin writing output file printf("Open output file: %s\nOutput container: %s\n", outfile, out->oformat->long_name); r = avio_open2(&out->pb, outfile, AVIO_FLAG_WRITE, NULL, NULL); if (r) { printf("err %x\n", r); return r; } printf("write out header\n"); r = avformat_write_header(out, NULL); if (r) { printf("err %x\n", r); return r; } printf("begin input loop\n"); while (1) { av_init_packet(&pkt); r = av_read_frame(in, &pkt); if (r) { if (r == AVERROR_EOF) printf("EOF\n"); else printf("read error %x\n", r); break; } printf("src pkt stream %d, pts %"PRId64", dts %"PRId64"\n", pkt.stream_index, pkt.pts, pkt.dts); if (first_pts == -1 && pkt.pts != AV_NOPTS_VALUE) first_pts = pkt.pts; if (pkt.stream_index == in_astream->index) { // decode audio srcaudio = avcodec_alloc_frame(); avcodec_get_frame_defaults(srcaudio); got_audio = 0; r = avcodec_decode_audio4(in_acodec, srcaudio, &got_audio, &pkt); if (r < 0) { av_strerror(r, errbuf, 128); printf("audio decode error %d %s\n", r, errbuf); break; } else if (got_audio) { // convert audio AVPacket newpkt; AVFrame *destaudio; // frame for resampled audio int64_t timestamp = av_frame_get_best_effort_timestamp(srcaudio); int nb_samples; av_init_packet(&newpkt); destaudio = avcodec_alloc_frame(); avcodec_get_frame_defaults(destaudio); destaudio->extended_data = av_malloc(sizeof(uint8_t*)); destaudio->extended_data[0] = av_malloc(audio_bufsize); got_packet_ptr = 0; printf("got_audio linesize[0]=%d nb_samples=%d\n", srcaudio->linesize[0], srcaudio->nb_samples); // resample to dest format nb_samples = avresample_convert(avr, (void**)destaudio->extended_data, destaudio->linesize[0], audio_bufsize, (void**)srcaudio->extended_data, srcaudio->linesize[0], srcaudio->nb_samples); if (nb_samples < 0) { av_strerror(nb_samples, errbuf, 128); printf("avr_convert() error %d %s\n", nb_samples, errbuf); break; } printf("avr_convert() ret len %d\n", nb_samples); if (timestamp != AV_NOPTS_VALUE) destaudio->pts = av_rescale_q(timestamp, in_astream->time_base, out_astream->time_base); else destaudio->pts = first_pts + (int)((double)audio_samples * (90000.0/out_acodec->sample_rate)); printf("destaudio pts %"PRId64"\n", destaudio->pts); // why does this return -22 after the first successfull call? r = avcodec_encode_audio2(out_acodec, &newpkt, destaudio, &got_packet_ptr); if (r < 0) { av_strerror(r, errbuf, 128); printf("avcodec_encode_audio2() error %d %s\n", r, errbuf); //break; } else if (got_packet_ptr) { // write frame printf("avcodec_encode_audio2() success\n"); newpkt.stream_index = out_astream->index; newpkt.flags |= AV_PKT_FLAG_KEY; printf("write audio pkt: stream %d, pts %"PRId64", dts %"PRId64"\n", newpkt.stream_index, newpkt.pts, newpkt.dts); r = av_interleaved_write_frame(out, &newpkt); if (r) { printf("audio write error %x\n", r); break; } } av_free(destaudio->extended_data[0]); av_free(destaudio->extended_data); av_free(destaudio); av_free_packet(&newpkt); audio_samples += nb_samples; } av_free(srcaudio); } av_free_packet(&pkt); } avcodec_close(in_acodec); avcodec_close(out_acodec); // TODO: anything else to free/close? r = av_write_trailer(out); if (r) { printf("error closing output %x\n", r); } avformat_close_input(&in); printf("Wrote output file: %s\n", outfile); return 0; } -- View this message in context: http://libav-users.943685.n4.nabble.com/Example-for-recompressing-a-video-tp4655098p4655143.html Sent from the libav-users mailing list archive at Nabble.com. _______________________________________________ Libav-user mailing list Libav-user@ffmpeg.org http://ffmpeg.org/mailman/listinfo/libav-user