[Libav-user] Encoding/Decoding Audio
Steve Myers
musicspeedchanger at gmail.com
Tue Jan 24 03:04:38 EET 2017
> On Jan 23, 2017, at 5:38 PM, Cesareo Fernandez <cesareof at gmail.com> wrote:
>
> 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.
>
>
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user <http://ffmpeg.org/mailman/listinfo/libav-user>
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);
}
This looks wrong, you should be using the return of swr_convert to base the number of bytes to write. Also, why allocate out_buffer, and open and close the file on every frame?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20170123/d77077f8/attachment.html>
More information about the Libav-user
mailing list