All pastes #741522 Raw Edit

avcodec_sample_audio

public text v1 · immutable
·published 2007-10-18 19:35 UTC
rendered paste body
// 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;
}