c++cffmpeglibavformat

avformat_write_header() doesn't work when writing data to memory instead of file


i want to resample a given input format from memory to memory everything is good so far.

but when trying to get the output header from ffmpeg it doesn't work.

here i allocate the context and pass the write_buffer function pointer so that it doesn't write to a file but instead it will call my function with the required data

unsigned char * aviobuffer = (unsigned char *) av_malloc (32768);
AVIOContext * avio = avio_alloc_context (aviobuffer, 32768,1, NULL, NULL, write_buffer, NULL);

AVFormatContext* containerContext;
avformat_alloc_output_context2(&containerContext, NULL, "s16le", NULL);
containerContext->pb = avio;

here is my write_buffer function

std::vector<char>* data;
int write_buffer(void *opaque, uint8_t *buf, int buf_size)
{
    std::vector<char> tmp;
    tmp.assign(buf, buf + buf_size);
    data->insert(data->end(), tmp.begin(), tmp.end());
    return buf_size;
}

now when i call avformat_write_header() it doesn't call my write_buffer() function + it returns 0 which means success.

int ret = avformat_write_header(containerContext, NULL);

after that i call the appropriate functions to get the data body itself and my write_buffer() get called normally so i am now left with the data body with no header !!

how can i get the output header anyways?


Solution

  • well, after a lot of debugging that led me to discover the way ffmpeg writes format headers.

    long story short, some formats are associated with special functions for writing their headers.

    the "s16le" format inside ffmpeg is not associated with one. but surprisingly as i stated in the question ffmpeg can write its data body but no header!! so i searched for a format that is close to what i want and supports writing its header. i found the "wav" format, tried it and it worked nicely. fortunately wav's default is s16le which is exactly what i want.

    so in conclusion i changed this line of code

    avformat_alloc_output_context2(&containerContext, NULL, "s16le", NULL);
    

    to

    avformat_alloc_output_context2(&containerContext, NULL, "wav", NULL);