Recording Video from USB Cam with Qt5 - c++

I am trying to record a video acquired from a webcam connect to the usb device. I am workin with Qt5.1.0 in Linux 64 bit.
I have the following code:
camera = new QCamera(this);
viewFinder = new QCameraViewfinder(this);
camera->setViewfinder(viewFinder);
recorder = new QMediaRecorder(camera,this);
QVideoEncoderSettings settings = recorder->videoSettings();
settings.setResolution(1280,720);
settings.setQuality(QMultimedia::VeryHighQuality);
settings.setFrameRate(30.0);
recorder->setVideoSettings(settings);
camera->setCaptureMode(QCamera::CaptureVideo);
camera->start();
QString name = filename + QDateTime::currentDateTime().toString("dd.MM.yy-h-m-s");
recorder->setOutputLocation(QUrl::fromLocalFile(outputpath + "/" + name + ".mp4"));
recorder->record();
When I run this code I get the following warning and error
CameraBin error: "Internal data flow error."
CameraBin error: "Could not negotiate format"
And in fact nothing is recorded.
If I change the line
camera->setCaptureMode(QCamera::CaptureVideo);
for
camera->setCaptureMode(QCamera::CaptureViewFinder);
No error is output, the file is generated, but it only contains one frame (fixed image)
If I remove this piece of code:
QVideoEncoderSettings settings = recorder->videoSettings();
settings.setResolution(1280,720);
settings.setQuality(QMultimedia::VeryHighQuality);
settings.setFrameRate(30.0);
I get two different errors:
CameraBin warning: "A lot of buffers are being dropped."
CameraBin error: "Could not encode stream."
But the video is actually recorded.

I'm having almost the same problem, with capturing an image. I discovered that it is only working with the default resolution 640 x 480. If you set the resolution to a higher value it does not work. I've also tried with 2 different cameras with no success, so it seems to be a qt5 problem. You could try to don't set a resolution, then you should be able to record a video, but only with the default resolution of 640 x 480.

Related

Ffmpeg video output is 0 seconds with correct filesize when uploading to google cloud bucket

