Search code examples
ffmpeglibavformat

avformat_open_input fails only with a custom IO context


Running into an odd issue with avformat_open_input, it is failing with:

Invalid data found when processing input

But this only happens when I attempt to read the file using a custom AVIOContext.

My custom code is as follows (error checking omitted for clarity):

auto fmtCtx = avformat_alloc_context();
auto ioBufferSize = 32768;
auto ioBuffer = (unsigned char *)av_malloc(ioBufferSize);
auto ioCtx = avio_alloc_context(ioBuffer,
                                ioBufferSize,
                                0,
                                reinterpret_cast<void *>(this),
                                &imageIORead,
                                NULL,
                                &imageIOSeek));

fmtCtx -> pb = ioCtx;
fmtCtx -> flags |= AVFMT_FLAG_CUSTOM_IO;

int err = avformat_open_input(&fmtCtx, NULL, NULL, NULL);

imageIOSeek is never called, but properly handles the whence parameter including the AVSEEK_SIZE option. My file data is already loaded in memory, so imageIORead is trivial (returning 0 at EOF):

int imageIORead(void *opaque, uint8_t *buf, int buf_size) {
    Image *d = (Image *)buf;
    int rc = std::min(buf_size, static_cast<int>(d->data.size() - d->pos));

    memcpy(buf, d->data.data() + d->pos, rc);
    d->pos += rc;
    return rc;
}

The data being read is loaded from a file on disk:

/tmp/25.jpeg

The following code is able to open and extract the image correctly:

auto fmtCtx = avformat_alloc_context();
int err = avformat_open_input(&fmtCtx, "/tmp/25.jpeg", NULL, NULL);

The project is using a minified version of libavformat including only the formats we need. I don't believe this is the cause of the problem since the file can be open and handled properly when the path is specified. I haven't seen any configure options specifically targeting support for custom IO contexts.

This is the image in question: 25.jpeg


