0

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;
mattobob
  • 833
  • 4
  • 15
  • 37

1 Answers1

0

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);
user3770489
  • 186
  • 4
  • You might face the issue that the format of audio in m_samBuf is not the same as the input format. avcodec_encode_audio() took interleaved 16-bit integer audio, avcodec_encode_audio2() takes interleaved or planar audio in any format, and the encoder selects which one you should use. You might need to use libswresample to convert between interleaved 16bit integer and the encoder's format. – Ronald S. Bultje Feb 22 '16 at 14:09
  • Thanks man! Can i calculate the sample per channels like: `m_Frame->nb_samples = m_handle->sample_rate / m_handle->channels;` or similar? – mattobob Feb 22 '16 at 14:20
  • how do i convert the samples for avcodec_encode_audio2(), could not be so complicated... – mattobob Feb 22 '16 at 14:30
  • I changed the code as user3770489 suggested, now it is crashing on AVfunction: `AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type) { ... if (frame->side_data[i]->type == type) return frame->side_data[i]; }` much probably when asking for `side_data[i] ` any suggestions? – mattobob Feb 22 '16 at 14:46
  • What is the side data? – mattobob Feb 22 '16 at 15:03
  • m_handle->frame_size returns 0 for some codecs, if you know how many samples are in m_samBuf then divide that by the number of channels for your m_Frame->nb_samples value – user3770489 Feb 24 '16 at 10:10