[Libav-user] Audio encoding: more samples than frame size (avcodec_encode_audio2)
Yu Ang Tan
yuang86 at gmail.com
Tue Sep 20 11:02:06 EEST 2016
I am trying to read an RTP audio stream, and encode it into a FLAC file.
However, when I am reading the stream, I get this error:
[libvorbis @ 028b1520] more samples than frame size
(avcodec_encode_audio2)
During debug mode, it seems the frame_size of my input and output codec
context are mismatched:
inCodecCtx->frame_size = 1152;
outCodecCtx->frame_size = 64;
I tried to write 1152 to outCodecCtx->frame_size, but it gets overwritten
with 64 at `avcodec_open2()`. Why can't I set the frame_size to match the
input frame_size? Should I create an additional output frame to copy the
contents over in a loop?
I'd really appreciate it if you could help me some help or suggestions.
Here is my source:
//
// Test with this command: ffmpeg -re -f lavfi -i
aevalsrc="atan(t/2)*sin(400*2*PI*t)" -ar 16000 -c:a pcm_s16be -f rtp rtp://
127.0.0.1:8554
// ffmpeg -f dshow -i audio="Microphone (High Definition Audio Device)"
-ar 16000 -c:a pcm_s16be -ac 1 -f rtp rtp://127.0.0.1:8554
// Working code
#include "stdafx.h"
#include <math.h>
extern "C"
{
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
#include <libavformat/avformat.h>
}
#define AUDIO_INBUF_SIZE 20480
#define ERRBUFFLEN 200
char errbuf[ERRBUFFLEN];
#define av_err2str(ret) av_strerror(ret, errbuf, ERRBUFFLEN)
const int samp_rate = 16000;
int count = 0;
// Callback function
int _ffmpeg_interrupt_fcn(void* ptr)
{
int &r = *((int*)ptr);
//double &r = *((double*)ptr);
r += 1;
printf("Interrupted! %d\n", r);
if (r > 30) return 1;
return 0;
}
static int write_frame(AVFormatContext *fmt_ctx, const AVRational
*time_base, AVStream *st, AVPacket *pkt)
{
/* rescale output packet timestamp values from codec to stream
timebase */
av_packet_rescale_ts(pkt, *time_base, st->time_base);
pkt->stream_index = st->index;
/* Write the compressed frame to the media file. */
#ifdef DEBUG_PACKET
log_packet(fmt_ctx, pkt);
#endif
return av_interleaved_write_frame(fmt_ctx, pkt);
}
/*
* Audio decoding.
*/
static void audio_decode_example(const char *outfilename, const char
*filename)
{
int len;
FILE *f, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
AVPacket inpkt, outpkt;
AVCodec *inCodec = NULL;
AVCodecContext *inCodecCtx = NULL;
AVFrame *decoded_frame = NULL;
AVFormatContext *inFormatCtx = NULL;
AVCodec *outCodec = NULL;
AVCodecContext *outCodecCtx = NULL;
AVFormatContext *outFormatCtx = NULL;
AVStream * outAudioStream = NULL;
int ret;
av_init_packet(&inpkt);
AVDictionary *d = NULL; // "create" an empty dictionary
av_dict_set(&d, "protocol_whitelist", "file,udp,rtp", 0); // add an
entry
// Open video file
ret = avformat_open_input(&inFormatCtx, filename, NULL, &d);
if (ret <0)
{
printf_s("Failed: cannot open input.\n");
av_strerror(ret, errbuf, ERRBUFFLEN);
fprintf(stderr, "avformat_open_input() fail: %s\n", errbuf);
exit(1);
}
printf_s("Retrieve stream information.\n");
ret = avformat_find_stream_info(inFormatCtx, NULL);
if (ret <0)
{
printf_s("Failed: cannot find stream.\n");
av_strerror(ret, errbuf, ERRBUFFLEN);
fprintf(stderr, "avformat_find_stream_info() fail: %s\n",
errbuf);
exit(1);
}
av_dump_format(inFormatCtx, 0, filename, 0);
int stream_idx = -1;
for (int i = 0; i < inFormatCtx->nb_streams; i++)
if (inFormatCtx->streams[i]->codec->codec_type ==
AVMEDIA_TYPE_AUDIO) {
stream_idx = i;
break;
}
if (stream_idx == -1)
{
fprintf(stderr, "Video stream not found\n");
exit(1);
}
inCodec =
avcodec_find_decoder(inFormatCtx->streams[stream_idx]->codec->codec_id);
if (!inCodec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
inCodecCtx = avcodec_alloc_context3(inCodec);
if (!inCodecCtx) {
fprintf(stderr, "Could not allocate audio codec context\n");
exit(1);
}
inCodecCtx->channels = 1;
ret = avcodec_open2(inCodecCtx, inCodec, NULL);
if (ret < 0) {
fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
exit(1);
}
// Set output
ret = avformat_alloc_output_context2(&outFormatCtx, NULL, NULL,
outfilename);
if (!outFormatCtx || ret < 0)
{
fprintf(stderr, "Could not allocate output context");
}
outFormatCtx->flags |= AVFMT_FLAG_NOBUFFER |
AVFMT_FLAG_FLUSH_PACKETS;
outFormatCtx->audio_codec_id = AV_CODEC_ID_FLAC;
// Find the codec.
outCodec = avcodec_find_encoder(outFormatCtx->oformat->audio_codec);
if (outCodec == NULL) {
fprintf(stderr, "Codec not found\n");
return;
}
// Add stream to pFormatCtx
outAudioStream = avformat_new_stream(outFormatCtx, outCodec);
if (!outAudioStream)
{
fprintf(stderr, "Cannot add new video stream\n");
return;
}
outAudioStream->id = outFormatCtx->nb_streams - 1;
outCodecCtx = outAudioStream->codec;
outCodecCtx->sample_rate = samp_rate;
outCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
outCodecCtx->channels = 1;
outCodecCtx->frame_size = 1152;
if (outFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
outCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
// Open the codec.
if (avcodec_open2(outCodecCtx, outCodec, NULL) < 0)
{
fprintf(stderr, "Cannot open audio codec\n");
return;
}
if (avio_open2(&outFormatCtx->pb, outfilename, AVIO_FLAG_WRITE,
NULL, NULL) < 0)
{
av_strerror(ret, errbuf, ERRBUFFLEN);
fprintf(stderr, "avio_open2 fail: %s\n", errbuf);
return;
}
// Write file header.
ret = avformat_write_header(outFormatCtx, NULL);
if (ret < 0)
{
fprintf(stderr, "error writing header");
return;
}
// Set callback
inFormatCtx->interrupt_callback.callback = _ffmpeg_interrupt_fcn;
inFormatCtx->interrupt_callback.opaque = &count;
/**************************************************************
* Input Code Ctx Frame size: 1152
* Output Code Ctx Frame size: 64
**************************************************************/
printf("Input Code Ctx Frame size: %d\n", inCodecCtx->frame_size);
printf("Output Code Ctx Frame size: %d\n", inCodecCtx->frame_size);
int got_packet = 0;
while (av_read_frame(inFormatCtx, &inpkt) == 0) {
int i, ch;
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "Could not allocate audio frame\n");
exit(1);
}
}
len = avcodec_decode_audio4(inCodecCtx, decoded_frame,
&got_frame, &inpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
exit(1);
}
if (got_frame) {
printf("Packet size: %d\n", decoded_frame->pkt_size);
printf("Frame samples: %d\n", decoded_frame->nb_samples);
got_packet = 0;
av_init_packet(&outpkt);
int error = avcodec_encode_audio2(outCodecCtx, &outpkt,
decoded_frame, &got_packet);
if (!error && got_packet > 0)
{
// Write packet with frame.
ret = write_frame(outFormatCtx,
&outCodecCtx->time_base, outAudioStream, &outpkt);
}
av_packet_unref(&outpkt);
}
count = 0;
}
// Flush remaining encoded data
while (1)
{
got_packet = 0;
// Encode frame to packet.
int error = avcodec_encode_audio2(outCodecCtx, &outpkt, NULL,
&got_packet);
if (!error && got_packet > 0)
{
av_init_packet(&outpkt);
// Write packet with frame.
ret = write_frame(outFormatCtx, &outCodecCtx->time_base,
outAudioStream, &outpkt);
av_packet_unref(&outpkt);
}
else
{
break;
}
}
av_write_trailer(outFormatCtx);
avcodec_close(outAudioStream->codec); // codecCtx
avio_close(outFormatCtx->pb);
avformat_free_context(outFormatCtx);
avcodec_close(inCodecCtx);
av_free(inCodecCtx);
av_frame_free(&decoded_frame);
}
int main(int argc, char **argv)
{
const char *output_type;
av_register_all();
avformat_network_init(); // for network streaming
audio_decode_example("test.flac", "test.sdp");
return 0;
}
Cheers,
ytan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20160920/fee79ffc/attachment.html>
More information about the Libav-user
mailing list