Repository: incubator-guacamole-server
Updated Branches:
  refs/heads/master 135514a0d -> 701268271


GUACAMOLE-167: Use avcodec_send_frame() / avcodec_receive_packet() when 
available.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/9a51675e
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/9a51675e
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/9a51675e

Branch: refs/heads/master
Commit: 9a51675e32fe4c2c29d325750beb110e9d985b18
Parents: ea6b094
Author: Michael Jumper <[email protected]>
Authored: Fri Jan 27 20:29:45 2017 -0800
Committer: Michael Jumper <[email protected]>
Committed: Fri Jan 27 20:29:45 2017 -0800

----------------------------------------------------------------------
 src/guacenc/ffmpeg-compat.c | 85 +++++++++++++++++++++++++++++++---------
 1 file changed, 66 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/9a51675e/src/guacenc/ffmpeg-compat.c
----------------------------------------------------------------------
diff --git a/src/guacenc/ffmpeg-compat.c b/src/guacenc/ffmpeg-compat.c
index fb280a3..218d450 100644
--- a/src/guacenc/ffmpeg-compat.c
+++ b/src/guacenc/ffmpeg-compat.c
@@ -31,9 +31,44 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+/**
+ * Writes a single packet of video data to the current output file. If an error
+ * occurs preventing the packet from being written, messages describing the
+ * error are logged.
+ *
+ * @param video
+ *     The video associated with the output file that the given packet should
+ *     be written to.
+ *
+ * @param data
+ *     The buffer of data containing the video packet which should be written.
+ *
+ * @param size
+ *     The number of bytes within the video packet.
+ *
+ * @return
+ *     Zero if the packet was written successfully, non-zero otherwise.
+ */
+static int guacenc_write_packet(guacenc_video* video, void* data, int size) {
+
+    /* Write data, logging any errors */
+    if (fwrite(data, 1, size, video->output) == 0) {
+        guacenc_log(GUAC_LOG_ERROR, "Unable to write frame "
+                "#%" PRId64 ": %s", video->next_pts, strerror(errno));
+        return -1;
+    }
+
+    /* Data was written successfully */
+    guacenc_log(GUAC_LOG_DEBUG, "Frame #%08" PRId64 ": wrote %i bytes",
+            video->next_pts, size);
+
+    return 0;
+
+}
+
 int guacenc_avcodec_encode_video(guacenc_video* video, AVFrame* frame) {
 
-/* For libavcodec < 54.1.0: avcodec_encode_video2() did not exist */
+/* For libavcodec < 54.1.0: packets were handled as raw malloc'd buffers */
 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,1,0)
 
     AVCodecContext* context = video->context;
@@ -62,14 +97,7 @@ int guacenc_avcodec_encode_video(guacenc_video* video, 
AVFrame* frame) {
     }
 
     /* Write data, logging any errors */
-    if (fwrite(data, 1, used, video->output) == 0) {
-        guacenc_log(GUAC_LOG_ERROR, "Unable to write frame "
-                "#%" PRId64 ": %s", video->next_pts, strerror(errno));
-        free(data);
-        return -1;
-    }
-
-    /* Data was written successfully */
+    guacenc_write_packet(video, data, used);
     free(data);
     return 1;
 
@@ -83,6 +111,8 @@ int guacenc_avcodec_encode_video(guacenc_video* video, 
AVFrame* frame) {
     packet.data = NULL;
     packet.size = 0;
 
+/* For libavcodec < 57.16.0: input/output was not decoupled */
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,16,0)
     /* Write frame to video */
     int got_data;
     if (avcodec_encode_video2(video->context, &packet, frame, &got_data) < 0) {
@@ -93,23 +123,40 @@ int guacenc_avcodec_encode_video(guacenc_video* video, 
AVFrame* frame) {
 
     /* Write corresponding data to file */
     if (got_data) {
+        guacenc_write_packet(video, packet.data, packet.size);
+        av_packet_unref(&packet);
+    }
+#else
+    /* Write frame to video */
+    int result = avcodec_send_frame(video->context, frame);
 
-        /* Write data, logging any errors */
-        if (fwrite(packet.data, 1, packet.size, video->output) == 0) {
-            guacenc_log(GUAC_LOG_ERROR, "Unable to write frame "
-                    "#%" PRId64 ": %s", video->next_pts, strerror(errno));
-            return -1;
-        }
+    /* Stop once encoded has been flushed */
+    if (result == AVERROR_EOF)
+        return 0;
 
-        /* Data was written successfully */
-        guacenc_log(GUAC_LOG_DEBUG, "Frame #%08" PRId64 ": wrote %i bytes",
-                video->next_pts, packet.size);
+    /* Abort on error */
+    else if (result < 0) {
+        guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64,
+                video->next_pts);
+        return -1;
+    }
+
+    /* Flush all available packets */
+    int got_data = 0;
+    while (avcodec_receive_packet(video->context, &packet) == 0) {
+
+        /* Data was received */
+        got_data = 1;
+
+        /* Attempt to write data to output file */
+        guacenc_write_packet(video, packet.data, packet.size);
         av_packet_unref(&packet);
 
     }
+#endif
 
     /* Frame may have been queued for later writing / reordering */
-    else
+    if (!got_data)
         guacenc_log(GUAC_LOG_DEBUG, "Frame #%08" PRId64 ": queued for later",
                 video->next_pts);
 

Reply via email to