Posted: Tue Jun 10, 2008 6:54 pm Post subject: [Asterisk-video] ast_queue_frame: Exceptionally long queue l
Hi Emmanuel,
I was working in a problem related issue. I think that the common problem is that I use a different thread for receiving channel data and decoding it, and another
different one for encoding and sending. To avoid the locks I have to call directly to the channel->tech->write which could be causing serious problems.
I think that the solution would be also move the sending part into the receiving thread and call ast_write as usual. The problem is that I don't see a clean way of
signalling from the encoding thread to the ast_wait function in the receiving thread to wake up and send the data so you don't have to wait for incoming data to send.
A non-clean way could be to create an internal socket and add it to the wait function so I can write some dummy data in the enconding thread to make the decoder thread wake up.
BR
Sergio
Emmanuel BUU escribió:
Quote:
Quote:
According to my tests, tt seems that app_transcoder gets into a deadlock after a few second of operation.
I am trying to identify the issue. It could be related to this issue.
On Mon, 9 Jun 2008 09:58:34 +0200, "Nico Gundacker" <nico.gundacker@dynetic.de> (nico.gundacker@dynetic.de) wrote:
Quote:
Hi guys,
as you see at the topic asterisk send out the following warning message:
[Jun 9 10:47:21] WARNING[25155]: channel.c:916 ast_queue_frame:
Exceptionally long queue length queuing to
Local/1001@menue-vidoestreamen-adbc,2
Sometimes these warning are shown at the screen until the call is hung up
and sometimes even after call is hung up. Then I need to kill asterisk
process. Is there any solution for this problem?
Posted: Tue Jun 10, 2008 8:23 pm Post subject: [Asterisk-video] ast_queue_frame: Exceptionally long queue l
Hi alls,
Here my contribution to this problem.
I have made a modification in order to disable the thread created to
schedule the fps.
The limitation is that we cannot increase or fine tune the fps.
(the Asterisk channel thread is use to encode/decode too).
So this application don't use new thread creation, but I still having
the locks.
I have added some traces to qualify where the application locks...
I will work on it this week (with Emmanuel).
Regards,
Borja
Sergio Garcia Murillo a écrit :
Quote:
Hi Emmanuel,
I was working in a problem related issue. I think that the common
problem is that I use a different thread for receiving channel data
and decoding it, and another
different one for encoding and sending. To avoid the locks I have to
call directly to the channel->tech->write which could be causing
serious problems.
I think that the solution would be also move the sending part into the
receiving thread and call ast_write as usual. The problem is that I
don't see a clean way of
signalling from the encoding thread to the ast_wait function in the
receiving thread to wake up and send the data so you don't have to
wait for incoming data to send.
A non-clean way could be to create an internal socket and add it to
the wait function so I can write some dummy data in the enconding
thread to make the decoder thread wake up.
BR
Sergio
Emmanuel BUU escribió:
> According to my tests, tt seems that app_transcoder gets into a deadlock after a few second of operation.
> I am trying to identify the issue. It could be related to this issue.
>
> On Mon, 9 Jun 2008 09:58:34 +0200, "Nico Gundacker" <nico.gundacker@dynetic.de> wrote:
>
>> Hi guys,
>>
>>
>>
>> as you see at the topic asterisk send out the following warning message:
>>
>> [Jun 9 10:47:21] WARNING[25155]: channel.c:916 ast_queue_frame:
>> Exceptionally long queue length queuing to
>> Local/1001@menue-vidoestreamen-adbc,2
>>
>>
>>
>> Sometimes these warning are shown at the screen until the call is hung up
>> and sometimes even after call is hung up. Then I need to kill asterisk
>> process. Is there any solution for this problem?
>>
>> I used a 3 g phone and the following dial-plan:
>>
>>
>>
>> ..
>>
>> exten => 101,1,Answer
>>
>> exten =>
>> 101,2,transcode(,1001@menue-vidoestreamen,h263@qcif/fps=12/kb=52/qmin=4/qmax
>> =12/gs=50)
>>
>> ...
>>
>> exten => 1001,1,Answer
>>
>> exten => 1001,2,rtsp(rtsp://xx.xx.xx.xx/xxxx/xxxx_direkt/28766.3gp)
>>
>> exten => 1001,3,Goto(0,2)
>>
>>
>>
>> Thank you for your help
>>
>>
>>
>> BR Nico
>>
>>
>>
>>
>
>
>
> _______________________________________________
> --Bandwidth and Colocation Provided by http://www.api-digital.com--
>
> asterisk-video mailing list
> To UNSUBSCRIBE or update options visit:
> http://lists.digium.com/mailman/listinfo/asterisk-video
>
/*
* Asterisk -- An open source telephony toolkit.
*
* Sergio Garcia Murillo <sergio.garcia@fontventa.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
char* buffer;
unsigned int bufferSize;
unsigned int bufferLen;
int mb;
int mb_total;
int sent_bytes;
/* Encoder Params */
int bitrate;
int fps;
int format;
int qMin;
int qMax;
int encoderWidth;
int encoderHeight;
int gop_size;
/* Encoder thread */
pthread_t encoderThread;
/* Resize */
struct SwsContext* resizeCtx;
int resizeWidth;
int resizeHeight;
char* resizeBuffer;
int resizeSrc[3];
int resizeDst[3];
int resizeFlags;
};
struct RFC2190H263HeadersBasic
{
//F=0 F=1
//P=0 I/P frame I/P mode b
//P=1 B frame B fame mode C
unsigned int trb:9;
unsigned int tr:3;
unsigned int dbq:2;
unsigned int r:3;
unsigned int a:1;
unsigned int s:1;
unsigned int u:1;
unsigned int i:1;
unsigned int src:3;
unsigned int ebits:3;
unsigned int sbits:3;
unsigned int p:1;
unsigned int f:1;
};
void RtpCallback(struct AVCodecContext *avctx, void *data, int size, int mb_nb);
void * VideoTranscoderEncode(void *param);
static void SendVideoFrame(struct VideoTranscoder *vtc, void *data, unsigned int size, int first, int last)
{
struct ast_frame *send;
static int VideoTranscoderSetResize(struct VideoTranscoder *vtc,int width,int height)
{
/* If already resizing that size */
if (width==vtc->resizeWidth && height==vtc->resizeHeight)
/* Nothing to do */
return 1;
/* if got contex */
if (vtc->resizeCtx)
/* Free it */
sws_freeContext(vtc->resizeCtx);
/* Get new context */
vtc->resizeCtx = sws_getContext(vtc->width, vtc->height, PIX_FMT_YUV420P, vtc->encoderWidth, vtc->encoderHeight, PIX_FMT_YUV420P, vtc->resizeFlags, NULL, NULL, NULL);
/* Check */
if (!vtc->resizeCtx)
/* Exit */
return 0;
/* Set values */
vtc->resizeWidth = width;
vtc->resizeHeight = height;
/* Do we need to resize the image */
if ( vtc->width!=vtc->encoderWidth || vtc->height!=vtc->encoderHeight)
{
/* Set size */
if (!VideoTranscoderSetResize(vtc, vtc->width, vtc->height))
/* Next frame */
//continue;
return 0;
int first = 1;
int last = 0;
unsigned int sent = 0;
unsigned int len = 0;
/* Send */
while(sent<vtc->bufferLen)
{
/* Check remaining */
if (sent+1400>vtc->bufferLen)
{
/* last */
last = 1;
/* send the rest */
len = vtc->bufferLen-sent;
} else
/* Fill */
len = 1400;
/*Send packet */
SendVideoFrame(vtc,vtc->buffer+sent,len,first,last);
/* Unset first */
first = 0;
/* Increment size */
sent += len;
}
/* Reset new pic flag */
vtc->newPic = 0;
}
}
/* Exit */
return 0;
}
static int VideoTranscoderDestroy(struct VideoTranscoder *vtc)
{
/* End encoder */
vtc->end = 1;
/* Wait encoder thread to stop */
//pthread_join(vtc->encoderThread,0);
/* Free decoder */
if (vtc->decoderCtx)
{
/*If already open */
if (vtc->decoderOpened)
/* Close */
avcodec_close(vtc->decoderCtx);
/* Free */
free(vtc->decoderCtx);
}
/* Free pic */
if (vtc->decoderPic)
free(vtc->decoderPic);
/* Free encoder */
if (vtc->encoderCtx)
{
/* If encoder opened */
if (vtc->encoderOpened)
/* Close */
avcodec_close(vtc->encoderCtx);
free(vtc->encoderCtx);
}
/* Free pic */
if (vtc->encoderPic)
free(vtc->encoderPic);
/* if got contex */
if (vtc->resizeCtx)
/* Free it */
sws_freeContext(vtc->resizeCtx);
/* Free resize buffer*/
if (vtc->resizeBuffer)
/* Free */
free(vtc->resizeBuffer);
/* Get ini */
unsigned char* in = buffer+2+plen;
unsigned int len = bufferLen-2-plen;
/* Check */
if (v)
{
/* Increase ini */
in++;
len--;
}
/* Check p bit */
if (p)
{
/* Decrease ini */
in -= 2;
len += 2;
/* Append 0s */
buffer[0] = 0;
buffer[1] = 0;
}
/* Copy the rest */
memcpy(dest+destLen,in,len);
/* Return added */
return len;
}
static unsigned int mpeg4_append(unsigned char *dest, unsigned int destLen, unsigned char *buffer, unsigned int bufferLen)
{
/* Just copy */
memcpy(dest+destLen,buffer,bufferLen);
/* Return added */
return bufferLen;
}
static unsigned int VideoTranscoderWrite(struct VideoTranscoder *vtc, int codec, unsigned char *buffer, unsigned int bufferLen, int mark)
{
/* If not enougth */
if (bufferLen + vtc->frameLen > vtc->frameSize);
/* Clean frame */
/* Depending on the code */
if (codec & AST_FORMAT_H263)
{
/* Check codec */
VideoTranscoderSetDecoder(vtc,CODEC_ID_H263);
/* Depacketize */
vtc->frameLen += rfc2190_append(vtc->frame,vtc->frameLen,buffer,bufferLen);
/* Find fwd params */
if (!(a=strchr((char*)data,'|')))
return 0;
/* Find local channel params */
if (!(b=strchr(a+1,'|')))
return 0;
/* Set local params */
fwdParams = strndup((char*)data,a-(char*)data);
local = strndup(a+1,b-a-1);
revParams = strndup(b+1,strlen((char*)data)-(b-(char*)data)-1);
/* Set caller id */
ast_set_callerid(pseudo, chan->cid.cid_num, chan->cid.cid_name, chan->cid.cid_num);
/* Place call */
if (ast_call(pseudo,data,0))
/* if fail goto clean */
goto clean_pseudo;
/* while not setup */
while (pseudo->_state!=AST_STATE_UP) {
/* Wait for data */
if (ast_waitfor(pseudo, 0)<0)
/* error, timeout, or done */
break;
/* Read frame */
f = ast_read(pseudo);
/* If not frame */
if (!f)
/* done */
break;
/* If it's a control frame */
if (f->frametype == AST_FRAME_CONTROL) {
/* Dependinf on the event */
switch (f->subclass) {
case AST_CONTROL_RINGING:
break;
case AST_CONTROL_BUSY:
case AST_CONTROL_CONGESTION:
/* Save cause */
reason = pseudo->hangupcause;
/* exit */
goto hangup_pseudo;
break;
case AST_CONTROL_ANSWER:
/* Set UP*/
reason = 0;
break;
}
}
/* Delete frame */
ast_frfree(f);
}
/* If no answer */
if (pseudo->_state != AST_STATE_UP)
/* goto end */
goto clean_pseudo;
/* Answer channel */
ast_answer(chan);
/* Set up array */
channels[0] = chan;
channels[1] = pseudo;
/* No timeout */
ms = -1;
/* Wait for data avaiable on any channel */
while (!reason && (where = ast_waitfor_n(channels, 2, &ms)) != NULL)
{
/* Read frame from channel */
ast_log(LOG_DEBUG,"-> ast_read\n");
f = ast_read(where);
ast_log(LOG_DEBUG,"<- ast_read\n");
/* if it's null */
if (f == NULL)
break;
/* Depending on the channel */
if (where == chan)
{
/* if it's video */
if (f->frametype == AST_FRAME_VIDEO) {
/* If transcode forwdward */
if (fwd)
{
/* Transcode */
ast_log(LOG_DEBUG,"-> VideoTranscoderWrite fwd\n");
VideoTranscoderWrite(fwd,f->subclass,f->data,f->datalen,f->subclass & 1);
ast_log(LOG_DEBUG,"<- VideoTranscoderWrite fwd\n");
/* Delete frame */
ast_frfree(f);
} else {
/* Just copy */
ast_write(pseudo,f);
}
} else if (f->frametype == AST_FRAME_CONTROL) {
/* Check for hangup */
if (f->subclass == AST_CONTROL_HANGUP)
/* Hangup */
reason = AST_CAUSE_NORMAL_CLEARING;
/* delete frame */
ast_frfree(f);
} else {
/* Fordward */
ast_write(pseudo,f);
}
} else {
/* if it's video */
if (f->frametype == AST_FRAME_VIDEO) {
/* If transcode backward */
if (rev)
{
/* Transcode */
ast_log(LOG_DEBUG,"-> VideoTranscoderWrite rev\n");
VideoTranscoderWrite(rev,f->subclass,f->data,f->datalen,f->subclass & 1);
ast_log(LOG_DEBUG,"-> VideoTranscoderWrite rev\n");
/* Delete frame */
ast_frfree(f);
} else {
/* Just copy */
ast_write(chan,f);
}
} else if (f->frametype == AST_FRAME_CONTROL) {
/* Check for hangup */
if (f->subclass == AST_CONTROL_HANGUP)
/* Hangup */
reason = AST_CAUSE_NORMAL_CLEARING;
/* delete frame */
ast_frfree(f);
} else {
/* Fordward */
ast_write(chan,f);
}
}
}
hangup_pseudo:
/* Hangup pseudo channel if needed */
ast_softhangup(pseudo, reason);
Posted: Thu Jun 12, 2008 8:31 pm Post subject: [Asterisk-video] ast_queue_frame: Exceptionally long queue l
Hi,
Emmanuel had a great idea last day...
He suspected the direct calling vtc->channel->tech->write_video.
I have replaced this function by an ast_write function and I don't have
locks now.
The ast_write function check the channels locks before calling the write
function.
With the original sources I have a lot of coredumps if I made hard
tests...(calls / hangups frequently).
We think (Emmanuel and I) that the context with the image buffer is not
protected by a lock.
I some cases, we suspect that the context content or the image buffer is
partially overwritten before the sending.
We probably need a dual buffer mode.
In my version (without the thread that schedule the frame rate, all the
processing is generated in the channel thread, so I don't have the
problem for the moment but I don't control the image rate and so the
bandwidth...).
We continue working on it, and thanks to Emmanuel.
Can someone confirm the correction too ?
Regards,
Emmanuel and Borja
Borja SIXTO a écrit :
Quote:
Hi alls,
Here my contribution to this problem.
I have made a modification in order to disable the thread created to
schedule the fps.
The limitation is that we cannot increase or fine tune the fps.
(the Asterisk channel thread is use to encode/decode too).
So this application don't use new thread creation, but I still having
the locks.
I have added some traces to qualify where the application locks...
I will work on it this week (with Emmanuel).
Regards,
Borja
Sergio Garcia Murillo a écrit :
> Hi Emmanuel,
>
> I was working in a problem related issue. I think that the common
> problem is that I use a different thread for receiving channel data
> and decoding it, and another
> different one for encoding and sending. To avoid the locks I have to
> call directly to the channel->tech->write which could be causing
> serious problems.
>
> I think that the solution would be also move the sending part into
> the receiving thread and call ast_write as usual. The problem is that
> I don't see a clean way of
> signalling from the encoding thread to the ast_wait function in the
> receiving thread to wake up and send the data so you don't have to
> wait for incoming data to send.
>
> A non-clean way could be to create an internal socket and add it to
> the wait function so I can write some dummy data in the enconding
> thread to make the decoder thread wake up.
>
> BR
> Sergio
>
>
> Emmanuel BUU escribió:
>> According to my tests, tt seems that app_transcoder gets into a
>> deadlock after a few second of operation.
>> I am trying to identify the issue. It could be related to this issue.
>>
>> On Mon, 9 Jun 2008 09:58:34 +0200, "Nico Gundacker"
>> <nico.gundacker@dynetic.de> wrote:
>>
>>> Hi guys,
>>>
>>>
>>>
>>> as you see at the topic asterisk send out the following warning
>>> message:
>>>
>>> [Jun 9 10:47:21] WARNING[25155]: channel.c:916 ast_queue_frame:
>>> Exceptionally long queue length queuing to
>>> Local/1001@menue-vidoestreamen-adbc,2
>>>
>>>
>>>
>>> Sometimes these warning are shown at the screen until the call is
>>> hung up
>>> and sometimes even after call is hung up. Then I need to kill asterisk
>>> process. Is there any solution for this problem?
>>>
>>> I used a 3 g phone and the following dial-plan:
>>>
>>>
>>>
>>> ..
>>>
>>> exten => 101,1,Answer
>>>
>>> exten =>
>>> 101,2,transcode(,1001@menue-vidoestreamen,h263@qcif/fps=12/kb=52/qmin=4/qmax
>>>
>>> =12/gs=50)
>>>
>>> ...
>>>
>>> exten => 1001,1,Answer
>>>
>>> exten => 1001,2,rtsp(rtsp://xx.xx.xx.xx/xxxx/xxxx_direkt/28766.3gp)
>>>
>>> exten => 1001,3,Goto(0,2)
>>>
>>>
>>>
>>> Thank you for your help
>>>
>>>
>>>
>>> BR Nico
>>>
>>>
>>>
>>>
>>
>>
>>
>> _______________________________________________
>> --Bandwidth and Colocation Provided by http://www.api-digital.com--
>>
>> asterisk-video mailing list
>> To UNSUBSCRIBE or update options visit:
>> http://lists.digium.com/mailman/listinfo/asterisk-video
>>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> --Bandwidth and Colocation Provided by http://www.api-digital.com--
>
> asterisk-video mailing list
> To UNSUBSCRIBE or update options visit:
> http://lists.digium.com/mailman/listinfo/asterisk-video
_______________________________________________
--Bandwidth and Colocation Provided by http://www.api-digital.com--
You can post new topics in this forum You can reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum