[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1004782: A patch



Hello,

Attached is a patch with which the package successfully build with
FFMPEG 7:5.0-3 from experimental.

*NOTE:* The patch is FUNCTIONALLY UNTESTED. It's based on my limited
understanding of the recommended replacements for deprecated and removed
FFMPEG functionality. If someone could test it, or suggest a good way
for me to do so, that would be great. I have never used the video
features of Caffe, so I would need to know what to try out.


 Best,
 Gard

From: Gard Spreemann <gspr@nonempty.org>
Date: Fri, 11 Feb 2022 20:59:35 +0100
Subject: FFMPEG 5.0 support

---
 caffe2/video/video_decoder.cc | 77 ++++++++++++++++++++++++++++++-------------
 caffe2/video/video_decoder.h  |  1 +
 2 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/caffe2/video/video_decoder.cc b/caffe2/video/video_decoder.cc
index d40bc05..9ab7271 100644
--- a/caffe2/video/video_decoder.cc
+++ b/caffe2/video/video_decoder.cc
@@ -12,8 +12,10 @@ VideoDecoder::VideoDecoder() {
   static std::mutex gMutex;
   std::unique_lock<std::mutex> lock(gMutex);
   if (!gInitialized) {
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
     av_register_all();
     avcodec_register_all();
+#endif
     avformat_network_init();
     gInitialized = true;
   }
@@ -27,8 +29,20 @@ void VideoDecoder::getAudioSample(
     Callback& callback,
     const Params& params) {
   int frame_finished = 0;
-  auto result = avcodec_decode_audio4(
-      audioCodecContext_, audioStreamFrame_, &frame_finished, &packet);
+
+  int result = avcodec_send_packet(audioCodecContext_, &packet);
+  if (result < 0) {
+    LOG(ERROR) << "Failed to decode audio packet: " << ffmpegErrorStr(result);
+    return;
+  }
+  result = avcodec_receive_frame(audioCodecContext_, audioStreamFrame_);
+  if (result == 0) {
+    frame_finished = 1;
+  }
+  else if (result < 0 && result != AVERROR(EAGAIN) && result != AVERROR_EOF) {
+    LOG(ERROR) << "Failed to decode audio packet: " << ffmpegErrorStr(result);
+    return;
+  }
 
   if (frame_finished) {
     // from
@@ -185,12 +199,12 @@ void VideoDecoder::decodeLoop(
     if (params.streamIndex_ == -1) {
       for (int i = 0; i < inputContext->nb_streams; i++) {
         auto stream = inputContext->streams[i];
-        if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+        if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
             videoStreamIndex_ == -1) {
           videoStreamIndex_ = i;
           videoStream_ = stream;
         } else if (
-            stream->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+            stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
             audioStreamIndex_ == -1) {
           audioStreamIndex_ = i;
         }
@@ -207,7 +221,11 @@ void VideoDecoder::decodeLoop(
 
     // Initialize codec
     AVDictionary* opts = nullptr;
-    videoCodecContext_ = videoStream_->codec;
+    ret = avcodec_parameters_to_context(videoCodecContext_, videoStream_->codecpar);
+    if (ret < 0) {
+      LOG(ERROR) << "Cannot get codec context from parameters";
+      return;
+    }
     try {
       ret = avcodec_open2(
           videoCodecContext_,
@@ -226,7 +244,11 @@ void VideoDecoder::decodeLoop(
 
     if (params.getAudio_ && audioStreamIndex_ >= 0) {
       // see e.g. ridge/decoder/StreamDecoder.cpp
-      audioCodecContext_ = inputContext->streams[audioStreamIndex_]->codec;
+      ret = avcodec_parameters_to_context(audioCodecContext_, inputContext->streams[audioStreamIndex_]->codecpar);
+      if (ret < 0) {
+        LOG(ERROR) << "Failed to get codec parameters: " << ffmpegErrorStr(ret);
+        return;
+      }
       ret = avcodec_open2(
           audioCodecContext_,
           avcodec_find_decoder(audioCodecContext_->codec_id),
@@ -452,12 +474,12 @@ void VideoDecoder::decodeLoop(
           ret = av_read_frame(inputContext, &packet);
           if (ret == AVERROR_EOF) {
             eof = 1;
-            av_free_packet(&packet);
+            av_packet_unref(&packet);
             packet.data = nullptr;
             packet.size = 0;
             // stay in the while loop to flush frames
           } else if (ret == AVERROR(EAGAIN)) {
-            av_free_packet(&packet);
+            av_packet_unref(&packet);
             continue;
           } else if (ret < 0) {
             LOG(ERROR) << "Error reading packet : " << ffmpegErrorStr(ret);
@@ -483,13 +505,17 @@ void VideoDecoder::decodeLoop(
           }
 
           if (si != videoStreamIndex_) {
-            av_free_packet(&packet);
+            av_packet_unref(&packet);
             continue;
           }
         }
 
-        ret = avcodec_decode_video2(
-            videoCodecContext_, videoStreamFrame_, &gotPicture, &packet);
+        ret = avcodec_send_packet(videoCodecContext_, &packet);
+        if (ret < 0) {
+          LOG(ERROR) << "Error decoding video frame : " << ffmpegErrorStr(ret);
+          return;
+        }
+        ret = avcodec_receive_frame(videoCodecContext_, videoStreamFrame_);
         if (ret < 0) {
           LOG(ERROR) << "Error decoding video frame : " << ffmpegErrorStr(ret);
           return;
@@ -497,13 +523,12 @@ void VideoDecoder::decodeLoop(
         try {
           // Nothing to do without a picture
           if (!gotPicture) {
-            av_free_packet(&packet);
+            av_packet_unref(&packet);
             continue;
           }
           frameIndex++;
 
-          long int frame_ts =
-              av_frame_get_best_effort_timestamp(videoStreamFrame_);
+          long int frame_ts = videoStreamFrame_->best_effort_timestamp;
           timestamp = frame_ts * av_q2d(videoStream_->time_base);
           if ((frame_ts >= start_ts && !mustDecodeAll) || mustDecodeAll) {
             /* process current frame if:
@@ -534,7 +559,7 @@ void VideoDecoder::decodeLoop(
             if (!keyFrame) {
               // if fps == SpecialFps::SAMPLE_NO_FRAME (0), don't sample at all
               if (currFps == SpecialFps::SAMPLE_NO_FRAME) {
-                av_free_packet(&packet);
+                av_packet_unref(&packet);
                 continue;
               }
 
@@ -560,7 +585,7 @@ void VideoDecoder::decodeLoop(
                    timestamp >= lastFrameTimestamp + (1 / currFps));
 
               if (!fpsReached) {
-                av_free_packet(&packet);
+                av_packet_unref(&packet);
                 continue;
               }
             }
@@ -571,7 +596,7 @@ void VideoDecoder::decodeLoop(
             if (params.maximumOutputFrames_ != -1 &&
                 outputFrameIndex >= params.maximumOutputFrames_) {
               // enough frames
-              av_free_packet(&packet);
+              av_packet_unref(&packet);
               break;
             }
 
@@ -583,16 +608,22 @@ void VideoDecoder::decodeLoop(
 
             try {
               // Determine required buffer size and allocate buffer
-              int numBytes = avpicture_get_size(pixFormat, outWidth, outHeight);
+              int numBytes = av_image_get_buffer_size(pixFormat, outWidth, outHeight, 1);
               DecodedFrame::AvDataPtr buffer(
                   (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)));
 
-              int size = avpicture_fill(
-                  (AVPicture*)rgbFrame,
+              int size = av_image_fill_arrays(
+                  rgbFrame->data,
+                  rgbFrame->linesize,
                   buffer.get(),
                   pixFormat,
                   outWidth,
-                  outHeight);
+                  outHeight,
+                  1);
+              if (size < 0) {
+                LOG(ERROR) << "Failed to fill frame";
+                return;
+              }
 
               sws_scale(
                   scaleContext_,
@@ -628,9 +659,9 @@ void VideoDecoder::decodeLoop(
           av_frame_unref(audioStreamFrame_);
         }
 
-        av_free_packet(&packet);
+        av_packet_unref(&packet);
       } catch (const std::exception&) {
-        av_free_packet(&packet);
+        av_packet_unref(&packet);
       }
     } // of while loop
     callback.videoDecodingEnded(timestamp);
diff --git a/caffe2/video/video_decoder.h b/caffe2/video/video_decoder.h
index a091142..8c061fd 100644
--- a/caffe2/video/video_decoder.h
+++ b/caffe2/video/video_decoder.h
@@ -11,6 +11,7 @@ extern "C" {
 #include <libavcodec/avcodec.h>
 #include <libavformat/avformat.h>
 #include <libavformat/avio.h>
+#include <libavutil/imgutils.h>
 #include <libavutil/log.h>
 #include <libavutil/motion_vector.h>
 #include <libswresample/swresample.h>

Attachment: signature.asc
Description: PGP signature


Reply to: