[asterisk-commits] rizzo: branch rizzo/video_v2 r82624 - /team/rizzo/video_v2/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Sep 17 12:33:17 CDT 2007
Author: rizzo
Date: Mon Sep 17 12:33:17 2007
New Revision: 82624
URL: http://svn.digium.com/view/asterisk?view=rev&rev=82624
Log:
Finally, found out the bug that caused the crash when sending video.
In order to handle H263+,
ffmpeg apparently requires CODEC_ID_H263P for encoding,
but CODEC_ID_H263 for decoding!
To fix this, i have implemented a video formats table that has separate entries
for encoding and decoding.
All the rest is misc cleanup for debugging code that i put in while
trying to figure out what was wrong.
Index: channels/console_video.c
===================================================================
--- channels/console_video.c (revision 82591)
+++ channels/console_video.c (working copy)
@@ -112,8 +112,6 @@
int fps;
int bitrate;
struct dbuf_t decbuf;
- struct timeval ts;
- struct timeval msts;
int mtu;
struct timeval last_frame;
@@ -157,14 +155,16 @@
struct _cm { /* map ffmpeg codec types to asterisk formats */
uint32_t ast_format; /* 0 is a terminator */
enum CodecID codec;
+ enum { CM_RD = 1, CM_WR = 2, CM_RDWD = 3 } rw; /* read or write or both ? */
};
/*! the list of video formats we support */
#define CONSOLE_FORMAT_VIDEO AST_FORMAT_H263_PLUS
static struct _cm video_formats[] = {
- { AST_FORMAT_H263_PLUS, CODEC_ID_H263 }, /* XXX H263P ? */
- { 0, 0 },
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263, CM_RD }, /* XXX H263P ? */
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263P, CM_WR }, /* XXX H263P ? */
+ { 0, 0, 0 },
};
#if defined(HAVE_V4L) && HAVE_V4L > 0
@@ -285,21 +285,19 @@
*/
static int video_read(struct video_out_desc *v)
{
+ struct timeval now = ast_tvnow();
// fprintf(stderr, "video_read %p buf %p image %p\n", v, v->buf.data, v->image);
if (v->buf.data == NULL) /* not initialized */
return 0;
- if (v->image) { // X11 grabber
- struct timeval now = ast_tvnow();
- int td = 1000/v->fps;
+ /* check if it is time to read */
+ if (ast_tvzero(v->last_frame))
+ v->last_frame = now;
+ if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
+ return 0; /* too early */
+ v->last_frame = now; /* XXX actually, should correct for drift */
- /* check if it is time to read */
- if (ast_tvzero(v->last_frame))
- v->last_frame = now;
- if (ast_tvdiff_ms(now, v->last_frame) < td) {
- return 0; /* too early */
- }
- v->last_frame = now; /* XXX actually, should correct for drift */
+ if (v->image) { // X11 grabber
/* read frame from X11 */
XGetSubImage(v->dpy,
RootWindow(v->dpy, DefaultScreen(v->dpy)),
@@ -360,12 +358,12 @@
static struct video_desc *get_video_desc(struct ast_channel *c);
/*! \brief map an asterisk format into an ffmpeg one */
-static enum CodecID map_video_format(uint32_t ast_format)
+static enum CodecID map_video_format(uint32_t ast_format, int rw)
{
struct _cm *i;
for (i = video_formats; i->ast_format != 0; i++)
- if (ast_format & i->ast_format)
+ if (ast_format & i->ast_format && rw & i->rw && rw & i->rw)
return i->codec;
return CODEC_ID_NONE;
}
@@ -400,7 +398,7 @@
v->discard = 1;
v->ts = ast_tvnow();
- codec = map_video_format(format);
+ codec = map_video_format(format, CM_RD);
ast_log(LOG_WARNING, "init for format 0x%x gives %d\n", format, codec);
v->codec = avcodec_find_decoder(codec);
@@ -482,7 +480,7 @@
v->lasttxframe = -1;
v->decbuf.data = NULL;
- codec = map_video_format(format);
+ codec = map_video_format(format, CM_WR);
v->codec = avcodec_find_encoder(codec);
if (!v->codec) {
ast_log(LOG_WARNING, "Unable to find the encoder for format %d\n", codec);
@@ -541,8 +539,6 @@
v->decbuf.size = v->buf.size;
v->decbuf.used = 0;
- v->msts = ast_tvnow();
-
v->mtu = 1400;
return 0;
@@ -758,11 +754,11 @@
bmp = env->bmp[out];
SDL_LockYUVOverlay(bmp);
pict.data[0] = bmp->pixels[0];
- pict.data[1] = bmp->pixels[2];
- pict.data[2] = bmp->pixels[1];
+ pict.data[1] = bmp->pixels[1];
+ pict.data[2] = bmp->pixels[2];
pict.linesize[0] = bmp->pitches[0];
- pict.linesize[1] = bmp->pitches[2];
- pict.linesize[2] = bmp->pitches[1];
+ pict.linesize[1] = bmp->pitches[1];
+ pict.linesize[2] = bmp->pitches[2];
if (pict_in == NULL) { /* raw stream in YUV format, usually from camera */
int l4 = w*h/4; /* size of U or V frame */
@@ -770,8 +766,8 @@
ast_log(LOG_WARNING, "no buffer for show frame\n");
} else {
bcopy(src, bmp->pixels[0], 4*l4);
- bcopy(src + 5*l4, bmp->pixels[2], l4);
bcopy(src + 4*l4, bmp->pixels[1], l4);
+ bcopy(src + 5*l4, bmp->pixels[2], l4);
}
} else { /* decode */
#ifdef OLD_FFMPEG /* XXX img_convert is deprecated */
@@ -873,7 +869,7 @@
return 0;
}
len = f->datalen;
- ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, f->datalen);
+ // ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, f->datalen);
data = pre_process_data(f->data, &len);
if (len < 1 || len > 128*1024) {
ast_log(LOG_WARNING, "--- huge frame %d\n", len);
@@ -925,7 +921,7 @@
struct ast_frame *cur = NULL, *first = NULL;
uint8_t *d = out->decbuf.data;
int l = len; /* size of the current fragment. If 0, must look for a psc */
- int totlen = len, frags = 0;
+ int frags = 0;
for (;len > 0; len -= l, d += l) {
uint8_t *data;
@@ -941,12 +937,11 @@
}
}
}
- if (l > out->mtu || l > len) {
- /* psc not found, split */
- ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
+ if (l > out->mtu || l > len) { /* psc not found, split */
+ // ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
l = MIN(len, out->mtu);
}
- if (l < 1 || l > 128*1024) {
+ if (l < 1 || l > out->mtu) {
ast_log(LOG_WARNING, "--- frame error l %d\n", l);
break;
}
@@ -974,8 +969,8 @@
f->datalen = l + 2;
}
- f->has_timing_info = 1;
- f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
+ //f->has_timing_info = 1;
+ //f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
f->frametype = AST_FRAME_VIDEO;
f->subclass = CONSOLE_FORMAT_VIDEO;
f->samples = 0;
@@ -992,44 +987,30 @@
first = f;
cur = f;
frags++;
- ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
+ // ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
}
if (cur)
cur->subclass |= 1; // RTP Marker
- ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
+ // ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
return first;
}
static struct ast_frame *get_video_frames(struct video_desc *env)
{
- int webcam_buflen;
- struct timeval tvnow;
- int period, fdiff;
+ int buflen;
if (!video_read(&env->out))
return NULL;
// fprintf(stderr, "video read\n");
- // XXX - questa porzione di codice limita la generazione dei
- // frame al framerate specificato nel file di configurazione
- // I frame della webcam che non rientrano nel framerate
- // vengono scartati.
- tvnow = ast_tvnow();
- period = 1000/env->out.fps;
- fdiff = ast_tvdiff_ms(tvnow, env->out.msts);
- if (fdiff < period) /* drop frame if too early */
- return NULL;
-
- env->out.msts.tv_sec = tvnow.tv_sec;
- env->out.msts.tv_usec = tvnow.tv_usec;
/* get frame and put them in the queue */
show_frame(env, 1);
- webcam_buflen = avcodec_encode_video(env->out.context,
+ buflen = avcodec_encode_video(env->out.context,
env->out.decbuf.data, env->out.decbuf.size, env->out.frame);
- // fprintf(stderr, "avcodec_encode_video returns %d\n", webcam_buflen);
- return split_frame(&(env->out), webcam_buflen);
+ // fprintf(stderr, "avcodec_encode_video returns %d\n", buflen);
+ return split_frame(&(env->out), buflen);
}
/*!
@@ -1069,11 +1050,10 @@
show_frame(env, 1);
if (env->out.buf.data && owner) { /* talk to the local video source */
- if (env->out.fd >= 0)
+ if (0 && env->out.fd >= 0)
ast_channel_set_fd(owner, 1, env->out.fd);
fprintf(stderr, "video_out_init fd %d\n", env->out.fd);
video_out_init(&env->out, CONSOLE_FORMAT_VIDEO);
}
- env->out.ts = ast_tvnow();
}
#endif /* video support */
diff: missing operand
diff: Try `diff --help' for more information.
Modified:
team/rizzo/video_v2/channels/console_video.c
Modified: team/rizzo/video_v2/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/console_video.c?view=diff&rev=82624&r1=82623&r2=82624
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (original)
+++ team/rizzo/video_v2/channels/console_video.c Mon Sep 17 12:33:17 2007
@@ -112,8 +112,6 @@
int fps;
int bitrate;
struct dbuf_t decbuf;
- struct timeval ts;
- struct timeval msts;
int mtu;
struct timeval last_frame;
@@ -157,14 +155,16 @@
struct _cm { /* map ffmpeg codec types to asterisk formats */
uint32_t ast_format; /* 0 is a terminator */
enum CodecID codec;
+ enum { CM_RD = 1, CM_WR = 2, CM_RDWD = 3 } rw; /* read or write or both ? */
};
/*! the list of video formats we support */
#define CONSOLE_FORMAT_VIDEO AST_FORMAT_H263_PLUS
static struct _cm video_formats[] = {
- { AST_FORMAT_H263_PLUS, CODEC_ID_H263 }, /* XXX H263P ? */
- { 0, 0 },
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263, CM_RD }, /* XXX H263P ? */
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263P, CM_WR }, /* XXX H263P ? */
+ { 0, 0, 0 },
};
#if defined(HAVE_V4L) && HAVE_V4L > 0
@@ -285,21 +285,19 @@
*/
static int video_read(struct video_out_desc *v)
{
+ struct timeval now = ast_tvnow();
// fprintf(stderr, "video_read %p buf %p image %p\n", v, v->buf.data, v->image);
if (v->buf.data == NULL) /* not initialized */
return 0;
+ /* check if it is time to read */
+ if (ast_tvzero(v->last_frame))
+ v->last_frame = now;
+ if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
+ return 0; /* too early */
+ v->last_frame = now; /* XXX actually, should correct for drift */
+
if (v->image) { // X11 grabber
- struct timeval now = ast_tvnow();
- int td = 1000/v->fps;
-
- /* check if it is time to read */
- if (ast_tvzero(v->last_frame))
- v->last_frame = now;
- if (ast_tvdiff_ms(now, v->last_frame) < td) {
- return 0; /* too early */
- }
- v->last_frame = now; /* XXX actually, should correct for drift */
/* read frame from X11 */
XGetSubImage(v->dpy,
RootWindow(v->dpy, DefaultScreen(v->dpy)),
@@ -360,12 +358,12 @@
static struct video_desc *get_video_desc(struct ast_channel *c);
/*! \brief map an asterisk format into an ffmpeg one */
-static enum CodecID map_video_format(uint32_t ast_format)
+static enum CodecID map_video_format(uint32_t ast_format, int rw)
{
struct _cm *i;
for (i = video_formats; i->ast_format != 0; i++)
- if (ast_format & i->ast_format)
+ if (ast_format & i->ast_format && rw & i->rw && rw & i->rw)
return i->codec;
return CODEC_ID_NONE;
}
@@ -400,7 +398,7 @@
v->discard = 1;
v->ts = ast_tvnow();
- codec = map_video_format(format);
+ codec = map_video_format(format, CM_RD);
ast_log(LOG_WARNING, "init for format 0x%x gives %d\n", format, codec);
v->codec = avcodec_find_decoder(codec);
@@ -482,7 +480,7 @@
v->lasttxframe = -1;
v->decbuf.data = NULL;
- codec = map_video_format(format);
+ codec = map_video_format(format, CM_WR);
v->codec = avcodec_find_encoder(codec);
if (!v->codec) {
ast_log(LOG_WARNING, "Unable to find the encoder for format %d\n", codec);
@@ -540,8 +538,6 @@
v->decbuf.data = ast_calloc(1, v->buf.size);
v->decbuf.size = v->buf.size;
v->decbuf.used = 0;
-
- v->msts = ast_tvnow();
v->mtu = 1400;
@@ -758,11 +754,11 @@
bmp = env->bmp[out];
SDL_LockYUVOverlay(bmp);
pict.data[0] = bmp->pixels[0];
- pict.data[1] = bmp->pixels[2];
- pict.data[2] = bmp->pixels[1];
+ pict.data[1] = bmp->pixels[1];
+ pict.data[2] = bmp->pixels[2];
pict.linesize[0] = bmp->pitches[0];
- pict.linesize[1] = bmp->pitches[2];
- pict.linesize[2] = bmp->pitches[1];
+ pict.linesize[1] = bmp->pitches[1];
+ pict.linesize[2] = bmp->pitches[2];
if (pict_in == NULL) { /* raw stream in YUV format, usually from camera */
int l4 = w*h/4; /* size of U or V frame */
@@ -770,8 +766,8 @@
ast_log(LOG_WARNING, "no buffer for show frame\n");
} else {
bcopy(src, bmp->pixels[0], 4*l4);
+ bcopy(src + 4*l4, bmp->pixels[1], l4);
bcopy(src + 5*l4, bmp->pixels[2], l4);
- bcopy(src + 4*l4, bmp->pixels[1], l4);
}
} else { /* decode */
#ifdef OLD_FFMPEG /* XXX img_convert is deprecated */
@@ -873,7 +869,7 @@
return 0;
}
len = f->datalen;
- ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, f->datalen);
+ // ast_log(LOG_WARNING, "received video frame %d size %d\n", f->seqno, f->datalen);
data = pre_process_data(f->data, &len);
if (len < 1 || len > 128*1024) {
ast_log(LOG_WARNING, "--- huge frame %d\n", len);
@@ -925,7 +921,7 @@
struct ast_frame *cur = NULL, *first = NULL;
uint8_t *d = out->decbuf.data;
int l = len; /* size of the current fragment. If 0, must look for a psc */
- int totlen = len, frags = 0;
+ int frags = 0;
for (;len > 0; len -= l, d += l) {
uint8_t *data;
@@ -941,12 +937,11 @@
}
}
}
- if (l > out->mtu || l > len) {
- /* psc not found, split */
- ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
+ if (l > out->mtu || l > len) { /* psc not found, split */
+ // ast_log(LOG_WARNING, "no psc in frame sized %d\n", len);
l = MIN(len, out->mtu);
}
- if (l < 1 || l > 128*1024) {
+ if (l < 1 || l > out->mtu) {
ast_log(LOG_WARNING, "--- frame error l %d\n", l);
break;
}
@@ -974,8 +969,8 @@
f->datalen = l + 2;
}
- f->has_timing_info = 1;
- f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
+ //f->has_timing_info = 1;
+ //f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
f->frametype = AST_FRAME_VIDEO;
f->subclass = CONSOLE_FORMAT_VIDEO;
f->samples = 0;
@@ -992,44 +987,30 @@
first = f;
cur = f;
frags++;
- ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
+ // ast_log(LOG_WARNING, "-- frag %d size %d left %d\n", frags, f->datalen, len - l);
}
if (cur)
cur->subclass |= 1; // RTP Marker
- ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
+ // ast_log(LOG_WARNING, "done, totlen %d frags %d\n", totlen, frags);
return first;
}
static struct ast_frame *get_video_frames(struct video_desc *env)
{
- int webcam_buflen;
- struct timeval tvnow;
- int period, fdiff;
+ int buflen;
if (!video_read(&env->out))
return NULL;
// fprintf(stderr, "video read\n");
- // XXX - questa porzione di codice limita la generazione dei
- // frame al framerate specificato nel file di configurazione
- // I frame della webcam che non rientrano nel framerate
- // vengono scartati.
- tvnow = ast_tvnow();
- period = 1000/env->out.fps;
- fdiff = ast_tvdiff_ms(tvnow, env->out.msts);
- if (fdiff < period) /* drop frame if too early */
- return NULL;
-
- env->out.msts.tv_sec = tvnow.tv_sec;
- env->out.msts.tv_usec = tvnow.tv_usec;
/* get frame and put them in the queue */
show_frame(env, 1);
- webcam_buflen = avcodec_encode_video(env->out.context,
+ buflen = avcodec_encode_video(env->out.context,
env->out.decbuf.data, env->out.decbuf.size, env->out.frame);
- // fprintf(stderr, "avcodec_encode_video returns %d\n", webcam_buflen);
- return split_frame(&(env->out), webcam_buflen);
+ // fprintf(stderr, "avcodec_encode_video returns %d\n", buflen);
+ return split_frame(&(env->out), buflen);
}
/*!
@@ -1069,11 +1050,10 @@
show_frame(env, 1);
if (env->out.buf.data && owner) { /* talk to the local video source */
- if (env->out.fd >= 0)
+ if (0 && env->out.fd >= 0)
ast_channel_set_fd(owner, 1, env->out.fd);
fprintf(stderr, "video_out_init fd %d\n", env->out.fd);
video_out_init(&env->out, CONSOLE_FORMAT_VIDEO);
}
- env->out.ts = ast_tvnow();
}
#endif /* video support */
More information about the asterisk-commits
mailing list