Newest 'libx264' Questions - Stack Overflow

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

Les articles publiés sur le site

  • Force x264 to encode all frames relative to the first (IDR) frame

    12 décembre 2019, par cloudraven

    I want to generate a h.264 stream in which P-frames are using references exclusively using a long-term reference to the first frame (an IDR frame). This would also require the first frame to be an IDR frame.

    This is an academic experiment to understand the encoding behavior of long-term references and the consequences of forcing frames to refer to a specific (single) frame rather than several.

    It would be great if I could do this from the command line, but if not possible I am open to modifying x264 for this purpose.

    Could anyone point me to where in the source code it is determined:

    • the reference frame / macroblock / partition for the current macroblock
    • changes made to the short term, long term reference frame list
    • whether to use a short term reference frame or a long term reference frame.

    Using another encoder like nvenc is also acceptable.

  • Force x264 to only use long term reference frames

    12 décembre 2019, par cloudraven

    I want to generate a h.264 stream in which P-frames are using references exclusively using long-term references identifiers rather than defaulting to a short-term reference given by the previous frame.

    At this point this is an academic experiment to understand the encoding behavior of long-term references and the consequences of forcing frames to refer to a specific frame rather than several.

    It would be great if I could do this from the command line, but if not possible I am open to modifying x264 for this purpose.

    Could anyone point me to where in the source code it is determined:

    • the reference frame / macroblock / partition for the current macroblock
    • changes made to the short term, long term reference frame list
    • whether to use a short term reference frame or a long term reference frame.

    Using another encoder like nvenc is also acceptable.

  • How to set the PTS field with the time the frame was actual captured (using FFmpeg) ?

    28 novembre 2019, par J.M.

    Using FFmpeg, I want to update the PTS field with the time the frame was actual captured. I'm doing it with the following FFmpeg command (the "copyts" flag does the job):

    ffmpeg -re -f v4l2 -copyts -i /dev/video0 -c:v libx264 -intra -f mpegts -mpegts_copyts 1 udp://192.168.10.199:1234

    However, it only works with a small help... I had to edit the v4l2.c file:

    static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
    {
       ...
       ...
       ...
    
       pkt->pts = buf_ts.tv_sec * INT64_C(1000000) + buf_ts.tv_usec; 
    
       pkt->pts &= 0x1ffffffff;  /*modified by me*/                                            
       pkt->dts = 0;             /*modified by me*/
    
       av_log(ctx, AV_LOG_ERROR, "pts: %lld, dts: %lld\n", pkt->pts, pkt->dts);       
       convert_timestamp(ctx, &pkt->pts);                                             
    
       return pkt->size;                                                                                                                                               
    }
    

    Of course, I don't want to modify the function...

    Any idea of to use the "copyts" flag so it will work without editing the function mmap_read_frame() ?

    I'm using the latest FFmpeg source. Without my modifications I get this:

    Output #0, mpegts, to 'udp://192.168.10.55:1234':
      Metadata:
        encoder         : Lavf58.35.100
        Stream #0:0: Video: h264 (cedrus264), nv12, 1280x720, q=2-31, 200 kb/s, 10 fps, 90k tbn, 10 tbc
        Metadata:
          encoder         : Lavc58.64.101 cedrus264
    frame=    1 fps=0.2 q=-0.0 Lsize=      28kB time=59652:19:24.70 bitrate=   0.0kbits/s speed=4.82e+07x    
    video:27kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 4.599154%
    
  • x264 encoded frames into a mp4 container with ffmpeg API

    10 septembre 2019, par PJD

    I'm struggling with understanding what is and what is not needed in getting my already encoded x264 frames into a video container file using ffmpeg's libavformat API.

    My current program will get the x264 frames like this -

    while( x264_encoder_delayed_frames( h ) )
    {
        printf("Writing delayed frame %u\n", delayed_frame_counter++);
        i_frame_size = x264_encoder_encode( h, &nal, &i_nal, NULL, &pic_out );
        if( i_frame_size < 0 ) {
                printf("Failed to encode a delayed x264 frame.\n");
                return ERROR;
            }
        else if( i_frame_size )
        {
            if( !fwrite(nal->p_payload, i_frame_size, 1, video_file_ptr) ) {
                printf("Failed to write a delayed x264 frame.\n");
                return ERROR;
            }
        }
    }
    

    If I use the CLI to the ffmpeg binary, I can put these frames into a container using:

    ffmpeg -i "raw_frames.h264" -c:v copy -f mp4 "video.mp4"
    

    I would like to code this function into my program using the libavformat API though. I'm a little stuck in the concepts and the order on which each ffmpeg function is needed to be called.

    So far I have written:

            mAVOutputFormat = av_guess_format("gen_vid.mp4", NULL, NULL);
            printf("Guessed format\n");
    
            int ret = avformat_alloc_output_context2(&mAVFormatContext, NULL, NULL, "gen_vid.mp4");
            printf("Created context = %d\n", ret);
            printf("Format = %s\n", mAVFormatContext->oformat->name);
    
            mAVStream = avformat_new_stream(mAVFormatContext, 0);
            if (!mAVStream) {
                printf("Failed allocating output stream\n");
            } else {
                printf("Allocated stream.\n");
            }
    
            mAVCodecParameters = mAVStream->codecpar;
            if (mAVCodecParameters->codec_type != AVMEDIA_TYPE_AUDIO &&
                mAVCodecParameters->codec_type != AVMEDIA_TYPE_VIDEO &&
                mAVCodecParameters->codec_type != AVMEDIA_TYPE_SUBTITLE) {
                printf("Invalid codec?\n");
            }
    
            if (!(mAVFormatContext->oformat->flags & AVFMT_NOFILE)) {
                ret = avio_open(&mAVFormatContext->pb, "gen_vid.mp4", AVIO_FLAG_WRITE);
                if (ret < 0) {
                  printf("Could not open output file '%s'", "gen_vid.mp4");
                }
              }
    
            ret = avformat_write_header(mAVFormatContext, NULL);
            if (ret < 0) {
              printf("Error occurred when opening output file\n");
            }
    

    This will print out:

    Guessed format
    Created context = 0
    Format = mp4
    Allocated stream.
    Invalid codec?
    [mp4 @ 0x55ffcea2a2c0] Could not find tag for codec none in stream #0, codec not currently supported in container
    Error occurred when opening output file
    

    How can I make sure the codec type is set correctly for my video? Next I need to somehow point my mAVStream to use my x264 frames - advice would be great.

    Update 1: So I've tried to set the H264 codec, so the codec's meta-data is available. I seem to hit 2 newer issues now. 1) It cannot find the device and therefore cannot configure the encoder. 2) I get the "dimensions not set".

    mAVOutputFormat = av_guess_format("gen_vid.mp4", NULL, NULL);
    printf("Guessed format\n");
    
    // MUST allocate the media file format context. 
    int ret = avformat_alloc_output_context2(&mAVFormatContext, NULL, NULL, "gen_vid.mp4");
    printf("Created context = %d\n", ret);
    printf("Format = %s\n", mAVFormatContext->oformat->name);
    
    // Even though we already have encoded the H264 frames using x264,
    // we still need the codec's meta-data.
    const AVCodec *mAVCodec;
    mAVCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (!mAVCodec) {
        fprintf(stderr, "Codec '%s' not found\n", "H264");
        exit(1);
    }
    mAVCodecContext = avcodec_alloc_context3(mAVCodec);
    if (!mAVCodecContext) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }
    printf("Codec context allocated with defaults.\n");
    /* put sample parameters */
    mAVCodecContext->bit_rate = 400000;
    mAVCodecContext->width = width;
    mAVCodecContext->height = height;
    mAVCodecContext->time_base = (AVRational){1, 30};
    mAVCodecContext->framerate = (AVRational){30, 1};
    mAVCodecContext->gop_size = 10;
    mAVCodecContext->level = 31;
    mAVCodecContext->max_b_frames = 1;
    mAVCodecContext->pix_fmt = AV_PIX_FMT_NV12;
    
    av_opt_set(mAVCodecContext->priv_data, "preset", "slow", 0);
    printf("Set codec parameters.\n");
    
    // Initialize the AVCodecContext to use the given AVCodec.
    avcodec_open2(mAVCodecContext, mAVCodec, NULL);            
    
    // Add a new stream to a media file. Must be called before
    // calling avformat_write_header().
    mAVStream = avformat_new_stream(mAVFormatContext, mAVCodec);
    if (!mAVStream) {
        printf("Failed allocating output stream\n");
    } else {
        printf("Allocated stream.\n");
    }
    
    // TODO How should codecpar be set?
    mAVCodecParameters = mAVStream->codecpar;
    if (mAVCodecParameters->codec_type != AVMEDIA_TYPE_AUDIO &&
        mAVCodecParameters->codec_type != AVMEDIA_TYPE_VIDEO &&
        mAVCodecParameters->codec_type != AVMEDIA_TYPE_SUBTITLE) {
        printf("Invalid codec?\n");
    }
    
    if (!(mAVFormatContext->oformat->flags & AVFMT_NOFILE)) {
        ret = avio_open(&mAVFormatContext->pb, "gen_vid.mp4", AVIO_FLAG_WRITE);
        if (ret < 0) {
          printf("Could not open output file '%s'", "gen_vid.mp4");
        }
      }
    printf("Called avio_open()\n");
    
    // MUST write a header.
    ret = avformat_write_header(mAVFormatContext, NULL);
    if (ret < 0) {
      printf("Error occurred when opening output file (writing header).\n");
    }
    

    Now I am getting this output -

    Guessed format
    Created context = 0
    Format = mp4
    Codec context allocated with defaults.
    Set codec parameters.
    [h264_v4l2m2m @ 0x556460344b40] Could not find a valid device
    [h264_v4l2m2m @ 0x556460344b40] can't configure encoder
    Allocated stream.
    Invalid codec?
    Called avio_open()
    [mp4 @ 0x5564603442c0] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
    [mp4 @ 0x5564603442c0] dimensions not set
    Error occurred when opening output file (writing header).
    
  • What is the difference between libx264 and h264_nvenc ?

    18 août 2019, par Jonathan Morrall

    I am trying to encode some videos but when I use the libx264 they don't work but change the codec to h264_nvenc and they play.

    If I change the profile to baseline when using the libx264 the videos play.

    what is the difference? I could use the h264_nvenc but I want to use the libx264 for the better quality for storage.

    My code

    bin\ffmpeg -i "Input-File" -c:v h264_nvenc -bf 3 -b_strategy 2 -temporal-aq 1 -rc-lookahead 20 -profile:v high -preset slow -rc vbr_hq -rc:v vbr_hq -qmin 0 -cq:v 19 -b:v 900k -maxrate:v 5000k -bufsize 2000K -c:a aac -ar 48000 -b:a 128k "Output-File.mp4"