[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