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 if((((i = fwrite(stream->og.header, 1, stream->og.header_len, state->vf))) != stream->og.header_len) || (stream->og.body_len && (((i = fwrite(stream->og.body, 1, stream->og.body_len, state->vf))) != stream->og.body_len))) {
00081 j = errno;
00082 D2(fprintf(debug_file, "\nogm_flush_to_file() fail: %d %ld %ld\n", i, stream->og.header_len, stream->og.body_len));
00083 return -CAMOGM_FRAME_FILE_ERR;
00084 }
00085 }
00086 return 0;
00087 }
00088
00089
00090 int camogm_audio_init(void);
00091 int camogm_audio_end(void);
00092
00094 int camogm_init_ogm(void) {
00095 return 0;
00096 }
00097
00098 void camogm_free_ogm(void) {
00099 }
00100
00101 int camogm_start_ogm(void) {
00102 char vendor[]= "CamOGM";
00103 int pos;
00104 int rez = 0;
00105 stream_header sh;
00106 char hdbuf[sizeof(stream_header) + 1];
00107 ogg_packet ogg_header;
00108 sprintf(state->path, "%s%010ld_%06ld.ogm", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
00109 if(!((state->vf = fopen(state->path, "w+")))) {
00110 D0(fprintf(debug_file, "Error opening %s for writing\n", state->path));
00111 return -CAMOGM_FRAME_FILE_ERR;
00112 }
00113 ogg_stream_init(&(svideo.os), state->serialno);
00114 svideo.packetno = 0;
00115
00116 memset(&sh, 0, sizeof(sh));
00117 memcpy(sh.streamtype, "video", 5);
00118 memcpy(sh.subtype, "MJPG", 4);
00119 put_uint32(&sh.size, sizeof(stream_header));
00120
00121 put_uint64(&sh.time_unit, state->time_unit);
00122
00123
00124
00125 put_uint64(&sh.samples_per_unit, (ogg_int64_t)state->timescale);
00126
00127
00128 put_uint32(&sh.default_len, 1);
00129 put_uint32(&sh.buffersize, state->width * state->height);
00130
00131 put_uint16(&sh.bits_per_sample, 0);
00132 put_uint32(&sh.sh.video.width, state->width);
00133 put_uint32(&sh.sh.video.height, state->height);
00134 memcpy(&hdbuf[1], &sh, sizeof(sh));
00135 hdbuf[0] = 1;
00137 ogg_header.packet = hdbuf;
00138 ogg_header.bytes = sizeof(sh) + 1;
00139 ogg_header.b_o_s = 1;
00140 ogg_header.e_o_s = 0;
00141 ogg_header.packetno = svideo.packetno++;;
00142 ogg_header.granulepos = 0;
00143 ogg_stream_packetin(&svideo.os, &ogg_header);
00144
00145 if((rez = ogm_flush_to_file(&svideo)) != 0)
00146 return rez;
00147
00150 memset(hdbuf, 0, sizeof(hdbuf));
00151 hdbuf[0] = PACKET_TYPE_COMMENT;
00152 memcpy(&hdbuf[1], "vorbis", 6);
00153 pos = 7;
00154 put_uint32(&hdbuf[pos], strlen(vendor));
00155 pos += 4;
00156 strcpy(&hdbuf[pos], vendor);
00157 pos += strlen(vendor);
00158 put_uint32(&hdbuf[pos], 0);
00159 pos += 4;
00160 hdbuf[pos++] = 1;
00162 ogg_header.packet = hdbuf;
00163 ogg_header.bytes = pos;
00164 ogg_header.b_o_s = 0;
00165 ogg_header.e_o_s = 0;
00166 ogg_header.packetno = svideo.packetno++;;
00167 ogg_header.granulepos = 0;
00168 ogg_stream_packetin(&svideo.os, &ogg_header);
00171
00172 svideo.granulepos = (ogg_int64_t)((((double) state->frame_params.timestamp_usec) +
00173 (((double) 1000000) * ((double)state->frame_params.timestamp_sec))) *
00174 ((double) 10) /
00175 ((double) state->time_unit) *
00176 ((double) state->timescale));
00177
00178
00179
00180
00182 svideo.granulepos = 0;
00183
00185 rez = 0;
00186 if(state->audio_enable)
00187 rez = camogm_audio_init();
00188 return rez;
00189 }
00190
00191 int camogm_frame_ogm(void){
00192 int indx;
00193 int rez;
00194
00195 elph_ogg_packet elp_packet;
00196 elp_packet.bytes = 0;
00197 for(indx = 0; indx < state->chunk_index; indx++)
00198 elp_packet.bytes += state->packetchunks[indx].bytes;
00199 elp_packet.packet = state->packetchunks;
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 elp_packet.b_o_s = 0;
00216 elp_packet.e_o_s = 0;
00217 elp_packet.packetno = svideo.packetno++;;
00218
00219
00220
00221 elp_packet.granulepos = svideo.granulepos;
00223
00224 svideo.granulepos += (ogg_int64_t)state->timescale;
00225
00226 ogg_stream_packetin_elph(&svideo.os, &elp_packet);
00227 if((rez = ogm_flush_to_file(&svideo)) != 0)
00228 return rez;
00229
00230 if(state->allow_sync)
00231 sync();
00232 return 0;
00233 }
00234
00235 int camogm_end_ogm(void){
00236 int rez = 0;
00237 ogg_packet ogg_header;
00238 char buf[1] = {0x00};
00239
00240 ogg_header.packet = buf;
00241 ogg_header.bytes = 1;
00242 ogg_header.b_o_s = 0;
00243 ogg_header.e_o_s = 1;
00244 ogg_header.packetno = svideo.packetno++;
00245 ogg_header.granulepos = ++(svideo.granulepos);
00246 ogg_stream_packetin(&svideo.os, &ogg_header);
00247
00248 if((rez = ogm_flush_to_file(&svideo)) != 0)
00249 return rez;
00250 rez = 0;
00251 if(state->audio_enable)
00252 rez = camogm_audio_end();
00253 return rez;
00254 }
00255
00256 int camogm_audio_init(void) {
00257 char vendor[]= "CamOGM";
00258 char hdbuf[sizeof(stream_header) + 1];
00259 int pos;
00260 int rez;
00261
00262 stream_header sh_audio;
00263 ogg_packet ogg_header;
00264
00265 saudio.packetno = 0;
00266 saudio.granulepos = 0;
00267
00268 ogg_stream_init(&saudio.os, 0x28);
00269 saudio.packetno = 0;
00270 memset(&sh_audio, 0, sizeof(stream_header));
00271 memcpy(sh_audio.streamtype, "audio", 5);
00272 memcpy(sh_audio.subtype, "0001", 4);
00273 put_uint32(&sh_audio.size, sizeof(stream_header));
00274 put_uint64(&sh_audio.time_unit, 1000);
00275 put_uint64(&sh_audio.samples_per_unit, (ogg_int64_t)state->audio_rate);
00276 put_uint32(&sh_audio.default_len, 0);
00277 put_uint32(&sh_audio.buffersize, 0);
00278 put_uint16(&sh_audio.bits_per_sample, 16);
00279 put_uint32(&sh_audio.sh.audio.channels, state->audio_channels);
00280 put_uint32(&sh_audio.sh.audio.blockalign, 1);
00281 put_uint32(&sh_audio.sh.audio.avgbytespersec, state->audio_channels * state->audio_rate * 2);
00282 memcpy(&hdbuf[1], &sh_audio, sizeof(sh_audio));
00283 hdbuf[0] = 1;
00284
00286 ogg_header.packet = hdbuf;
00287 ogg_header.bytes = sizeof(sh_audio) + 1;
00288 ogg_header.b_o_s = 1;
00289 ogg_header.e_o_s = 0;
00290 ogg_header.packetno = saudio.packetno++;
00291 ogg_header.granulepos = 0;
00292 ogg_stream_packetin(&saudio.os, &ogg_header);
00293
00294 if((rez = ogm_flush_to_file(&saudio)) != 0)
00295 return rez;
00298 memset(hdbuf, 0, sizeof(hdbuf));
00299 hdbuf[0] = PACKET_TYPE_COMMENT;
00300 memcpy(&hdbuf[1], "vorbis", 6);
00301 pos=7;
00302 put_uint32(&hdbuf[pos], strlen(vendor));
00303 pos += 4;
00304 strcpy(&hdbuf[pos], vendor);
00305 pos += strlen(vendor);
00306 put_uint32(&hdbuf[pos], 0);
00307 pos += 4;
00308 hdbuf[pos++] = 1;
00310 ogg_header.packet = hdbuf;
00311 ogg_header.bytes = pos;
00312 ogg_header.b_o_s = 0;
00313 ogg_header.e_o_s = 0;
00314 ogg_header.packetno = saudio.packetno++;;
00315 ogg_header.granulepos = 0;
00316 ogg_stream_packetin(&saudio.os, &ogg_header);
00317
00318 if((rez = ogm_flush_to_file(&saudio)) != 0)
00319 return rez;
00320 return 0;
00321 }
00322
00323 int camogm_audio_end(void) {
00324 ogg_packet ogg_header;
00325 int rez;
00326 char buf[1] = {0x00};
00327
00328 ogg_header.packet = buf;
00329 ogg_header.bytes = 1;
00330 ogg_header.b_o_s = 0;
00331 ogg_header.e_o_s = 1;
00332 ogg_header.packetno = saudio.packetno++;
00333 ogg_header.granulepos = saudio.granulepos;
00334 ogg_stream_packetin(&saudio.os, &ogg_header);
00335 if((rez = ogm_flush_to_file(&saudio)) != 0)
00336 return rez;
00337 return 0;
00338 }
00339
00340 void camogm_audio_ogm_push(void *buf, int len, long granules_shift, int prefix) {
00341 u_int16_t samp_in_subpacket = granules_shift;
00342 unsigned char *h = (unsigned char *)buf - (1 + sizeof(samp_in_subpacket));
00343 int j;
00344 int rez;
00345
00346 h[0] = 0x00;
00347 h[0] = ((sizeof(samp_in_subpacket) & 3) << 6) + ((sizeof(samp_in_subpacket) & 4) >> 1);
00348 h[0] |= PACKET_IS_SYNCPOINT;
00349 for(j = 0; j < sizeof(samp_in_subpacket); j++) {
00350 h[j + 1] = (unsigned char)(samp_in_subpacket & 0xFF);
00351 samp_in_subpacket = samp_in_subpacket >> 8;
00352 }
00353 ogg_packet packet;
00354 packet.bytes = len + 1 + sizeof(samp_in_subpacket);
00355 packet.packet = (char *)h;
00356 packet.b_o_s = 0;
00357 packet.e_o_s = 0;
00358 packet.packetno = saudio.packetno++;;
00359 packet.granulepos = saudio.granulepos;
00360 saudio.granulepos += (ogg_int64_t)granules_shift;
00361 ogg_stream_packetin(&saudio.os, &packet);
00362 rez = ogm_flush_to_file(&saudio);
00363 }