1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2026-02-11 13:54:39 +03:00
committed by Alexander Smorkalov
468 changed files with 16647 additions and 11284 deletions
+171 -201
View File
@@ -1155,228 +1155,198 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
double fps, const cv::Size& frame_size,
int is_color) {
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
@autoreleasepool {
frameCount = 0;
movieFPS = fps;
movieSize = frame_size;
movieColor = is_color;
argbimage = cv::Mat(movieSize, CV_8UC4);
path = [[[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] stringByExpandingTildeInPath] retain];
/*
AVFileTypeQuickTimeMovie
UTI for the QuickTime movie file format.
The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions.
frameCount = 0;
movieFPS = fps;
movieSize = frame_size;
movieColor = is_color;
argbimage = cv::Mat(movieSize, CV_8UC4);
path = [[[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] stringByExpandingTildeInPath] retain];
AVFileTypeMPEG4
UTI for the MPEG-4 file format.
The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension.
AVFileTypeAppleM4V
UTI for the iTunes video file format.
The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension.
/*
AVFileTypeQuickTimeMovie
UTI for the QuickTime movie file format.
The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions.
AVFileType3GPP
UTI for the 3GPP file format.
The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions.
*/
AVFileTypeMPEG4
UTI for the MPEG-4 file format.
The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension.
AVFileTypeAppleM4V
UTI for the iTunes video file format.
The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension.
AVFileType3GPP
UTI for the 3GPP file format.
The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions.
*/
NSString *fileExt =[[[path pathExtension] lowercaseString] copy];
if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]){
fileType = [AVFileTypeQuickTimeMovie copy];
}else if ([fileExt isEqualToString:@"mp4"]){
fileType = [AVFileTypeMPEG4 copy];
}else if ([fileExt isEqualToString:@"m4v"]){
fileType = [AVFileTypeAppleM4V copy];
NSString *fileExt = [[[path pathExtension] lowercaseString] copy];
if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]) {
fileType = [AVFileTypeQuickTimeMovie copy];
} else if ([fileExt isEqualToString:@"mp4"]) {
fileType = [AVFileTypeMPEG4 copy];
} else if ([fileExt isEqualToString:@"m4v"]) {
fileType = [AVFileTypeAppleM4V copy];
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
}else if ([fileExt isEqualToString:@"3gp"] || [fileExt isEqualToString:@"3gpp"] || [fileExt isEqualToString:@"sdv"] ){
fileType = [AVFileType3GPP copy];
} else if ([fileExt isEqualToString:@"3gp"] || [fileExt isEqualToString:@"3gpp"] || [fileExt isEqualToString:@"sdv"]) {
fileType = [AVFileType3GPP copy];
#endif
} else{
fileType = [AVFileTypeMPEG4 copy]; //default mp4
}
[fileExt release];
} else {
fileType = [AVFileTypeMPEG4 copy]; //default mp4
}
[fileExt release];
char cc[5];
cc[0] = fourcc & 255;
cc[1] = (fourcc >> 8) & 255;
cc[2] = (fourcc >> 16) & 255;
cc[3] = (fourcc >> 24) & 255;
cc[4] = 0;
int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
if (cc2!=fourcc) {
std::cout << "WARNING: Didn't properly encode FourCC. Expected " << fourcc
<< " but got " << cc2 << "." << std::endl;
//exception;
}
char cc[5];
cc[0] = fourcc & 255;
cc[1] = (fourcc >> 8) & 255;
cc[2] = (fourcc >> 16) & 255;
cc[3] = (fourcc >> 24) & 255;
cc[4] = 0;
int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
if (cc2 != fourcc) {
std::cout << "WARNING: Didn't properly encode FourCC. Expected " << fourcc
<< " but got " << cc2 << "." << std::endl;
}
// Three codec supported AVVideoCodecTypeH264 AVVideoCodecTypeJPEG AVVideoCodecTypeHEVC
// On iPhone 3G H264 is not supported.
if (fourcc == CV_FOURCC('J','P','E','G') || fourcc == CV_FOURCC('j','p','e','g') ||
fourcc == CV_FOURCC('M','J','P','G') || fourcc == CV_FOURCC('m','j','p','g')){
codec = [AVVideoCodecTypeJPEG copy]; // Use JPEG codec if specified, otherwise H264
}else if(fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')){
codec = [AVVideoCodecTypeH264 copy];
// Three codec supported AVVideoCodecTypeH264 AVVideoCodecTypeJPEG AVVideoCodecTypeHEVC
// On iPhone 3G H264 is not supported.
if (fourcc == CV_FOURCC('J','P','E','G') || fourcc == CV_FOURCC('j','p','e','g') ||
fourcc == CV_FOURCC('M','J','P','G') || fourcc == CV_FOURCC('m','j','p','g')) {
codec = [AVVideoCodecTypeJPEG copy]; // Use JPEG codec if specified, otherwise H264
} else if (fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')) {
codec = [AVVideoCodecTypeH264 copy];
// Available since iOS 11
#if TARGET_OS_VISION || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000)
}else if(fourcc == CV_FOURCC('H','2','6','5') || fourcc == CV_FOURCC('h','v','c','1') ||
fourcc == CV_FOURCC('H','E','V','C') || fourcc == CV_FOURCC('h','e','v','c')){
if (@available(iOS 11, *)) {
codec = [AVVideoCodecTypeHEVC copy];
} else {
codec = [AVVideoCodecTypeH264 copy];
}
} else if (fourcc == CV_FOURCC('H','2','6','5') || fourcc == CV_FOURCC('h','v','c','1') ||
fourcc == CV_FOURCC('H','E','V','C') || fourcc == CV_FOURCC('h','e','v','c')) {
if (@available(iOS 11, *)) {
codec = [AVVideoCodecTypeHEVC copy];
} else {
codec = [AVVideoCodecTypeH264 copy];
}
#endif
}else{
codec = [AVVideoCodecTypeH264 copy]; // default canonical H264.
} else {
codec = [AVVideoCodecTypeH264 copy]; // default canonical H264.
}
NSError *error = nil;
// Wire the writer:
// Supported file types:
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
fileType:fileType
error:&error];
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
codec, AVVideoCodecKey,
[NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
[NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
nil];
mMovieWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
[mMovieWriter addInput:mMovieWriterInput];
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
//Start a session:
[mMovieWriter startWriting];
[mMovieWriter startSessionAtSourceTime:kCMTimeZero];
if (mMovieWriter.status == AVAssetWriterStatusFailed) {
NSLog(@"%@", [mMovieWriter.error localizedDescription]);
// TODO: error handling, cleanup. Throw exception?
}
}
//NSLog(@"Path: %@", path);
NSError *error = nil;
// Make sure the file does not already exist. Necessary to overwrite??
/*
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]){
[fileManager removeItemAtPath:path error:&error];
}
*/
// Wire the writer:
// Supported file types:
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
fileType:fileType
error:&error];
//NSParameterAssert(mMovieWriter);
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
codec, AVVideoCodecKey,
[NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
[NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
nil];
mMovieWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
//NSParameterAssert(mMovieWriterInput);
//NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
[mMovieWriter addInput:mMovieWriterInput];
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
//Start a session:
[mMovieWriter startWriting];
[mMovieWriter startSessionAtSourceTime:kCMTimeZero];
if(mMovieWriter.status == AVAssetWriterStatusFailed){
NSLog(@"%@", [mMovieWriter.error localizedDescription]);
// TODO: error handling, cleanup. Throw exception?
// return;
}
[localpool drain];
}
CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() {
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
[mMovieWriterInput markAsFinished];
[mMovieWriter finishWritingWithCompletionHandler:^() {
[mMovieWriter release];
[mMovieWriterInput release];
[mMovieWriterAdaptor release];
[path release];
[codec release];
[fileType release];
argbimage.release();
[localpool drain];
}];
@autoreleasepool {
[mMovieWriterInput markAsFinished];
[mMovieWriter finishWritingWithCompletionHandler:^() {
@autoreleasepool {
[mMovieWriter release];
[mMovieWriterInput release];
[mMovieWriterAdaptor release];
[path release];
[codec release];
[fileType release];
argbimage.release();
}
}];
}
}
void CvVideoWriter_AVFoundation::write(cv::InputArray image) {
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
@autoreleasepool {
// writer status check
if (![mMovieWriterInput isReadyForMoreMediaData] || mMovieWriter.status != AVAssetWriterStatusWriting) {
NSLog(@"[mMovieWriterInput isReadyForMoreMediaData] Not ready for media data or ...");
NSLog(@"mMovieWriter.status: %d. Error: %@", (int)mMovieWriter.status, [mMovieWriter.error localizedDescription]);
return;
}
// writer status check
if (![mMovieWriterInput isReadyForMoreMediaData] || mMovieWriter.status != AVAssetWriterStatusWriting ) {
NSLog(@"[mMovieWriterInput isReadyForMoreMediaData] Not ready for media data or ...");
NSLog(@"mMovieWriter.status: %d. Error: %@", (int)mMovieWriter.status, [mMovieWriter.error localizedDescription]);
[localpool drain];
return;
BOOL success = FALSE;
if (image.size().height != movieSize.height || image.size().width != movieSize.width) {
std::cout << "Frame size does not match video size." << std::endl;
return;
}
if (movieColor) {
cv::cvtColor(image, argbimage, cv::COLOR_BGR2BGRA);
} else {
cv::cvtColor(image, argbimage, cv::COLOR_GRAY2BGRA);
}
//IplImage -> CGImage conversion
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSData *nsData = [NSData dataWithBytes:argbimage.data length:argbimage.total() * argbimage.elemSize()];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)nsData);
CGImageRef cgImage = CGImageCreate(argbimage.size().width, argbimage.size().height,
8, 32, argbimage.step[0],
colorSpace, kCGImageAlphaLast|kCGBitmapByteOrderDefault,
provider, NULL, false, kCGRenderingIntentDefault);
//CGImage -> CVPixelBufferRef conversion
CVPixelBufferRef pixelBuffer = NULL;
CFDataRef cfData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
int status = CVPixelBufferCreateWithBytes(NULL,
movieSize.width,
movieSize.height,
kCVPixelFormatType_32BGRA,
(void*)CFDataGetBytePtr(cfData),
CGImageGetBytesPerRow(cgImage),
NULL,
0,
NULL,
&pixelBuffer);
if (status == kCVReturnSuccess) {
success = [mMovieWriterAdaptor appendPixelBuffer:pixelBuffer
withPresentationTime:CMTimeMake(frameCount, movieFPS)];
}
//cleanup
CFRelease(cfData);
CVPixelBufferRelease(pixelBuffer);
CGImageRelease(cgImage);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
if (success) {
frameCount++;
return;
} else {
NSLog(@"Frame appendPixelBuffer failed.");
return;
}
}
BOOL success = FALSE;
if (image.size().height!=movieSize.height || image.size().width!=movieSize.width){
std::cout<<"Frame size does not match video size."<<std::endl;
[localpool drain];
return;
}
if (movieColor) {
//assert(image->nChannels == 3);
cv::cvtColor(image, argbimage, cv::COLOR_BGR2BGRA);
}else{
//assert(image->nChannels == 1);
cv::cvtColor(image, argbimage, cv::COLOR_GRAY2BGRA);
}
//IplImage -> CGImage conversion
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSData *nsData = [NSData dataWithBytes:argbimage.data length:argbimage.total() * argbimage.elemSize()];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)nsData);
CGImageRef cgImage = CGImageCreate(argbimage.size().width, argbimage.size().height,
8, 32, argbimage.step[0],
colorSpace, kCGImageAlphaLast|kCGBitmapByteOrderDefault,
provider, NULL, false, kCGRenderingIntentDefault);
//CGImage -> CVPixelBufferRef conversion
CVPixelBufferRef pixelBuffer = NULL;
CFDataRef cfData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
int status = CVPixelBufferCreateWithBytes(NULL,
movieSize.width,
movieSize.height,
kCVPixelFormatType_32BGRA,
(void*)CFDataGetBytePtr(cfData),
CGImageGetBytesPerRow(cgImage),
NULL,
0,
NULL,
&pixelBuffer);
if(status == kCVReturnSuccess){
success = [mMovieWriterAdaptor appendPixelBuffer:pixelBuffer
withPresentationTime:CMTimeMake(frameCount, movieFPS)];
}
//cleanup
CFRelease(cfData);
CVPixelBufferRelease(pixelBuffer);
CGImageRelease(cgImage);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
[localpool drain];
if (success) {
frameCount ++;
//NSLog(@"Frame #%d", frameCount);
return;
}else{
NSLog(@"Frame appendPixelBuffer failed.");
return;
}
}
#pragma clang diagnostic pop
#pragma clang diagnostic pop
+4 -4
View File
@@ -2394,7 +2394,7 @@ int videoInput::getVideoPropertyFromCV(int cv_property){
case CAP_PROP_MONOCHROME:
return VideoProcAmp_ColorEnable;
case CAP_PROP_WHITE_BALANCE_BLUE_U:
case cv::VideoCaptureProperties::CAP_PROP_WB_TEMPERATURE:
return VideoProcAmp_WhiteBalance;
case cv::VideoCaptureProperties::CAP_PROP_AUTO_WB:
@@ -3422,7 +3422,7 @@ double VideoCapture_DShow::getProperty(int propIdx) const
case CAP_PROP_SHARPNESS:
case CAP_PROP_GAMMA:
case CAP_PROP_MONOCHROME:
case CAP_PROP_WHITE_BALANCE_BLUE_U:
case cv::VideoCaptureProperties::CAP_PROP_WB_TEMPERATURE:
case CAP_PROP_BACKLIGHT:
case CAP_PROP_GAIN:
if (g_VI.getVideoSettingFilter(m_index, g_VI.getVideoPropertyFromCV(propIdx), min_value, max_value, stepping_delta, current_value, flags, defaultValue))
@@ -3589,7 +3589,7 @@ bool VideoCapture_DShow::setProperty(int propIdx, double propVal)
else
flags = VideoProcAmp_Flags_Manual;
break;
case CAP_PROP_WHITE_BALANCE_BLUE_U:
case cv::VideoCaptureProperties::CAP_PROP_WB_TEMPERATURE:
flags = VideoProcAmp_Flags_Manual;
break;
}
@@ -3604,7 +3604,7 @@ bool VideoCapture_DShow::setProperty(int propIdx, double propVal)
case CAP_PROP_SHARPNESS:
case CAP_PROP_GAMMA:
case CAP_PROP_MONOCHROME:
case CAP_PROP_WHITE_BALANCE_BLUE_U:
case cv::VideoCaptureProperties::CAP_PROP_WB_TEMPERATURE:
case cv::VideoCaptureProperties::CAP_PROP_AUTO_WB:
case CAP_PROP_BACKLIGHT:
case CAP_PROP_GAIN:
+136 -16
View File
@@ -524,6 +524,17 @@ inline static std::string _opencv_ffmpeg_get_error_string(int error_code)
return std::string("Unknown error");
}
static inline int64_t to_avtb(int64_t ts, AVRational tb)
{
return av_rescale_q(ts, tb, AV_TIME_BASE_Q);
}
static inline int64_t from_avtb(int64_t ts_avtb, AVRational tb)
{
return av_rescale_q(ts_avtb, AV_TIME_BASE_Q, tb);
}
struct CvCapture_FFMPEG
{
bool open(const char* filename, int index, const Ptr<IStreamReader>& stream, const VideoCaptureParameters& params);
@@ -563,6 +574,10 @@ struct CvCapture_FFMPEG
int64_t pts_in_fps_time_base;
int64_t dts_delay_in_fps_time_base;
/// Timestamp offset in AV_TIME_BASE units for normalization
int64_t ts_offset_avtb = 0;
bool ts_offset_decided = false;
AVIOContext * avio_context;
AVPacket packet;
@@ -623,6 +638,8 @@ void CvCapture_FFMPEG::init()
picture_pts = AV_NOPTS_VALUE_;
pts_in_fps_time_base = 0;
dts_delay_in_fps_time_base = 0;
ts_offset_avtb = 0;
ts_offset_decided = false;
first_frame_number = -1;
memset( &rgb_picture, 0, sizeof(rgb_picture) );
memset( &frame, 0, sizeof(frame) );
@@ -1705,15 +1722,74 @@ bool CvCapture_FFMPEG::grabFrame()
if (picture_pts == AV_NOPTS_VALUE_) {
int64_t dts = 0;
if (!rawMode) {
picture_pts = picture->CV_FFMPEG_PTS_FIELD != AV_NOPTS_VALUE_ && picture->CV_FFMPEG_PTS_FIELD != 0 ? picture->CV_FFMPEG_PTS_FIELD : picture->pkt_dts;
if(frame_number == 0) dts = picture->pkt_dts;
}
else {
const AVPacket& packet_raw = packet.data != 0 ? packet : packet_filtered;
picture_pts = packet_raw.pts != AV_NOPTS_VALUE_ && packet_raw.pts != 0 ? packet_raw.pts : packet_raw.dts;
picture_pts = (picture->CV_FFMPEG_PTS_FIELD != AV_NOPTS_VALUE_)
? picture->CV_FFMPEG_PTS_FIELD
: picture->pkt_dts;
if (frame_number == 0) dts = picture->pkt_dts;
} else {
const AVPacket& packet_raw = (packet.data != 0) ? packet : packet_filtered;
picture_pts = (packet_raw.pts != AV_NOPTS_VALUE_)
? packet_raw.pts
: packet_raw.dts;
if (frame_number == 0) dts = packet_raw.dts;
if (picture_pts < 0) picture_pts = 0;
}
// Decide timestamp offset once on first frame to normalize all timestamps to start at zero.
// This handles videos with negative DTS values (e.g., from B-frame reordering) or non-zero
// start_time. Similar to FFmpeg's -avoid_negative_ts make_zero option.
if (!ts_offset_decided)
{
int64_t min_start_avtb = INT64_MAX;
// Check container start_time (already in AV_TIME_BASE units)
if (ic && ic->start_time != AV_NOPTS_VALUE_)
{
min_start_avtb = ic->start_time;
}
// Check stream start_time
AVStream* st = ic->streams[video_stream];
if (st->start_time != AV_NOPTS_VALUE_)
{
int64_t s = to_avtb(st->start_time, st->time_base);
if (s < min_start_avtb) min_start_avtb = s;
}
// Check first observed timestamp (PTS preferred, else DTS from frame 0)
int64_t first_ts_stream = picture_pts;
if (first_ts_stream == AV_NOPTS_VALUE_ && dts != AV_NOPTS_VALUE_)
{
first_ts_stream = dts;
}
if (first_ts_stream != AV_NOPTS_VALUE_)
{
int64_t t = to_avtb(first_ts_stream, st->time_base);
if (t < min_start_avtb) min_start_avtb = t;
}
// Compute offset to shift negative timestamps to zero
ts_offset_avtb = (min_start_avtb != INT64_MAX && min_start_avtb < 0) ? -min_start_avtb : 0;
ts_offset_decided = true;
}
// Apply normalization to picture_pts
if (picture_pts != AV_NOPTS_VALUE_)
{
int64_t t = to_avtb(picture_pts, video_st->time_base);
t += ts_offset_avtb;
picture_pts = from_avtb(t, video_st->time_base);
}
// Also normalize dts
if (dts != AV_NOPTS_VALUE_)
{
int64_t t = to_avtb(dts, video_st->time_base);
t += ts_offset_avtb;
dts = from_avtb(t, video_st->time_base);
}
#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0) || LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
AVRational frame_rate = video_st->avg_frame_rate;
#else
@@ -1769,16 +1845,28 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
// if hardware frame, copy it to system memory
if (picture && picture->hw_frames_ctx) {
sw_picture = av_frame_alloc();
if (!sw_picture) {
CV_LOG_ERROR(NULL, "av_frame_alloc failed");
return false;
}
//if (av_hwframe_map(sw_picture, picture, AV_HWFRAME_MAP_READ) < 0) {
if (av_hwframe_transfer_data(sw_picture, picture, 0) < 0) {
CV_LOG_ERROR(NULL, "Error copying data from GPU to CPU (av_hwframe_transfer_data)");
av_frame_free(&sw_picture);
return false;
}
}
#endif
if (!sw_picture || !sw_picture->data[0])
{
#if USE_AV_HW_CODECS
if (sw_picture != picture)
av_frame_free(&sw_picture);
#endif
CV_LOG_ERROR(NULL, "Picture does not contain data");
return false;
}
#if LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(56, 72, 0)
const char* color_space_name = av_color_space_name(sw_picture->colorspace);
@@ -1829,7 +1917,14 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
img_convert_ctx = sws_alloc_context();
if (img_convert_ctx == NULL)
return false;//CV_Error(0, "Cannot initialize the conversion context!");
{
CV_LOG_ERROR(NULL, "Cannot initialize the conversion context!");
#if USE_AV_HW_CODECS
if (sw_picture != picture)
av_frame_free(&sw_picture);
#endif
return false;
}
av_opt_set_int(img_convert_ctx, "sws_flags", SWS_BICUBIC, 0);
av_opt_set_int(img_convert_ctx, "threads", requestedThreads, 0);
@@ -1870,8 +1965,14 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
);
#endif
if (img_convert_ctx == NULL)
return false;//CV_Error(0, "Cannot initialize the conversion context!");
if (img_convert_ctx == NULL) {
CV_LOG_ERROR(NULL, "Cannot initialize the conversion context!");
#if USE_AV_HW_CODECS
if (sw_picture != picture)
av_frame_free(&sw_picture);
#endif
return false;
}
#if USE_AV_FRAME_GET_BUFFER
av_frame_unref(&rgb_picture);
@@ -1880,7 +1981,11 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
rgb_picture.height = buffer_height;
if (0 != av_frame_get_buffer(&rgb_picture, 32))
{
CV_WARN("OutOfMemory");
CV_LOG_ERROR(NULL, "Out of memory issue on av_frame_get_buffer!");
#if USE_AV_HW_CODECS
if (sw_picture != picture)
av_frame_free(&sw_picture);
#endif
return false;
}
#else
@@ -2120,8 +2225,13 @@ int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts)
double CvCapture_FFMPEG::dts_to_sec(int64_t dts) const
{
return (double)(dts - ic->streams[video_stream]->start_time) *
r2d(ic->streams[video_stream]->time_base);
const AVStream* st = ic->streams[video_stream];
int64_t ts = dts;
if (ts_offset_avtb == 0 && st->start_time != AV_NOPTS_VALUE_)
ts -= st->start_time;
return ts * r2d(st->time_base);
}
void CvCapture_FFMPEG::get_rotation_angle()
@@ -2174,9 +2284,19 @@ void CvCapture_FFMPEG::seek(int64_t _frame_number)
{
int64_t _frame_number_temp = std::max(_frame_number-delta, (int64_t)0);
double sec = (double)_frame_number_temp / get_fps();
int64_t time_stamp = ic->streams[video_stream]->start_time;
double time_base = r2d(ic->streams[video_stream]->time_base);
time_stamp += (int64_t)(sec / time_base + 0.5);
AVStream* st = ic->streams[video_stream];
int64_t time_stamp = st->start_time;
double time_base = r2d(st->time_base);
int64_t ts_norm = (int64_t)(sec / time_base + 0.5);
if (ts_offset_avtb != 0) {
// map normalized target back to original demux timeline
time_stamp += ts_norm - from_avtb(ts_offset_avtb, st->time_base);
} else {
time_stamp += ts_norm;
}
if (get_total_frames() > 1) av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD);
if(!rawMode)
avcodec_flush_buffers(context);
+1 -1
View File
@@ -1103,7 +1103,7 @@ bool CvCaptureCAM_V4L::grabFrame()
FirstCapture = false;
#if defined(V4L_ABORT_BADJPEG)
// skip first frame. it is often bad -- this is unnotied in traditional apps,
// skip first frame. it is often bad -- this is unnoticed in traditional apps,
// but could be fatal if bad jpeg is enabled
if (!read_frame_v4l2())
return false;