$ git clone http://tcclient.ion.nu/tc_client.git
commit c1fa8fa855c1b45a119a6aeac1d3e1f572820a02
Author: Alicia <...>
Date:   Thu Sep 15 01:07:10 2016 +0200

    tc_client-gtk: optimized incoming audio/video by checking for "Video:" and "Audio:" first when handling lines from the tc_client core.

diff --git a/ChangeLog b/ChangeLog
index 6419984..fb184a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -24,6 +24,7 @@ tc_client-gtk: break the cameras into two or more rows if it means they can be l
 tc_client-gtk: un-highlight selected PM tabs even if the sender has left.
 tc_client-gtk: prevent new PM tabs from stopping automatic scrolling.
 tc_client-gtk: if the server disconnects, print the notification and stop any outgoing broadcast.
+tc_client-gtk: optimized incoming audio/video by checking for "Video:" and "Audio:" first when handling lines from the tc_client core.
 tc_client-gtk and camviewer: fixed compatibility with newer libavutil.
 tc_client-gtk and camviewer: added compatibility fallbacks for av_image_get_buffer_size() and av_packet_unref()
 tc_client-gtk and camviewer: specify a scaling algorithm for libswscale (mandatory for older versions of libswscale)
diff --git a/utilities/gtk/camviewer.c b/utilities/gtk/camviewer.c
index cd4397b..e760e65 100644
--- a/utilities/gtk/camviewer.c
+++ b/utilities/gtk/camviewer.c
@@ -172,6 +172,91 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     if(buf[i]=='\r'||buf[i]=='\n'){break;}
   }
   buf[i]=0;
+  if(!strncmp(buf, "Video: ", 7))
+  {
+    char* sizestr=strchr(&buf[7], ' ');
+    if(!sizestr){return 1;}
+    sizestr[0]=0;
+    // Find the camera representation for the given ID
+    struct camera* cam=camera_find(&buf[7]);
+    unsigned int size=strtoul(&sizestr[1], 0, 0);
+    if(!size){return 1;}
+    // Mostly ignore the first byte (contains frame type (e.g. keyframe etc.) in 4 bits and codec in the other 4)
+    --size;
+    AVPacket pkt;
+    av_init_packet(&pkt);
+    unsigned char databuf[size+4];
+    pkt.data=databuf;
+    unsigned char frameinfo;
+    g_io_channel_read_chars(iochannel, (gchar*)&frameinfo, 1, 0, 0);
+//   printf("Frametype-frame: %x\n", ((unsigned int)frameinfo&0xf0)/16);
+//   printf("Frametype-codec: %x\n", (unsigned int)frameinfo&0xf);
+    unsigned int pos=0;
+    while(pos<size)
+    {
+      g_io_channel_read_chars(iochannel, (gchar*)pkt.data+pos, size-pos, &r, 0);
+      pos+=r;
+    }
+    if((frameinfo&0xf)!=2){return 1;} // Not FLV1, get data but discard it
+    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;}
+
+    // Scale and convert to RGB24 format
+    unsigned int bufsize=av_image_get_buffer_size(AV_PIX_FMT_RGB24, camsize_scale.width, camsize_scale.height, 1);
+    unsigned char* buf=malloc(bufsize);
+    cam->dstframe->data[0]=buf;
+    cam->dstframe->linesize[0]=camsize_scale.width*3;
+    struct SwsContext* swsctx=sws_getContext(cam->frame->width, cam->frame->height, cam->frame->format, camsize_scale.width, camsize_scale.height, AV_PIX_FMT_RGB24, SWS_BICUBIC, 0, 0, 0);
+    sws_scale(swsctx, (const uint8_t*const*)cam->frame->data, cam->frame->linesize, 0, cam->frame->height, cam->dstframe->data, cam->dstframe->linesize);
+    sws_freeContext(swsctx);
+    camera_postproc(cam, cam->dstframe->data[0], camsize_scale.width, camsize_scale.height);
+
+    GdkPixbuf* oldpixbuf=gtk_image_get_pixbuf(GTK_IMAGE(cam->cam));
+    GdkPixbuf* gdkframe=gdk_pixbuf_new_from_data(cam->dstframe->data[0], GDK_COLORSPACE_RGB, 0, 8, camsize_scale.width, camsize_scale.height, cam->dstframe->linesize[0], freebuffer, 0);
+    gtk_image_set_from_pixbuf(GTK_IMAGE(cam->cam), gdkframe);
+    g_object_unref(oldpixbuf);
+    return 1;
+  }
+  if(!strncmp(buf, "Audio: ", 7))
+  {
+    char* sizestr=strchr(&buf[7], ' ');
+    if(!sizestr){return 1;}
+    sizestr[0]=0;
+    unsigned int size=strtoul(&sizestr[1], 0, 0);
+    if(!size){return 1;}
+    unsigned char frameinfo;
+    g_io_channel_read_chars(iochannel, (gchar*)&frameinfo, 1, 0, 0);
+    --size; // For the byte we read above
+    AVPacket pkt;
+    av_init_packet(&pkt);
+    unsigned char databuf[size];
+    pkt.data=databuf;
+    pkt.size=size;
+    unsigned int pos=0;
+    while(pos<size)
+    {
+      g_io_channel_read_chars(iochannel, (gchar*)pkt.data+pos, size-pos, &r, 0);
+      pos+=r;
+    }
+#if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
+    // Find the camera representation for the given ID (for decoder context)
+    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;}
+  #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
+    int outlen=swr_convert(data->swrctx, cam->frame->data, cam->frame->nb_samples, (const uint8_t**)cam->frame->data, cam->frame->nb_samples);
+  #endif
+    if(outlen>0){camera_playsnd(data->audiopipe, cam, (short*)cam->frame->data[0], outlen);}
+#endif
+    return 1;
+  }
   if(!strncmp(buf, "Currently online: ", 18))
   {
     printchat(buf, 0);
@@ -476,89 +561,8 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     }
     return 1;
   }
