$ 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);