$ git clone http://tcclient.ion.nu/tc_client.git
commit ac065f4a684c2e4266a01915a3dedc163532cd8c
Author: Alicia <...>
Date:   Fri Sep 23 17:26:54 2016 +0200

    tc_client-gtk and camviewer: updated to libavcodec's avcodec_{send,receive}_{frame,packet} API.

diff --git a/ChangeLog b/ChangeLog
index 043c7f1..19d3f49 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@
 tc_client-gtk: merged camera_remove() and camera_removebynick() into a single function, merged the deallocation of camera data into camera_free()
 tc_client-gtk: moved the postprocessing code into its own source file.
 tc_client-gtk: added greenscreen postprocessor.
+tc_client-gtk and camviewer: updated to libavcodec's avcodec_{send,receive}_{frame,packet} API.
 0.39:
 Added a /closecam command to stop receiving a cam stream.
 Use uintX_t for endianness functions instead of unsigned long*x int.
diff --git a/configure b/configure
index 1ec2937..10b0229 100755
--- a/configure
+++ b/configure
@@ -130,6 +130,7 @@ if [ "x$avcodeclibs" != "x" ]; then
       echo '}' >> config.h
     fi
     if testbuild 'buf in AVPacket' 'AVPacket x; x.buf=0;' 'libavcodec/avcodec.h' "$avcodecflags"; then echo '#define AVPACKET_HAS_BUF 1' >> config.h; fi
+    if ! testbuild 'avcodec_send_packet and avcodec_receive_frame' 'void* x=avcodec_send_packet; x=avcodec_receive_frame;' 'libavcodec/avcodec.h' "$avcodecflags"; then echo '#define AVCODEC_NO_SEND_RECEIVE_API 1' >> config.h; fi
   fi
 else
   echo no
