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
00032
00033
00035 #include <unistd.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <signal.h>
00039 #include <fcntl.h>
00040 #include <sys/uio.h>
00041 #include <errno.h>
00042 #include <sys/types.h>
00043 #include <sys/socket.h>
00044 #include <sys/stat.h>
00045
00046
00047 #include <time.h>
00048 #include <string.h>
00049
00050 #include <netinet/in.h>
00051 #include <sys/mman.h>
00052 #include <sys/ioctl.h>
00053
00054 #include <asm/elphel/c313a.h>
00055 #include <asm/elphel/ext353.h>
00056 #include <asm/byteorder.h>
00057
00058
00059 #include <ogg/ogg.h>
00060 #include "ogmstreams.h"
00061
00062 #include "camogm_ogm.h"
00063 #include "camogm.h"
00064
00065 struct ogm_stream_t {
00066 ogg_stream_state os;
00067 ogg_page og;
00068 ogg_packet op;
00069 elph_ogg_packet eop;
00070 ogg_int64_t packetno;
00071 ogg_int64_t granulepos;
00072 };
00073
00074 struct ogm_stream_t svideo;
00075 struct ogm_stream_t saudio;
00076
00077 int ogm_flush_to_file(struct ogm_stream_t *stream) {
00078 int i, j;
00079 while(ogg_stream_flush(&(stream->os), &(stream->og))) {
00080
00081 if((((i = write(state->vf, stream->og.header, stream->og.header_len))) != stream->og.header_len) || (stream->og.body_len && (((i = write(state->vf, stream->og.body, stream->og.body_len))) != stream->og.body_len))) {
00082 j = errno;
00083 D2(fprintf(debug_file, "\nogm_flush_to_file() fail: %d %ld %ld\n", i, stream->og.header_len, stream->og.body_len));
00084 return -CAMOGM_FRAME_FILE_ERR;
00085 }
00086 }
00087 return 0;
00088 }
00089
00090
00091 int camogm_audio_init(void);
00092 int camogm_audio_end(void);
00093
00095 int camogm_init_ogm(void) {
00096 return 0;
00097 }
00098
00099 void camogm_free_ogm(void) {
00100 }
00101
00102 int camogm_start_ogm(void) {
00103 char vendor[]= "CamOGM";
00104 int pos;
00105 int rez = 0;
00106 stream_header sh;
00107 char hdbuf[sizeof(stream_header) + 1];
00108 ogg_packet ogg_header;
00109 sprintf(state->path, "%s%010ld_%06ld.ogm", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
00110
00111
00112
00113
00114
00115
00116 if(!((state->vf = open(state->path, O_RDWR | O_CREAT)))) {
00117 D0(fprintf(debug_file, "Error opening %s for writing\n", state->path));
00118 return -CAMOGM_FRAME_FILE_ERR;
00119 }
00120 ogg_stream_init(&(svideo.os), state->serialno);
00121 svideo.packetno = 0;
00122
00123 memset(&sh, 0, sizeof(sh));
00124 memcpy(sh.streamtype, "video", 5);
00125 memcpy(sh.subtype, "MJPG", 4);
00126 put_uint32(&sh.size, sizeof(stream_header));
00127
00128 put_uint64(&sh.time_unit, state->time_unit);
00129
00130
00131
00132 put_uint64(&sh.samples_per_unit, (ogg_int64_t)state->timescale);
00133
00134
00135 put_uint32(&sh.default_len, 1);
00136 put_uint32(&sh.buffersize, state->width * state->height);
00137
00138 put_uint16(&sh.bits_per_sample, 0);
00139 put_uint32(&sh.sh.video.width, state->width);
00140 put_uint32(&sh.sh.video.height, state->height);
00141 memcpy(&hdbuf[1], &sh, sizeof(sh));
00142 hdbuf[0] = 1;
00144 ogg_header.packet = hdbuf;
00145 ogg_header.bytes = sizeof(sh) + 1;
00146 ogg_header.b_o_s = 1;
00147 ogg_header.e_o_s = 0;
00148 ogg_header.packetno = svideo.packetno++;;
00149 ogg_header.granulepos = 0;
00150 ogg_stream_packetin(&svideo.os, &ogg_header);
00151
00152 if((rez = ogm_flush_to_file(&svideo)) != 0)
00153 return rez;
00154
00157 memset(hdbuf, 0, sizeof(hdbuf));
00158 hdbuf[0] = PACKET_TYPE_COMMENT;
00159 memcpy(&hdbuf[1], "vorbis", 6);
00160 pos = 7;
00161 put_uint32(&hdbuf[pos], strlen(vendor));
00162 pos += 4;
00163 strcpy(&hdbuf[pos], vendor);
00164 pos += strlen(vendor);
00165 put_uint32(&hdbuf[pos], 0);
00166 pos += 4;
00167 hdbuf[pos++] = 1;
00169 ogg_header.packet = hdbuf;
00170 ogg_header.bytes = pos;
00171 ogg_header.b_o_s = 0;
00172 ogg_header.e_o_s = 0;
00173 ogg_header.packetno = svideo.packetno++;;
00174 ogg_header.granulepos = 0;
00175 ogg_stream_packetin(&svideo.os, &ogg_header);
00178
00179 svideo.granulepos = (ogg_int64_t)((((double) state->frame_params.timestamp_usec) +
00180 (((double) 1000000) * ((double)state->frame_params.timestamp_sec))) *
00181 ((double) 10) /
00182 ((double) state->time_unit) *
00183 ((double) state->timescale));
00184
00185
00186
00187
00189 svideo.granulepos = 0;
00190
00192 rez = 0;
00193 if(state->audio_enable)
00194 rez = camogm_audio_init();
00195 return rez;
00196 }
00197
00198 int camogm_frame_ogm(void){
00199 int indx;
00200 int rez;
00201
00202 elph_ogg_packet elp_packet;
00203 elp_packet.bytes = 0;
00204 for(indx = 0; indx < state->chunk_index; indx++)
00205 elp_packet.bytes += state->packetchunks[indx].bytes;
00206 elp_packet.packet = state->packetchunks;
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 elp_packet.b_o_s = 0;
00223 elp_packet.e_o_s = 0;
00224 elp_packet.packetno = svideo.packetno++;;
00225
00226
00227
00228 elp_packet.granulepos = svideo.granulepos;
00230
00231 svideo.granulepos += (ogg_int64_t)state->timescale;
00232
00233 ogg_stream_packetin_elph(&svideo.os, &elp_packet);
00234 if((rez = ogm_flush_to_file(&svideo)) != 0)
00235 return rez;
00236
00237 if(state->allow_sync)
00238 sync();
00239 return 0;
00240 }
00241
00242 int camogm_end_ogm(void){
00243 int rez = 0;
00244 ogg_packet ogg_header;
00245 char buf[1] = {0x00};
00246
00247 ogg_header.packet = buf;
00248 ogg_header.bytes = 1;
00249 ogg_header.b_o_s = 0;
00250 ogg_header.e_o_s = 1;
00251 ogg_header.packetno = svideo.packetno++;
00252 ogg_header.granulepos = ++(svideo.granulepos);
00253 ogg_stream_packetin(&svideo.os, &ogg_header);
00254
00255 if((rez = ogm_flush_to_file(&svideo)) != 0)
00256 return rez;
00257 rez = 0;
00258 if(state->audio_enable)
00259 rez = camogm_audio_end();
00260 return rez;
00261 }
00262
00263 int camogm_audio_init(void) {
00264 char vendor[]= "CamOGM";
00265 char hdbuf[sizeof(stream_header) + 1];
00266 int pos;
00267 int rez;
00268
00269 stream_header sh_audio;
00270 ogg_packet ogg_header;
00271
00272 saudio.packetno = 0;
00273 saudio.granulepos = 0;
00274
00275 ogg_stream_init(&saudio.os, 0x28);
00276 saudio.packetno = 0;
00277 memset(&sh_audio, 0, sizeof(stream_header));
00278 memcpy(sh_audio.streamtype, "audio", 5);
00279 memcpy(sh_audio.subtype, "0001", 4);
00280 put_uint32(&sh_audio.size, sizeof(stream_header));
00281 put_uint64(&sh_audio.time_unit, 1000);
00282 put_uint64(&sh_audio.samples_per_unit, (ogg_int64_t)state->audio_rate);
00283 put_uint32(&sh_audio.default_len, 0);
00284 put_uint32(&sh_audio.buffersize, 0);
00285 put_uint16(&sh_audio.bits_per_sample, 16);
00286 put_uint32(&sh_audio.sh.audio.channels, state->audio_channels);
00287 put_uint32(&sh_audio.sh.audio.blockalign, 1);
00288 put_uint32(&sh_audio.sh.audio.avgbytespersec, state->audio_channels * state->audio_rate * 2);
00289 memcpy(&hdbuf[1], &sh_audio, sizeof(sh_audio));
00290 hdbuf[0] = 1;
00291
00293 ogg_header.packet = hdbuf;
00294 ogg_header.bytes = sizeof(sh_audio) + 1;
00295 ogg_header.b_o_s = 1;
00296 ogg_header.e_o_s = 0;
00297 ogg_header.packetno = saudio.packetno++;
00298 ogg_header.granulepos = 0;
00299 ogg_stream_packetin(&saudio.os, &ogg_header);
00300
00301 if((rez = ogm_flush_to_file(&saudio)) != 0)
00302 return rez;
00305 memset(hdbuf, 0, sizeof(hdbuf));
00306 hdbuf[0] = PACKET_TYPE_COMMENT;
00307 memcpy(&hdbuf[1], "vorbis", 6);
00308 pos=7;
00309 put_uint32(&hdbuf[pos], strlen(vendor));
00310 pos += 4;
00311 strcpy(&hdbuf[pos], vendor);
00312 pos += strlen(vendor);
00313 put_uint32(&hdbuf[pos], 0);
00314 pos += 4;
00315 hdbuf[pos++] = 1;
00317 ogg_header.packet = hdbuf;
00318 ogg_header.bytes = pos;
00319 ogg_header.b_o_s = 0;
00320 ogg_header.e_o_s = 0;
00321 ogg_header.packetno = saudio.packetno++;;
00322 ogg_header.granulepos = 0;
00323 ogg_stream_packetin(&saudio.os, &ogg_header);
00324
00325 if((rez = ogm_flush_to_file(&saudio)) != 0)
00326 return rez;
00327 return 0;
00328 }
00329
00330 int camogm_audio_end(void) {
00331 ogg_packet ogg_header;
00332 int rez;
00333 char buf[1] = {0x00};
00334
00335 ogg_header.packet = buf;
00336 ogg_header.bytes = 1;
00337 ogg_header.b_o_s = 0;
00338 ogg_header.e_o_s = 1;
00339 ogg_header.packetno = saudio.packetno++;
00340 ogg_header.granulepos = saudio.granulepos;
00341 ogg_stream_packetin(&saudio.os, &ogg_header);
00342 if((rez = ogm_flush_to_file(&saudio)) != 0)
00343 return rez;
00344 return 0;
00345 }
00346
00347 void camogm_audio_ogm_push(void *buf, int len, long granules_shift, int prefix) {
00348 u_int16_t samp_in_subpacket = granules_shift;
00349 unsigned char *h = (unsigned char *)buf - (1 + sizeof(samp_in_subpacket));
00350 int j;
00351 int rez;
00352
00353 h[0] = 0x00;
00354 h[0] = ((sizeof(samp_in_subpacket) & 3) << 6) + ((sizeof(samp_in_subpacket) & 4) >> 1);
00355 h[0] |= PACKET_IS_SYNCPOINT;
00356 for(j = 0; j < sizeof(samp_in_subpacket); j++) {
00357 h[j + 1] = (unsigned char)(samp_in_subpacket & 0xFF);
00358 samp_in_subpacket = samp_in_subpacket >> 8;
00359 }
00360 ogg_packet packet;
00361 packet.bytes = len + 1 + sizeof(samp_in_subpacket);
00362 packet.packet = (char *)h;
00363 packet.b_o_s = 0;
00364 packet.e_o_s = 0;
00365 packet.packetno = saudio.packetno++;;
00366 packet.granulepos = saudio.granulepos;
00367 saudio.granulepos += (ogg_int64_t)granules_shift;
00368 ogg_stream_packetin(&saudio.os, &packet);
00369 rez = ogm_flush_to_file(&saudio);
00370 }