mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge branch 4.x
This commit is contained in:
@@ -612,6 +612,7 @@ struct CvCapture_FFMPEG
|
||||
bool rawModeInitialized;
|
||||
bool rawSeek;
|
||||
bool convertRGB;
|
||||
bool enableAlpha;
|
||||
AVPacket packet_filtered;
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(58, 20, 100)
|
||||
AVBSFContext* bsfc;
|
||||
@@ -669,6 +670,7 @@ void CvCapture_FFMPEG::init()
|
||||
rawModeInitialized = false;
|
||||
rawSeek = false;
|
||||
convertRGB = true;
|
||||
enableAlpha = false;
|
||||
memset(&packet_filtered, 0, sizeof(packet_filtered));
|
||||
av_init_packet(&packet_filtered);
|
||||
bsfc = NULL;
|
||||
@@ -1085,9 +1087,10 @@ bool CvCapture_FFMPEG::open(const char* _filename, int index, const Ptr<IStreamR
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO/FFMPEG: BGR conversion turned OFF, decoded frame will be "
|
||||
"returned in its original format. "
|
||||
"Multiplanar formats are not supported by the backend. "
|
||||
"Only GRAY8/GRAY16LE pixel formats have been tested. "
|
||||
"Only GRAY8/GRAY16LE/RGBA pixel formats have been tested. "
|
||||
"Use at your own risk.");
|
||||
}
|
||||
|
||||
if (params.has(CAP_PROP_FORMAT))
|
||||
{
|
||||
int value = params.get<int>(CAP_PROP_FORMAT);
|
||||
@@ -1098,8 +1101,19 @@ bool CvCapture_FFMPEG::open(const char* _filename, int index, const Ptr<IStreamR
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: " << value);
|
||||
return false;
|
||||
if (value == CV_8UC3)
|
||||
{
|
||||
enableAlpha = false;
|
||||
}
|
||||
if (value == CV_8UC4)
|
||||
{
|
||||
enableAlpha = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: " << value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!rawMode) {
|
||||
@@ -1879,9 +1893,12 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
|
||||
<< ", primaries: " << av_color_primaries_name(sw_picture->color_primaries)
|
||||
<< ", transfer: " << av_color_transfer_name(sw_picture->color_trc)
|
||||
);
|
||||
const AVPixelFormat result_format = convertRGB ? AV_PIX_FMT_BGR24 : (AVPixelFormat)sw_picture->format;
|
||||
|
||||
const AVPixelFormat color_format = enableAlpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR24;
|
||||
const AVPixelFormat result_format = convertRGB ? color_format : (AVPixelFormat)sw_picture->format;
|
||||
switch (result_format)
|
||||
{
|
||||
case AV_PIX_FMT_BGRA: *depth = CV_8U; *cn = 4; break;
|
||||
case AV_PIX_FMT_BGR24: *depth = CV_8U; *cn = 3; break;
|
||||
case AV_PIX_FMT_GRAY8: *depth = CV_8U; *cn = 1; break;
|
||||
case AV_PIX_FMT_GRAY16LE: *depth = CV_16U; *cn = 1; break;
|
||||
@@ -2122,6 +2139,12 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
|
||||
case CAP_PROP_FORMAT:
|
||||
if (rawMode)
|
||||
return -1;
|
||||
else if (!convertRGB)
|
||||
return CV_8UC1;
|
||||
else if (enableAlpha)
|
||||
return CV_8UC4;
|
||||
else
|
||||
return CV_8UC3;
|
||||
break;
|
||||
case CAP_PROP_CONVERT_RGB:
|
||||
return convertRGB;
|
||||
@@ -2365,8 +2388,20 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
|
||||
seek((int64_t)(value*ic->duration));
|
||||
return true;
|
||||
case CAP_PROP_FORMAT:
|
||||
if (!convertRGB)
|
||||
return false;
|
||||
if (value == -1)
|
||||
return setRaw();
|
||||
else if (value == CV_8UC3)
|
||||
{
|
||||
enableAlpha = false;
|
||||
return true;
|
||||
}
|
||||
else if (value == CV_8UC4)
|
||||
{
|
||||
enableAlpha = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case CAP_PROP_CONVERT_RGB:
|
||||
convertRGB = (value != 0);
|
||||
@@ -2775,6 +2810,12 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (input_pix_fmt == AV_PIX_FMT_BGRA) {
|
||||
if (cn != 4) {
|
||||
CV_LOG_WARNING(NULL, "write frame skipped - expected 4 channels but got " << cn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (input_pix_fmt == AV_PIX_FMT_GRAY8 || input_pix_fmt == AV_PIX_FMT_GRAY16LE) {
|
||||
if (cn != 1) {
|
||||
CV_LOG_WARNING(NULL, "write frame skipped - expected 1 channel but got " << cn);
|
||||
@@ -3151,6 +3192,8 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
use_opencl = params.get<int>(VIDEOWRITER_PROP_HW_ACCELERATION_USE_OPENCL);
|
||||
}
|
||||
|
||||
bool enable_alpha = params.get<bool>(VIDEOWRITER_PROP_ENABLE_ALPHA, false);
|
||||
|
||||
if (params.warnUnusedParameters())
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in VideoWriter, see logger INFO channel for details");
|
||||
@@ -3185,7 +3228,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
{
|
||||
switch (depth)
|
||||
{
|
||||
case CV_8U: input_pix_fmt = AV_PIX_FMT_BGR24; break;
|
||||
case CV_8U: input_pix_fmt = enable_alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR24; break;
|
||||
default:
|
||||
CV_LOG_WARNING(NULL, "Unsupported input depth for color image: " << depth);
|
||||
return false;
|
||||
@@ -3387,7 +3430,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
break;
|
||||
default:
|
||||
// good for lossy formats, MPEG, etc.
|
||||
codec_pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
codec_pix_fmt = enable_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2512,25 +2512,43 @@ bool CvVideoWriter_GStreamer::open( const std::string &filename, int fourcc,
|
||||
CV_WARN("OpenCV backend does not support this file type (extension): " << filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
//create pipeline elements
|
||||
encodebin.reset(gst_element_factory_make("encodebin", NULL));
|
||||
|
||||
if (!encodebin)
|
||||
{
|
||||
CV_WARN("GStreamer: cannot create encodebin element");
|
||||
return false;
|
||||
}
|
||||
GSafePtr<GstCaps> containercaps;
|
||||
GSafePtr<GstEncodingContainerProfile> containerprofile;
|
||||
GSafePtr<GstEncodingVideoProfile> videoprofile;
|
||||
|
||||
containercaps.attach(gst_caps_from_string(mime));
|
||||
|
||||
//create encodebin profile
|
||||
containerprofile.attach(gst_encoding_container_profile_new("container", "container", containercaps.get(), NULL));
|
||||
videoprofile.reset(gst_encoding_video_profile_new(videocaps.get(), NULL, NULL, 1));
|
||||
gst_encoding_container_profile_add_profile(containerprofile.get(), (GstEncodingProfile*)videoprofile.get());
|
||||
|
||||
unsigned int colorspace_fourcc = (unsigned int)params.get(VIDEOWRITER_PROP_COLOR_SPACE, CV_FOURCC('I', '4', '2', '0'));
|
||||
const char* colorspace = gst_video_format_to_string(gst_video_format_from_fourcc(colorspace_fourcc));
|
||||
GSafePtr<GstCaps> prof_caps;
|
||||
std::string caps_str = std::string("video/x-raw, format=") + std::string(colorspace);
|
||||
prof_caps.attach(gst_caps_from_string(caps_str.c_str()));
|
||||
videoprofile.attach(gst_encoding_video_profile_new(prof_caps.get(), NULL, NULL, 1));
|
||||
// Transfer ownership to the container profile
|
||||
gst_encoding_container_profile_add_profile(
|
||||
containerprofile.get(),
|
||||
(GstEncodingProfile*)videoprofile.detach()
|
||||
);
|
||||
g_object_set(G_OBJECT(encodebin.get()), "profile", containerprofile.get(), NULL);
|
||||
|
||||
source.reset(gst_element_factory_make("appsrc", NULL));
|
||||
if (!source)
|
||||
{
|
||||
CV_WARN("GStreamer: cannot create appsrc element");
|
||||
return false;
|
||||
}
|
||||
file.reset(gst_element_factory_make("filesink", NULL));
|
||||
if (!file)
|
||||
{
|
||||
CV_WARN("GStreamer: cannot create filesink element");
|
||||
return false;
|
||||
}
|
||||
g_object_set(G_OBJECT(file.get()), "location", (const char*)filename.c_str(), NULL);
|
||||
}
|
||||
|
||||
@@ -2709,21 +2727,22 @@ void CvVideoWriter_GStreamer::write(InputArray image)
|
||||
|
||||
Mat imageMat = image.getMat();
|
||||
const size_t buf_size = imageMat.total() * imageMat.elemSize();
|
||||
duration = ((double)1/framerate) * GST_SECOND;
|
||||
timestamp = num_frames * duration;
|
||||
duration = gst_util_uint64_scale_int(GST_SECOND, 1, framerate);
|
||||
timestamp = gst_util_uint64_scale_int(num_frames, GST_SECOND, framerate);
|
||||
|
||||
//gst_app_src_push_buffer takes ownership of the buffer, so we need to supply it a copy
|
||||
GstBuffer *buffer = gst_buffer_new_allocate(NULL, buf_size, NULL);
|
||||
GstMapInfo info;
|
||||
gst_buffer_map(buffer, &info, (GstMapFlags)GST_MAP_READ);
|
||||
memcpy(info.data, (guint8*)imageMat.data, buf_size);
|
||||
gst_buffer_unmap(buffer, &info);
|
||||
if (gst_buffer_map(buffer, &info, (GstMapFlags)GST_MAP_WRITE)) {
|
||||
memcpy(info.data, (guint8*)imageMat.data, buf_size);
|
||||
gst_buffer_unmap(buffer, &info);
|
||||
}
|
||||
GST_BUFFER_DURATION(buffer) = duration;
|
||||
GST_BUFFER_PTS(buffer) = timestamp;
|
||||
GST_BUFFER_DTS(buffer) = timestamp;
|
||||
//set the current number in the frame
|
||||
GST_BUFFER_OFFSET(buffer) = num_frames;
|
||||
|
||||
GST_BUFFER_OFFSET_END(buffer) = num_frames + 1;
|
||||
ret = gst_app_src_push_buffer(GST_APP_SRC(source.get()), buffer);
|
||||
if (ret != GST_FLOW_OK)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user