View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000590 | Cinelerra-GG | [All Projects] Bug | public | 2021-09-20 11:11 | 2021-12-26 23:44 |
Reporter | Andrew-R | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | always |
Status | new | Resolution | open | ||
Product Version | |||||
Target Version | Fixed in Version | ||||
Summary | 0000590: MJPEG Webcam not recordable? | ||||
Description | I have weird 'webcam' (actually action cam) connected to my computer. It requires weird workaround described at https://www.linuxquestions.org/questions/linux-hardware-18/cheap-actioncams-allwinner-renkforce-pruveeo-andoer-as-a-usb-webcam-under-linux-4175673473/ basically while :; do cat /dev/video*; sleep 1; done line running in background ... But with this line running I can see image from camera in mplayer *and* CinGG. Unfortunately, recording only result in green screen? mplayer tv:// -tv driver=v4l2:device=/dev/video0 -demuxer tv MPlayer SVN-r38313-10.0.1 (C) 2000-2021 MPlayer Team parse error at line 423 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 tv://. TV file format detected. Selected driver: v4l2 name: Video 4 Linux 2 input author: Martin Olschewski <[email protected]> comment: first try, more to come ;-) v4l2: your device driver does not support VIDIOC_G_STD ioctl, VIDIOC_G_PARM was used instead. Selected device: Android: UVC Camera Capabilities: video capture streaming supported norms: inputs: 0 = Camera 1; Current input: 0 Current format: MJPEG tv.c: norm_from_string(pal): Bogus norm parameter, setting default. v4l2: ioctl enum norm failed: Inappropriate ioctl for device Error: Cannot set norm! Selected input hasn't got a tuner! v4l2: ioctl set mute failed: Invalid argument v4l2: ioctl query control failed: Invalid argument v4l2: ioctl query control failed: Invalid argument v4l2: ioctl query control failed: Invalid argument v4l2: ioctl query control failed: Invalid argument ========================================================================== Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family libavcodec version 59.7.100 (internal) [mjpeg @ 0x5765dcd0]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: [ffmjpeg] vfm: ffmpeg (FFmpeg MJPEG) ========================================================================== Audio: no sound Starting playback... Movie-Aspect is undefined - no prescaling applied. VO: [vdpau] 1280x720 => 1280x720 Planar YV12 Movie-Aspect is undefined - no prescaling applied. VO: [vdpau] 1280x720 => 1280x720 Planar YV12 V: 0.0 259/259 ??% ??% ??,?% 0 0 v4l2: ioctl set mute failed: Invalid argument v4l2: 261 frames successfully processed, 1 frames dropped. Exiting... (Quit) | ||||
Steps To Reproduce | Find cheap webcam that only gives you mjpeg stream Connect webcam and test it with mplayer for example. Set CinGG to mjpeg webcam in input config. You probably need to create two symlinks: ln -s /usr/share/cin/ffmpeg/video/mjpg.qt /usr/share/cin/ffmpeg/video/mjpg ln -s /usr/share/cin/ffmpeg/video/mjpg.qt /usr/share/cin/ffmpeg/video/jpeg Launch cin, try to enter 'recording' mode (press r), then you will see yourself if you enable 'monitor video' but attempt at recording video will result in those messages and green-screen-only file: cin Cinelerra Infinity - built: Sep 4 2021 14:49:50 git://git.cinelerra-gg.org/goodguy/cinelerra.git (c) 2006-2019 Heroine Virtual Ltd. by Adam Williams 2007-2020 mods for Cinelerra-GG by W.P.Morrow aka goodguy Cinelerra is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. There is absolutely no warranty for Cinelerra. RenderFarmClient::main_loop: client started DeviceV4L2Base::v4l2_open pixels="MJPG"; res="1280x720" v4l2 s_fmt 1280x720 MJPG DeviceV4L2Base::v4l2_open VIDIOC_S_STD: Inappropriate ioctl for device DeviceV4L2Base::v4l2_open VIDIOC_G_JPEGCOMP: Inappropriate ioctl for device DeviceV4L2Base::v4l2_open VIDIOC_S_JPEGCOMP: Inappropriate ioctl for device BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) BC_CModels::transfer failed:208 1(0x0) to 7(1280x720) Total excess of backups: 1 Mesa: User error: GL_INVALID_OPERATION in glDeleteShader Session time: 0:00:25 Cpu time: user: 0:00:06.790 sys: 0:00:01.565 | ||||
Additional Information | recording without 'monitor video' also sadly does not work :( Recording works with screencapture | ||||
Tags | No tags attached. | ||||
note, ffmpeg 4.3+ probably can simulate mjpeg cam via v4l2 loopback device: https://forums.developer.nvidia.com/t/solved-gstreamer-help-mpeg2-source-file-to-mjpeg-at-v4l2-loopback-device/178853 |
|
I tried to add mjpeg decoding, but it still reads (?) from wrong buffer? WARNING - this is just debug sketch - there is no deleting/stopping mjpeg engine ...it hangs eventually ....
ffmpeg_compr_attempt.diff (4,101 bytes)
diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index b05a455d..7bad7cd3 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -1304,10 +1304,19 @@ int FFVideoStream::video_seek(int64_t pos) if( pos == curr_pos-1 && !seeked ) return 0; // if close enough, just read up to current int gop = avctx->gop_size; - if( gop < 4 ) gop = 4; + if( gop < 4 && gop != 0) gop = 4; if( gop > 64 ) gop = 64; + if( gop == 0 ) gop = 1; + //fprintf(stderr, "GOP: %i \n", gop); int read_limit = curr_pos + 3*gop; if( pos >= curr_pos && pos <= read_limit ) return 0; + // fixup for I-only codecs, not sure why it needed with ffmpeg 4.2 + if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO || st->codecpar->codec_id == AV_CODEC_ID_MJPEG || + st->codecpar->codec_id == AV_CODEC_ID_FFVHUFF || st->codecpar->codec_id == AV_CODEC_ID_DNXHD || + st->codecpar->codec_id ==AV_CODEC_ID_HUFFYUV || st->codecpar->codec_id == AV_CODEC_ID_PRORES) { + gop = 1; + if( seek(pos - 2*gop, frame_rate) < 0 ) return -1; + } // guarentee preload more than 2*gop frames if( seek(pos - 3*gop, frame_rate) < 0 ) return -1; return 1; @@ -1755,12 +1764,20 @@ int FFVideoConvert::convert_pixfmt(VFrame *frame, AVFrame *op) if( !convert_vframe_picture(frame, op) ) return 1; // use indirect transfer int cmodel = frame->get_color_model(); + //printf("cmodel from convert_pixfmts %i \n", cmodel); int max_bits = BC_CModels::calculate_pixelsize(cmodel) * 8; + //printf("max_bits 1: %i \n", max_bits); + //printf("BC_components: %i \n", BC_CModels::components(cmodel)); + if(BC_CModels::components(cmodel)) max_bits /= BC_CModels::components(cmodel); + //printf("max_bits %i \n", max_bits); AVPixelFormat ofmt = (AVPixelFormat)op->format; int imodel = pix_fmt_to_color_model(ofmt); + //printf("imodel: %i \n", imodel); int imodel_is_yuv = BC_CModels::is_yuv(imodel); + //printf("imodel_is_yuv: %i \n", imodel_is_yuv); int cmodel_is_yuv = BC_CModels::is_yuv(cmodel); + //printf("cmodel_is_yuv %i \n", cmodel_is_yuv); if( imodel < 0 || imodel_is_yuv != cmodel_is_yuv ) { imodel = cmodel_is_yuv ? (BC_CModels::has_alpha(cmodel) ? @@ -1771,7 +1788,28 @@ int FFVideoConvert::convert_pixfmt(VFrame *frame, AVFrame *op) (max_bits > 8 ? BC_RGB161616 : BC_RGB888)) ; } VFrame vframe(frame->get_w(), frame->get_h(), imodel); - vframe.transfer_from(frame); + + if(cmodel == BC_COMPRESSED) { + printf("Compressed - no decoding yet! \n"); + VFrame output_frame(frame->get_w(), frame->get_h(), BC_YUV422P); + + mjpeg = mjpeg_new(frame->get_w(),frame->get_h(), 1); + + mjpeg_decompress(mjpeg, + frame->get_data(), + frame->get_compressed_size(), + frame->get_field2_offset(), + output_frame.get_rows(), + output_frame.get_y(), + output_frame.get_u(), + output_frame.get_v(), + output_frame.get_color_model(), + 1); + + output_frame.transfer_from(&output_frame); + } else { + + vframe.transfer_from(frame);} if( !convert_vframe_picture(&vframe, op) ) return 1; return -1; } @@ -2717,6 +2755,7 @@ int FFMPEG::init_encoder(const char *filename) ret = get_file_format(); if( ret > 0 ) { eprintf(_("bad file format: %s\n"), filename); + eprintf( "ret, %i \n", ret); return 1; } if( ret < 0 ) { diff --git a/cinelerra-5.1/cinelerra/ffmpeg.h b/cinelerra-5.1/cinelerra/ffmpeg.h index 4f1624ce..53df96f1 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.h +++ b/cinelerra-5.1/cinelerra/ffmpeg.h @@ -15,6 +15,7 @@ #include "cstrdup.h" #include "edl.inc" #include "linklist.h" +#include "libmjpeg.h" #include "ffmpeg.inc" #include "filebase.inc" #include "fileffmpeg.inc" @@ -235,6 +236,9 @@ public: int convert_vframe_picture(VFrame *frame, AVFrame *op, AVFrame *opic); int convert_pixfmt(VFrame *frame, AVFrame *op); int transfer_pixfmt(VFrame *frame, AVFrame *ofp); + +private: + mjpeg_t *mjpeg; }; class FFVideoStream : public FFStream, public FFVideoConvert { @@ -479,6 +483,8 @@ public: const char *ff_hw_dev(); Preferences *ff_prefs(); void dump_context(AVCodecContext *ctx); + + }; #endif /* FFMPEG_H */ |
|
also, without some check in FFVideoConvert::convert_pixfmt attempt to use ffmpeg encoder with compressed (jpeg) v4l2 resulted in SIGFPE, this patch has unrelated lines, main one is + if(BC_CModels::components(cmodel)) (so we not divide by zero here) Sadly, this does not result in picture_with_sound recording, screen still empty/black (not green). Output with patch: ----[snip]--- BC_CModels::transfer failed:208 1(1280x720) to 9(1280x720) cmodel from convert_pixfmts 1 max_bits 1: 8 BC_components: 0 max_bits 8 imodel: -1 imodel_is_yuv: 0 cmodel_is_yuv 0 BC_CModels::transfer failed:208 1(1280x720) to 9(1280x720) cmodel from convert_pixfmts 1 max_bits 1: 8 BC_components: 0 max_bits 8 imodel: -1 imodel_is_yuv: 0 cmodel_is_yuv 0 ---[snip]--- so, apparently encoding from compressed source still require more work, but at least with this check Cin does not crash .... diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index b05a455d..a2d59244 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -1304,10 +1304,19 @@ int FFVideoStream::video_seek(int64_t pos) if( pos == curr_pos-1 && !seeked ) return 0; // if close enough, just read up to current int gop = avctx->gop_size; - if( gop < 4 ) gop = 4; + if( gop < 4 && gop != 0) gop = 4; if( gop > 64 ) gop = 64; + if( gop == 0 ) gop = 1; + //fprintf(stderr, "GOP: %i \n", gop); int read_limit = curr_pos + 3*gop; if( pos >= curr_pos && pos <= read_limit ) return 0; + // fixup for I-only codecs, not sure why it needed with ffmpeg 4.2 + if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO || st->codecpar->codec_id == AV_CODEC_ID_MJPEG || + st->codecpar->codec_id == AV_CODEC_ID_FFVHUFF || st->codecpar->codec_id == AV_CODEC_ID_DNXHD || + st->codecpar->codec_id ==AV_CODEC_ID_HUFFYUV || st->codecpar->codec_id == AV_CODEC_ID_PRORES) { + gop = 1; + if( seek(pos - 2*gop, frame_rate) < 0 ) return -1; + } // guarentee preload more than 2*gop frames if( seek(pos - 3*gop, frame_rate) < 0 ) return -1; return 1; @@ -1755,12 +1764,20 @@ int FFVideoConvert::convert_pixfmt(VFrame *frame, AVFrame *op) if( !convert_vframe_picture(frame, op) ) return 1; // use indirect transfer int cmodel = frame->get_color_model(); + printf("cmodel from convert_pixfmts %i \n", cmodel); int max_bits = BC_CModels::calculate_pixelsize(cmodel) * 8; + printf("max_bits 1: %i \n", max_bits); + printf("BC_components: %i \n", BC_CModels::components(cmodel)); + if(BC_CModels::components(cmodel)) max_bits /= BC_CModels::components(cmodel); + printf("max_bits %i \n", max_bits); AVPixelFormat ofmt = (AVPixelFormat)op->format; int imodel = pix_fmt_to_color_model(ofmt); + printf("imodel: %i \n", imodel); int imodel_is_yuv = BC_CModels::is_yuv(imodel); + printf("imodel_is_yuv: %i \n", imodel_is_yuv); int cmodel_is_yuv = BC_CModels::is_yuv(cmodel); + printf("cmodel_is_yuv %i \n", cmodel_is_yuv); if( imodel < 0 || imodel_is_yuv != cmodel_is_yuv ) { imodel = cmodel_is_yuv ? (BC_CModels::has_alpha(cmodel) ? @@ -2717,6 +2734,7 @@ int FFMPEG::init_encoder(const char *filename) ret = get_file_format(); if( ret > 0 ) { eprintf(_("bad file format: %s\n"), filename); + eprintf( "ret, %i \n", ret); return 1; } if( ret < 0 ) { |
|
v4l2 info: v4l2-ctl --all Driver Info: Driver name : uvcvideo Card type : Android: UVC Camera Bus info : usb-0000:00:13.2-3 Driver version : 5.6.14 Capabilities : 0x84a00001 Video Capture Metadata Capture Streaming Extended Pix Format Device Capabilities Device Caps : 0x04200001 Video Capture Streaming Extended Pix Format Priority: 2 Video input : 0 (Camera 1: ok) Format Video Capture: Width/Height : 1280/720 Pixel Format : 'MJPG' (Motion-JPEG) Field : None Bytes per Line : 0 Size Image : 1843200 Colorspace : sRGB Transfer Function : Default (maps to sRGB) YCbCr/HSV Encoding: Default (maps to ITU-R 601) Quantization : Default (maps to Full Range) Flags : Crop Capability Video Capture: Bounds : Left 0, Top 0, Width 1280, Height 720 Default : Left 0, Top 0, Width 1280, Height 720 Pixel Aspect: 1/1 Selection Video Capture: crop_default, Left 0, Top 0, Width 1280, Height 720, Flags: Selection Video Capture: crop_bounds, Left 0, Top 0, Width 1280, Height 720, Flags: Streaming Parameters Video Capture: Capabilities : timeperframe Frames per second: 30.000 (30/1) Read buffers : 0 |
|
@Andrew-R Unfortunately, I did not get time to look at this today but did download the VIDEODEVICE_FIX.diff file and will try again tomorrow. |
|
so, something like this fix allowed me to record jpeg_list out of mjpeg webcam ..... Warning, also designed to affect raw_DV (from DV input), untested due to lack of device ...
VIDEODEVICE_FIX.diff (1,085 bytes)
diff --git a/cinelerra-5.1/cinelerra/videodevice.C b/cinelerra-5.1/cinelerra/videodevice.C index 3ca744b4..2f279b6c 100644 --- a/cinelerra-5.1/cinelerra/videodevice.C +++ b/cinelerra-5.1/cinelerra/videodevice.C @@ -348,6 +348,8 @@ int VideoDevice::is_compressed(int use_file, int use_fixed) void VideoDevice::fix_asset(Asset *asset, int driver) { + + int override = 0; // Fix asset using legacy routine const char *vcodec = 0; switch(driver) { @@ -355,17 +357,26 @@ void VideoDevice::fix_asset(Asset *asset, int driver) case CAPTURE_IEC61883: case CAPTURE_FIREWIRE: vcodec = CODEC_TAG_DVSD; + if (asset->format != FILE_RAWDV ) + override = 1; break; #endif case VIDEO4LINUX2JPEG: vcodec = CODEC_TAG_MJPEG; + if (asset->format != FILE_JPEG_LIST) + override = 1; break; case CAPTURE_JPEG_WEBCAM: vcodec = CODEC_TAG_JPEG; + if (asset->format != FILE_JPEG_LIST) + override = 1; break; } + if( vcodec ) { + //printf("override: %i \n", override); + if (override) asset->format = FILE_FFMPEG; strcpy(asset->vcodec, vcodec); return; |
|
It seems cinelerra/recordmonitor.C implements its own decoding for mjpeg/dv (see for example RecVideoMJPGThread::render_frame) so probably RecordVideo::decompress_buffer(VFrame *frame) from cinelerra/recordvideo.C need to grow some of this decoding too ... but then it should somewhat replace original buffer (vframe) with decompressed copy? Because apparently transfer from/to BC_COMPRESSED not implemented in guicast/ code ? I was able to get mjpeg sequence out of device by commenting out 'asset->format = FILE_FFMPEG;' in void VideoDevice::fix_asset in cinelerra/videodevice.C - this allowed selection of jpeg/jpeg sequence but sadly it makes nearly all other choices crashy :( so may be special-case it some more, so only jpeg sequence will be allowed (no audio but slightly better than nothing).... |
|
webcam_cingg_dark.png (618,849 bytes) |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2021-09-20 11:11 | Andrew-R | New Issue | |
2021-09-20 11:13 | Andrew-R | File Added: webcam_cingg_dark.png | |
2021-09-20 23:13 | Andrew-R | Note Added: 0004973 | |
2021-09-21 00:29 | Andrew-R | File Added: VIDEODEVICE_FIX.diff | |
2021-09-21 00:29 | Andrew-R | Note Added: 0004974 | |
2021-09-21 00:49 | PhyllisSmith | Note Added: 0004975 | |
2021-09-21 01:05 | Andrew-R | Note Added: 0004976 | |
2021-09-21 02:03 | Andrew-R | Note Added: 0004980 | |
2021-09-21 04:12 | Andrew-R | File Added: ffmpeg_compr_attempt.diff | |
2021-09-21 04:12 | Andrew-R | Note Added: 0004981 | |
2021-12-26 23:44 | Andrew-R | Note Added: 0005206 |