Add H.263 video support

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1131 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2003-06-29 03:24:39 +00:00
parent 3b78918878
commit 9c9ee7c952
7 changed files with 438 additions and 17 deletions

157
file.c
View File

@@ -65,6 +65,11 @@ struct ast_format {
struct ast_filestream {
/* Everybody reserves a block of AST_RESERVED_POINTERS pointers for us */
struct ast_format *fmt;
int flags;
mode_t mode;
char *filename;
/* Video file stream */
struct ast_filestream *vfs;
/* Transparently translate from another format -- just once */
struct ast_trans_pvt *trans;
struct ast_tranlator_pvt *tr;
@@ -157,11 +162,13 @@ int ast_format_unregister(char *name)
int ast_stopstream(struct ast_channel *tmp)
{
/* Stop a running stream if there is one */
if (!tmp->stream)
return 0;
ast_closestream(tmp->stream);
if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
if (tmp->vstream)
ast_closestream(tmp->vstream);
if (tmp->stream) {
ast_closestream(tmp->stream);
if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
}
return 0;
}
@@ -169,11 +176,29 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
{
struct ast_frame *trf;
int res = -1;
if (f->frametype != AST_FRAME_VOICE) {
int alt=0;
if (f->frametype == AST_FRAME_VIDEO) {
if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) {
/* This is the audio portion. Call the video one... */
if (!fs->vfs && fs->filename) {
/* XXX Support other video formats XXX */
char *type = "h263";
fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
ast_log(LOG_DEBUG, "Opened video output file\n");
}
if (fs->vfs)
return ast_writestream(fs->vfs, f);
/* Ignore */
return 0;
} else {
/* Might / might not have mark set */
alt = 1;
}
} else if (f->frametype != AST_FRAME_VOICE) {
ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
return -1;
}
if ((fs->fmt->format & f->subclass) == f->subclass) {
if (((fs->fmt->format | alt) & f->subclass) == f->subclass) {
res = fs->fmt->write(fs, f);
if (res < 0)
ast_log(LOG_WARNING, "Natural write failed\n");
@@ -335,7 +360,8 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
ast_log(LOG_WARNING, "Out of memory\n");
break;
case ACTION_OPEN:
if ((ret < 0) && ((chan->writeformat & f->format))) {
if ((ret < 0) && ((chan->writeformat & f->format) ||
((f->format >= AST_FORMAT_MAX_AUDIO) && fmt))) {
ret = open(fn, O_RDONLY);
if (ret >= 0) {
s = f->open(ret);
@@ -343,7 +369,11 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
s->lasttimeout = -1;
s->fmt = f;
s->trans = NULL;
chan->stream = s;
s->filename = NULL;
if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
chan->stream = s;
else
chan->vstream = s;
} else {
close(ret);
ast_log(LOG_WARNING, "Unable to open fd on %s\n", filename);
@@ -397,11 +427,11 @@ struct ast_filestream *ast_openstream(struct ast_channel *chan, char *filename,
if (chan->generator)
ast_deactivate_generator(chan);
if (preflang && strlen(preflang)) {
snprintf(filename2, sizeof(filename2), "%s-%s", filename, preflang);
snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
fmts = ast_fileexists(filename2, NULL, NULL);
if (fmts < 1) {
strncpy(lang2, preflang, sizeof(lang2)-1);
snprintf(filename2, sizeof(filename2), "%s-%s", filename, lang2);
snprintf(filename2, sizeof(filename2), "%s/%s", lang2, filename);
fmts = ast_fileexists(filename2, NULL, NULL);
}
}
@@ -423,6 +453,49 @@ struct ast_filestream *ast_openstream(struct ast_channel *chan, char *filename,
return NULL;
}
struct ast_filestream *ast_openvstream(struct ast_channel *chan, char *filename, char *preflang)
{
/* This is a fairly complex routine. Essentially we should do
the following:
1) Find which file handlers produce our type of format.
2) Look for a filename which it can handle.
3) If we find one, then great.
4) If not, see what files are there
5) See what we can actually support
6) Choose the one with the least costly translator path and
set it up.
*/
int fd = -1;
int fmts = -1;
char filename2[256];
char lang2[MAX_LANGUAGE];
/* XXX H.263 only XXX */
char *fmt = "h263";
if (preflang && strlen(preflang)) {
snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
fmts = ast_fileexists(filename2, fmt, NULL);
if (fmts < 1) {
strncpy(lang2, preflang, sizeof(lang2)-1);
snprintf(filename2, sizeof(filename2), "%s/%s", lang2, filename);
fmts = ast_fileexists(filename2, fmt, NULL);
}
}
if (fmts < 1) {
strncpy(filename2, filename, sizeof(filename2)-1);
fmts = ast_fileexists(filename2, fmt, NULL);
}
if (fmts < 1) {
return NULL;
}
fd = ast_filehelper(filename2, (char *)chan, fmt, ACTION_OPEN);
if(fd >= 0)
return chan->vstream;
ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
return NULL;
}
static int ast_readaudio_callback(void *data)
{
struct ast_filestream *s = data;
@@ -451,6 +524,34 @@ static int ast_readaudio_callback(void *data)
return 1;
}
static int ast_readvideo_callback(void *data)
{
struct ast_filestream *s = data;
struct ast_frame *fr;
int whennext = 0;
while(!whennext) {
fr = s->fmt->read(s, &whennext);
if (fr) {
if (ast_write(s->owner, fr)) {
ast_log(LOG_WARNING, "Failed to write frame\n");
s->owner->vstreamid = -1;
return 0;
}
} else {
/* Stream has finished */
s->owner->vstreamid = -1;
return 0;
}
}
if (whennext != s->lasttimeout) {
s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s);
s->lasttimeout = whennext;
return 0;
}
return 1;
}
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
{
s->owner = chan;
@@ -459,7 +560,10 @@ int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
int ast_playstream(struct ast_filestream *s)
{
ast_readaudio_callback(s);
if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
ast_readaudio_callback(s);
else
ast_readvideo_callback(s);
return 0;
}
@@ -498,10 +602,19 @@ int ast_closestream(struct ast_filestream *f)
/* Stop a running stream if there is one */
if (f->owner) {
f->owner->stream = NULL;
if (f->owner->streamid > -1)
ast_sched_del(f->owner->sched, f->owner->streamid);
f->owner->streamid = -1;
if (f->fmt->format < AST_FORMAT_MAX_AUDIO) {
if (f->owner->streamid > -1)
ast_sched_del(f->owner->sched, f->owner->streamid);
f->owner->streamid = -1;
} else {
if (f->owner->vstreamid > -1)
ast_sched_del(f->owner->sched, f->owner->vstreamid);
f->owner->vstreamid = -1;
}
}
if (f->filename)
free(f->filename);
f->filename = NULL;
f->fmt->close(f);
return 0;
}
@@ -565,13 +678,23 @@ int ast_filecopy(char *filename, char *filename2, char *fmt)
int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
{
struct ast_filestream *fs;
struct ast_filestream *vfs;
fs = ast_openstream(chan, filename, preflang);
vfs = ast_openvstream(chan, filename, preflang);
if (vfs)
ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
else
ast_log(LOG_DEBUG, "Waaah, '%s' has no video stream :(\n", filename);
if(fs){
if(ast_applystream(chan, fs))
return -1;
if(vfs && ast_applystream(chan, vfs))
return -1;
if(ast_playstream(fs))
return -1;
if(vfs && ast_playstream(vfs))
return -1;
#if 1
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Playing '%s'\n", filename);
@@ -612,6 +735,10 @@ struct ast_filestream *ast_writefile(char *filename, char *type, char *comment,
if ((fs = f->rewrite(fd, comment))) {
fs->trans = NULL;
fs->fmt = f;
fs->flags = flags;
fs->mode = mode;
fs->filename = strdup(filename);
fs->vfs = NULL;
} else {
ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
close(fd);