00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <unistd.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 #include <stdlib.h>
00030 #include <sys/time.h>
00031 #include <stdio.h>
00032 #include <errno.h>
00033 #include <string.h>
00034
00035 #include "asterisk.h"
00036
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 37808 $")
00038
00039 #include "asterisk/lock.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/file.h"
00042 #include "asterisk/logger.h"
00043 #include "asterisk/sched.h"
00044 #include "asterisk/module.h"
00045 #include "asterisk/endian.h"
00046
00047
00048
00049
00050
00051 struct ast_filestream {
00052 void *reserved[AST_RESERVED_POINTERS];
00053
00054
00055
00056 FILE *f;
00057 unsigned int lastts;
00058 struct ast_frame fr;
00059 char waste[AST_FRIENDLY_OFFSET];
00060 char empty;
00061 unsigned char h263[32768];
00062 };
00063
00064
00065 AST_MUTEX_DEFINE_STATIC(h263_lock);
00066 static int glistcnt = 0;
00067
00068 static char *name = "h263";
00069 static char *desc = "Raw h263 data";
00070 static char *exts = "h263";
00071
00072 static struct ast_filestream *h263_open(FILE *f)
00073 {
00074
00075
00076
00077 struct ast_filestream *tmp;
00078 unsigned int ts;
00079 int res;
00080 if ((res = fread(&ts, 1, sizeof(ts), f)) < sizeof(ts)) {
00081 ast_log(LOG_WARNING, "Empty file!\n");
00082 return NULL;
00083 }
00084
00085 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00086 memset(tmp, 0, sizeof(struct ast_filestream));
00087 if (ast_mutex_lock(&h263_lock)) {
00088 ast_log(LOG_WARNING, "Unable to lock h263 list\n");
00089 free(tmp);
00090 return NULL;
00091 }
00092 tmp->f = f;
00093 tmp->fr.data = tmp->h263;
00094 tmp->fr.frametype = AST_FRAME_VIDEO;
00095 tmp->fr.subclass = AST_FORMAT_H263;
00096
00097 tmp->fr.src = name;
00098 tmp->fr.mallocd = 0;
00099 glistcnt++;
00100 ast_mutex_unlock(&h263_lock);
00101 ast_update_use_count();
00102 }
00103 return tmp;
00104 }
00105
00106 static struct ast_filestream *h263_rewrite(FILE *f, const char *comment)
00107 {
00108
00109
00110
00111 struct ast_filestream *tmp;
00112 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00113 memset(tmp, 0, sizeof(struct ast_filestream));
00114 if (ast_mutex_lock(&h263_lock)) {
00115 ast_log(LOG_WARNING, "Unable to lock h263 list\n");
00116 free(tmp);
00117 return NULL;
00118 }
00119 tmp->f = f;
00120 glistcnt++;
00121 ast_mutex_unlock(&h263_lock);
00122 ast_update_use_count();
00123 } else
00124 ast_log(LOG_WARNING, "Out of memory\n");
00125 return tmp;
00126 }
00127
00128 static void h263_close(struct ast_filestream *s)
00129 {
00130 if (ast_mutex_lock(&h263_lock)) {
00131 ast_log(LOG_WARNING, "Unable to lock h263 list\n");
00132 return;
00133 }
00134 glistcnt--;
00135 ast_mutex_unlock(&h263_lock);
00136 ast_update_use_count();
00137 fclose(s->f);
00138 free(s);
00139 s = NULL;
00140 }
00141
00142 static struct ast_frame *h263_read(struct ast_filestream *s, int *whennext)
00143 {
00144 int res;
00145 int mark=0;
00146 unsigned short len;
00147 unsigned int ts;
00148
00149 s->fr.frametype = AST_FRAME_VIDEO;
00150 s->fr.subclass = AST_FORMAT_H263;
00151 s->fr.offset = AST_FRIENDLY_OFFSET;
00152 s->fr.mallocd = 0;
00153 s->fr.data = s->h263;
00154 if ((res = fread(&len, 1, sizeof(len), s->f)) < 1) {
00155 return NULL;
00156 }
00157 len = ntohs(len);
00158 if (len & 0x8000) {
00159 mark = 1;
00160 }
00161 len &= 0x7fff;
00162 if (len > sizeof(s->h263)) {
00163 ast_log(LOG_WARNING, "Length %d is too long\n", len);
00164 return NULL;
00165 }
00166 if ((res = fread(s->h263, 1, len, s->f)) != len) {
00167 if (res)
00168 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00169 return NULL;
00170 }
00171 s->fr.samples = s->lastts;
00172 s->fr.datalen = len;
00173 s->fr.subclass |= mark;
00174 s->fr.delivery.tv_sec = 0;
00175 s->fr.delivery.tv_usec = 0;
00176 if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
00177 s->lastts = ntohl(ts);
00178 *whennext = s->lastts * 4/45;
00179 } else
00180 *whennext = 0;
00181 return &s->fr;
00182 }
00183
00184 static int h263_write(struct ast_filestream *fs, struct ast_frame *f)
00185 {
00186 int res;
00187 unsigned int ts;
00188 unsigned short len;
00189 int subclass;
00190 int mark=0;
00191 if (f->frametype != AST_FRAME_VIDEO) {
00192 ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
00193 return -1;
00194 }
00195 subclass = f->subclass;
00196 if (subclass & 0x1)
00197 mark=0x8000;
00198 subclass &= ~0x1;
00199 if (subclass != AST_FORMAT_H263) {
00200 ast_log(LOG_WARNING, "Asked to write non-h263 frame (%d)!\n", f->subclass);
00201 return -1;
00202 }
00203 ts = htonl(f->samples);
00204 if ((res = fwrite(&ts, 1, sizeof(ts), fs->f)) != sizeof(ts)) {
00205 ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
00206 return -1;
00207 }
00208 len = htons(f->datalen | mark);
00209 if ((res = fwrite(&len, 1, sizeof(len), fs->f)) != sizeof(len)) {
00210 ast_log(LOG_WARNING, "Bad write (%d/2): %s\n", res, strerror(errno));
00211 return -1;
00212 }
00213 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00214 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00215 return -1;
00216 }
00217 return 0;
00218 }
00219
00220 static char *h263_getcomment(struct ast_filestream *s)
00221 {
00222 return NULL;
00223 }
00224
00225 static int h263_seek(struct ast_filestream *fs, long sample_offset, int whence)
00226 {
00227
00228 return -1;
00229 }
00230
00231 static int h263_trunc(struct ast_filestream *fs)
00232 {
00233
00234 if (ftruncate(fileno(fs->f), ftell(fs->f)) < 0)
00235 return -1;
00236 return 0;
00237 }
00238
00239 static long h263_tell(struct ast_filestream *fs)
00240 {
00241
00242 off_t offset;
00243 offset = ftell(fs->f);
00244 return (offset/20)*160;
00245 }
00246
00247 int load_module()
00248 {
00249 return ast_format_register(name, exts, AST_FORMAT_H263,
00250 h263_open,
00251 h263_rewrite,
00252 h263_write,
00253 h263_seek,
00254 h263_trunc,
00255 h263_tell,
00256 h263_read,
00257 h263_close,
00258 h263_getcomment);
00259
00260
00261 }
00262
00263 int unload_module()
00264 {
00265 return ast_format_unregister(name);
00266 }
00267
00268 int usecount()
00269 {
00270 return glistcnt;
00271 }
00272
00273 char *description()
00274 {
00275 return desc;
00276 }
00277
00278
00279 char *key()
00280 {
00281 return ASTERISK_GPL_KEY;
00282 }