Search code examples
c++ffmpeglibavcodecavcodec

FFmpeg audio encoder new encode function


I would like to update an AV Audio encoder using function avcodec_encode_audio (deprecated) to avcodec_encode_audio2, without modifying the structure of existing encoder:

 outBytes = avcodec_encode_audio(m_handle, dst, sizeBytes, (const short int*)m_samBuf);

where:

1) m_handle AVCodecContext

2) dst, uint8_t * destination buffer

3) sizeBytes, uint32_t size of the destination buffer

4) m_samBuf void * to the input chunk of data to encode (this is casted to: const short int*)

is there a simply way to do it?

Im tryng with:

int gotPack = 1;
memset (&m_Packet, 0, sizeof (m_Packet));
m_Frame = av_frame_alloc();

av_init_packet(&m_Packet);
m_Packet.data = dst;
m_Packet.size = sizeBytes;

uint8_t* buffer = (uint8_t*)m_samBuf;
m_Frame->nb_samples = m_handle->frame_size;

avcodec_fill_audio_frame(m_Frame,m_handle->channels,m_handle->sample_fmt,buffer,m_FrameSize,1);

outBytes = avcodec_encode_audio2(m_handle, &m_Packet, m_Frame, &gotPack);
char error[256];
av_strerror(outBytes,error,256);

if (outBytes<0){
    m_server->log(1,1,"Input data: %d, encode function call error: %s \n",gotPack, error);
    return AUDIOWRAPPER_ERROR;
}
av_frame_free(&m_Frame);

it compiles but it does not encode anything, i dont here audio at the output if I pipe the output stream on mplayer, wich was warking prior to the upgrade.

What am I doing wrong?

The encoder accept only two sample formats:

AV_SAMPLE_FMT_S16,         ///< signed 16 bits
AV_SAMPLE_FMT_FLT,         ///< float

here is how the buffer is allocated:

free(m_samBuf);
int bps = 2;
if(m_handle->codec->sample_fmts[0] == AV_SAMPLE_FMT_FLT) {
    bps = 4;
}
m_FrameSize = bps * m_handle->frame_size * m_handle->channels;
m_samBuf = malloc(m_FrameSize);
m_numSam = 0;

Solution

  • avcodec_fill_audio_frame should get you there

    memset (&m_Packet, 0, sizeof (m_Packet));
    memset (&m_Frame, 0, sizeof (m_Frame));
    
    av_init_packet(&m_Packet);
    
    m_Packet.data = dst;
    m_Packet.size = sizeBytes;
    
    m_Frame->nb_samples = //you need to get this value from somewhere, it is the number of samples (per channel) this frame represents
    avcodec_fill_audio_frame(m_Frame, m_handle->channels, m_handle->sample_fmt,
            buffer,
            sizeBytes, 1);
    
    
    int gotPack = 1;
    
    avcodec_encode_audio2(m_handle, &m_Packet, &m_Frame, &gotPack);