Newest 'libx264' Questions - Stack Overflow

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

Les articles publiés sur le site

  • ffmpeg x264 CPU core scaling

    15 décembre 2019, par alex416

    Does anyone have any experence with this type of thing? Currently using a Ryzen 7 8c/16T CPU, and using a program called BES. Using 10% CPU, is almost no slower at transcoding from mkv to mp4 (both x264, i know i can just copy them) than using 100% cpu on all 16 threads. So, Since this is the case, What is the ideal core count for libx264? I mean, Does the same type of thing happen with 32 threads? Or 8 threads, etc.

  • 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).