Newest 'x264' Questions - Stack Overflow

http://stackoverflow.com/questions/tagged/x264

Les articles publiés sur le site

  • Encoding images to h264 and rtp output : SDP file without sprop-parameter-sets does not play

    14 septembre 2021, par oarfish

    tl;dr: I try to encode acquired camera frames to h264, send via RTP and play this back on another device. SDP file generated by ffmpeg for a sample video has info which my own SDP file misses. My SDP file plays in ffplay, but not VLC, while both play ffmpeg's SDP file. I am suspecting missing sprop-parameter-sets in my SDP file.

    Ultimately I want to play this back in VLC.


    I am writing code that encodes images to h264 and outputs to an RTP server (or client? anyway the part that is listening). I generate an SDP file for this.

    • ffplay plays the stream without problem
    • mplayer shows a green box embedded in a larger black box, but I read somewhere it only supports mpegts over RTP, so not sure
    • VLC does not play the SDP file.

    Now when instead I use some random video and have ffmpeg output an SDP file like so

    ffmpeg     -re     -i some.mp4     -an     -c:v copy -f rtp -sdp_file
    video.sdp     "rtp://127.0.0.1:5004"
    

    I can see that the generated SDP file – which plays in both ffplay and VLC – includes the base64 encoded sprop-parameter-sets field, and removing this causes the stream to not play.

    > cat video.sdp
    v=0
    o=- 0 0 IN IP4 127.0.0.1
    s=No Name
    c=IN IP4 127.0.0.1
    t=0 0
    a=tool:libavformat 58.76.100
    m=video 5004 RTP/AVP 96
    b=AS:1034
    a=rtpmap:96 H264/90000
    a=fmtp:96 packetization-mode=1;
    sprop-parameter-sets=Z2QANKzZQDAA7fiMBagICAoAAAMAAgAAAwDwHjBjLA==,aOvjyyLA;
    profile-level-id=640034
    

    My own SDP file on the other hand, does not contain this information, and VLC hangs for 10s and then stops trying with "no data received".

    > cat test.sdp
    v=0
    o=- 0 0 IN IP4 127.0.0.1
    s=No Name
    c=IN IP4 127.0.0.1
    t=0 0
    a=tool:libavformat 58.76.100
    m=video 44499 RTP/AVP 96
    b=AS:2000
    a=rtpmap:96 H264/90000
    a=fmtp:96 packetization-mode=1
    

    So my theory is that my custom code must somehow add this SPS information to the SDP file. But despite hours of searching, I could not find a structured way to set the extradata field on the AVStream's AVCodecParams. The code I'm using is roughly this (I'm sure there's unrelated errors in there):

    // variables
    std::vector imgbuf;
    AVFormatContext *ofmt_ctx = nullptr;
    AVCodec *out_codec = nullptr;
    AVStream *out_stream = nullptr;
    AVCodecContext *out_codec_ctx = nullptr;
    SwsContext *swsctx = nullptr;
    cv::Mat canvas_;
    unsigned int height_;
    unsigned int width_;
    unsigned int fps_;
    AVFrame *frame_ = nullptr;
    
    AVOutputFormat *format = av_guess_format("rtp", nullptr, nullptr);
    const auto url = std::string("rtp://127.0.0.1:5001");
    avformat_alloc_output_context2(ofmt_ctx, format, format->name, url.c_str());
    
    out_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    stream = avformat_new_stream(ofmt_ctx, out_codec);
    out_codec_ctx = avcodec_alloc_context3(out_codec);
    
    // then, for each incoming image:
    while (receive_image) {
      static bool first_time = true;
      if (first_time) {
        // discover necessary params such as image dimensions from the first
        // received image
        first_time = false;
        height_ = image.rows;
        width_ = image.cols;
    
        codec_ctx->codec_tag = 0;
        codec_ctx->bit_rate = 2e6;
        // does nothing, unfortunately
        codec_ctx->thread_count = 1;
        codec_ctx->codec_id = AV_CODEC_ID_H264;
        codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
        codec_ctx->width = width_;
        codec_ctx->height = height_;
        codec_ctx->gop_size = 6;
        codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
        codec_ctx->framerate = fps_;
        codec_ctx->time_base = av_inv_q(fps_);
    
        avcodec_parameters_from_context(stream, out_codec_ctx);
    
        // this stuff is empty: is that the problem?
        stream->codecpar->extradata = codec_ctx->extradata;
        stream->codecpar->extradata_size = codec_ctx->extradata_size;
    
        AVDictionary *codec_options = nullptr;
        av_dict_set(&codec_options, "profile", "high", 0);
        av_dict_set(&codec_options, "preset", "ultrafast", 0);
        av_dict_set(&codec_options, "tune", "zerolatency", 0);
    
        // open video encoder
        avcodec_open2(codec_ctx, codec, &codec_options);
    
        stream->time_base.num = 1;
        stream->time_base.den = fps_;
        avio_open(&(ofmt_ctx->pb), ofmt_ctx->filename, AVIO_FLAG_WRITE);
    
        /* Write a file for VLC */
        char buf[200000];
        AVFormatContext *ac[] = {ofmt_ctx};
        av_sdp_create(ac, 1, buf, 20000);
        printf("sdp:\n%s\n", buf);
        FILE *fsdp = fopen("test.sdp", "w");
        fprintf(fsdp, "%s", buf);
        fclose(fsdp);
    
        swsctx = sws_getContext(width_, height_, AV_PIX_FMT_BGR24, width_, height_,
                                out_codec_ctx->pix_fmt, SWS_BICUBIC, nullptr,
                                nullptr, nullptr);
      }
    
      if (!frame_) {
        frame_ = av_frame_alloc();
    
        std::uint8_t *framebuf = new uint8_t[av_image_get_buffer_size(
            codec_ctx->pix_fmt, width_, height_, 1)];
        av_image_fill_arrays(frame_->data, frame_->linesize, framebuf,
                             codec_ctx->pix_fmt, width, height, 1);
        frame_->width = width_;
        frame_->height = height_;
        frame_->format = static_cast(codec_ctx->pix_fmt);
        success = avformat_write_header(ofmt_ctx, nullptr);
      }
      if (imgbuf.empty()) {
        imgbuf.resize(height_ * width_ * 3 + 16);
        canvas_ = cv::Mat(height_, width_, CV_8UC3, imgbuf.data(), width_ * 3);
      } else {
        image.copyTo(canvas_);
      }
    
      const int stride[] = {static_cast(image.step[0])};
    
      sws_scale(swsctx, &canvas_.data, stride, 0, canvas_.rows, frame_->data,
                frame_->linesize);
      frame_->pts += av_rescale_q(1, out_codec_ctx->time_base, stream->time_base);
    
      AVPacket pkt = {0};
      avcodec_send_frame(out_codec_ctx, frame_);
      avcodec_receive_packet(out_codec_ctx, &pkt);
      av_interleaved_write_frame(ofmt_ctx, &pkt);
    }
    

    Can anyone offer some advice here?

    --

    Update

    When setting

    this->out_codec_ctx->flags |=AV_CODEC_FLAG_GLOBAL_HEADER;
    

    extradata is actually present in the codec context, but I had to move avcodec_parameters_from_context() after avcodec_open2(), as the extradata is empty before opening the codec. I now get sprop-parameter-sets in the SDP file, but VLC still does not play it.

  • Error in compiling x264 on ARM 64-bit platform

    2 septembre 2021, par yanzhang.guo

    The same x264 source code I compiled on Debian 10 (Buster) system has no problem, but I can't compile it on an ARM 64-bit platform. Why?

    Maybe there is something wrong with the Makefile, but I don't know where it is.

    1. Configure

      ./configure --disable-asm --enable-shared  --host=aarch64-linux
      
      platform:      AARCH64
      byte order:    little-endian
      system:        LINUX
      cli:           yes
      libx264:       internal
      shared:        yes
      static:        no
      asm:           no
      interlaced:    yes
      avs:           avxsynth
      lavf:          no
      ffms:          no
      mp4:           no
      gpl:           yes
      thread:        posix
      opencl:        yes
      filters:       crop select_every
      lto:           no
      debug:         no
      gprof:         no
      strip:         no
      PIC:           yes
      bit depth:     all
      chroma format: all
      
    2. Edit file config.mak,

      SRCPATH=.
      prefix=/usr/local
      exec_prefix=${prefix}
      bindir=${exec_prefix}/bin
      libdir=${exec_prefix}/lib
      includedir=${prefix}/include
      SYS_ARCH=AARCH64
      SYS=LINUX
      CC=aarch64-linux-gnu-gcc
      CFLAGS=-Wno-maybe-uninitialized -Wshadow -O3 -ffast-math  -Wall -I. -I$(SRCPATH) -std=gnu99 -
      D_GNU_SOURCE -fPIC -fomit-frame-pointer -fno-tree-vectorize
      COMPILER=GNU
      COMPILER_STYLE=GNU
      DEPMM=-MM -g0
      DEPMT=-MT
      LD=aarch64-linux-gnu-gcc -o
      LDFLAGS= -lm -lpthread -ldl
      LIBX264=libx264.a
      AR=aarch64-linux-gnu-gcc-ar rc
      RANLIB=aarch64-linux-gnu-gcc-ranlib
      STRIP=aarch64-linux-gnu-strip
      INSTALL=install
      AS=
      ASFLAGS= -I. -I$(SRCPATH) -DSTACK_ALIGNMENT=16 -DPIC
      RC=
      RCFLAGS=
      EXE=
      HAVE_GETOPT_LONG=1
      DEVNULL=/dev/null
      PROF_GEN_CC=-fprofile-generate
      PROF_GEN_LD=-fprofile-generate
      PROF_USE_CC=-fprofile-use
      PROF_USE_LD=-fprofile-use
      HAVE_OPENCL=yes
      CC_O=-o $@
      default: cli
      install: install-cli
      SOSUFFIX=so
      SONAME=libx264.so.157
      SOFLAGS=-shared -Wl,-soname,$(SONAME)  -Wl,-Bsymbolic
      default: lib-shared
      install: install-lib-shared
      LDFLAGSCLI = -ldl
      CLI_LIBX264 = $(LIBX264)
      
    3. Make, an error occurred, details in error.

    4. Add file config.h after configure,

       #define HAVE_MALLOC_H 1
       #define ARCH_X86_64 1
       #define SYS_LINUX 1
       #define STACK_ALIGNMENT 64
       #define HAVE_POSIXTHREAD 1
       #define HAVE_CPU_COUNT 1
       #define HAVE_THREAD 1
       #define HAVE_LOG2F 1
       #define HAVE_STRTOK_R 1
       #define HAVE_CLOCK_GETTIME 1
       #define HAVE_MMAP 1
       #define HAVE_THP 1
       #define HAVE_AVS 1
       #define USE_AVXSYNTH 1
       #define HAVE_VECTOREXT 1
       #define fseek fseeko
       #define ftell ftello
       #define HAVE_BITDEPTH8 1
       #define HAVE_BITDEPTH10 1
       #define HAVE_GPL 1
       #define HAVE_INTERLACED 1
       #define HAVE_OPENCL (BIT_DEPTH==8)
       #define HAVE_ALTIVEC 0
       #define HAVE_ALTIVEC_H 0
       #define HAVE_MMX 0
       #define HAVE_ARMV6 0
       #define HAVE_ARMV6T2 0
       #define HAVE_NEON 0
       #define HAVE_BEOSTHREAD 0
       #define HAVE_WIN32THREAD 0
       #define HAVE_SWSCALE 0
       #define HAVE_LAVF 0
       #define HAVE_FFMS 0
       #define HAVE_GPAC 0
       #define HAVE_LSMASH 0
       #define HAVE_X86_INLINE_ASM 0
       #define HAVE_AS_FUNC 0
       #define HAVE_INTEL_DISPATCHER 0
       #define HAVE_MSA 0
       #define HAVE_WINRT 0
       #define HAVE_VSX 0
       #define HAVE_ARM_INLINE_ASM 0
      
  • High Quality Screen Capture with FFmpeg

    27 août 2021, par plumzl

    I'm trying to figure out a command for high quality screen capture on REHL.

    I have tried various options, but none really worked. The quality is not good enough. I'm quite new to ffmpeg and doesn't quite understand all the different flags. So any help would be appreciated!

    The commands I have tried:

    ffmpeg -y -f x11grab -r 30 -s 1920x1080 -i :0.0+0,0 -vcodec libx264 -strict -2 -b:v 16M output.mov
    

    The first command I tried. The weird thing is it doesn't seem to preserve the bitrate specified -b:v 16M. The output video's bitrate is only 2mb/s. Is that not the correct way to specify bitrate when doing screen capture?

    ffmpeg -f x11grab -s 1920x1080 -r 30 -i :0.0 -qscale 0 -vcodec huffyuv output.mov
    

    The huffyuv codec is supposed to be lossless, but the quality doesn't seem to be any better than the libx264 output.

    ffmpeg -f x11grab -r 30 -s 1920x1080 -i :0.0+0,0 -vcodec copy -pix_fmt yuv420p -qscale 0 -an output.mkv
    ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 1920x1080 -r 30 -i output.mkv -an -c:v libx264 -qscale 0 result.mov 
    

    I'm even trying to capture rawvideo and then convert it to libx264 codec viedeo. But the output is corrupted.

    I'm using the version of ffmpeg that's built on April 23rd this year. It doesn't have the preset like -vpre lossless_ultrafast which I see mentioned in a lot posts.

    Edit:

    After more research, this is the command I end up using. I have to use h264 codec and yuv420p as pixel_fmt since I need to be able to play the quicktimes using quicktime.

    ffmpeg -y -f x11grab -framerate 30 -video_size 1920x1080 -i :0.0+0,0 -c:v libx264 -pix_fmt yuv420p -qp 0 -preset ultrafast output.mov
    

    The quality doesn't seem to be much improved even though -qp is set to 0. But it could also because of the rgb conversion to yuv color space according to this post.

    https://trac.ffmpeg.org/wiki/Encode/H.264

  • Gstreamer, x264enc "Redistribute latency..." error

    20 août 2021, par Jason

    I'm trying to setup a video pipeline with very limited bandwidth. I was able to do it with two raspberry pis using the below lines. The first is for the camera pi and the second is to watch stream:

    gst-launch-1.0 rpicamsrc preview=false !  'video/x-h264, width=800, height=600, framerate=30/1' ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! udpsink host=YOUR_PC_IP port=5000
    gst-launch-1.0 udpsrc port=5000 ! gdpdepay ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink sync=false
    

    It works but I go over my bandwidth limit if there is movement. I'm not sure if there is a way to limit bandwidth by setting a parameter here:

    'video/x-h264, width=800, height=600, framerate=30/1'
    

    From what I can find online, I have to use something like x264enc. I've followed tutorials but I can't get x264enc to work. it always outputs "Redistribute latency..." on both machines when run and it stays there.

    I've tried using x264enc like follows:

    gst-launch-1.0 rpicamsrc preview=false !  'video/x-raw, width=800, height=600, framerate=30/1' ! x264enc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! udpsink host=YOUR_PC_IP port=5000
    gst-launch-1.0 rpicamsrc preview=false !  'video/x-raw, width=800, height=600, framerate=30/1' ! x264enc tune=zerolatency ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! udpsink host=YOUR_PC_IP port=5000
    gst-launch-1.0 rpicamsrc preview=false ! x264enc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! udpsink host=YOUR_PC_IP port=5000
    gst-launch-1.0 rpicamsrc preview=false ! x264enc tune=zerolatency ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! udpsink host=YOUR_PC_IP port=5000
    

    Based on tutorials, I would think some of those should work. Other threads say that tune=zerolatency fixes my problem. At least the ones with same output of "Redistribute latency..." I don't know what I'm doing wrong.

    Any help would be appreciated. Thanks!

  • How to encode multiple files with a batch file

    11 juillet 2021, par Black Butterfly

    I am Encoding my own anime videos to save some space on my HDD using this script

    https://gist.github.com/ScarletDevil25/9d71e4a7f5c215e558ecad158aa52600

    However I can only encode one video at a time by dragging said video to the batch file and allowing it to run.

    What I would like to be able to do is have the batch file encode multiple videos at once.

    also as another question if someone could tell me how I would run this as admin