Solution

  • The problem was caused by a my compiling ffmpeg with a custom configure script trying to disable all the formats I have no use for.

    If I remember correctly the missing configure flag was --enable-protocol=pipe.

    This is the list of arguments to configure that I'm using to enable only audio and image file formats of interest to my application and thus create a cut down ffmpeg build:

    --disable-doc
    --disable-debug
    --disable-avdevice
    --enable-swscale
    --enable-rdft
    --disable-ffmpeg
    --disable-ffplay
    --disable-ffprobe
    --disable-ffserver
    --disable-network
    --disable-muxers
    --disable-demuxers
    --disable-zlib
    --disable-bzlib
    --disable-iconv
    --disable-bsfs
    --disable-filters
    --disable-parsers
    --disable-indevs
    --disable-outdevs
    --disable-encoders
    --disable-decoders
    --disable-hwaccels
    --disable-nvenc
    --disable-xvmc
    --disable-videotoolbox
    --disable-audiotoolbox
    --disable-libxcb
    --disable-network
    --disable-sdl2
    --disable-securetransport
    --disable-xlib
    --disable-filters
    --enable-filter=aformat
    --enable-filter=anull
    --enable-filter=atrim
    --enable-filter=format
    --enable-filter=null
    --enable-filter=setpts
    --enable-filter=trim
    --disable-protocols
    --enable-protocol=file
    --enable-protocol=pipe
    --enable-demuxer=image2
    --enable-demuxer=aac
    --enable-demuxer=ac3
    --enable-demuxer=aiff
    --enable-demuxer=ape
    --enable-demuxer=asf
    --enable-demuxer=au
    --enable-demuxer=avi
    --enable-demuxer=flac
    --enable-demuxer=flv
    --enable-demuxer=matroska
    --enable-demuxer=mov
    --enable-demuxer=m4v
    --enable-demuxer=mp3
    --enable-demuxer=mpc
    --enable-demuxer=mpc8
    --enable-demuxer=ogg
    --enable-demuxer=pcm_alaw
    --enable-demuxer=pcm_mulaw
    --enable-demuxer=pcm_f64be
    --enable-demuxer=pcm_f64le
    --enable-demuxer=pcm_f32be
    --enable-demuxer=pcm_f32le
    --enable-demuxer=pcm_s32be
    --enable-demuxer=pcm_s32le
    --enable-demuxer=pcm_s24be
    --enable-demuxer=pcm_s24le
    --enable-demuxer=pcm_s16be
    --enable-demuxer=pcm_s16le
    --enable-demuxer=pcm_s8
    --enable-demuxer=pcm_u32be
    --enable-demuxer=pcm_u32le
    --enable-demuxer=pcm_u24be
    --enable-demuxer=pcm_u24le
    --enable-demuxer=pcm_u16be
    --enable-demuxer=pcm_u16le
    --enable-demuxer=pcm_u8
    --enable-demuxer=rm
    --enable-demuxer=shorten
    --enable-demuxer=tak
    --enable-demuxer=tta
    --enable-demuxer=wav
    --enable-demuxer=wv
    --enable-demuxer=xwma
    --enable-demuxer=dsf
    --enable-decoder=aac
    --enable-decoder=aac_latm
    --enable-decoder=ac3
    --enable-decoder=alac
    --enable-decoder=als
    --enable-decoder=ape
    --enable-decoder=atrac1
    --enable-decoder=atrac3
    --enable-decoder=eac3
    --enable-decoder=flac
    --enable-decoder=gsm
    --enable-decoder=gsm_ms
    --enable-decoder=mp1
    --enable-decoder=mp1float
    --enable-decoder=mp2
    --enable-decoder=mp2float
    --enable-decoder=mp3
    --enable-decoder=mp3adu
    --enable-decoder=mp3adufloat
    --enable-decoder=mp3float
    --enable-decoder=mp3on4
    --enable-decoder=mp3on4float
    --enable-decoder=mpc7
    --enable-decoder=mpc8
    --enable-decoder=opus
    --enable-decoder=ra_144
    --enable-decoder=ra_288
    --enable-decoder=ralf
    --enable-decoder=shorten
    --enable-decoder=tak
    --enable-decoder=tta
    --enable-decoder=vorbis
    --enable-decoder=wavpack
    --enable-decoder=wmalossless
    --enable-decoder=wmapro
    --enable-decoder=wmav1
    --enable-decoder=wmav2
    --enable-decoder=wmavoice
    --enable-decoder=pcm_alaw
    --enable-decoder=pcm_bluray
    --enable-decoder=pcm_dvd
    --enable-decoder=pcm_f32be
    --enable-decoder=pcm_f32le
    --enable-decoder=pcm_f64be
    --enable-decoder=pcm_f64le
    --enable-decoder=pcm_lxf
    --enable-decoder=pcm_mulaw
    --enable-decoder=pcm_s8
    --enable-decoder=pcm_s8_planar
    --enable-decoder=pcm_s16be
    --enable-decoder=pcm_s16be_planar
    --enable-decoder=pcm_s16le
    --enable-decoder=pcm_s16le_planar
    --enable-decoder=pcm_s24be
    --enable-decoder=pcm_s24daud
    --enable-decoder=pcm_s24le
    --enable-decoder=pcm_s24le_planar
    --enable-decoder=pcm_s32be
    --enable-decoder=pcm_s32le
    --enable-decoder=pcm_s32le_planar
    --enable-decoder=pcm_u8
    --enable-decoder=pcm_u16be
    --enable-decoder=pcm_u16le
    --enable-decoder=pcm_u24be
    --enable-decoder=pcm_u24le
    --enable-decoder=pcm_u32be
    --enable-decoder=pcm_u32le
    --enable-decoder=pcm_zork
    --enable-decoder=dsd_lsbf
    --enable-decoder=dsd_msbf
    --enable-decoder=dsd_lsbf_planar
    --enable-decoder=dsd_msbf_planar
    --enable-parser=aac
    --enable-parser=aac_latm
    --enable-parser=ac3
    --enable-parser=cook
    --enable-parser=dca
    --enable-parser=flac
    --enable-parser=gsm
    --enable-parser=mpegaudio
    --enable-parser=tak
    --enable-parser=vorbis
    --enable-decoder=bmp
    --enable-decoder=gif
    --enable-decoder=jpeg2000
    --enable-decoder=jpegls
    --enable-decoder=mjpeg
    --enable-decoder=mjpegb
    --enable-decoder=pgm
    --enable-decoder=png
    --enable-decoder=ppm
    --enable-decoder=tiff
    --enable-demuxer=gif
    --enable-demuxer=image2pipe
    --enable-demuxer=image_bmp_pipe
    --enable-demuxer=image_jpeg_pipe
    --enable-demuxer=image_jpegls_pipe
    --enable-demuxer=image_pgm_pipe
    --enable-demuxer=image_png_pipe
    --enable-demuxer=image_tiff_pipe
    --enable-demuxer=mjpeg
    --enable-demuxer=mjpeg_2000
    --enable-encoder=mjpeg
    --enable-encoder=png
    --enable-muxer=image2
    --enable-muxer=mjpeg
    --enable-muxer=singlejpeg
    --enable-parser=bmp
    --enable-parser=mjpeg
    --enable-parser=png
    --enable-parser=pnm
    --enable-bsf=mjpeg2jpeg
    

    It is quite possible that the list contains some extra features not strictly needed for audio and image processing, but these options solved the reported problem.