ClaireXie / ffmpeg-Opencv

Wrapper class of using OpenCV in ffmpeg
9 stars 5 forks source link

[patch] Code upgrade with current ffmpeg #2

Open ebachard opened 6 years ago

ebachard commented 6 years ago

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