Comment 5 for bug 141379

Revision history for this message
Mats (matsben) wrote :

El jue, 25-10-2007 a las 16:14 +0100, Mats Bengtsson escribió:
> Well, I don't have much of ideas either ;-)
> I don't know the code.
> Start with SDL and try make that work then I could try to make a video widget.

For me perfect, first make it works. Have you try to test in your
computer? I have a linux and a mac, the first work but I'm not able to
build the second one. My girlfriend has got a winbox but is a little
older and she doesn't let me install devil dev tools.

> But the frames come uncompressed in YUV format from some callback on
> another thread,
> like the State callbacks?
> Then it has to be delivered to the main UI thread like we do with the
> callbacks, and keep
> track of mem alloc stuff. It will likely take some effort to make
> efficient code since
> it takes a lot of cpu otherwise. Perhaps it is worth to look inside
> SDL and see how they do it?
> Then just extract what we need.
>

Ok, like other callbacks (netstat, level, call_state) the new iaxclient
offer a new one called video. This callback gets an iaxc_ev_video struct
wich has the properties:
        http://iaxclient.sourceforge .net/doc/html/structiaxc__ev_ _video.html

One of this properties is a char* data wich includes de video image.

The Event function in the tcl extension:
static void EventVideo(struct iaxc_ev_video video)
{
   MUTEXLOCK(&notifyRecordMutex);
   if (sNotifyRecord[kNotifyCmdVideo ]) {
       char *cmd;
       char buf[32];
       int len;
       Tcl_DString ds;

       if ( !video.encoded ) {
               if ( video_mode ) {
                       display_video(video, video.source == IAXC_SOURCE_REMOTE);
               }

               Tcl_DStringInit(&ds);
               cmd = Tcl_GetStringFromObj(sNotifyRe cord[kNotifyCmdVideo],
&len);
               Tcl_DStringAppend(&ds, cmd, len);

               /* Remote or local frame */
               sprintf(buf, "%d", video.callNo);
               Tcl_DStringAppendElement(&ds, buf);

               sprintf(buf, "%d", video.ts);
               Tcl_DStringAppendElement(&ds, buf);

               Tcl_DStringAppendElement(&ds, GetMapIntString(mapFormat,
video.format));

               sprintf(buf, "%d", video.width);
               Tcl_DStringAppendElement(&ds, buf);

               sprintf(buf, "%d", video.height);
               Tcl_DStringAppendElement(&ds, buf);

               sprintf(buf, "%d", video.encoded);
               Tcl_DStringAppendElement(&ds, buf);

               sprintf(buf, "%d", video.source);
               Tcl_DStringAppendElement(&ds, buf);

               sprintf(buf, "%d", video.size);
               Tcl_DStringAppendElement(&ds, buf);

               XThread_EvalInThread(sMainThre adID, Tcl_DStringValue(&ds), 0);
               Tcl_DStringFree(&ds);
       } else {
// Tcl_SetObjResult(interp, Tcl_NewStringObj("We cannot handle encoded
video in callbacks yet\n", -1)); }
       }
   }
   MUTEXUNLOCK(&notifyRecordMutex );
}

You'll see at the beginning that I call a display_video function, there
is where the SDL functions are executed for showing the webcam image. If
we've got a Tk widget for showing the video data, then this is dropped
and the Event will have to return the data.

The data by now is YUV encoded, then we have to do something like:

               char* new_data_buffer;

               if ( new_data_buffer != NULL )
               {
                       free(new_data_buffer);
                       new_data_buffer = NULL;
               }
               new_data_buffer = (unsigned char *)malloc(video.size);

               iaxc_YUV420_to_RGB32(video.width, video.height, video.data,
new_data_buffer);
               Tcl_DStringAppend(&ds, new_data_buffer, video.size);

And we'll get in the Tcl callback a long string (video.size) with the
video raw image in RGB mode.