// avcodec_sample_audio.cpp
// A small sample program that shows how to use libavformat and libavcodec to
// read audio from a file.
//
// Use
//
// g++ -o avcodec_sample_audio avcodec_sample_audio.cpp -lavformat -lavcodec -lz
//
// to build (assuming libavformat and libavcodec are correctly installed on
// your system).
//
// Run using
//
// avcodec_sample_audio myvideofile.mpg
//
// to extract audio track from the file and write samples to a file,
// further play that file with smth.
#include <avcodec.h>
#include <avformat.h>
#include <stdio.h>
#include <stdlib.h>
bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx,
int audioStream, uint8_t* out_buf, int* out_size)
{
static AVPacket packet;
static int bytesRemaining=0;
static uint8_t *rawData;
static bool fFirstTime=true;
int bytesDecoded;
// First time we're called, set packet.data to NULL to indicate it
// doesn't have to be freed
if(fFirstTime)
{
fFirstTime=false;
packet.data=NULL;
}
// Decode packets until we have decoded a complete frame
while(true)
{
// Work on the current packet until we have decoded all of it
while(bytesRemaining > 0)
{
// Decode the next chunk of data
bytesDecoded=avcodec_decode_audio(pCodecCtx, (short*)out_buf,
out_size, rawData, bytesRemaining);
// Was there an error?
if(bytesDecoded < 0)
{
fprintf(stderr, "Error while decoding frame\n");
return false;
}
bytesRemaining-=bytesDecoded;
rawData+=bytesDecoded;
// Did we finish the current frame? Then we can return
if(*out_size>0)
return true;
}
// Read the next packet, skipping all packets that aren't for this
// stream
do
{
// Free old packet
if(packet.data!=NULL)
av_free_packet(&packet);
// Read new packet
if(av_read_packet(pFormatCtx, &packet)<0)
goto loop_exit;
} while(packet.stream_index!=audioStream);
bytesRemaining=packet.size;
rawData=packet.data;
}
loop_exit:
// Decode the rest of the last frame
bytesDecoded=avcodec_decode_audio(pCodecCtx, (short*)out_buf, out_size,
rawData, bytesRemaining);
// Free last packet
if(packet.data!=NULL)
av_free_packet(&packet);
return *out_size>0;
}
void SaveFrame(const uint8_t* buffer, int size, int iFrame)
{
FILE *pFile;
char szFilename[100];
int y;
// Open file
sprintf(szFilename, "/home/stalker/Desktop/frames/frame%d.jpg", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;
// Write pixel data
fwrite(buffer, 1, size, pFile);
// Close file
fclose(pFile);
}
int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx;
int i, audioStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
int out_size;
uint8_t *out_buf;
// Register all formats and codecs
av_register_all();
// Open video file
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
return -1; // Couldn't open file
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
return -1; // Couldn't find stream information
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, argv[1], false);
// Find the first audio stream
audioStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
{
audioStream=i;
break;
}
if(audioStream==-1)
return -1; // Didn't find a audio stream
// Get a pointer to the codec context for the audio stream
pCodecCtx=pFormatCtx->streams[audioStream]->codec;
// Find the decoder for the audio stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
return -1; // Codec not found
// Open codec
if(avcodec_open(pCodecCtx, pCodec)<0)
return -1; // Could not open codec
// Read audio samples and save them to disk
out_buf = (uint8_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
while(GetNextFrame(pFormatCtx, pCodecCtx, audioStream, out_buf, &out_size))
{
}
free (out_buf);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
return 0;
}