[Libav-user] Encoding/Decoding Audio

Cesareo Fernandez cesareof at gmail.com
Tue Jan 24 00:38:15 EET 2017


I have been attempting to use the ffmpeg libraries to take as input a RTMP
stream consisting of a video stream and an audio stream, and decode the
respective streams in order to push the contents out to a website via a
websocket. The video portion of this task is complete and works fine
without issue. Converting frames of h.264 video to single motion jpeg
images and pushing those on without a problem. I am attempting to do
something similar with audio, takes frames of aac audio and passing those
out through a websocket to be played back in chunks, this portion of the
task is proving to be a lot more difficult than I thought it would be.

The way I am testing this is simply learning the way to decode an encode
audio (if necessary) to a file before trying to implement it practically
via websockets and even this is proving more difficult than I expected, I
found some examples via google, but I can't get any of these to work:


int PullAudioFrames( char input[], char output[] )
{
const int MAX_AUDIO_FRAME_SIZE = 192000;
    bool bRet = false;
bool bFileOpened = false;
bool bAudioCodecOpen = false;
bool abort = false;

int nVideoStream = -1;
int nAudioStream = -1;
AVDictionary *optionsDict = NULL;
//-- Register all formats and codecs and network tools
avcodec_register_all();
av_register_all();
avformat_network_init();
//--

AVCodecContext *pIn_AudioCodecCtx = NULL;
AVCodec *pIn_AudioCodec = NULL;
struct SwrContext *au_convert_ctx;

AVFormatContext *pFormatCtx = avformat_alloc_context();
if(avformat_open_input(&pFormatCtx, input, NULL, &optionsDict) == 0 ) //Open
Stream
{
bFileOpened = true;
if(avformat_find_stream_info(pFormatCtx, &optionsDict) >= 0 ) //Get Stream
information (video, audio, subtitle)
{
for(int i=0; i<(int)pFormatCtx->nb_streams; i++) //Find the video stream
{
if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO)
nAudioStream=i;
if( nAudioStream >= 0 )
break;
}
bool bCleanUp = false;
if( nAudioStream >= 0 )
{
pIn_AudioCodec = avcodec_find_decoder(
pFormatCtx->streams[nAudioStream]->codecpar->codec_id );
if(pIn_AudioCodec  != NULL)
{
pIn_AudioCodecCtx = avcodec_alloc_context3(pIn_AudioCodec);
// Fill the codecCtx with the parameters of the codec used in the read file.
if( avcodec_parameters_to_context(pIn_AudioCodecCtx,
pFormatCtx->streams[nAudioStream]->codecpar) == 0  )
{
if( avcodec_open2(pIn_AudioCodecCtx, pIn_AudioCodec, NULL) >= 0 ) //Open
Audio codec
bAudioCodecOpen = true;
else
bCleanUp = true;
}
else
bCleanUp = true;
}
}
if( bCleanUp )
{
avcodec_close( pIn_AudioCodecCtx );
avcodec_free_context( &pIn_AudioCodecCtx );
}

if( bAudioCodecOpen )
{
au_convert_ctx = swr_alloc();
au_convert_ctx=swr_alloc_set_opts(au_convert_ctx, AV_CH_LAYOUT_STEREO,
AV_SAMPLE_FMT_S16, 44100,
av_get_default_channel_layout(pIn_AudioCodecCtx->channels),
pIn_AudioCodecCtx->sample_fmt , pIn_AudioCodecCtx->sample_rate,0, NULL);
swr_init(au_convert_ctx);

AVFrame *pFrame=av_frame_alloc();
AVPacket packet;
av_init_packet(&packet);

while( !abort )
{
av_packet_unref(&packet);
av_frame_unref(pFrame);
int result = av_read_frame( pFormatCtx, &packet);
if( result < 0 )
{
if( result == AVERROR(EAGAIN) )
continue;
else if( result == AVERROR(EPIPE) )
printf( "[\"Error\", {\"message\" : \"Unable to read Frame pipe error. [%d]
[%d]\"}]", result, AVERROR(result) );
else if (result == AVERROR_EOF)
printf( "[\"Error\", {\"message\" : \"Unable to read Frame end of File.
[%d] [%d]\"}]", result, AVERROR(result) );
else
printf( "[\"Error\", {\"message\" : \"Unable to read Frame. [%d] [%d]\"}]
", result, AVERROR(result) );
abort = true;
}
else
{
if(packet.stream_index==nAudioStream)
{
int frameFinished=0;
int nResult = avcodec_send_packet(pIn_AudioCodecCtx, &packet);
if( nResult == 0 )
nResult = avcodec_receive_frame( pIn_AudioCodecCtx, pFrame );

if( nResult == 0 )
{
uint8_t *out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE*2);
int data_size = av_samples_get_buffer_size(NULL,
pIn_AudioCodecCtx->channels, pFrame->nb_samples,
pIn_AudioCodecCtx->sample_fmt, 1);
swr_convert(au_convert_ctx,&out_buffer, MAX_AUDIO_FRAME_SIZE,(const uint8_t
**)pFrame->data , pFrame->nb_samples);

FILE *fOut;
if( fopen_s( &fOut, output, "a+" ) == 0 )
{
fwrite(out_buffer, 1, data_size, fOut);
fclose(fOut);
}
}
}
}
av_packet_unref(&packet);
}
av_frame_free(&pFrame);
}
else
printf( "Unable to open Codec in %s", input );
}
else
printf( "No stream information found in %s", input );
}
else
printf("Unable to open live video stream %s", input );


if( bAudioCodecOpen )
{
avcodec_close(pIn_AudioCodecCtx);
avcodec_free_context(&pIn_AudioCodecCtx);
swr_free(&au_convert_ctx);
bAudioCodecOpen  = false;
}

if(bFileOpened)
{
if( pFormatCtx )
avformat_close_input(&pFormatCtx);
bFileOpened = false;
}
return 0;
}


The resulting file is not playable and passing it back through CLI
ffmpeg.exe doesn't give a whole lot of useful information why that is. Any
help, or point in the right direction would be greatly appreciated.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20170123/844df501/attachment.html>


More information about the Libav-user mailing list