Allow setting container format and fps
This commit is contained in:
parent
c8f8ee5e68
commit
066f2b652c
60
src/main.cpp
60
src/main.cpp
@ -244,7 +244,8 @@ static void receive_frames(AVCodecContext *av_codec_context, AVStream *stream,
|
|||||||
|
|
||||||
static AVStream *add_stream(AVFormatContext *av_format_context, AVCodec **codec,
|
static AVStream *add_stream(AVFormatContext *av_format_context, AVCodec **codec,
|
||||||
enum AVCodecID codec_id,
|
enum AVCodecID codec_id,
|
||||||
const WindowPixmap &window_pixmap) {
|
const WindowPixmap &window_pixmap,
|
||||||
|
int fps) {
|
||||||
//*codec = avcodec_find_encoder(codec_id);
|
//*codec = avcodec_find_encoder(codec_id);
|
||||||
*codec = avcodec_find_encoder_by_name("h264_nvenc");
|
*codec = avcodec_find_encoder_by_name("h264_nvenc");
|
||||||
if (!*codec) {
|
if (!*codec) {
|
||||||
@ -288,7 +289,7 @@ static AVStream *add_stream(AVFormatContext *av_format_context, AVCodec **codec,
|
|||||||
// timebase should be 1/framerate and timestamp increments should be
|
// timebase should be 1/framerate and timestamp increments should be
|
||||||
// identical to 1
|
// identical to 1
|
||||||
codec_context->time_base.num = 1;
|
codec_context->time_base.num = 1;
|
||||||
codec_context->time_base.den = 60;
|
codec_context->time_base.den = fps;
|
||||||
// codec_context->framerate.num = 60;
|
// codec_context->framerate.num = 60;
|
||||||
// codec_context->framerate.den = 1;
|
// codec_context->framerate.den = 1;
|
||||||
codec_context->sample_aspect_ratio.num = 1;
|
codec_context->sample_aspect_ratio.num = 1;
|
||||||
@ -403,13 +404,20 @@ static void close_video(AVStream *video_stream, AVFrame *frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 3) {
|
if (argc < 4) {
|
||||||
fprintf(stderr, "usage: hardware-screen-recorder <window_id> <output_file>\n");
|
fprintf(stderr, "usage: hardware-screen-recorder <window_id> <container_format> <fps>\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window src_window_id = strtol(argv[1], nullptr, 0);
|
Window src_window_id = strtol(argv[1], nullptr, 0);
|
||||||
const char *filename = argv[2];
|
const char *container_format = argv[2];
|
||||||
|
int fps = atoi(argv[3]);
|
||||||
|
if(fps <= 0 || fps > 255) {
|
||||||
|
fprintf(stderr, "invalid fps argument: %s\n", argv[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float target_fps = 1.0f / (float)fps;
|
||||||
|
|
||||||
Display *dpy = XOpenDisplay(nullptr);
|
Display *dpy = XOpenDisplay(nullptr);
|
||||||
if (!dpy) {
|
if (!dpy) {
|
||||||
@ -476,8 +484,8 @@ int main(int argc, char **argv) {
|
|||||||
// Video start
|
// Video start
|
||||||
AVFormatContext *av_format_context;
|
AVFormatContext *av_format_context;
|
||||||
// The output format is automatically guessed by the file extension
|
// The output format is automatically guessed by the file extension
|
||||||
avformat_alloc_output_context2(&av_format_context, nullptr, nullptr,
|
avformat_alloc_output_context2(&av_format_context, nullptr, container_format,
|
||||||
filename);
|
nullptr);
|
||||||
if (!av_format_context) {
|
if (!av_format_context) {
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
@ -489,7 +497,7 @@ int main(int argc, char **argv) {
|
|||||||
AVCodec *video_codec;
|
AVCodec *video_codec;
|
||||||
AVStream *video_stream =
|
AVStream *video_stream =
|
||||||
add_stream(av_format_context, &video_codec, output_format->video_codec,
|
add_stream(av_format_context, &video_codec, output_format->video_codec,
|
||||||
window_pixmap);
|
window_pixmap, fps);
|
||||||
if (!video_stream) {
|
if (!video_stream) {
|
||||||
fprintf(stderr, "Error: Failed to create video stream\n");
|
fprintf(stderr, "Error: Failed to create video stream\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -504,23 +512,8 @@ int main(int argc, char **argv) {
|
|||||||
CUgraphicsResource cuda_graphics_resource;
|
CUgraphicsResource cuda_graphics_resource;
|
||||||
open_video(video_codec, video_stream, window_pixmap, &device_ctx,
|
open_video(video_codec, video_stream, window_pixmap, &device_ctx,
|
||||||
&cuda_graphics_resource);
|
&cuda_graphics_resource);
|
||||||
av_dump_format(av_format_context, 0, filename, 1);
|
|
||||||
|
|
||||||
if (!(output_format->flags & AVFMT_NOFILE)) {
|
output_format->flags = AVFMT_NOFILE;
|
||||||
int ret = avio_open(&av_format_context->pb, filename, AVIO_FLAG_WRITE);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "Error: Could not open '%s': %s\n", filename,
|
|
||||||
"blabla"); // av_err2str(ret));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = avformat_write_header(av_format_context, nullptr);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "Error occurred when opening output file: %s\n",
|
|
||||||
"blabla"); // av_err2str(ret));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
AVHWDeviceContext *hw_device_context =
|
AVHWDeviceContext *hw_device_context =
|
||||||
(AVHWDeviceContext *)device_ctx->data;
|
(AVHWDeviceContext *)device_ctx->data;
|
||||||
@ -568,7 +561,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
double start_time = glfwGetTime();
|
double start_time = glfwGetTime();
|
||||||
double frame_timer_start = start_time;
|
double frame_timer_start = start_time;
|
||||||
int fps = 0;
|
int fps_counter = 0;
|
||||||
int current_fps = 30;
|
int current_fps = 30;
|
||||||
|
|
||||||
AVFrame *frame = av_frame_alloc();
|
AVFrame *frame = av_frame_alloc();
|
||||||
@ -634,18 +627,16 @@ int main(int argc, char **argv) {
|
|||||||
// res = cuCtxPopCurrent(&old_ctx);
|
// res = cuCtxPopCurrent(&old_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
++fps;
|
++fps_counter;
|
||||||
|
|
||||||
const double target_fps = 0.0166666666;
|
|
||||||
|
|
||||||
double time_now = glfwGetTime();
|
double time_now = glfwGetTime();
|
||||||
double frame_timer_elapsed = time_now - frame_timer_start;
|
double frame_timer_elapsed = time_now - frame_timer_start;
|
||||||
double elapsed = time_now - start_time;
|
double elapsed = time_now - start_time;
|
||||||
if (elapsed >= 1.0) {
|
if (elapsed >= 1.0) {
|
||||||
fprintf(stderr, "fps: %d\n", fps);
|
fprintf(stderr, "fps: %d\n", fps_counter);
|
||||||
start_time = time_now;
|
start_time = time_now;
|
||||||
current_fps = fps;
|
current_fps = fps_counter;
|
||||||
fps = 0;
|
fps_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double frame_time_overflow = frame_timer_elapsed - target_fps;
|
double frame_time_overflow = frame_timer_elapsed - target_fps;
|
||||||
@ -666,9 +657,10 @@ int main(int argc, char **argv) {
|
|||||||
usleep(5000);
|
usleep(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av_write_trailer(av_format_context) != 0) {
|
/* add sequence end code to have a real MPEG file */
|
||||||
fprintf(stderr, "Failed to write trailer\n");
|
const uint8_t endcode[] = { 0, 0, 1, 0xb7 };
|
||||||
}
|
if (video_codec->id == AV_CODEC_ID_MPEG1VIDEO || video_codec->id == AV_CODEC_ID_MPEG2VIDEO)
|
||||||
|
write(STDOUT_FILENO, endcode, sizeof(endcode));
|
||||||
|
|
||||||
// close_video(video_stream, NULL);
|
// close_video(video_stream, NULL);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
[ "$#" -ne 2 ] && echo "usage: twitch-stream.sh <window_id> <livestream_key>" && exit 1
|
[ "$#" -ne 3 ] && echo "usage: twitch-stream.sh <window_id> <fps> <livestream_key>" && exit 1
|
||||||
sibs build --release && ./sibs-build/linux_x86_64/release/hardware-screen-recorder "$1" "dummy.h264" | ffmpeg -i pipe:0 -c:v copy -f flv "rtmp://live.twitch.tv/app/$2"
|
sibs build --release && ./sibs-build/linux_x86_64/release/hardware-screen-recorder "$1" h264 "$2" | ffmpeg -i pipe:0 -c:v copy -f flv "rtmp://live.twitch.tv/app/$3"
|
||||||
|
Loading…
Reference in New Issue
Block a user