This commit is contained in:
dec05eba 2020-03-29 17:48:17 +02:00
parent 7c8c97b1a8
commit 405f810457
4 changed files with 77 additions and 36 deletions

View File

@ -16,7 +16,7 @@ typedef struct {
*/ */
int sound_device_get_by_name(SoundDevice *device, const char *name = "default", unsigned int num_channels = 1, unsigned int period_frame_size = 32); int sound_device_get_by_name(SoundDevice *device, const char *name = "default", unsigned int num_channels = 1, unsigned int period_frame_size = 32);
int sound_device_close(SoundDevice *device); void sound_device_close(SoundDevice *device);
/* /*
Returns the next chunk of audio into @buffer. Returns the next chunk of audio into @buffer.

View File

@ -15,7 +15,6 @@ glx = ">=1"
libavcodec = ">=58" libavcodec = ">=58"
libavformat = ">=58" libavformat = ">=58"
libavutil = ">=56.2" libavutil = ">=56.2"
OpenCL = ">=2"
x11 = ">=1" x11 = ">=1"
xcomposite = ">=0.2" xcomposite = ">=0.2"
xdamage = "1" xdamage = "1"

View File

@ -27,7 +27,7 @@ extern "C" {
#include <libavutil/hwcontext.h> #include <libavutil/hwcontext.h>
} }
#include <CL/cl.h> //#include <CL/cl.h>
struct ScopedGLXFBConfig { struct ScopedGLXFBConfig {
~ScopedGLXFBConfig() { ~ScopedGLXFBConfig() {
@ -294,7 +294,12 @@ static void receive_frames(AVCodecContext *av_codec_context, AVStream *stream, A
//av_packet_unref(&av_packet); //av_packet_unref(&av_packet);
} }
#else #else
static void receive_frames(AVCodecContext *av_codec_context, AVStream *stream, AVFormatContext *av_format_context) { static int64_t rescale_ts(AVStream *stream, int64_t val) {
return av_rescale_q_rnd(val,
stream->codec->time_base, stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
}
static void receive_frames(AVCodecContext *av_codec_context, AVStream *stream, AVFormatContext *av_format_context, int fps) {
AVPacket av_packet; AVPacket av_packet;
av_init_packet(&av_packet); av_init_packet(&av_packet);
for( ; ; ) { for( ; ; ) {
@ -310,8 +315,13 @@ static void receive_frames(AVCodecContext *av_codec_context, AVStream *stream, A
//av_packet.dts = av_rescale_q_rnd(av_packet.dts, av_codec_context->time_base, stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); //av_packet.dts = av_rescale_q_rnd(av_packet.dts, av_codec_context->time_base, stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
//av_packet.duration = 60;//av_rescale_q(av_packet->duration, av_codec_context->time_base, stream->time_base); //av_packet.duration = 60;//av_rescale_q(av_packet->duration, av_codec_context->time_base, stream->time_base);
av_packet_rescale_ts(&av_packet, av_codec_context->time_base, stream->time_base); av_packet_rescale_ts(&av_packet, av_codec_context->time_base, stream->time_base);
//av_packet.pts /= 2; //double timescale = ((double)fps / 60.0);
//av_packet.dts /= 2; //av_packet.pts *= timescale;
//av_packet.dts *= timescale;
//stream->codec->time_base.num = 1;
//stream->codec->time_base.den = fps;
//av_packet.pts = rescale_ts(stream, av_packet.pts);
//av_packet.pts = rescale_ts(stream, av_packet.dts);
av_packet.stream_index = stream->index; av_packet.stream_index = stream->index;
//av_packet->stream_index = 0; //av_packet->stream_index = 0;
@ -345,7 +355,10 @@ static AVStream* add_stream(AVFormatContext *av_format_context, AVCodec **codec,
//*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) {
fprintf(stderr, "Error: Could not find encoder for '%s'\n", avcodec_get_name(codec_id)); *codec = avcodec_find_encoder_by_name("nvenc_h264");
}
if(!*codec) {
fprintf(stderr, "Error: Could not find h264_nvenc or nvenc_h264 encoder for %s\n", avcodec_get_name(codec_id));
exit(1); exit(1);
} }
@ -376,8 +389,8 @@ static AVStream* add_stream(AVFormatContext *av_format_context, AVCodec **codec,
// timebase should be 1/framerate and timestamp increments should be identical to 1 // timebase should be 1/framerate and timestamp increments should be 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 = 60;
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;
codec_context->sample_aspect_ratio.den = 1; codec_context->sample_aspect_ratio.den = 1;
codec_context->gop_size = 12; // Emit one intra frame every twelve frames at most codec_context->gop_size = 12; // Emit one intra frame every twelve frames at most
@ -465,6 +478,7 @@ static void open_video(AVCodec *codec, AVStream *stream, WindowPixmap &window_pi
res = cuCtxPopCurrent(&old_ctx); res = cuCtxPopCurrent(&old_ctx);
res = cuCtxPushCurrent(*cuda_context); res = cuCtxPushCurrent(*cuda_context);
res = cuGraphicsGLRegisterImage(cuda_graphics_resource, window_pixmap.target_texture_id, GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY); res = cuGraphicsGLRegisterImage(cuda_graphics_resource, window_pixmap.target_texture_id, GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
//cuGraphicsUnregisterResource(*cuda_graphics_resource);
if(res != CUDA_SUCCESS) { if(res != CUDA_SUCCESS) {
fprintf(stderr, "Error: cuGraphicsGLRegisterImage failed, error %d, texture id: %u\n", res, window_pixmap.target_texture_id); fprintf(stderr, "Error: cuGraphicsGLRegisterImage failed, error %d, texture id: %u\n", res, window_pixmap.target_texture_id);
exit(1); exit(1);
@ -628,46 +642,74 @@ int main(int argc, char **argv) {
exit(1); exit(1);
} }
//double start_time = glfwGetTime(); double start_time = glfwGetTime();
int fps = 0;
int current_fps = 30;
XEvent e;
while(!glfwWindowShouldClose(window)) { while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
// TODO: Use a framebuffer instead. glCopyImageSubData requires opengl 4.2 double time_now = glfwGetTime();
glCopyImageSubData( if(time_now - start_time >= 1.0) {
window_pixmap.texture_id, GL_TEXTURE_2D, 0, 0, 0, 0, printf("fps: %d\n", fps);
window_pixmap.target_texture_id, GL_TEXTURE_2D, 0, 0, 0, 0, start_time = time_now;
window_pixmap.texture_width, window_pixmap.texture_height, 1); current_fps = fps;
//int err = glGetError(); fps = 0;
//printf("error: %d\n", err); }
CUDA_MEMCPY2D memcpy_struct; if (XCheckTypedEvent(dpy, ConfigureNotify, &e)) {
memcpy_struct.srcXInBytes = 0; // Window resize
memcpy_struct.srcY = 0; printf("Resize window!\n");
memcpy_struct.srcMemoryType = CUmemorytype::CU_MEMORYTYPE_ARRAY; recreate_window_pixmap(dpy, src_window_id, window_pixmap);
}
memcpy_struct.dstXInBytes = 0;
memcpy_struct.dstY = 0;
memcpy_struct.dstMemoryType = CUmemorytype::CU_MEMORYTYPE_DEVICE;
memcpy_struct.srcArray = mapped_array; if (XCheckTypedEvent(dpy, damage_event + XDamageNotify, &e)) {
memcpy_struct.dstDevice = (CUdeviceptr)frame->data[0]; //printf("Redraw!\n");
memcpy_struct.dstPitch = frame->linesize[0]; XDamageNotifyEvent *de = (XDamageNotifyEvent*)&e;
memcpy_struct.WidthInBytes = frame->width * 4; // de->drawable is the window ID of the damaged window
memcpy_struct.Height = frame->height; XserverRegion region = XFixesCreateRegion(dpy, nullptr, 0);
cuMemcpy2D(&memcpy_struct); // Subtract all the damage, repairing the window
//res = cuCtxPopCurrent(&old_ctx); XDamageSubtract(dpy, de->damage, None, region);
XFixesDestroyRegion(dpy, region);
//double time_now = glfwGetTime(); // TODO: Use a framebuffer instead. glCopyImageSubData requires opengl 4.2
glCopyImageSubData(
window_pixmap.texture_id, GL_TEXTURE_2D, 0, 0, 0, 0,
window_pixmap.target_texture_id, GL_TEXTURE_2D, 0, 0, 0, 0,
window_pixmap.texture_width, window_pixmap.texture_height, 1);
//int err = glGetError();
//printf("error: %d\n", err);
CUDA_MEMCPY2D memcpy_struct;
memcpy_struct.srcXInBytes = 0;
memcpy_struct.srcY = 0;
memcpy_struct.srcMemoryType = CUmemorytype::CU_MEMORYTYPE_ARRAY;
memcpy_struct.dstXInBytes = 0;
memcpy_struct.dstY = 0;
memcpy_struct.dstMemoryType = CUmemorytype::CU_MEMORYTYPE_DEVICE;
memcpy_struct.srcArray = mapped_array;
memcpy_struct.dstDevice = (CUdeviceptr)frame->data[0];
memcpy_struct.dstPitch = frame->linesize[0];
memcpy_struct.WidthInBytes = frame->width * 4;
memcpy_struct.Height = frame->height;
cuMemcpy2D(&memcpy_struct);
//res = cuCtxPopCurrent(&old_ctx);
}
++fps;
//int frame_cc = (time_now - start_time) * 0.66666; //int frame_cc = (time_now - start_time) * 0.66666;
//printf("elapsed time: %d\n", frame_cc); //printf("elapsed time: %d\n", frame_cc);
frame->pts = frame_count++; frame->pts = frame_count;
frame_count += 1;
if(avcodec_send_frame(video_stream->codec, frame) < 0) { if(avcodec_send_frame(video_stream->codec, frame) < 0) {
fprintf(stderr, "Error: avcodec_send_frame failed\n"); fprintf(stderr, "Error: avcodec_send_frame failed\n");
} }
receive_frames(video_stream->codec, video_stream, av_format_context); receive_frames(video_stream->codec, video_stream, av_format_context, current_fps);
} }
#if 0 #if 0

View File

@ -59,7 +59,7 @@ int sound_device_get_by_name(SoundDevice *device, const char *name, unsigned int
return 0; return 0;
} }
int sound_device_close(SoundDevice *device) { void sound_device_close(SoundDevice *device) {
/* TODO: Is this also needed in @sound_device_get_by_name on failure? */ /* TODO: Is this also needed in @sound_device_get_by_name on failure? */
snd_pcm_drain((snd_pcm_t*)device->handle); snd_pcm_drain((snd_pcm_t*)device->handle);
snd_pcm_close((snd_pcm_t*)device->handle); snd_pcm_close((snd_pcm_t*)device->handle);