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: 328209 $")
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
00142 if (ftruncate(fileno(fs->f), ftell(fs->f)) < 0)
00143 return -1;
00144 return 0;
00145 }
00146
00147 static off_t h264_tell(struct ast_filestream *fs)
00148 {
00149 off_t offset = ftell(fs->f);
00150 return offset;
00151 }
00152
00153 static const struct ast_format h264_f = {
00154 .name = "h264",
00155 .exts = "h264",
00156 .format = AST_FORMAT_H264,
00157 .open = h264_open,
00158 .write = h264_write,
00159 .seek = h264_seek,
00160 .trunc = h264_trunc,
00161 .tell = h264_tell,
00162 .read = h264_read,
00163 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00164 .desc_size = sizeof(struct h264_desc),
00165 };
00166
00167 static int load_module(void)
00168 {
00169 if (ast_format_register(&h264_f))
00170 return AST_MODULE_LOAD_FAILURE;
00171 return AST_MODULE_LOAD_SUCCESS;
00172 }
00173
00174 static int unload_module(void)
00175 {
00176 return ast_format_unregister(h264_f.name);
00177 }
00178
00179 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw H.264 data",
00180 .load = load_module,
00181 .unload = unload_module,
00182 .load_pri = AST_MODPRI_APP_DEPEND
00183 );