1 /*
2   ogminfo -- utility for extracting raw streams from an OGG media file
3 
4   Written by Moritz Bunkus <moritz@bunkus.org>
5   Integrated into transcode by Tilmann Bitterberg <transcode@tibit.org>
6 
7   Distributed under the GPL
8   see the file COPYING for details
9   or visit http://www.gnu.org/copyleft/gpl.html
10 */
11 
12 #include "transcode.h"
13 #include "libtc/libtc.h"
14 #include "tcinfo.h"
15 
16 #include <sys/types.h>
17 
18 #include "ioaux.h"
19 #include "tc.h"
20 
21 #define NOAUDIO 0
22 #define NOVIDEO 1
23 #define NOTEXT  2
24 
25 unsigned char *xaudio = NULL;
26 unsigned char *xvideo = NULL;
27 unsigned char *xtext = NULL;
28 int no[3];
29 int      xraw = 0;
30 
31 static int verbose_flag = TC_QUIET;
32 
33 #if (HAVE_OGG && HAVE_VORBIS)
34 
35 #include <ogg/ogg.h>
36 #include <vorbis/codec.h>
37 
38 #include "ogmstreams.h"
39 
40 #define BLOCK_SIZE 4096
41 
42 #define ACVORBIS 0xffff
43 #define ACPCM    0x0001
44 #define ACMP3    0x0055
45 #define ACAC3    0x2000
46 
47 typedef struct stream_t {
48   int                 serial;
49   int                 fd;
50   double              sample_rate;
51   int                 eos, comment;
52   int                 sno;
53   char                stype;
54   ogg_stream_state    instate;
55   struct stream_t    *next;
56 
57   int                 acodec;
58   ogg_int64_t         bwritten;
59 
60   ogg_stream_state    outstate;
61   int                 packetno;
62   ogg_int64_t         max_granulepos;
63 
64   int                 subnr;
65 } stream_t;
66 
67 stream_t *first;
68 int      nastreams = 0, nvstreams = 0, ntstreams = 0, numstreams = 0;
69 char basename[] = "stdout";
70 
add_stream(stream_t * ndmx)71 static void add_stream(stream_t *ndmx) {
72   stream_t *cur = first;
73 
74   if (first == NULL) {
75     first = ndmx;
76     first->next = NULL;
77   } else {
78     cur = first;
79     while (cur->next != NULL)
80       cur = cur->next;
81     cur->next = ndmx;
82     ndmx->next = NULL;
83   }
84 }
85 
find_stream(int fserial)86 static stream_t *find_stream(int fserial) {
87   stream_t *cur = first;
88 
89   while (cur != NULL) {
90     if (cur->serial == fserial)
91       break;
92     cur = cur->next;
93   }
94 
95   return cur;
96 }
97 
98 double highest_ts = 0;
99 
extraction_requested(unsigned char * s,int stream,int type)100 static int extraction_requested(unsigned char *s, int stream, int type) {
101   int i;
102 
103   if (no[type])
104     return 0;
105   if (strlen((char *)s) == 0)
106     return 1;
107   for (i = 0; i < strlen((char *)s); i++)
108     if (s[i] == stream)
109       return 1;
110 
111   return 0;
112 }
113 
flush_pages(stream_t * stream,ogg_packet * op)114 static void flush_pages(stream_t *stream, ogg_packet *op) {
115   ogg_page page;
116 
117   while (ogg_stream_flush(&stream->outstate, &page)) {
118     int ih, ib;
119 
120     ih = tc_pwrite(stream->fd, page.header, page.header_len);
121     if (ih != page.header_len) {
122         tc_log_error(__FILE__, "error while writing page header");
123         import_exit(1); /* XXX ugly */
124     }
125     ib = tc_pwrite(stream->fd, page.body, page.body_len);
126     if (ib != page.body_len) {
127         tc_log_error(__FILE__, "error while writing page bofy");
128         import_exit(1); /* XXX ugly */
129     }
130     if (verbose_flag & TC_DEBUG)
131       tc_log_msg(__FILE__, "x/a%d: %d + %d written", stream->sno, ih, ib);
132   }
133 }
134 
write_pages(stream_t * stream,ogg_packet * op)135 static void write_pages(stream_t *stream, ogg_packet *op) {
136   ogg_page page;
137 
138   while (ogg_stream_pageout(&stream->outstate, &page)) {
139     int ih, ib;
140 
141     ih = tc_pwrite(stream->fd, page.header, page.header_len);
142     if (ih != page.header_len) {
143         tc_log_error(__FILE__, "error while writing page header");
144         import_exit(1); /* XXX ugly */
145     }
146     ib = tc_pwrite(stream->fd, page.body, page.body_len);
147     if (ib != page.body_len) {
148         tc_log_error(__FILE__, "error while writing page bofy");
149         import_exit(1); /* XXX ugly */
150     }
151     if (verbose_flag & TC_DEBUG)
152       tc_log_msg(__FILE__, "x/a%d: %d + %d written", stream->sno, ih, ib);
153   }
154 }
155 
handle_packet(stream_t * stream,ogg_packet * pack,ogg_page * page)156 static void handle_packet(stream_t *stream, ogg_packet *pack, ogg_page *page) {
157   int i, w, hdrlen, end;
158   long long lenbytes;
159   char *sub;
160   char out[100];
161   ogg_int64_t pgp, sst;
162 
163   //tc_log_msg(__FILE__, "Going handle 1");
164   if (pack->e_o_s) {
165     stream->eos = 1;
166     pack->e_o_s = 1;
167   }
168 
169   if (((double)pack->granulepos * 1000.0 / (double)stream->sample_rate) >
170       highest_ts)
171     highest_ts = (double)pack->granulepos * 1000.0 /
172                   (double)stream->sample_rate;
173 
174   switch (stream->stype) {
175     case 'v':
176       if (!extraction_requested(xvideo, stream->sno, NOVIDEO))
177         return;
178       break;
179     case 'a':
180       if (!extraction_requested(xaudio, stream->sno, NOAUDIO))
181         return;
182       break;
183     case 't':
184       if (!extraction_requested(xtext, stream->sno, NOTEXT))
185         return;
186       break;
187   }
188 
189   hdrlen = (*pack->packet & OGM_PACKET_LEN_BITS01) >> 6;
190   hdrlen |= (*pack->packet & OGM_PACKET_LEN_BITS2) << 1;
191   for (i = 0, lenbytes = 0; i < hdrlen; i++) {
192     lenbytes = lenbytes << 8;
193     lenbytes += *((unsigned char *)pack->packet + hdrlen - i);
194   }
195 
196   switch (stream->stype) {
197     case 'v':
198       if (((*pack->packet & 3) == OGM_PACKET_TYPE_HEADER) ||
199           ((*pack->packet & 3) == OGM_PACKET_TYPE_COMMENT))
200         return;
201       i = tc_pwrite(stream->fd, (char *)&pack->packet[hdrlen + 1],
202                     pack->bytes - 1 - hdrlen);
203       if (i != pack->bytes - 1 - hdrlen) {
204         tc_log_error(__FILE__, "error while writing data");
205         import_exit(1); /* XXX ugly */
206       }
207       if (verbose_flag & TC_DEBUG)
208         tc_log_msg(__FILE__, "x/v%d: %d written", stream->sno, i);
209       break;
210     case 't':
211       if (((*pack->packet & 3) == OGM_PACKET_TYPE_HEADER) ||
212           ((*pack->packet & 3) == OGM_PACKET_TYPE_COMMENT))
213         return;
214 
215       if (xraw) {
216         i = tc_pwrite(stream->fd, (char *)&pack->packet[hdrlen + 1],
217                       pack->bytes - 1 - hdrlen);
218         if (i != pack->bytes - 1 - hdrlen) {
219           tc_log_error(__FILE__, "error while writing data");
220           import_exit(1); /* XXX ugly */
221         }
222         if (verbose_flag & TC_DEBUG)
223           tc_log_msg(__FILE__, "x/t%d: %d written", stream->sno, i);
224         return;
225       }
226 
227       sub = (char *)&pack->packet[hdrlen + 1];
228       if ((strlen(sub) > 1) || (*sub != ' ')) {
229         sst = (pack->granulepos / stream->sample_rate) * 1000;
230         pgp = sst + lenbytes;
231         tc_snprintf(out,sizeof(out), "%d\r\n%02d:%02d:%02d,%03d --> " \
232 		    "%02d:%02d:%02d,%03d\r\n", stream->subnr + 1,
233 		    (int)(sst / 3600000),
234 		    (int)(sst / 60000) % 60,
235 		    (int)(sst / 1000) % 60,
236 		    (int)(sst % 1000),
237 		    (int)(pgp / 3600000),
238 		    (int)(pgp / 60000) % 60,
239 		    (int)(pgp / 1000) % 60,
240 		    (int)(pgp % 1000));
241         i = tc_pwrite(stream->fd, out, strlen(out));
242         if (i != strlen(out)) {
243           tc_log_error(__FILE__, "error while writing data");
244           import_exit(1); /* XXX ugly */
245         }
246         end = strlen(sub) - 1;
247         while ((end >= 0) && ((sub[end] == '\n') || (sub[end] == '\r'))) {
248           sub[end] = 0;
249           end--;
250         }
251         w = tc_pwrite(stream->fd, sub, strlen(sub));
252         if (i == strlen(sub)) {
253             i += w;
254         } else {
255             tc_log_error(__FILE__, "error while writing data");
256             import_exit(1);
257         }
258         w = tc_pwrite(stream->fd, "\r\n\r\n", 4);
259         if (w == 4) {
260             i += w;
261         } else {
262             tc_log_error(__FILE__, "error while writing data");
263             import_exit(1);
264         }
265         stream->subnr++;
266         if (verbose_flag & TC_DEBUG)
267           tc_log_msg(__FILE__, "x/t%d: %d written", stream->sno, i);
268       }
269       break;
270     case 'a':
271       switch (stream->acodec) {
272         case ACVORBIS:
273           if (xraw) {
274             if (stream->packetno == 0) {
275               i = tc_pwrite(stream->fd, (char *)pack->packet, pack->bytes);
276               if (i != pack->bytes) {
277                 tc_log_error(__FILE__, "error while writing data");
278                 import_exit(1); /* XXX ugly */
279               }
280             } else {
281               i = tc_pwrite(stream->fd, (char *)&pack->packet[1],
282                         pack->bytes - 1);
283               if (i != pack->bytes - 1) {
284                 tc_log_error(__FILE__, "error while writing data");
285                 import_exit(1); /* XXX ugly */
286               }
287             }
288             if (verbose_flag & TC_DEBUG)
289               tc_log_msg(__FILE__, "x/a%d: %d written", stream->sno, i);
290             return;
291           }
292           stream->max_granulepos = (pack->granulepos > stream->max_granulepos ?
293                                     pack->granulepos : stream->max_granulepos);
294           if ((stream->packetno == 0) || (stream->packetno == 2)) {
295             ogg_stream_packetin(&stream->outstate, pack);
296             flush_pages(stream, pack);
297           } else {
298             ogg_stream_packetin(&stream->outstate, pack);
299             write_pages(stream, pack);
300           }
301           stream->packetno++;
302           break;
303         default:
304           if (((*pack->packet & 3) == OGM_PACKET_TYPE_HEADER) ||
305               ((*pack->packet & 3) == OGM_PACKET_TYPE_COMMENT))
306             return;
307 
308           i = tc_pwrite(stream->fd, pack->packet + 1 + hdrlen,
309                         pack->bytes - 1 - hdrlen);
310           if (i != pack->bytes - 1 - hdrlen) {
311             tc_log_error(__FILE__, "error while writing data");
312             import_exit(1); /* XXX ugly */
313           }
314           stream->bwritten += i;
315           if (verbose_flag & TC_DEBUG)
316             tc_log_msg(__FILE__, "x/a%d: %d written", stream->sno, i);
317           break;
318       }
319     break;
320   }
321 }
322 
process_ogm(int fdin,int fdout)323 static void process_ogm(int fdin, int fdout)
324 {
325   ogg_sync_state    sync;
326   ogg_page          page;
327   ogg_packet        pack;
328   vorbis_info       vi;
329   vorbis_comment    vc;
330   char             *buf, *new_name;
331   int               nread, np, sno;
332   int               endofstream = 0;
333   stream_t         *stream = NULL;
334 
335   ogg_sync_init(&sync);
336   while (1) {
337     np = ogg_sync_pageseek(&sync, &page);
338     if (np < 0) {
339       tc_log_error(__FILE__, "ogg_sync_pageseek failed");
340       return;
341     }
342     if (np == 0) {
343       buf = ogg_sync_buffer(&sync, BLOCK_SIZE);
344       if (!buf) {
345         tc_log_error(__FILE__, "ogg_sync_buffer failed");
346         return;
347       }
348       if ((nread = read(fdin, buf, BLOCK_SIZE)) <= 0) {
349         if (verbose_flag & TC_INFO)
350           tc_log_info(__FILE__, "end of stream 1");
351         return;
352       }
353       ogg_sync_wrote(&sync, nread);
354       continue;
355     }
356 
357     if (!ogg_page_bos(&page)) {
358       break;
359     } else {
360       ogg_stream_state sstate;
361       sno = ogg_page_serialno(&page);
362       if (ogg_stream_init(&sstate, sno)) {
363         tc_log_error(__FILE__, "ogg_stream_init failed");
364         return;
365       }
366       ogg_stream_pagein(&sstate, &page);
367       ogg_stream_packetout(&sstate, &pack);
368 
369       if ((pack.bytes >= 7) && ! strncmp(&pack.packet[1], "vorbis", 6)) {
370 
371         stream = tc_malloc(sizeof(stream_t));
372         if (stream == NULL) {
373           tc_log_error(__FILE__, "malloc failed.");
374           exit(1);
375         }
376 
377         memset(stream, 0, sizeof(stream_t));
378         if (verbose_flag & TC_INFO) {
379           vorbis_info_init(&vi);
380           vorbis_comment_init(&vc);
381           if (vorbis_synthesis_headerin(&vi, &vc, &pack) >= 0) {
382             tc_log_info(__FILE__, "(a%d/%d) Vorbis audio (channels %d "
383                         "rate %ld)", nastreams + 1, numstreams + 1,
384                         vi.channels, vi.rate);
385             stream->sample_rate = vi.rate;
386           } else
387             tc_log_warn(__FILE__, "(a%d/%d) Vorbis audio stream indicated "
388                         "but no Vorbis stream header found.",
389                         nastreams + 1, numstreams + 1);
390         }
391         stream->serial = sno;
392         stream->acodec = ACVORBIS;
393         stream->sample_rate = -1;
394         stream->sno = nastreams + 1;
395         stream->stype = 'a';
396         ac_memcpy(&stream->instate, &sstate, sizeof(sstate));
397         if (extraction_requested(xaudio, nastreams + 1, NOAUDIO)) {
398 	  stream->fd = fdout;
399           if (stream->fd == -1) {
400             tc_log_error(__FILE__, "Failed to create \"%s\" (%d, %s).",
401                          "new_name", errno, strerror(errno));
402             exit(1);
403           }
404           if (!xraw)
405             ogg_stream_init(&stream->outstate, rand());
406           if (verbose_flag & TC_INFO)
407             tc_log_info(__FILE__, "Extracting a%d to \"%s\".",
408                         nastreams + 1, "new_name");
409           do
410             handle_packet(stream, &pack, &page);
411           while (ogg_stream_packetout(&stream->instate, &pack) == 1);
412         }
413         add_stream(stream);
414         nastreams++;
415         numstreams++;
416       } else if ((pack.bytes >= 142) &&
417                  !strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",
418                           35) ) {
419         if ((*(int32_t*)(pack.packet+96) == 0x05589f80) &&
420             (pack.bytes >= 184)) {
421           tc_log_warn(__FILE__, "(v%d/%d) Found old video header. Not "
422                       "supported.", nvstreams + 1, numstreams + 1);
423         } else if (*(int32_t*)pack.packet+96 == 0x05589F81) {
424           tc_log_warn(__FILE__, "(a%d/%d) Found old audio header. Not "
425                       "supported.", nastreams + 1, numstreams + 1);
426         } else {
427           if (verbose_flag & TC_INFO)
428             tc_log_warn(__FILE__, "OGG stream %d has an old header with an "
429                         "unknown type.", numstreams + 1);
430         }
431       }  else if (((*pack.packet & OGM_PACKET_TYPE_BITS ) == OGM_PACKET_TYPE_HEADER) &&
432 	          (pack.bytes >= (int)(sizeof(ogm_stream_header) + 1 - sizeof(int)))) {
433         ogm_stream_header *sth = (ogm_stream_header *)(pack.packet + 1);
434         if (!strncmp(sth->streamtype, "video", 5)) {
435           unsigned long codec;
436           char ccodec[5];
437           strncpy(ccodec, sth->subtype, 4);
438           ccodec[4] = 0;
439           codec = (sth->subtype[0] << 24) +
440             (sth->subtype[1] << 16) + (sth->subtype[2] << 8) + sth->subtype[3];
441           if (verbose_flag & TC_INFO)
442             tc_log_info(__FILE__, "(v%d/%d) fps: %.3f width height: %dx%d "
443                         "codec: %p (%s)", nvstreams + 1, numstreams + 1,
444                         (double)10000000 / (double)sth->time_unit,
445                         sth->sh.video.width, sth->sh.video.height,
446                         (void *)codec, ccodec);
447           stream = tc_malloc(sizeof(stream_t));
448           if (stream == NULL) {
449             tc_log_error(__FILE__, "malloc failed.");
450             exit(1);
451           }
452           stream->stype = 'v';
453           stream->serial = sno;
454           stream->sample_rate = (double)10000000 / (double)sth->time_unit;
455           stream->sno = nvstreams + 1;
456           ac_memcpy(&stream->instate, &sstate, sizeof(sstate));
457           if (extraction_requested(xvideo, nvstreams + 1, NOVIDEO)) {
458 	    stream->fd = fdout;
459 
460             if (verbose_flag & TC_INFO)
461               tc_log_info(__FILE__, "Extracting v%d to \"%s\".",
462                           nvstreams + 1, "new_name");
463             do {
464               handle_packet(stream, &pack, &page);
465 	    } while (ogg_stream_packetout(&stream->instate, &pack) == 1);
466           }
467           add_stream(stream);
468           nvstreams++;
469           numstreams++;
470         } else if (!strncmp(sth->streamtype, "audio", 5)) {
471           int codec;
472           char buf[5];
473           ac_memcpy(buf, sth->subtype, 4);
474           buf[4] = 0;
475           codec = strtoul(buf, NULL, 16);
476           if (verbose_flag & TC_INFO) {
477             tc_log_info(__FILE__, "(a%d/%d) codec: %d (0x%04x) (%s), bits per "
478                         "sample: %d channels: %hd  samples per second: %lld "
479                         " avgbytespersec: %hd blockalign: %d",
480                         nastreams + 1, numstreams + 1, codec, codec,
481                         codec == ACPCM ? "PCM" : codec == 55 ? "MP3" :
482                         codec == ACMP3 ? "MP3" :
483                         codec == ACAC3 ? "AC3" : "unknown",
484                         sth->bits_per_sample, sth->sh.audio.channels,
485                         (long long)sth->samples_per_unit,
486                         sth->sh.audio.avgbytespersec, sth->sh.audio.blockalign);
487           }
488           stream = tc_malloc(sizeof(stream_t));
489           if (stream == NULL) {
490             tc_log_error(__FILE__, "malloc failed.");
491             exit(1);
492           }
493           stream->sno = nastreams + 1;
494           stream->stype = 'a';
495           stream->sample_rate = sth->samples_per_unit *
496                                 sth->sh.audio.channels;
497           stream->serial = sno;
498           stream->acodec = codec;
499           ac_memcpy(&stream->instate, &sstate, sizeof(sstate));
500           if (extraction_requested(xaudio, nastreams + 1, NOAUDIO)) {
501 
502 	    /*
503                       codec == ACPCM ? "wav" :
504                       codec == ACMP3 ? "mp3" :
505                       codec == ACAC3 ? "ac3" : "audio");
506 		      */
507             stream->fd = fdout;
508             if (verbose_flag & TC_INFO)
509               tc_log_info(__FILE__, "Extracting a%d to \"%s\".",
510                           nastreams + 1, "new_name");
511             do {
512               handle_packet(stream, &pack, &page);
513 	    } while (ogg_stream_packetout(&stream->instate, &pack) == 1);
514           }
515           add_stream(stream);
516           nastreams++;
517           numstreams++;
518         } else if (!strncmp(sth->streamtype, "text", 4)) {
519           if (verbose_flag & TC_INFO)
520             tc_log_info(__FILE__, "(t%d/%d) text/subtitle stream",
521                         ntstreams + 1, numstreams + 1);
522           stream = tc_malloc(sizeof(stream_t));
523           if (stream == NULL) {
524             tc_log_error(__FILE__, "malloc failed.");
525             exit(1);
526           }
527           stream->sno = ntstreams + 1;
528           stream->stype = 't';
529           stream->sample_rate = (double)10000000 / (double)sth->time_unit;
530           stream->serial = sno;
531           ac_memcpy(&stream->instate, &sstate, sizeof(sstate));
532           if (extraction_requested(xtext, ntstreams + 1, NOTEXT)) {
533             new_name = tc_malloc(strlen(basename) + 20);
534             if (!new_name) {
535               tc_log_error(__FILE__, "Failed to allocate %d bytes.",
536                            (int)strlen(basename) + 20);
537               exit(1);
538             }
539             if (!xraw)
540               tc_snprintf(new_name, strlen(basename) + 20, "%s-t%d.srt", basename, ntstreams + 1);
541             else
542               tc_snprintf(new_name, strlen(basename) + 20, "%s-t%d.raw", basename, ntstreams + 1);
543             //stream->fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC,
544             //                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
545             stream->fd = fdout;
546             if (stream->fd == -1) {
547               tc_log_error(__FILE__, "Failed to create \"%s\" (%d, %s).",
548                            new_name, errno, strerror(errno));
549               exit(1);
550             }
551             if (verbose_flag & TC_INFO)
552               tc_log_info(__FILE__, "Extracting t%d to \"%s\".",
553                           ntstreams + 1, new_name);
554             do
555               handle_packet(stream, &pack, &page);
556             while (ogg_stream_packetout(&stream->instate, &pack) == 1);
557           }
558           add_stream(stream);
559           ntstreams++;
560           numstreams++;
561         } else {
562           tc_log_warn(__FILE__, "(%d) found new header of unknown/"
563                       "unsupported type\n", numstreams + 1);
564         }
565 
566       } else {
567 	tc_log_warn(__FILE__, "OGG stream %d is of an unknown type "
568                     "(bad header?)\n", numstreams + 1);
569       }
570     }
571   }
572 
573   endofstream = 0;
574   while (!endofstream) {
575     sno = ogg_page_serialno(&page);
576     stream = find_stream(sno);
577     if (stream == NULL) {
578       if (verbose_flag & TC_DEBUG)
579         tc_log_warn(__FILE__, "Encountered packet for an unknown serial "
580                     "%d !?\n", sno);
581     } else {
582       if (verbose_flag & TC_DEBUG)
583         tc_log_msg(__FILE__, "%c%d: NEW PAGE", stream->stype, stream->sno);
584 
585       ogg_stream_pagein(&stream->instate, &page);
586       while (ogg_stream_packetout(&stream->instate, &pack) == 1)
587         handle_packet(stream, &pack, &page);
588     }
589 
590     while (ogg_sync_pageseek(&sync, &page) <= 0) {
591       buf = ogg_sync_buffer(&sync, BLOCK_SIZE);
592       nread = read(fdin, buf, BLOCK_SIZE);
593       if (nread <= 0) {
594         stream = first;
595         while (stream != NULL) {
596           switch (stream->stype) {
597             case 'v':
598 	      close(stream->fd);
599               break;
600             case 't':
601               if (stream->fd > 0)
602                 close(stream->fd);
603               break;
604             case 'a':
605               if ((stream->fd > 0) && !xraw) {
606                 switch (stream->acodec) {
607                   case ACVORBIS:
608                     if (!stream->eos) {
609                       pack.b_o_s = 0;
610                       pack.e_o_s = 1;
611                       pack.packet = NULL;
612                       pack.bytes = 0;
613                       pack.granulepos = stream->max_granulepos;
614                       pack.packetno = stream->packetno;
615                       ogg_stream_packetin(&stream->outstate, &pack);
616                     }
617                     flush_pages(stream, &pack);
618                     ogg_stream_clear(&stream->outstate);
619                     break;
620                 }
621                 close(stream->fd);
622               } else if (stream->fd > 0)
623                 close(stream->fd);
624               break;
625           }
626           stream = stream->next;
627         }
628         if (verbose_flag & TC_INFO)
629           tc_log_info(__FILE__, "end of stream");
630         endofstream = 1;
631         break;
632       } else
633         ogg_sync_wrote(&sync, nread);
634     }
635   }
636 }
637 #endif /* have OGG */
638 
extract_ogm(info_t * ipipe)639 void extract_ogm (info_t *ipipe)
640 {
641   // track
642 
643   no[NOTEXT]  = 1;
644   no[NOAUDIO] = 0;
645   no[NOVIDEO] = 0;
646   xraw = 1;
647 
648   xvideo = tc_zalloc (16); xaudio = tc_zalloc (16); xtext = tc_zalloc (16);
649 
650   verbose_flag = ipipe->verbose;
651 
652   if (ipipe->select == TC_VIDEO) {
653 
654     no[NOAUDIO] = 1;
655     xvideo[0] = (unsigned char)(ipipe->track+1);
656 
657   }
658 
659   if (ipipe->select == TC_AUDIO) {
660 
661     no[NOVIDEO] = 1;
662     xaudio[0] = (unsigned char)(ipipe->track+1);
663 
664     // we need !xraw because no tool seems to be able to handle
665     // raw vorbis streams -- tibit
666 
667     if (ipipe->codec == TC_CODEC_VORBIS) {
668       xraw = 0;
669     }
670 
671   }
672 
673 #if (HAVE_OGG && HAVE_VORBIS)
674   process_ogm(ipipe->fd_in, ipipe->fd_out);
675 #else
676   tc_log_error(__FILE__, "No support for Ogg/Vorbis compiled in");
677   import_exit(1);
678 #endif
679 }
680 
681 
682 
683 /* vim: sw=2
684  */
685