diff --git a/utilities/camviewer/camviewer.c b/utilities/camviewer/camviewer.c
index fc462b6..a395578 100644
--- a/utilities/camviewer/camviewer.c
+++ b/utilities/camviewer/camviewer.c
@@ -1,6 +1,6 @@
 /*
     camviewer, a sample application to view tinychat cam streams
-    Copyright (C) 2015  alicia@ion.nu
+    Copyright (C) 2015-2016  alicia@ion.nu
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Affero General Public License as published by
@@ -304,8 +304,9 @@ gboolean handledata(GIOChannel* channel, GIOCondition condition, gpointer datap)
     }
     if(!cam){printf("No cam found with ID '%s'\n", &buf[7]); return 1;}
     int gotframe;
-    avcodec_decode_audio4(cam->actx, cam->frame, &gotframe, &pkt);
-    if(!gotframe){return 1;}
+    avcodec_send_packet(cam->actx, &pkt);
+    gotframe=avcodec_receive_frame(cam->actx, cam->frame);
+    if(gotframe){return 1;}
   #ifdef HAVE_AVRESAMPLE
     int outlen=avresample_convert(data->resamplectx, cam->frame->data, cam->frame->linesize[0], cam->frame->nb_samples, cam->frame->data, cam->frame->linesize[0], cam->frame->nb_samples);
   #else
@@ -347,8 +348,9 @@ gboolean handledata(GIOChannel* channel, GIOCondition condition, gpointer datap)
   if(!cam){printf("No cam found with ID '%s'\n", &buf[7]); return 1;}
   pkt.size=size;
   int gotframe;
-  avcodec_decode_video2(cam->vctx, cam->frame, &gotframe, &pkt);
-  if(!gotframe){return 1;}
+  avcodec_send_packet(cam->vctx, &pkt);
+  gotframe=avcodec_receive_frame(cam->vctx, cam->frame);
+  if(gotframe){return 1;}
 
   // Convert to RGB24 format
   unsigned int bufsize=av_image_get_buffer_size(AV_PIX_FMT_RGB24, cam->frame->width, cam->frame->height, 1);
@@ -461,7 +463,9 @@ void togglecam(GtkButton* button, struct viddata* data)
       av_init_packet(&packet);
       packet.data=0;
 packet.size=0;
-      avcodec_encode_video2(ctx, &packet, dstframe, &gotpacket);
+      avcodec_send_frame(ctx, dstframe);
+      gotpacket=avcodec_receive_packet(ctx, &packet);
+      if(gotpacket){continue;}
       unsigned char frameinfo=0x22; // Note: differentiating between keyframes and non-keyframes seems to break stuff, so let's just go with all being interframes (1=keyframe, 2=interframe, 3=disposable interframe)
       dprintf(tc_client_in[1], "/video %i\n", packet.size+1);
       write(tc_client_in[1], &frameinfo, 1);
diff --git a/utilities/compat.c b/utilities/compat.c
index 5fe6ca3..198e55b 100644
--- a/utilities/compat.c
+++ b/utilities/compat.c
@@ -50,3 +50,41 @@ char* strndup(const char* in, unsigned int length)
   return out;
 }
 #endif
+
+#ifdef AVCODEC_NO_SEND_RECEIVE_API
+void* compat_sendreceive_object=0;
+
+int compat_avcodec_send_packet(AVCodecContext* ctx, AVPacket* packet)
+{
+  compat_sendreceive_object=packet;
+  return 0;
+}
+
+int compat_avcodec_receive_frame(AVCodecContext* ctx, AVFrame* frame)
+{
+  int got;
+  if(ctx->codec_type==AVMEDIA_TYPE_VIDEO)
+  {
+    avcodec_decode_video2(ctx, frame, &got, compat_sendreceive_object);
+  }else{
+    avcodec_decode_audio4(ctx, frame, &got, compat_sendreceive_object);
+  }
+  return !got;
+}
+
+int compat_avcodec_send_frame(AVCodecContext* ctx, AVFrame* frame)
+{
+  compat_sendreceive_object=frame;
+  return 0;
+}
+
+int compat_avcodec_receive_packet(AVCodecContext* ctx, AVPacket* packet)
+{
+  int got;
+  if(ctx->codec_type==AVMEDIA_TYPE_VIDEO)
+  {
+    avcodec_encode_video2(ctx, packet, compat_sendreceive_object, &got);
+  }
+  return !got;
+}
+#endif
diff --git a/utilities/compat.h b/utilities/compat.h
index 0b6c66b..ef0c72d 100644
--- a/utilities/compat.h
+++ b/utilities/compat.h
@@ -34,3 +34,13 @@
 #if GLIB_MAJOR_VERSION<2 || (GLIB_MAJOR_VERSION==2 && GLIB_MINOR_VERSION<2)
   #define g_io_channel_read_chars(a,b,c,d,e) g_io_channel_read(a,b,c,d)
 #endif
+#ifdef AVCODEC_NO_SEND_RECEIVE_API
+  #define avcodec_send_packet compat_avcodec_send_packet
+  #define avcodec_receive_frame compat_avcodec_receive_frame
+  #define avcodec_send_frame compat_avcodec_send_frame
+  #define avcodec_receive_packet compat_avcodec_receive_packet
+  extern int compat_avcodec_send_packet(AVCodecContext* ctx, AVPacket* packet);
+  extern int compat_avcodec_receive_frame(AVCodecContext* ctx, AVFrame* frame);
+  extern int compat_avcodec_send_frame(AVCodecContext* ctx, AVFrame* frame);
+  extern int compat_avcodec_receive_packet(AVCodecContext* ctx, AVPacket* packet);
+#endif
diff --git a/utilities/gtk/camviewer.c b/utilities/gtk/camviewer.c
index 59ee2d4..ba02661 100644
--- a/utilities/gtk/camviewer.c
+++ b/utilities/gtk/camviewer.c
@@ -201,8 +201,9 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     if(!cam){printf("No cam found with ID '%s'\n", &buf[7]); return 1;}
     pkt.size=size;
     int gotframe;
-    avcodec_decode_video2(cam->vctx, cam->frame, &gotframe, &pkt);
-    if(!gotframe){return 1;}
+    avcodec_send_packet(cam->vctx, &pkt);
+    gotframe=avcodec_receive_frame(cam->vctx, cam->frame);
+    if(gotframe){return 1;}
 
     if(cam->placeholder) // Remove the placeholder animation if it has it
     {
@@ -251,8 +252,9 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     struct camera* cam=camera_find(&buf[7]);
     if(!cam){printf("No cam found with ID '%s'\n", &buf[7]); return 1;}
     int gotframe;
-    avcodec_decode_audio4(cam->actx, cam->frame, &gotframe, &pkt);
-    if(!gotframe){return 1;}
+    avcodec_send_packet(cam->actx, &pkt);
+    gotframe=avcodec_receive_frame(cam->actx, cam->frame);
+    if(gotframe){return 1;}
   #ifdef HAVE_AVRESAMPLE
     int outlen=avresample_convert(data->resamplectx, cam->frame->data, cam->frame->linesize[0], cam->frame->nb_samples, cam->frame->data, cam->frame->linesize[0], cam->frame->nb_samples);
   #else
diff --git a/utilities/gtk/media.c b/utilities/gtk/media.c
index d0b409f..ea01daa 100644
--- a/utilities/gtk/media.c
+++ b/utilities/gtk/media.c
@@ -244,7 +244,9 @@ gboolean cam_encode(GIOChannel* iochannel, GIOCondition condition, gpointer data
     .pts=AV_NOPTS_VALUE
   };
   av_init_packet(&packet);
-  avcodec_encode_video2(cam->vctx, &packet, cam->dstframe, &gotpacket);
+  avcodec_send_frame(cam->vctx, cam->dstframe);
+  gotpacket=avcodec_receive_packet(cam->vctx, &packet);
+  if(gotpacket){return 1;}
   unsigned char frameinfo=0x22; // Note: differentiating between keyframes and non-keyframes seems to break stuff, so let's just go with all being interframes (1=keyframe, 2=interframe, 3=disposable interframe)
   // Send video
   dprintf(tc_client_in[1], "/video %i\n", packet.size+1);