@@ -481,7 +481,8 @@ struct CvCapture_FFMPEG
481
481
double getProperty (int ) const ;
482
482
bool setProperty (int , double );
483
483
bool grabFrame ();
484
- bool retrieveFrame (int , unsigned char ** data, int * step, int * width, int * height, int * cn);
484
+ bool retrieveFrame (int , cv::Mat &mat);
485
+ void rotateFrame (cv::Mat &mat) const ;
485
486
486
487
void init ();
487
488
@@ -497,6 +498,7 @@ struct CvCapture_FFMPEG
497
498
double r2d (AVRational r) const ;
498
499
int64_t dts_to_frame_number (int64_t dts);
499
500
double dts_to_sec (int64_t dts) const ;
501
+ void get_rotation_angle ();
500
502
501
503
AVFormatContext * ic;
502
504
AVCodec * avcodec;
@@ -512,6 +514,8 @@ struct CvCapture_FFMPEG
512
514
513
515
int64_t frame_number, first_frame_number;
514
516
517
+ bool rotation_auto;
518
+ int rotation_angle; // valid 0, 90, 180, 270
515
519
double eps_zero;
516
520
/*
517
521
'filename' contains the filename of the videosource,
@@ -560,6 +564,9 @@ void CvCapture_FFMPEG::init()
560
564
frame_number = 0 ;
561
565
eps_zero = 0.000025 ;
562
566
567
+ rotation_auto = true ;
568
+ rotation_angle = 0 ;
569
+
563
570
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
564
571
dict = NULL ;
565
572
#endif
@@ -1032,6 +1039,7 @@ bool CvCapture_FFMPEG::open( const char* _filename )
1032
1039
frame.cn = 3 ;
1033
1040
frame.step = 0 ;
1034
1041
frame.data = NULL ;
1042
+ get_rotation_angle ();
1035
1043
break ;
1036
1044
}
1037
1045
}
@@ -1279,21 +1287,19 @@ bool CvCapture_FFMPEG::grabFrame()
1279
1287
return valid;
1280
1288
}
1281
1289
1282
-
1283
- bool CvCapture_FFMPEG::retrieveFrame (int , unsigned char ** data, int * step, int * width, int * height, int * cn)
1290
+ bool CvCapture_FFMPEG::retrieveFrame (int , cv::Mat &mat)
1284
1291
{
1285
1292
if (!video_st)
1286
1293
return false ;
1287
1294
1288
1295
if (rawMode)
1289
1296
{
1290
1297
AVPacket& p = bsfc ? packet_filtered : packet;
1291
- *data = p.data ;
1292
- *step = p.size ;
1293
- *width = p.size ;
1294
- *height = 1 ;
1295
- *cn = 1 ;
1296
- return p.data != NULL ;
1298
+ if (p.data == NULL )
1299
+ return false ;
1300
+
1301
+ mat = cv::Mat (1 , p.size , CV_MAKETYPE (CV_8U, 1 ), p.data , p.size );
1302
+ return true ;
1297
1303
}
1298
1304
1299
1305
if (!picture->data [0 ])
@@ -1356,15 +1362,29 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int*
1356
1362
rgb_picture.linesize
1357
1363
);
1358
1364
1359
- *data = frame.data ;
1360
- *step = frame.step ;
1361
- *width = frame.width ;
1362
- *height = frame.height ;
1363
- *cn = frame.cn ;
1364
-
1365
+ mat = cv::Mat (frame.height , frame.width , CV_MAKETYPE (CV_8U, frame.cn ), frame.data , frame.step );
1366
+ rotateFrame (mat);
1365
1367
return true ;
1366
1368
}
1367
1369
1370
+ void CvCapture_FFMPEG::rotateFrame (cv::Mat &mat) const {
1371
+ if (!rotation_auto || rotation_angle%360 == 0 ) {
1372
+ return ;
1373
+ }
1374
+
1375
+ cv::RotateFlags flag;
1376
+ if (rotation_angle == 90 || rotation_angle == -270 ) { // Rotate clockwise 90 degrees
1377
+ flag = cv::ROTATE_90_CLOCKWISE;
1378
+ } else if (rotation_angle == 270 || rotation_angle == -90 ) { // Rotate clockwise 270 degrees
1379
+ flag = cv::ROTATE_90_COUNTERCLOCKWISE;
1380
+ } else if (rotation_angle == 180 || rotation_angle == -180 ) { // Rotate clockwise 180 degrees
1381
+ flag = cv::ROTATE_180;
1382
+ } else { // Unsupported rotation
1383
+ return ;
1384
+ }
1385
+
1386
+ cv::rotate (mat, mat, flag);
1387
+ }
1368
1388
1369
1389
double CvCapture_FFMPEG::getProperty ( int property_id ) const
1370
1390
{
@@ -1389,9 +1409,9 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
1389
1409
case CV_FFMPEG_CAP_PROP_FRAME_COUNT:
1390
1410
return (double )get_total_frames ();
1391
1411
case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
1392
- return (double )frame.width ;
1412
+ return (double )((rotation_auto && rotation_angle% 360 ) ? frame.height : frame. width ) ;
1393
1413
case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
1394
- return (double )frame.height ;
1414
+ return (double )((rotation_auto && rotation_angle% 360 ) ? frame.width : frame. height ) ;
1395
1415
case CV_FFMPEG_CAP_PROP_FPS:
1396
1416
return get_fps ();
1397
1417
case CV_FFMPEG_CAP_PROP_FOURCC:
@@ -1435,6 +1455,10 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
1435
1455
break ;
1436
1456
case CV_FFMPEG_CAP_PROP_BITRATE:
1437
1457
return static_cast <double >(get_bitrate ());
1458
+ case CV_FFMPEG_CAP_PROP_ORIENTATION_META:
1459
+ return static_cast <double >(rotation_angle);
1460
+ case CV_FFMPEG_CAP_PROP_ORIENTATION_AUTO:
1461
+ return static_cast <double >(rotation_auto);
1438
1462
default :
1439
1463
break ;
1440
1464
}
@@ -1513,6 +1537,14 @@ double CvCapture_FFMPEG::dts_to_sec(int64_t dts) const
1513
1537
r2d (ic->streams [video_stream]->time_base );
1514
1538
}
1515
1539
1540
+ void CvCapture_FFMPEG::get_rotation_angle ()
1541
+ {
1542
+ rotation_angle = 0 ;
1543
+ AVDictionaryEntry *rotate_tag = av_dict_get (video_st->metadata , " rotate" , NULL , 0 );
1544
+ if (rotate_tag != NULL )
1545
+ rotation_angle = atoi (rotate_tag->value );
1546
+ }
1547
+
1516
1548
void CvCapture_FFMPEG::seek (int64_t _frame_number)
1517
1549
{
1518
1550
_frame_number = std::min (_frame_number, get_total_frames ());
@@ -1608,6 +1640,9 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
1608
1640
if (value == -1 )
1609
1641
return setRaw ();
1610
1642
return false ;
1643
+ case CV_FFMPEG_CAP_PROP_ORIENTATION_AUTO:
1644
+ rotation_auto = static_cast <bool >(value);
1645
+ break ;
1611
1646
default :
1612
1647
return false ;
1613
1648
}
@@ -2635,9 +2670,9 @@ int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)
2635
2670
return capture->grabFrame ();
2636
2671
}
2637
2672
2638
- int cvRetrieveFrame_FFMPEG (CvCapture_FFMPEG* capture, unsigned char ** data, int * step, int * width, int * height, int * cn )
2673
+ int cvRetrieveFrame_FFMPEG (CvCapture_FFMPEG* capture, cv::Mat &mat )
2639
2674
{
2640
- return capture->retrieveFrame (0 , data, step, width, height, cn );
2675
+ return capture->retrieveFrame (0 , mat );
2641
2676
}
2642
2677
2643
2678
CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG ( const char * filename, int fourcc, double fps,
0 commit comments