-  if(!strncmp(buf, "Audio: ", 7))
-  {
-    char* sizestr=strchr(&buf[7], ' ');
-    if(!sizestr){return 1;}
-    sizestr[0]=0;
-    unsigned int size=strtoul(&sizestr[1], 0, 0);
-    if(!size){return 1;}
-    unsigned char frameinfo;
-    g_io_channel_read_chars(iochannel, (gchar*)&frameinfo, 1, 0, 0);
-    --size; // For the byte we read above
-    AVPacket pkt;
-    av_init_packet(&pkt);
-    unsigned char databuf[size];
-    pkt.data=databuf;
-    pkt.size=size;
-    unsigned int pos=0;
-    while(pos<size)
-    {
-      g_io_channel_read_chars(iochannel, (gchar*)pkt.data+pos, size-pos, &r, 0);
-      pos+=r;
-    }
-#if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
-    // Find the camera representation for the given ID (for decoder context)
-    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;}
-  #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
-    int outlen=swr_convert(data->swrctx, cam->frame->data, cam->frame->nb_samples, (const uint8_t**)cam->frame->data, cam->frame->nb_samples);
-  #endif
-    if(outlen>0){camera_playsnd(data->audiopipe, cam, (short*)cam->frame->data[0], outlen);}
-#endif
-    return 1;
-  }
-  if(strncmp(buf, "Video: ", 7)){printf("Got '%s'\n", buf); fflush(stdout); return 1;} // Ignore anything else that isn't video
-  char* sizestr=strchr(&buf[7], ' ');
-  if(!sizestr){return 1;}
-  sizestr[0]=0;
-  // Find the camera representation for the given ID
-  struct camera* cam=camera_find(&buf[7]);
-  unsigned int size=strtoul(&sizestr[1], 0, 0);
-  if(!size){return 1;}
-  // Mostly ignore the first byte (contains frame type (e.g. keyframe etc.) in 4 bits and codec in the other 4)
-  --size;
-  AVPacket pkt;
-  av_init_packet(&pkt);
-  unsigned char databuf[size+4];
-  pkt.data=databuf;
-  unsigned char frameinfo;
-  g_io_channel_read_chars(iochannel, (gchar*)&frameinfo, 1, 0, 0);
-// printf("Frametype-frame: %x\n", ((unsigned int)frameinfo&0xf0)/16);
-// printf("Frametype-codec: %x\n", (unsigned int)frameinfo&0xf);
-  unsigned int pos=0;
-  while(pos<size)
-  {
-    g_io_channel_read_chars(iochannel, (gchar*)pkt.data+pos, size-pos, &r, 0);
-    pos+=r;
-  }
-  if((frameinfo&0xf)!=2){return 1;} // Not FLV1, get data but discard it
-  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;}
-
-  // Scale and convert to RGB24 format
-  unsigned int bufsize=av_image_get_buffer_size(AV_PIX_FMT_RGB24, camsize_scale.width, camsize_scale.height, 1);
-  unsigned char* buf=malloc(bufsize);
-  cam->dstframe->data[0]=buf;
-  cam->dstframe->linesize[0]=camsize_scale.width*3;
-  struct SwsContext* swsctx=sws_getContext(cam->frame->width, cam->frame->height, cam->frame->format, camsize_scale.width, camsize_scale.height, AV_PIX_FMT_RGB24, SWS_BICUBIC, 0, 0, 0);
-  sws_scale(swsctx, (const uint8_t*const*)cam->frame->data, cam->frame->linesize, 0, cam->frame->height, cam->dstframe->data, cam->dstframe->linesize);
-  sws_freeContext(swsctx);
-  camera_postproc(cam, cam->dstframe->data[0], camsize_scale.width, camsize_scale.height);
-
-  GdkPixbuf* oldpixbuf=gtk_image_get_pixbuf(GTK_IMAGE(cam->cam));
-  GdkPixbuf* gdkframe=gdk_pixbuf_new_from_data(cam->dstframe->data[0], GDK_COLORSPACE_RGB, 0, 8, camsize_scale.width, camsize_scale.height, cam->dstframe->linesize[0], freebuffer, 0);
-  gtk_image_set_from_pixbuf(GTK_IMAGE(cam->cam), gdkframe);
-  g_object_unref(oldpixbuf);
-
+  printf("Got '%s'\n", buf);
+  fflush(stdout);
   return 1;
 }
 
@@ -967,7 +971,7 @@ int main(int argc, char** argv)
   g_signal_connect(item, "activate", G_CALLBACK(showsettings), gui);
   item=GTK_WIDGET(gtk_builder_get_object(gui, "menuitem_options_settings2"));
   g_signal_connect(item, "activate", G_CALLBACK(showsettings), gui);
-  
+
   cambox=GTK_WIDGET(gtk_builder_get_object(gui, "cambox"));
   userlistwidget=GTK_WIDGET(gtk_builder_get_object(gui, "userlistbox"));
   GtkWidget* chatview=GTK_WIDGET(gtk_builder_get_object(gui, "chatview"));