1

I am writing a MP4 video from scratch using the C++ API (libav* 4.1.1). This video can be played back just fine using ffplay or VLC. But the Finder Preview and the Quicktime Player on OSX (10.13 and 10.14 tested) don't work, the finder hangs and Quicktime player shows black and silent.

This is the output of ffplay:

ffplay version 4.1.1 Copyright (c) 2003-2019 the FFmpeg developers
  built with Apple LLVM version 10.0.0 (clang-1000.11.45.5)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.1.1 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags='-I/Library/Java/JavaVirtualMachines/openjdk-11.0.2.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/openjdk-11.0.2.jdk/Contents/Home/include/darwin' --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libsnappy --enable-libtesseract --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-videotoolbox --disable-libjack --disable-indev=jack --enable-libaom --enable-libsoxr
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'demo.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.20.100
  Duration: 00:01:23.29, start: 0.000000, bitrate: 566 kb/s
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 800x576 [SAR 1:1 DAR 25:18], 498 kb/s, 23.99 fps, 23.98 tbr, 24k tbn, 48k tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 64 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

The video settings are chosen from a working MP4 video, and I can't spot any difference in ffprobe or ffplay.

This is, how I setup the streams (condensed):

// container:
avformat_alloc_output_context2 (&formatContext, NULL, NULL, filename);
// formatContext->oformat->flags has AVFMT_GLOBALHEADER set automatically

// video stream:
codec = av_guess_codec (formatContext->oformat, nullptr, filename, nullptr, AVMEDIA_TYPE_VIDEO);
auto* encoder = avcodec_find_encoder (codec);

stream->time_base = av_make_q (1, settings.timebase);
auto* context = avcodec_alloc_context3 (encoder);
context->width = settings.frameSize.width;
context->height = settings.frameSize.height;
context->pix_fmt = AV_PIX_FMT_YUV420P;
context->sample_aspect_ratio = av_make_q (1, 1);
context->color_range = AVCOL_RANGE_MPEG;
context->bit_rate  = 480000;
context->gop_size  = 10;
context->time_base = av_make_q (1, settings.timebase);
avcodec_parameters_from_context (stream->codecpar, context);

AVDictionary* options = nullptr;

if (encoder->id == AV_CODEC_ID_H264) {
    av_dict_set (&options, "preset", "slow", 0);
    av_dict_set (&options, "tune", "film", 0);
    av_opt_set (context->priv_data, "profile", "baseline", AV_OPT_SEARCH_CHILDREN);
}
if (formatContext->oformat->flags & AVFMT_GLOBALHEADER)
            context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

int ret = avcodec_open2 (context, encoder, &options);
av_dict_free (&options);

// audio stream:
codec = av_guess_codec (formatContext->oformat, nullptr, filename, nullptr, AVMEDIA_TYPE_AUDIO);
auto* encoder = avcodec_find_encoder (codec);

auto* stream = avformat_new_stream (formatContext, NULL);

auto channelLayout = AV_CH_LAYOUT_STEREO;

stream->time_base = av_make_q (1, settings.timebase);
auto* context = avcodec_alloc_context3 (encoder);
context->sample_rate = settings.timebase;
context->sample_fmt = AV_SAMPLE_FMT_FLTP;
context->channel_layout = channelLayout;
context->channels = av_get_channel_layout_nb_channels (channelLayout);
context->bit_rate = 64000;
context->frame_size = settings.defaultNumSamples;
context->bits_per_raw_sample = 32;
context->time_base = av_make_q (1, settings.timebase);
avcodec_parameters_from_context (stream->codecpar, context);

if (formatContext->oformat->flags & AVFMT_GLOBALHEADER)
            context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

int ret = avcodec_open2 (context, encoder, NULL);

// preparing for writing:
if (!(formatContext->oformat->flags & AVFMT_NOFILE))
    if (avio_open (&formatContext->pb, filename, AVIO_FLAG_WRITE) < 0)
        return false;

auto ret = avformat_write_header (formatContext, nullptr);

// send audio and video frames, writing using
av_interleaved_write_frame (formatContext, packet);

// closing container:
// [flushing sending nullptr frames]

av_write_trailer (formatContext);

The full source code is available on github: https://github.com/ffAudio/foleys_video_engine/blob/973019d0c85e740b6f7bfdda190de49ce8d0ce6a/ReadWrite/FFmpeg/FFmpegWriter.cpp

If necessary, I can add the parts, how I fill the frames and packets as well.

  • Are there only certain settings known to work?
  • Did I miss some setting to be declared, like frame duration?
  • Something completely different?

EDIT: this is the output of qtff-movdump:

➜  src git:(master) ✗ ./movdump ~/Movies/demo.mp4
ftyp: s=        32 (0x00000020), o=         0 (0x00000000)
  major_brand: isom (69 73 6f 6d)
  minor_version: 0x00000200
  compatible_brands: isom (69 73 6f 6d), iso2 (69 73 6f 32), avc1 (61 76 63 31), mp41 (6d 70 34 31)
free: s=         8 (0x00000008), o=        32 (0x00000020)
mdat: s=   5858977 (0x005966a1), o=        40 (0x00000028)
  ...skipped 5858969 bytes
