Newest 'libx264' Questions - Stack Overflow

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

Les articles publiés sur le site

  • GStreamer x264enc Buffered Frames are Sped-Up after EOS Event

    31 janvier 2024, par user21956843

    After sending EOS, the encoder sends its buffered frames down the pipeline, but the playback of those last ~2s of footage is sped up.

    Pipeline:

    autovideosrc [avfvideosrc] ! clockoverlay ! videoconvert ! video/x-raw,format=I420 !
    x264enc bframes=0 bitrate=512 ! video/x-264,stream-format=avc,alignment=au,framerate=20/1 ! kvssink
    

    The application plays the pipeline for 10s, then sends an EOS event on the source element. The custom sink kvssink streams frames to cloud storage, the playback of this 10s of footage is fine except for the encoder's ~2s of buffered frames that were sent out after the EOS event being sped up. How can I correct this?

  • How to write a video file using FFmpeg

    15 janvier 2024, par Summit

    I am trying to write a video file using FFMPEG but i get the following errors

    [libx264 @ 000002bdf90c3c00] broken ffmpeg default settings detected
    [libx264 @ 000002bdf90c3c00] use an encoding preset (e.g. -vpre medium)
    [libx264 @ 000002bdf90c3c00] preset usage: -vpre  -vpre 
    [libx264 @ 000002bdf90c3c00] speed presets are listed in x264 --help
    [libx264 @ 000002bdf90c3c00] profile is optional; x264 defaults to high
    

    This is my code

    #pragma warning(disable : 4996)
    
    extern "C" {
    #include avformat.h>
    #include opt.h>
    #include mathematics.h>
    #include swscale.h>
    }
    
    int main() {
        av_register_all();
        AVFormatContext* formatContext = nullptr;
        AVOutputFormat* outputFormat = nullptr;
        AVStream* videoStream = nullptr;
    
        const char* filename = "output.mp4";
    
        // Open the output file
        if (avformat_alloc_output_context2(&formatContext, nullptr, nullptr, filename) < 0) {
            fprintf(stderr, "Error allocating output format context\n");
            return -1;
        }
    
        outputFormat = formatContext->oformat;
    
        // Add a video stream
        videoStream = avformat_new_stream(formatContext, nullptr);
        if (!videoStream) {
            fprintf(stderr, "Error creating video stream\n");
            return -1;
        }
    
        // Set codec parameters, you may need to adjust these based on your needs
        AVCodecContext* codecContext = avcodec_alloc_context3(nullptr);
        codecContext->codec_id = outputFormat->video_codec;
        codecContext->codec_type = AVMEDIA_TYPE_VIDEO;
        codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
        codecContext->width = 640;
        codecContext->height = 480;
        codecContext->time_base = { 1, 25 };
    
        // Open the video codec
        AVCodec* videoCodec = avcodec_find_encoder(codecContext->codec_id);
        if (!videoCodec) {
            fprintf(stderr, "Error finding video codec\n");
            return -1;
        }
    
        if (avcodec_open2(codecContext, videoCodec, nullptr) < 0) {
            fprintf(stderr, "Error opening video codec\n");
            return -1;
        }
    
        videoStream->codecpar->codec_id = codecContext->codec_id;
        videoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
        videoStream->codecpar->format = codecContext->pix_fmt;
        videoStream->codecpar->width = codecContext->width;
        videoStream->codecpar->height = codecContext->height;
    
        if (avformat_write_header(formatContext, nullptr) < 0) {
            fprintf(stderr, "Error writing header\n");
            return -1;
        }
    
        // Create a frame
        AVFrame* frame = av_frame_alloc();
        frame->format = codecContext->pix_fmt;
        frame->width = codecContext->width;
        frame->height = codecContext->height;
        av_frame_get_buffer(frame, 32);
    
        // Fill the frame with red color
        for (int y = 0; y < codecContext->height; ++y) {
            for (int x = 0; x < codecContext->width; ++x) {
                frame->data[0][y * frame->linesize[0] + x * 3] = 255;     // Red component
                frame->data[0][y * frame->linesize[0] + x * 3 + 1] = 0;   // Green component
                frame->data[0][y * frame->linesize[0] + x * 3 + 2] = 0;   // Blue component
            }
        }
    
        // Write video frames
        AVPacket packet;
        for (int i = 0; i < 100; ++i) {
            // Send the frame for encoding
            if (avcodec_send_frame(codecContext, frame) < 0) {
                fprintf(stderr, "Error sending a frame for encoding\n");
                return -1;
            }
    
            // Receive the encoded packet
            while (avcodec_receive_packet(codecContext, &packet) == 0) {
                // Write the packet to the output file
                if (av_write_frame(formatContext, &packet) != 0) {
                    fprintf(stderr, "Error writing video frame\n");
                    return -1;
                }
                av_packet_unref(&packet);
            }
        }
    
        // Write the trailer
        if (av_write_trailer(formatContext) != 0) {
            fprintf(stderr, "Error writing trailer\n");
            return -1;
        }
    
        // Clean up resources
        av_frame_free(&frame);
        avcodec_free_context(&codecContext);
        avformat_free_context(formatContext);
    
        return 0;
    }
    
  • FFMPEG, want to encode 720x480 and automatically scale to 640x480 or 854x480 as necessary depending on the ratio

    2 décembre 2023, par boxylogan

    EDIT: See appended notes at the bottom of the post.

    Note: all MKVs are sourced from my original Farscape Starburst DVDs, MPEG2. I've been slowly re-encoding my old TV shows into a crisper format and I have for some shows, mainly extras (but also full episodes) MKVs that are a mix of 4:3 and 16:9. Usually I open the files up in Mediainfo and find out which ones are 4:3, stick them in one folder to encode in 640x480, then the same with 16:9. It's worked fine for the umpteen amount of times I've had to encode my shows. I would like to try to expedite the process with a single FFMPEG command that can automatically detect if the files are 4:3 or 16:9 and encode them properly to 640x480 or 854x480.

    My main FFMPEG commands have been these two, depending on which aspect ratio I'm using:

    854x480p

    `for i in *.mkv; do ffmpeg -i "$i" -c:v libx264 -profile:v main -level:v 4.0 -crf 20 -c:a copy -map 0 -vf scale=854:480,setdar=16/9 encoded/"${i%.mkv}.mkv"; done
    

    640x480p

    `for i in *.mkv; do ffmpeg -i "$i" -c:v libx264 -profile:v main -level:v 4.0 -crf 20 -c:a copy -map 0 -vf scale=640:480,setdar=4/3 encoded/"${i%.mkv}.mkv"; done
    

    These two have worked fine lately since I got away from the extraneous -x264-params nonsense I picked up years ago. Again, I'm trying to streamline. I found this command a day ago and it SEEMED to look PERFECT:

    `for i in *.mkv; do ffmpeg -i "$i" -c:v libx264 -profile:v main -level:v 4.0 -crf 20 -c:a copy -map 0 -vf scale=w='if(gt(dar,854/480),min(854,iw*sar),2*trunc(iw*sar*oh/ih/2))':h='if(gt(dar,854/480),2*trunc(ih*ow/iw/sar/2),min(480,ih))' encoded/"${i%.mkv}.mkv"; done
    

    Looks perfect and works great for 640x480. The only problem is that it returns 852x480, every time. I even tried a modification I found where you set the setsar=1 AFTER the scale filter, and it does nothing.

    These are the first warnings I get when I try to run the command, with a 16:9 video, but it still completes:

    `[Parsed_scale_0 @ 0x56299c22fcc0] Circular references detected for width 'if(gt(dar, 854/480), min(854,iw*sar), 2*trunc(iw*sar*oh/ih/2))' and height 'if(gt(dar, 854/480), 2*trunc(ih*ow/iw/sar/2), min(480,ih))' - possibly invalid.
    Stream mapping:
      Stream #0:0 -> #0:0 (mpeg2video (native) -> h264 (libx264))
      Stream #0:1 -> #0:1 (copy)
    Press [q] to stop, [?] for help
    [Parsed_scale_0 @ 0x56299c20e5c0] Circular references detected for width 'if(gt(dar, 854/480), min(854,iw*sar), 2*trunc(iw*sar*oh/ih/2))' and height 'if(gt(dar, 854/480), 2*trunc(ih*ow/iw/sar/2), min(480,ih))' - possibly invalid.
    

    It encodes and I can see the resolution it outputs to:

    `Stream #0:0(eng): Video: h264 (H264 / 0x34363248), yuv420p(tv, top coded first (swapped)), 852x480 [SAR 1:1 DAR 71:40], q=2-31, 29.97 fps, 1k tbn
    

    The next video is a 4:3 video and gives these warnings, however the video still completes, this time the video encodes properly to 640x480:your text

    `[Parsed_scale_0 @ 0x5623084d4140] Circular references detected for width 'if(gt(dar, 854/480), min(854,iw*sar), 2*trunc(iw*sar*oh/ih/2))' and height 'if(gt(dar, 854/480), 2*trunc(ih*ow/iw/sar/2), min(480,ih))' - possibly invalid.
    Stream mapping:
      Stream #0:0 -> #0:0 (mpeg2video (native) -> h264 (libx264))
      Stream #0:1 -> #0:1 (copy)`your text`
    Press [q] to stop, [?] for help
    [Parsed_scale_0 @ 0x5623084d7080] Circular references detected for width 'if(gt(dar, 854/480), min(854,iw*sar), 2*trunc(iw*sar*oh/ih/2))' and height 'if(gt(dar, 854/480), 2*trunc(ih*ow/iw/sar/2), min(480,ih))' - possibly invalid.
    

    The output details:

    `Stream #0:0(eng): Video: h264 (H264 / 0x34363248), yuv420p(tv, top coded first (swapped)), 640x48 [SAR 1:1 `your text`DAR 4:3], q=2-31, 29.97 fps, 1k tbn
    

    TL;DR

    EDIT: The actual problem is that the command is encoding the 16:9 aspect ratio files to 852x480 instead of 854x480. 854x480 is actually what I would like. 640x480 for the 4:3 is fine. Apologies, for the lack of clarification.

    Videos encode (from original Farscape Starburst DVDs MPEG2) properly to libx264 640x480 for 4:3 but not to 854x480 for 16:9. 16:9 instead encodes to 852x480, despite what command is telling it to do.

    Advice? Thanks in advance! Anything to make my re-encoding a little bit less tedious. I've been googling for hours and searching, but nothing seems to make it click. Thank you again!

  • ffmpeg memory leak when opening libx264 encoder

    18 octobre 2023, par ksb496

    I have spotted a memory leak issue when I use the libx264 encoder in the FFmpeg C API. Specifically, when it comes to deallocate memory after encoding a video. After tracking the factor that causes it, I realized that it happens after invoking avcodec_open2, which allocates some memory that afterwards cannot be freed. Once the video is processed, calling avcodec_close and then avcodec_free_context does not entirely free all the allocated memory.

    After some investigation, I found out that the problem could be located in AVCodecContext::priv_data being allocated but not being freed afterwards. In this question a solution to the issue is proposed. However, I tried to implement it without success (the memory being leaked seems to be exactly the same).

    As a matter of fact, the following simple code (which includes the patch that was proposed in the aforementioned question), in which the codec is being opened and closed multiple times without even writing a single frame or allocating an AVFormatContext, illustrates the memory leak.

    #include 
    extern "C"{
    #include 
    #include avcodec.h>
    #include opt.h>
    }
    
    int main()
    {
        avcodec_register_all();
    
        AVCodec *codec;
        AVCodecContext *c;
        for (int n=0; n<2000; n++)
        {
            codec = avcodec_find_encoder_by_name("libx264");
            c=avcodec_alloc_context3(codec);
            c->pix_fmt=AV_PIX_FMT_YUV420P;
            c->width=1920;
            c->height=1080;
            c->time_base=(AVRational){1, 30};
            c->framerate=(AVRational){30, 1};
            avcodec_open2(c, codec, NULL);
            avcodec_close(c);
            av_opt_free(c->priv_data);
            av_freep(&c->priv_data);
            avcodec_free_context(&c);
        }
        return 0;
    }
    

    It must be remarked that if the line codec = avcodec_find_encoder_by_name("libx264") is replaced to an invocation to an internal/native encoder, e.g., codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4), then the memory leak issue completely disappears. Hence, it certainly seems to be an issue related to some private data of the external encoder not being properly freed.

    It is also worth mentioning that I am using an old version of ffmpeg and libx264. To be more precise, ffmpeg version 2.8git and libx264 version 0.136.x. For technical reasons that are beyond the scope of this question, it is not possible to upgrade the libraries to newer versions onto the project in which these are being used. I am fully aware that most of the involved ffmpeg/libx264 code has been probably changed along the years and many functions became deprecated or fixed, and thus reporting this as a possible bug in the ffmpeg developer's mailbox is out of the question.

    Nevertheless, I am still asking this here because I would like to know whether it is just some mistake on my end and/or something I am not taking into account when it comes to free all the memory relative to an external encoder (best case scenario). Otherwise, I would like to know whether there can be some reasonably cheap solution through some custom code or function that can be implemented as a patch (assuming it is indeed an issue related to ffmpeg/libx264), no matter if it makes the whole deallocation code less elegant or concise. If someone is still working on these older versions of ffmpeg and can come up with a workaround, that would be highly appreciated.

  • Why does moviepy complain about bitrate while generating audiofile ?

    6 octobre 2023, par Roman

    I have just try to use moviepy library for the first time. Generation of movies from numpy arrays was really simple, intuitive and worked out of box. This is what I tried:

    from moviepy.editor import VideoClip
    import numpy as np
    
    def make_frame(t):
    
        val = int(255.0*(t/3.0))
    
        ls = []
        for height in range(100):
            row = []
            for width in range(300):
                row.append([val,0,0])
            ls.append(row)
        frame = np.array(ls)
        return frame
    
    animation = VideoClip(make_frame, duration = 3)
    
    animation.write_gif('first_try.gif', fps=24)
    animation.write_videofile('first_try.mp4', fps=24)
    

    Then I wanted to use moviepy to generate sound. In theory it should work in a very similar way. Here is what I tried:

    from moviepy.editor import AudioClip
    import numpy as np
    
    make_frame = lambda t : 2*[ np.sin(404 * 2 * np.pi * t) ]
    clip = AudioClip(make_frame, duration=5)
    
    clip.write_audiofile('sound.mp4')
    

    However, I got an error message:

    [MoviePy] Writing audio in sound.mp4
    |----------| 0/111   0% [elapsed: 00:00 left: ?, ? iters/sec]Traceback (most recent call last):
      File "sound.py", line 9, in 
        clip.write_audiofile('sound.mp4')
      File "", line 2, in write_audiofile
      File "/usr/local/lib/python2.7/dist-packages/moviepy/decorators.py", line 54, in requires_duration
        return f(clip, *a, **k)
      File "/usr/local/lib/python2.7/dist-packages/moviepy/audio/AudioClip.py", line 204, in write_audiofile
        verbose=verbose, ffmpeg_params=ffmpeg_params)
      File "", line 2, in ffmpeg_audiowrite
      File "/usr/local/lib/python2.7/dist-packages/moviepy/decorators.py", line 54, in requires_duration
        return f(clip, *a, **k)
      File "/usr/local/lib/python2.7/dist-packages/moviepy/audio/io/ffmpeg_audiowriter.py", line 162, in ffmpeg_audiowrite
        writer.write_frames(chunk)
      File "/usr/local/lib/python2.7/dist-packages/moviepy/audio/io/ffmpeg_audiowriter.py", line 122, in write_frames
        raise IOError(error)
    IOError: [Errno 32] Broken pipe
    
    MoviePy error: FFMPEG encountered the following error while writing file sound.mp4:
    
    Invalid encoder type 'libx264'
    
    
    The audio export failed, possily because the bitrate you specified was two high or too low for the video codec.
    

    Does anybody know what this error means and how this problem can be resolved?