Search code examples
stdvectorlibavcodeclibav

Using std::vector<char> instead of fread() in libav encode/decode example


I am attempting to take the api-example.c which reads in a file using fread to instead use memcpy (or the like) as I have loaded the file I wish to decode & encode into a different codec in a std::vector<char>. (Due to I read it to memory from a compressed archive to memory). Any suggestions or examples on how I could achieve this?

Original api-example http://svn.perian.org/ffmpeg/libavcodec/api-example.c

My current "progress" http://pastebin.com/Ag0KfEsg


Solution

  • Got a solution here http://pastebin.com/HsDUX8jp

    void AudioLibav::DecodeAudio(std::vector<char> *inputAudio)
    {
    
    //Wasteful?
    avcodec_register_all();
    
    unsigned int audioVectorPosition = 0;
    
    AVCodec *codec;
    AVCodecContext *codecContext = NULL;
    int length;
    FILE *memoutfile;
    uint8_t memBuffer[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    AVPacket memPkt;
    AVFrame *decoded_frame_mem = NULL;
    
    av_init_packet(&memPkt);
    
    printf("Audio decoding\n");
    
    /* find the mpeg audio decoder */
    codec = avcodec_find_decoder(AV_CODEC_ID_PCM_S16LE);
    if (!codec)
    {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }
    
    codecContext = avcodec_alloc_context3(codec);
    
    #warning Bad assumption
    codecContext->channels = 2;
    
    /* open it */
    if (avcodec_open2(codecContext, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }
    
    memoutfile = fopen("testrawmem", "wb");
    if (!memoutfile) {
        av_free(codecContext);
        exit(1);
    }
    
    /* decode until eof */
    memPkt.data = memBuffer;
    memPkt.size = AUDIO_INBUF_SIZE;
    memcpy(memBuffer, &inputAudio->at(0), AUDIO_INBUF_SIZE);
    
    inputAudioVectorPosition = AUDIO_INBUF_SIZE;
    
    while (memPkt.size > 0)
    {
        int got_frame_mem = 0;
    
        if(!decoded_frame_mem)
        {
            if (!(decoded_frame_mem = avcodec_alloc_frame()))
            {
                fprintf(stderr, "out of memory\n");
                exit(1);
            }
        }
        else
        {
                        avcodec_get_frame_defaults(decoded_frame_mem);
        }
    
        length = avcodec_decode_audio4(codecContext, decoded_frame_mem, &got_frame_mem, &memPkt);
    
        if (length < 0)
        {
            fprintf(stderr, "Error while decoding\n");
            exit(1);
        }
        if(got_frame_mem )
        {
            int data_size_mem = av_samples_get_buffer_size(NULL, codecContext->channels, decoded_frame_mem->nb_samples, codecContext->sample_fmt, 1);
    
    
            fwrite(decoded_frame_mem->data[0], 1, data_size_mem, memoutfile);
        }
    
        memPkt.size -= length;
        memPkt.data += length;
    
        if(memPkt.size < AUDIO_REFILL_THRESH)
        {
            memmove(memBuffer, memPkt.data, memPkt.size);
            memPkt.data = memBuffer;
            //std::cout << "Mempacket data: " << memPkt.data << "   MemPacket size: " << memPkt.size << "    memAUDIO BUFF - size: " << AUDIO_INBUF_SIZE - memPkt.size;
            if((inputAudio->size() - inputAudioVectorPosition) < (AUDIO_INBUF_SIZE - memPkt.size))
            {
                memcpy( (memPkt.data + memPkt.size) , &inputAudio->at(inputAudioVectorPosition), (inputAudio->size() - inputAudioVectorPosition));
                inputAudioVectorPosition = inputAudio->size() - 1;
                #warning Bad Assumption?
                //memlen = AUDIO_INBUF_SIZE - memPkt.size;
                length = 0;
            }
            else
            {
                memcpy( (memPkt.data + memPkt.size) , &inputAudio->at(inputAudioVectorPosition), AUDIO_INBUF_SIZE - memPkt.size);
                inputAudioVectorPosition = inputAudioVectorPosition + (AUDIO_INBUF_SIZE - memPkt.size);
                length = AUDIO_INBUF_SIZE - memPkt.size;
            }
    
            if(length > 0)
            {
                memPkt.size += length;
            }
    
        }
    
    }
    
    fclose(memoutfile);
    
    avcodec_close(codecContext);
    av_free(codecContext);
    avcodec_free_frame(&decoded_frame_mem);
    

    }