I've made a C++ program that lives in gke and takes some videos as input using ffmpeg, then does something with that input using opengl(not relevant), then finally encodes those edited videos as a single output. Normally the program works perfectly fine on my local machine, it encodes just as I want it to with no warnings or valgrind errors whatsoever. Then, after encoding the said video, I want my program to upload that video to the google cloud storage. This is where the problem comes, I have tried 2 methods for this: First, I tried using curl to upload to the cloud using a signed url. Second, I tried mounting the google storage using gcsfuse(I was already mounting the bucket to access the inputs in question). Both of those methods yielded undefined, weird behaviour's ranging from: Outputing a 0byte or 44byte file, (This is the most common one:) encoding in the correct file size ~500mb but the video is 0 seconds long, outputing a 0.4 second video or just encoding the desired output normally (really rare).
From the logs I can't see anything unusual, everything seems to work fine and ffmpeg does not give any errors or warnings, so does valgrind. Everything seems to work normally, even when I use curl to upload the video to the cloud the output is perfectly fine when it first encodes it (before sending it with curl) but the video gets messed up when curl uploads it to the cloud.
I'm using the muxing.c example of ffmpeg to encode my video with the only difference being:
void video_encoder::fill_yuv_image(AVFrame *frame, struct SwsContext *sws_context) {
const int in_linesize[1] = { 4 * width };
//uint8_t* dest[4] = { rgb_data, NULL, NULL, NULL };
sws_context = sws_getContext(
width, height, AV_PIX_FMT_RGBA,
width, height, AV_PIX_FMT_YUV420P,
SWS_BICUBIC, 0, 0, 0);
sws_scale(sws_context, (const uint8_t * const *)&rgb_data, in_linesize, 0,
height, frame->data, frame->linesize);
}
rgb_data is the data I got after editing the inputs. Again, this works fine and I don't think there are any errors here.
I'm not sure where the error is and since the code is huge I can't provide a replicable example. I'm just looking for someone to point me to the right direction.
Running the cloud's output in mplayer wields this result (This is when the video is the right size but is 0 seconds long, the most common one.):
MPlayer 1.4 (Debian), built with gcc-11 (C) 2000-2019 MPlayer Team
do_connect: could not connect to socket
connect: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
Playing /media/c36c2633-d4ee-4d37-825f-88ae54b86100.
libavformat version 58.76.100 (external)
libavformat file format detected.
[mov,mp4,m4a,3gp,3g2,mj2 # 0x7f2cba1168e0]moov atom not found
LAVF_header: av_open_input_stream() failed
libavformat file format detected.
[mov,mp4,m4a,3gp,3g2,mj2 # 0x7f2cba1168e0]moov atom not found
LAVF_header: av_open_input_stream() failed
RAWDV file format detected.
VIDEO: [DVSD] 720x480 24bpp 29.970 fps 0.0 kbps ( 0.0 kbyte/s)
X11 error: BadMatch (invalid parameter attributes)
Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory
[vdpau] Error when calling vdp_device_create_x11: 1
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 58.134.100 (external)
[dvvideo # 0x7f2cb987a380]Requested frame threading with a custom get_buffer2() implementation which is not marked as thread safe. This is not supported anymore, make your callback thread-safe.
Selected video codec: [ffdv] vfm: ffmpeg (FFmpeg DV)
==========================================================================
Load subtitles in /media/
==========================================================================
Opening audio decoder: [libdv] Raw DV Audio Decoder
Unknown/missing audio format -> no sound
ADecoder init failed :(
Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders
[dvaudio # 0x7f2cb987a380]Decoder requires channel count but channels not set
Could not open codec.
ADecoder init failed :(
ADecoder init failed :(
Cannot find codec for audio format 0x56444152.
Audio: no sound
Starting playback...
[dvvideo # 0x7f2cb987a380]could not find dv frame profile
Error while decoding frame!
[dvvideo # 0x7f2cb987a380]could not find dv frame profile
Error while decoding frame!
V: 0.0 2/ 2 ??% ??% ??,?% 0 0
Exiting... (End of file)
Edit: Since the code runs on a VM, I'm using xvfb-run ro start my application, but again even when using xvfb-run it works completely fine on when not encoding to the cloud.
Apparently, I'm assuming for security reasons, the google cloud storage does not allow us to do multiple continuous operations on a file, just a singular read/write operation. So I found a workaround by encoding my video to a local file inside the pod and then doing a copy operation to the cloud.

cv::videocapture can't open available USB cameras

I'm trying to connect to several USB cameras that are connected to different USB buses (hopefully cancelling the bandwidth bottleneck caused by the USB).
Before accessing to the cameras, I'm probing them with V4L2 API directly to see if they're accessible. For now, there are 3 cameras and V4L2 sees them all.
Then I'm trying to access them using openCV like this, each in its own object:
this->camera = new cv::VideoCapture(camera_port);
if(this->camera->isOpened()) {
....
cv::Mat capturedImage;
bool read;
read = this->camera->read(capturedImage);
....
}
where camera_port is 0,1,2.
Obviously this->camera is called with release() on program closure.
The problem arises when I'm accessing more than 1 camera. Only one camera out of the three returns an image. The others return errors that I'm seeing on the console (not the same on every run):
libv4l2: error turning on stream: Connection timed out,
VIDIOC_STREAMON: Connection timed out
libv4l2: error turning on stream: Input/output error,
VIDIOC_STREAMON: Input/output error
libv4l2: error turning on stream: Invalid argument,
VIDIOC_STREAMON: Invalid argument
Some other errors, but the above are the most frequent
However, this does work on the first run after replugging-in the USB cameras, but not on further runs of the program.
Thoughts?

Visualise audio waveform from video local file using Qmedia player

I try without success to plot waveform using qMediaPlayer and QaudioProbe object to get the QAudioBuffer but it's always fails when I try:
player = new QMediaPlayer;
audio = new QAudioProbe ;
QAudioRecorder *recorder = new QAudioRecorder();
if (audio->setSource(player))
{
// Probing succeeded, audioProbe->isValid() should be true.
std::cout << "probing succed"<< std::endl;
connect(audio, SIGNAL(audioBufferProbed(QAudioBuffer)), this,
SLOT(processBuffer(QAudioBuffer)));
}
this line:
if (audio->setSource(player))
always return false!
when I replace QMediaPlayer by QAudioRecorder the setSource function works well.
do you have any idea to do that, or m'I in a wrong direction?
otherwise is there other way to split audio from video file.
thanks a lot
From the documentation on QMediaPlayer, I would gather that since the property audioAvailable can change, the default is that audioAvailable is false.
If there is no audio available, the documentation of setSource states that
"If the media object does not support monitoring audio, this function
will return false."
Try loading an actual piece of media, that has audio available (check that first) before trying to set the source

an issue with cvGetCaptureProperty on opencv

I have a working opencv code that takes feed from my webcam and displays it. (The code is modified from the one here
The only issue is that when I try to print the frames-per-second value, as
int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
printf ("Frames per Second: %d\n",fps);
-1 gets printed.
Another (side) issue is that there appears to be some run time errors/warnings
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
select timeout
HIGHGUI ERROR: V4L2: Unable to get property <unknown property string>(5) - Invalid argument
HIGHGUI ERROR: V4L: Property <unknown property string>(2) not supported by device
HIGHGUI ERROR: V4L2: Unable to get property <unknown property string>(1) - Invalid argument
HIGHGUI ERROR: V4L: Property <unknown property string>(2) not supported by device
But the code does what it's supposed to do, ie, display video from the webcam.
Any ideas how to sort out the problems? I am using opencv on Eclipse with CDT on Ubuntu 11.10
Thanks in advance.
Judging from the error messages, this sounds like a problem your webcam driver. The error messages are from Video4Linux (V4L or V4L2 in the error messages), which is the part of the Linux kernel that contains webcam drivers. Getting a select() failure and the "not supported by device" error message probably means that your webcam didn't implement this part of the V4L2 API.
You can verify that this is the problem by testing your code with a camera that has a known-good driver. Unfortunately, this is very common in the webcam drivers included in the kernel. Many of them are reverse engineered, so it's quite a feat just access the video stream.
Try this for the HIGHGUI ERROR errors:
export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so

X264 encoding using Opencv

I am working with a high resolution camera: 4008x2672. I a writing a simple program which grabs frame from the camera and sends the frame to a avi file. For working with such a high resolution, I found only x264 codec that could do the trick (Suggestions welcome). I am using opencv for most of the image handling stuff. As mentioned in this post http://doom10.org/index.php?topic=1019.0 , I modified the AVCodecContext members as per ffmpeg presets for libx264 (Had to do this to avoid broken ffmpeg defaults settings error). This is output I am getting when I try to run the program
libx264 # 0x992d040]non-strictly-monotonic PTS
1294846981.526675 1 0 //Timestamp camera_no frame_no
1294846981.621101 1 1
1294846981.715521 1 2
1294846981.809939 1 3
1294846981.904360 1 4
1294846981.998782 1 5
1294846982.093203 1 6
Last message repeated 7 times
[avi # 0x992beb0]st:0 error, non monotone timestamps
-614891469123651720 >= -614891469123651720
OpenCV Error: Unspecified error (Error while writing video frame) in
icv_av_write_frame_FFMPEG, file
/home/ajoshi/ext/OpenCV-2.2.0/modules/highgui/src/cap_ffmpeg.cpp, line 1034
terminate called after throwing an instance of 'cv::Exception'
what(): /home/ajoshi/ext/OpenCV-2.2.0/modules/highgui/src/cap_ffmpeg.cpp:1034:
error: (-2) Error while writing video frame in function icv_av_write_frame_FFMPEG
Aborted
Modifications to the AVCodecContext are:
if(codec_id == CODEC_ID_H264)
{
//fprintf(stderr, "Trying to parse a preset file for libx264\n");
//Setting Values manually from medium preset
c->me_method = 7;
c->qcompress=0.6;
c->qmin = 10;
c->qmax = 51;
c->max_qdiff = 4;
c->i_quant_factor=0.71;
c->max_b_frames=3;
c->b_frame_strategy = 1;
c->me_range = 16;<br>
c->me_subpel_quality=7;
c->coder_type = 1;
c->scenechange_threshold=40;
c->partitions = X264_PART_I8X8 | X264_PART_I4X4 | X264_PART_P8X8 | X264_PART_B8X8;
c->flags = CODEC_FLAG_LOOP_FILTER;
c->flags2 = CODEC_FLAG2_BPYRAMID | CODEC_FLAG2_MIXED_REFS | CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT | CODEC_FLAG2_FASTPSKIP;
c->keyint_min = 25;
c->refs = 3;
c->trellis=1;
c->directpred = 1;
c->weighted_p_pred=2;
}
I am probably not setting the dts and pts values which I believed ffmpeg should be setting it for me.
Any sugggestions welcome.
Thanks in advance
I would probably run the x264 executable in another process and pipe either rgb or yuv pixels to it. Then you can use all the normal x264 (or ffmpeg) flags and it handles multi threading for you.
And since x264 is GPL licensed it also gives you more freedom on licensing your app.
ps. Here is some sample code using ffmpeg from Qt you can ignore the Qt specific bits but it gives a good starting point for using ffmpeg from a c++ app.
Actual error is "non monotone timestamps". I seems that you didn't properly initialized video frame properties. If its possible use libx264 directly. It'll be more easy to handle.
PS. you can work around ffmpeg x264 setting problem by specify 264 preset file with -fvpre option.
The pts value of the AVFrame you send as the last argument to avcodec_encode_video needs to be set by you. Once you set this, the codec context's coded_from->pts field will have the correct value which you can av_rescale_q() and set in the AVPacket for your av_interleaved_write_frame().