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
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 364578 $")
00034
00035 #include "asterisk/mod_format.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/endian.h"
00038
00039
00040
00041
00042
00043
00044 #define BUF_SIZE 4096
00045 struct h264_desc {
00046 unsigned int lastts;
00047 };
00048
00049 static int h264_open(struct ast_filestream *s)
00050 {
00051 unsigned int ts;
00052 int res;
00053 if ((res = fread(&ts, 1, sizeof(ts), s->f)) < sizeof(ts)) {
00054 ast_log(LOG_WARNING, "Empty file!\n");
00055 return -1;
00056 }
00057 return 0;
00058 }
00059
00060 static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext)
00061 {
00062 int res;
00063 int mark=0;
00064 unsigned short len;
00065 unsigned int ts;
00066 struct h264_desc *fs = (struct h264_desc *)s->_private;
00067
00068
00069 if ((res = fread(&len, 1, sizeof(len), s->f)) < 1)
00070 return NULL;
00071 len = ntohs(len);
00072 mark = (len & 0x8000) ? 1 : 0;
00073 len &= 0x7fff;
00074 if (len > BUF_SIZE) {
00075 ast_log(LOG_WARNING, "Length %d is too long\n", len);
00076 len = BUF_SIZE;
00077 }
00078 s->fr.frametype = AST_FRAME_VIDEO;
00079 s->fr.subclass.codec = AST_FORMAT_H264;
00080 s->fr.mallocd = 0;
00081 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, len);
00082 if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
00083 if (res)
00084 ast_log(LOG_WARNING, "Short read (%d of %d) (%s)!\n", res, len, strerror(errno));
00085 return NULL;
00086 }
00087 s->fr.samples = fs->lastts;
00088 s->fr.datalen = len;
00089 s->fr.subclass.codec |= mark;
00090 s->fr.delivery.tv_sec = 0;
00091 s->fr.delivery.tv_usec = 0;
00092 if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
00093 fs->lastts = ntohl(ts);
00094 *whennext = fs->lastts * 4/45;
00095 } else
00096 *whennext = 0;
00097 return &s->fr;
00098 }
00099
00100 static int h264_write(struct ast_filestream *s, struct ast_frame *f)
00101 {
00102 int res;
00103 unsigned int ts;
00104 unsigned short len;
00105 int mark;
00106
00107 if (f->frametype != AST_FRAME_VIDEO) {
00108 ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
00109 return -1;
00110 }
00111 mark = (f->subclass.codec & 0x1) ? 0x8000 : 0;
00112 if ((f->subclass.codec & ~0x1) != AST_FORMAT_H264) {
00113 ast_log(LOG_WARNING, "Asked to write non-h264 frame (%s)!\n", ast_getformatname(f->subclass.codec));
00114 return -1;
00115 }
00116 ts = htonl(f->samples);
00117 if ((res = fwrite(&ts, 1, sizeof(ts), s->f)) != sizeof(ts)) {
00118 ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
00119 return -1;
00120 }
00121 len = htons(f->datalen | mark);
00122 if ((res = fwrite(&len, 1, sizeof(len), s->f)) != sizeof(len)) {
00123 ast_log(LOG_WARNING, "Bad write (%d/2): %s\n", res, strerror(errno));
00124 return -1;
00125 }
00126 if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
00127 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00128 return -1;
00129 }
00130 return 0;
00131 }
00132
00133 static int h264_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00134 {
00135
00136 return -1;
00137 }
00138
00139 static int h264_trunc(struct ast_filestream *fs)
00140 {
00141 int fd;
00142 off_t cur;
00143
00144 if ((fd = fileno(fs->f)) < 0) {
00145 ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for h264 filestream %p: %s\n", fs, strerror(errno));
00146 return -1;
00147 }
00148 if ((cur = ftello(fs->f)) < 0) {
00149 ast_log(AST_LOG_WARNING, "Unable to determine current position in h264 filestream %p: %s\n", fs, strerror(errno));
00150 return -1;
00151 }
00152
00153 return ftruncate(fd, cur);
00154 }
00155
00156 static off_t h264_tell(struct ast_filestream *fs)
00157 {
00158 off_t offset = ftell(fs->f);
00159 return offset;
00160 }
00161
00162 static const struct ast_format h264_f = {
00163 .name = "h264",
00164 .exts = "h264",
00165 .format = AST_FORMAT_H264,
00166 .open = h264_open,
00167 .write = h264_write,
00168 .seek = h264_seek,
00169 .trunc = h264_trunc,
00170 .tell = h264_tell,
00171 .read = h264_read,
00172 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00173 .desc_size = sizeof(struct h264_desc),
00174 };
00175
00176 static int load_module(void)
00177 {
00178 if (ast_format_register(&h264_f))
00179 return AST_MODULE_LOAD_FAILURE;
00180 return AST_MODULE_LOAD_SUCCESS;
00181 }
00182
00183 static int unload_module(void)
00184 {
00185 return ast_format_unregister(h264_f.name);
00186 }
00187
00188 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw H.264 data",
00189 .load = load_module,
00190 .unload = unload_module,
00191 .load_pri = AST_MODPRI_APP_DEPEND
00192 );