From 8b0b5bde01921f3b478fcd10974556f6fa4dbede Mon Sep 17 00:00:00 2001 From: Barna Keresztes Date: Fri, 17 Dec 2021 18:08:04 +0100 Subject: [PATCH] Video mode working --- example/takephoto.cpp | 18 +++++++---- example/takevideo.cpp | 28 ++++++++++++++++ include/lccv.hpp | 10 +++--- include/libcamera_app.hpp | 2 +- src/lccv.cpp | 68 ++++++++++++++++++--------------------- src/libcamera_app.cpp | 54 ++++++++++--------------------- 6 files changed, 95 insertions(+), 85 deletions(-) create mode 100644 example/takevideo.cpp diff --git a/example/takephoto.cpp b/example/takephoto.cpp index d939486..5ce69b6 100644 --- a/example/takephoto.cpp +++ b/example/takephoto.cpp @@ -5,14 +5,20 @@ int main() { cv::Mat image; lccv::PiCamera cam; - cam.options->width=4056; - cam.options->height=3040; + //cam.options->width=4056; + //cam.options->height=3040; + cam.options->photo_width=2028; + cam.options->photo_height=1520; cam.options->verbose=true; - if(!cam.captureFrame(image)){ - std::cout<<"Camera error"< +#include + +int main() +{ + std::cout<<"Sample program for LCCV video capture"<video_width=1024; + cam.options->video_height=768; + cam.options->framerate=5; + cam.options->verbose=true; + cv::namedWindow("Video",cv::WINDOW_NORMAL); + cam.startVideo(); + int ch=0; + while(ch!=27){ + if(!cam.getVideoFrame(image,1000)){ + std::cout<<"Camera error"< running,frameready; - static uint8_t *framebuffer; - static std::mutex mtx; + unsigned int vw,vh,vstr; + std::atomic running,frameready; + uint8_t *framebuffer; + std::mutex mtx; }; } diff --git a/include/libcamera_app.hpp b/include/libcamera_app.hpp index e005971..464ddbe 100644 --- a/include/libcamera_app.hpp +++ b/include/libcamera_app.hpp @@ -96,7 +96,7 @@ class LibcameraApp void CloseCamera(); void ConfigureStill(unsigned int flags = FLAG_STILL_NONE); - void ConfigureVideo(unsigned int flags = FLAG_VIDEO_NONE); + void ConfigureViewfinder(); void Teardown(); void StartCamera(); diff --git a/src/lccv.cpp b/src/lccv.cpp index 50421b9..37dc6be 100644 --- a/src/lccv.cpp +++ b/src/lccv.cpp @@ -14,6 +14,7 @@ PiCamera::PiCamera() options->photo_height = 3040; options->video_width = 640; options->video_height = 480; + options->framerate = 30; options->denoise = "auto"; options->timeout = 1000; options->setMetering(Metering_Modes::METERING_MATRIX); @@ -47,7 +48,6 @@ void PiCamera::getImage(cv::Mat &frame, CompletedRequestPtr &payload) } } - bool PiCamera::capturePhoto(cv::Mat &frame) { app->OpenCamera(); @@ -82,10 +82,10 @@ bool PiCamera::startVideo() } frameready.store(false, std::memory_order_release); app->OpenCamera(); - app->ConfigureVideo(); + app->ConfigureViewfinder(); app->StartCamera(); - libcamera::Stream *stream = app->VideoStream(&vw,&vh,&vstr); - bool ret = pthread_create(&videothread, NULL, &videoThreadFunc, stream); + + bool ret = pthread_create(&videothread, NULL, &videoThreadFunc, this); if (ret != 0) { std::cerr<<"Error starting video thread"; return false; @@ -140,42 +140,38 @@ bool PiCamera::getVideoFrame(cv::Mat &frame, unsigned int timeout) void *PiCamera::videoThreadFunc(void *p) { - running.store(true, std::memory_order_release); - + PiCamera *t = (PiCamera *)p; + t->running.store(true, std::memory_order_release); //allocate framebuffer - //libcamera::Stream *stream = (libcamera::Stream *)p; - (void)p; - int buffersize=vh*vstr; - if(framebuffer)delete[] framebuffer; - framebuffer=new uint8_t[buffersize]; - const std::vector> mem; + //unsigned int vw,vh,vstr; + libcamera::Stream *stream = t->app->ViewfinderStream(&t->vw,&t->vh,&t->vstr); + int buffersize=t->vh*t->vstr; + if(t->framebuffer)delete[] t->framebuffer; + std::cout<<"Allocating buffer"<vh<<"x"<vstr<<")"<framebuffer=new uint8_t[buffersize]; + std::vector> mem; //main loop - while(running.load(std::memory_order_acquire)){ - //grab buffer *** - mtx.lock(); - memcpy(framebuffer,mem[0].data(),buffersize); - mtx.unlock(); - frameready.store(true, std::memory_order_release); + while(t->running.load(std::memory_order_acquire)){ + LibcameraApp::Msg msg = t->app->Wait(); + if (msg.type == LibcameraApp::MsgType::Quit){ + std::cerr<<"Quit message received"<running.store(false,std::memory_order_release); + } + else if (msg.type != LibcameraApp::MsgType::RequestComplete) + throw std::runtime_error("unrecognised message!"); + + + CompletedRequestPtr payload = std::get(msg.payload); + mem = t->app->Mmap(payload->buffers[stream]); + t->mtx.lock(); + memcpy(t->framebuffer,mem[0].data(),buffersize); + t->mtx.unlock(); + t->frameready.store(true, std::memory_order_release); } - if(framebuffer){ - delete[] framebuffer; - framebuffer=nullptr; + if(t->framebuffer){ + delete[] t->framebuffer; + t->framebuffer=nullptr; } return NULL; } -/*void PiCamera::videoThread() -{ - cv::Mat frame; - - while(GoOn){ - LibcameraApp::Msg msg = app->Wait(); - if (msg.type == LibcameraApp::MsgType::Quit) - GoOn=false; - else if (msg.type != LibcameraApp::MsgType::RequestComplete) - throw std::runtime_error("unrecognised message!"); - getVideoFrame(frame,std::get(msg.payload)); - } - app->StopCamera(); - app->CloseCamera(); -}*/ diff --git a/src/libcamera_app.cpp b/src/libcamera_app.cpp index 39fc6d6..3c430b9 100644 --- a/src/libcamera_app.cpp +++ b/src/libcamera_app.cpp @@ -124,51 +124,31 @@ void LibcameraApp::ConfigureStill(unsigned int flags) std::cerr << "Still capture setup complete" << std::endl; } -void LibcameraApp::ConfigureVideo(unsigned int flags) +void LibcameraApp::ConfigureViewfinder() { - if (options_->verbose) - std::cerr << "Configuring video..." << std::endl; + if (options_->verbose) + std::cerr << "Configuring viewfinder..." << std::endl; - bool have_raw_stream = flags & FLAG_VIDEO_RAW; - StreamRoles stream_roles = { StreamRole::VideoRecording }; - if (have_raw_stream) - { - stream_roles.push_back(StreamRole::Raw); - } - configuration_ = camera_->generateConfiguration(stream_roles); - if (!configuration_) - throw std::runtime_error("failed to generate video configuration"); + StreamRoles stream_roles = { StreamRole::Viewfinder }; + configuration_ = camera_->generateConfiguration(stream_roles); + if (!configuration_) + throw std::runtime_error("failed to generate viewfinder configuration"); - // Now we get to override any of the default settings from the options_-> - configuration_->at(0).pixelFormat = libcamera::formats::YUV420; - configuration_->at(0).bufferCount = 6; // 6 buffers is better than 4 - if (options_->video_width) - configuration_->at(0).size.width = options_->video_width; - if (options_->video_height) - configuration_->at(0).size.height = options_->video_height; + // Now we get to override any of the default settings from the options_-> + configuration_->at(0).pixelFormat = libcamera::formats::RGB888; + configuration_->at(0).size.width = options_->video_width; + configuration_->at(0).size.height = options_->video_height; + configuration_->at(0).bufferCount = 4; configuration_->transform = options_->transform; - if (have_raw_stream) - { - if (!options_->rawfull) - { - configuration_->at(1).size.width = configuration_->at(0).size.width; - configuration_->at(1).size.height = configuration_->at(0).size.height; - } - configuration_->at(1).bufferCount = configuration_->at(0).bufferCount; - } - configuration_->transform = options_->transform; - - configureDenoise(options_->denoise == "auto" ? "cdn_fast" : options_->denoise); - setupCapture(); + configureDenoise(options_->denoise == "auto" ? "cdn_off" : options_->denoise); + setupCapture(); - streams_["video"] = configuration_->at(0).stream(); - if (have_raw_stream) - streams_["raw"] = configuration_->at(1).stream(); + streams_["viewfinder"] = configuration_->at(0).stream(); - if (options_->verbose) - std::cerr << "Video setup complete" << std::endl; + if (options_->verbose) + std::cerr << "Viewfinder setup complete" << std::endl; } void LibcameraApp::Teardown()