Newest 'libx264' Questions - Stack Overflow
Les articles publiés sur le site
-
Proper use of `nalu_process` callback in x264
26 janvier 2021, par gsprI wish to make use of libx264's low-latency encoding mechanism, whereby a user-provided callback is called as soon as a single NAL unit is available instead of having to wait for a whole frame to be encoded before starting processing.
The x264 documentation states the following about that facility:
/* Optional low-level callback for low-latency encoding. Called for each output NAL unit * immediately after the NAL unit is finished encoding. This allows the calling application * to begin processing video data (e.g. by sending packets over a network) before the frame * is done encoding. * * This callback MUST do the following in order to work correctly: * 1) Have available an output buffer of at least size nal->i_payload*3/2 + 5 + 64. * 2) Call x264_nal_encode( h, dst, nal ), where dst is the output buffer. * After these steps, the content of nal is valid and can be used in the same way as if * the NAL unit were output by x264_encoder_encode. * * This does not need to be synchronous with the encoding process: the data pointed to * by nal (both before and after x264_nal_encode) will remain valid until the next * x264_encoder_encode call. The callback must be re-entrant. * * This callback does not work with frame-based threads; threads must be disabled * or sliced-threads enabled. This callback also does not work as one would expect * with HRD -- since the buffering period SEI cannot be calculated until the frame * is finished encoding, it will not be sent via this callback. * * Note also that the NALs are not necessarily returned in order when sliced threads is * enabled. Accordingly, the variable i_first_mb and i_last_mb are available in * x264_nal_t to help the calling application reorder the slices if necessary. * * When this callback is enabled, x264_encoder_encode does not return valid NALs; * the calling application is expected to acquire all output NALs through the callback. * * It is generally sensible to combine this callback with a use of slice-max-mbs or * slice-max-size. * * The opaque pointer is the opaque pointer from the input frame associated with this * NAL unit. This helps distinguish between nalu_process calls from different sources, * e.g. if doing multiple encodes in one process. */ void (*nalu_process)( x264_t *h, x264_nal_t *nal, void *opaque );
This seems straight forward enough. However, when I run the following dummy code, I get a segfault on the marked line. I've tried to add some debugging to
x264_nal_encode
itself to understand where it goes wrong, but it seems to be the function call itself that results in a segfault. Am I missing something here? (Let's ignore the fact that the use ofassert
probably makescb
non-reentrant – it's only there to indicate to the reader that my workspace buffer is more than large enough.)#include #include #include #include #include #include #define WS_SIZE 10000000 uint8_t * workspace; void cb(x264_t * h, x264_nal_t * nal, void * opaque) { assert((nal->i_payload*3)/2 + 5 + 64 < WS_SIZE); x264_nal_encode(h, workspace, nal); // Segfault here. // Removed: Process nal. } int main(int argc, char ** argv) { uint8_t * fake_frame = malloc(1280*720*3); memset(fake_frame, 0, 1280*720*3); workspace = malloc(WS_SIZE); x264_param_t param; int status = x264_param_default_preset(¶m, "ultrafast", "zerolatency"); assert(status == 0); param.i_csp = X264_CSP_RGB; param.i_width = 1280; param.i_height = 720; param.i_threads = 1; param.i_lookahead_threads = 1; param.i_frame_total = 0; param.i_fps_num = 30; param.i_fps_den = 1; param.i_slice_max_size = 1024; param.b_annexb = 1; param.nalu_process = cb; status = x264_param_apply_profile(¶m, "high444"); assert(status == 0); x264_t * h = x264_encoder_open(¶m); assert(h); x264_picture_t pic; status = x264_picture_alloc(&pic, param.i_csp, param.i_width, param.i_height); assert(pic.img.i_plane == 1); x264_picture_t pic_out; x264_nal_t * nal; // Not used. We process NALs in cb. int i_nal; for (int i = 0; i < 100; ++i) { pic.i_pts = i; pic.img.plane[0] = fake_frame; status = x264_encoder_encode(h, &nal, &i_nal, &pic, &pic_out); } x264_encoder_close(h); x264_picture_clean(&pic); free(workspace); free(fake_frame); return 0; }
Edit: The segfault happens the first time
cb
callsx264_nal_encode
. If I switch to a different preset, where more frames are encoded before the first callback happens, then several successful calls tox264_encoder_encode
are made before the first callback, and hence segfault, occurs. -
how to trim video in h264 format using ffmpeg while preserving quality ?
16 décembre 2020, par prisonmike11I'm new to ffmpeg,
I'm trimming a small clip from a bluray H264 video by providing start and end duration.
I tried:
ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4
but this results in stuttering issues in start of the video. The audio and video also don't match.
I tried using
-c libx264
but this is taking too long and the output video has much lower bit rate.My goal is to trim as fast as possible while preserving quality. I don't care about the frame accuracy of the trim. I plan on uploading the output to youtube.
what flags should I use?
-
Unknown decoder 'libx264'
29 octobre 2020, par Reboot_My_ComputerI have
ffmpeg
with libx264 enabled from BtbN for Windows 10. This is the command:ffmpeg -f gdigrab -c:v libx264 -framerate 30 -i title="FiveM" -f flv rtmp://MYSITE.COM/stream/MYSECRETKEY
Unfortunately I get this output:
Unknown decoder 'libx264'
-
Why i can't use libx264 with FFMPEG on windows ?
29 octobre 2020, par Reboot_My_ComputerHello there
I'm trying to build game launcher that will start streaming when game starts, for this i am using FFMPEG. It all works fine until i try to use libx264 as encoder.I have FFMPEG with libx264 compiled from https://github.com/BtbN/FFmpeg-Builds/releases. This is the command i am using for it :
ffmpeg -f gdigrab -c:v libx264 -framerate 30 -i title="FiveM" -f flv rtmp://MYSITE.COM/stream/MYSECRETKEY
Unfortunately i get this output: FFMPEG OUTPUT
You can clearly see in output picture that FFMPEG is compiled with libx264, please note that i'm doing this on Windows 10.
-
How do I force an IDR-frame using the x264 C API ?
28 octobre 2020, par KeithI am attempting to use an external bool signal to force the next encoded frame to be an IDR-frame using the x264 C API. I am using the "baseline" profile with the "ultrafast" and "zerolatency" presets. I tried to use the input pic settings prior to encoding, as in this code snippet, but this has not worked. My class Open() and Encode() methods are shown here. Any help will be appreciated.
int X264Encoder::Open(void) { if (_x264VideoEncoder != NULL) Close(); // Set up default parameters. if (x264_param_default_preset(&_param, _encoderSpeedPreset.c_str(), "zerolatency") < 0) // 0=success, -1=failed { _errStr = "X264Encoder::Open: Default parameter preset failed with " + _encoderSpeedPreset; return(0); } // Set non-default params. _param.i_bitdepth = 8; _param.i_csp = _colourSpaceMapping[_colourSpace]; // Input colour space if(!_param.i_csp) { _errStr = "X264Encoder::Open: Incompatible colour space " + to_string(_colourSpace); return(0); } _param.i_width = _width; _param.i_height = _height; _param.i_fps_num = _videoRateNumerator; _param.i_fps_den = _videoRateDenominator; _param.rc.i_bitrate = _avgBitsPerSecond / 1000; // bitrate units are in kbits/s _param.i_threads = 1; _param.b_vfr_input = 0; // VFR input. If 1, use timebase and timestamps for ratecontrol purposes. If 0, use fps only. _param.b_repeat_headers = 1; // Put SPS/PPS before each keyframe _param.b_annexb = 1; // If set, place start codes (4 bytes) before NAL units, otherwise place size (4 bytes) before NAL units. // Apply profile restrictions. if (x264_param_apply_profile(&_param, _profile.c_str()) < 0) // 0=success, -1=failed { _errStr = "X264Encoder::Open: Unable to set profile " + _profile; return(0); } // Initialise the encoder input pic buffer. if (x264_picture_alloc(&_picIn, _param.i_csp, _param.i_width, _param.i_height) < 0) { _errStr = "X264Encoder::Open: Unable to alloc input picture buffer"; return(0); } _inPicIsAllocated = true; // Instantiate the encoder. _x264VideoEncoder = x264_encoder_open(&_param); if (_x264VideoEncoder == NULL) { _errStr = "X264Encoder::Open: Unable to instantiate the encoder"; // Clean up before exit. x264_picture_clean(&_picIn); _inPicIsAllocated = false; return(0); }//end if !_x264VideoEncoder... // Frame counting for pts timestamps. _frameNum = 0; _lastPicType = 0; // IDR-frame d.clear(); return(1); }//end Open. int X264Encoder::Encode(void* pSrc, void* pCmp, void* codeParameter) { _encodedFrameSize = 0; // Validation house work. if(!Ready()) { _errStr = "X264Encoder::Encode: Not ready"; return(0); } if(!pSrc || !pCmp) { _errStr = "X264Encoder::Encode: Invalid function parameter list"; return(0); } // Load input image. if(_param.i_csp != X264_CSP_I420) // Can only process I420 input colour space. { _errStr = "X264Encoder::Encode: I420 colour space required"; return(0); } uint32_t lumSize = _width * _height; uint32_t chrSize = lumSize / 4; // Transfer the input source image into the x264 picture img structure. uint8_t* pImg = static_cast(pSrc); memcpy_s(_picIn.img.plane[0], lumSize, pImg, lumSize); pImg += lumSize; memcpy_s(_picIn.img.plane[1], chrSize, pImg, chrSize); pImg += chrSize; memcpy_s(_picIn.img.plane[2], chrSize, pImg, chrSize); // Encode single frame _picIn.i_pts = _frameNum; if (_idrFrameRequired) { _picIn.i_type = X264_TYPE_IDR; //... and clear the signal. _idrFrameRequired = false; }//end if _idrFrameRequired... else _picIn.i_type = X264_TYPE_AUTO; _encodedFrameSize = x264_encoder_encode(_x264VideoEncoder, &_nal, &_nalCnt, &_picIn, &_picOut); if (_encodedFrameSize > 0) { // Write the encoded stream to the output. uint8_t* pOut = static_cast(pCmp); memcpy_s(pOut, _encodedFrameSize, _nal->p_payload, _encodedFrameSize); }//end else if _encodedFrameSize... else { _errStr = "X264Encoder::Encode: Encode process failed"; return(0); } _lastPicType = 1; // Non-IDR if (_picOut.i_type == X264_TYPE_IDR) _lastPicType = 0; // IDR d.push_back({ _encodedFrameSize, _lastPicType }); _frameNum++; return(1); }//end Encode...