moov: s=     44032 (0x0000ac00), o=   5859017 (0x005966c9)
    mvhd: s=       108 (0x0000006c), o=   5859025 (0x005966d1)
      version: 0
      flags: 0x000000
      creation_time: 1904-01-01T00:00:00Z (0 sec since 1904-01-01)
      modification_time: 1904-01-01T00:00:00Z (0 sec since 1904-01-01)
      timescale: 1000
      duration: 83292 (83.292000 sec)
      preferred_rate: 1.000000
      preferred_volume: 1.000000
      reserved: (size 10)  00 00 00 00 00 00 00 00 00 00  |..........|
      matrix:
        1.000000 0.000000 0.000000
        0.000000 1.000000 0.000000
        0.000000 0.000000 1.000000
      preview_time: 0
      preview_duration: 0 (0.000000 sec)
      poster_time: 0
      selection_time: 0
      selection_duration: 0 (0.000000 sec)
      current_time: 0
      next_track_id: 3
    trak: s=     17539 (0x00004483), o=   5859133 (0x0059673d)
        tkhd: s=        92 (0x0000005c), o=   5859141 (0x00596745)
          version: 0
          flags: 0x000003
          creation_time: 1904-01-01T00:00:00Z (0 sec since 1904-01-01)
          modification_time: 1904-01-01T00:00:00Z (0 sec since 1904-01-01)
          track_id: 1
          reserved: 0x00000000
          duration: 83292 (83.292000 sec)
          reserved: (size 8)  00 00 00 00 00 00 00 00  |........|
          layer: 0
          alternate_group: 0
          volume: 0.000000
          reserved: 0x0000
          matrix:
            1.000000 0.000000 0.000000
            0.000000 1.000000 0.000000
            0.000000 0.000000 1.000000
          track_width: 800.000000
          track_height: 576.000000
        edts: s=        36 (0x00000024), o=   5859233 (0x005967a1)
            elst: s=        28 (0x0000001c), o=   5859241 (0x005967a9)
              version: 0
              flags: 0x000000
              edit_list_table (         1):
                     i    duration       time          rate
                  0000       83292          0      1.000000
        mdia: s=     17403 (0x000043fb), o=   5859269 (0x005967c5)
            mdhd: s=        32 (0x00000020), o=   5859277 (0x005967cd)
              version: 0
              flags: 0x000000
              creation_time: 1904-01-01T00:00:00Z (0 sec since 1904-01-01)
              modification_time: 1904-01-01T00:00:00Z (0 sec since 1904-01-01)
              timescale: 24000
              duration: 1998997 (83.291542 sec)
              language: 0x55c4 (und)
              quality: 0
            hdlr: s=        45 (0x0000002d), o=   5859309 (0x005967ed)
              version: 0
              flags: 0x000000
              component_type: .... (00 00 00 00)
              component_sub_type: vide
              component_manufacturer: 0
              component_flags: 0x00000000
              component_flags_mask: 0x00000000
              component_name: 'VideoHandler' + 0x00
            minf: s=     17318 (0x000043a6), o=   5859354 (0x0059681a)
                vmhd: s=        20 (0x00000014), o=   5859362 (0x00596822)
                  version: 0
                  flags: 0x000001 (no lean ahead)
                  graphics_mode: 00
                  opcolor: RGB(0x0000,0x0000,0x0000)
                dinf: s=        36 (0x00000024), o=   5859382 (0x00596836)
                    dref: s=        28 (0x0000001c), o=   5859390 (0x0059683e)
                      version: 0
                      flags: 0x000000
                      entries (         1):
                        url : s=        12 (0x0000000c), o=   5859406 (0x0059684e)
                          version: 0
                          flags: 0x000001 (self reference)
                          data: (0 bytes) url:
                stbl: s=     17254 (0x00004366), o=   5859418 (0x0059685a)
                    stsd: s=       126 (0x0000007e), o=   5859426 (0x00596862)
                      version: 0
                      flags: 0x000000
                      sample_descriptions (0x00000001):
                        size: 0000006e
                        data_format: avc1 (61 76 63 31)
                        reserved: (size 6)  00 00 00 00 00 00  |......|
                        data_ref_index: 0x0001
                        version: 0
                        revision: 0x0000
                        vendor: .... (00 00 00 00)
                        temporal_quality: 0x00000000
                        spatial_quality: 0x00000000
                        width: 800
                        height: 576
                        horizontal_resolution: 72.000000
                        vertical_resolution: 72.000000
                        data_size: 0
                        frame_count: 1
                        compressor_name: '' + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                        depth: 24
                        color_table_id: 0xffff
                        avcC: s=         8 (0x00000008), o=   5859528 (0x005968c8)
Exception: num_read <= CURRENT_ATOM.rem_size failed at line 177
  • What does movdump show as different between the files, especially on mvhd timescale and stsd? – Gyan Apr 29 '19 at 12:04
  • Thank you @Gyan for pointing me to that tool. I didn't see an output for mvhd and stsd, but that might be to my poor understanding of proper terminology. I'll add the relevant output in the question above. – Daniel Walz Apr 29 '19 at 12:44
  • movdump turns out to be a generic name. I meant the one here: github.com/bbc/qtff-parameter-editor – Gyan Apr 29 '19 at 14:06
  • Thanks @Gyan, that looks better now. I replaced the output in the post. It might also be a hint, that the movdump stops with an exception. – Daniel Walz Apr 29 '19 at 14:51
  • Your video stream config is corrupt: avcC: s= 8 (0x00000008), this indicates that no extradata was found by the muxer for the video stream. – Gyan Apr 29 '19 at 15:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.