ClaireXie/ffmpeg-Opencv

[patch] Code upgrade with current ffmpeg

Opened this issue · 0 comments

Hello,

I tested your code, and I had to fix some build issues + some warnings => see below (attached as a txt file, to simplify its application). Recent ffmpeg means current (28th August 2018) master ffmpeg version from github repo. Last, consider the changes are under MIT license.

As a patch : ffmpeg-OpenCV.diff.txt

Current status : the current code is warning free on Linux, but untested. Please tell me whethere there is crash in runtime, and I'll have a look.

diff --git a/README.md b/README.md
index f0569c5..4098f86 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,16 @@
 ffmpegOpencv
 ============
 This is a simple class for the interface between ffmpeg and openCV.
+
+Linux compilation instructions 
+
+1. uncomment the main()  in the .cpp file
+2. type (in one line) :
+
+g++ -Wall -I . -o ffcvmat  videoCodec.cpp `pkg-config --cflags --libs opencv libavformat libavcodec libavutil libavdevice libswscale`
+
+3. if nothinggoes wrong, a binary named ffcvmat should be built
+
+4. ./ffcvmat does nothing, just complete it !
+
+ericb / 28th August 2018
diff --git a/videoCodec.cpp b/videoCodec.cpp
index 156516c..5c6d3be 100644
--- a/videoCodec.cpp
+++ b/videoCodec.cpp
@@ -7,7 +7,7 @@ void VideoCodec::destory()
     av_free(c);
 	av_free(frame);
     av_freep(&frameRescaled->data[0]);
-    avcodec_free_frame(&frameRescaled);
+    av_frame_free(&frameRescaled);
 }
 
 bool VideoCodec::initBase(bool isEncoder)
@@ -15,12 +15,12 @@ bool VideoCodec::initBase(bool isEncoder)
 	
 	encoder = isEncoder;
 
-	orgFormat = PIX_FMT_RGB24;
+	orgFormat = AV_PIX_FMT_RGB24;
 
-	frame = avcodec_alloc_frame();
+	frame = av_frame_alloc();
 	
 	frame->format = orgFormat;
-	frameRescaled = avcodec_alloc_frame();
+	frameRescaled = av_frame_alloc();
 
 	avWidth = AVW;  
 	avHeight = AVH; 
@@ -62,8 +62,9 @@ VideoEncode::VideoEncode(AVCodecID id)
 
 bool VideoEncode::init(int w, int h)
 {
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
 	avcodec_register_all();
-
+#endif
 	if (!initBase(encoder)) return false;
 
     c->bit_rate = 6500000;
@@ -125,11 +126,22 @@ bool VideoEncode::loadcvFrame(cv::Mat input)
 	if (input.channels() != 3)
 		cvtColor(cvFrame, cvFrame, CV_GRAY2BGR);
 
-	avpicture_fill((AVPicture *)frame, cvFrame.data, orgFormat, cvFrame.cols, cvFrame.rows);
+//	avpicture_fill((AVPicture *)frame, cvFrame.data, orgFormat, cvFrame.cols, cvFrame.rows);
+
+        AVFrame frame;
+        av_image_fill_arrays(   frame.data,
+                                frame.linesize,
+                                &cvFrame.data[0],
+                                orgFormat,
+                                cvFrame.cols,
+                                cvFrame.rows,
+                                1
+                             );
+
 
 	// rescale to outStream format
-    int h = sws_scale(swsCtx, ((AVPicture*)frame)->data, ((AVPicture*)frame)->linesize, 
-		0, c->height, ((AVPicture*)frameRescaled)->data, ((AVPicture*)frameRescaled) ->linesize);
+    int h = sws_scale(swsCtx, frame.data, frame.linesize, 
+		0, c->height, frameRescaled->data, frameRescaled ->linesize);
 
 	if (h ==0) {
 		fprintf(stderr, "Fail to rescale\n");
@@ -155,19 +167,28 @@ int VideoEncode::encode(cv::Mat input, int index, unsigned char cdata[])
     pkt.size = 0;
 
     /* encode the image */
-	int got_output;
-    int ret = avcodec_encode_video2(c, &pkt, frameRescaled, &got_output);
-    if (ret < 0) {
-        fprintf(stderr, "Error encoding frame\n");
-        return -1;
-    }
+	int got_output = 0;
+        int ret = avcodec_send_packet(c, &pkt);
+
+        if (ret < 0) {
+            fprintf(stderr, "Error encoding frame\n");
+            return -1;
+        }
+
+        ret = avcodec_receive_frame(c, frameRescaled);
+
+        if ((ret == AVERROR_EOF))
+            got_output = 0;
+        else
+            got_output = 1;
+
 	if (got_output) {
 		size = pkt.size;
 		memcpy ( cdata, pkt.data, pkt.size*sizeof(unsigned char));
 		//fprintf(stderr, "Encoding %d bytes\n", size);
 	}
 
-	av_free_packet(&pkt);
+	av_packet_unref(&pkt);
 
 	return size;
 }
@@ -181,8 +202,9 @@ VideoDecode::VideoDecode(AVCodecID id)
 
 bool VideoDecode::init(int w, int h)
 {
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
 	avcodec_register_all();
-
+#endif
 	if (!initBase(encoder)) return false;
 
 	c->pix_fmt = codecFormat;
@@ -220,22 +242,41 @@ int VideoDecode::decode(cv::Mat &output, const unsigned char cdata[], int pkgSiz
 
     /* encode the image */
 	int got_frame;
-    int len = avcodec_decode_video2(c, frame, &got_frame, &pkt);
+
+    int len = avcodec_send_packet(c, &pkt);
+
     if (len < 0) {
-        fprintf(stderr, "Error decoding frame\n");
+        fprintf(stderr, "Error encoding frame\n");
         return -1;
     }
+
+    len = avcodec_receive_frame(c, frame);
+
+    if ((len == AVERROR_EOF))
+        got_frame = 0;
+    else
+        got_frame = 1;
+
 	if (got_frame) {
 		int h = sws_scale(swsCtx, frame->data, frame->linesize, 0, c->height, 
 					frameRescaled->data, frameRescaled ->linesize);
-
+		if (h != 0)
+		    fprintf(stderr, "error with swscale");
 		output = cv::Mat(cvHeight, cvWidth, CV_8UC3, frameRescaled->data[0]); 
 	}
 
-	av_free_packet(&pkt);
+	av_packet_unref(&pkt);
 
 	return len;
 }
 
+// uncomment for compilation tests
+/*
+int main (void)
+{
+  // do nothing
+  return EXIT_SUCCESS;
+}
+*/
 
 
diff --git a/videoCodec.h b/videoCodec.h
index fac96af..121b39d 100644
--- a/videoCodec.h
+++ b/videoCodec.h
@@ -15,9 +15,10 @@ extern "C" {
 
 #include <math.h>
 #include <stdio.h>
-#include "timer.h"
+//#include "timer.h"
 #include "opencv/cv.h"
-#include "opencv/highgui.h"
+#include <opencv2/opencv.hpp>
+#include <opencv2/highgui.hpp>
 
 
 #define inline __inline

HTH

--
ericb