diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/probe_ogg.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/probe_ogg.c | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/probe_ogg.c b/debian/transcode/transcode-1.1.7/import/probe_ogg.c new file mode 100644 index 00000000..e3eb92a2 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/probe_ogg.c @@ -0,0 +1,337 @@ +/* + * probe_ogg.c + * + * Copyright (C) Tilmann Bitterberg, July 2002 + * Based heavily on code by Moritz Bunkus for ogminfo from + * http://www.bunkus.org/videotools/ogmtools/index.html + * + * This file is part of transcode, a video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "transcode.h" +#include "tcinfo.h" +#include "ioaux.h" +#include "tc.h" +#include "libtc/libtc.h" +#include "libtc/ratiocodes.h" + +#include <sys/mman.h> + +#if (HAVE_OGG && HAVE_VORBIS) + +#include <ogg/ogg.h> +#include <vorbis/codec.h> + +#ifdef HAVE_THEORA +#include <theora/theora.h> +#endif + +#include "ogmstreams.h" + +#define MAX_AUDIO_TRACKS 255 +#define MAX_VIDEO_TRACKS 255 +#define BLOCK_SIZE 4096 + +//#define OGM_DEBUG + +struct demux_t { + int serial; + int fd; + int vorbis; + ogg_stream_state state; +}; + +enum { none, Vorbis, Theora, DirectShow, StreamHeader }; + +static int ogm_packet_type (ogg_packet pack) +{ + if ((pack.bytes >= 7) && ! strncmp(&pack.packet[1], "vorbis", 6)) + return Vorbis; + else if ((pack.bytes >= 7) && ! strncmp(&pack.packet[1], "theora", 6)) + return Theora; + else if ((pack.bytes >= 142) && + !strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg", 35) ) + return DirectShow; + else if (((*pack.packet & OGM_PACKET_TYPE_BITS ) == OGM_PACKET_TYPE_HEADER) && + (pack.bytes >= (int)sizeof(ogm_stream_header) + 1)) + return StreamHeader; + + return none; +} + +void probe_ogg(info_t *ipipe) +{ + ogg_sync_state sync; + ogg_page page; + ogg_packet pack; + char *buf; + int nread, np, sno, nvtracks = 0, natracks = 0, i, idx; + //int endofstream = 0, k, n; + struct demux_t streams[MAX_AUDIO_TRACKS + MAX_VIDEO_TRACKS]; + int fdin = -1; + char vid_codec[5]; + ogm_stream_header *sth; + + fdin = ipipe->fd_in; + + if (fdin == -1) { + tc_log_error(__FILE__, "Could not open file."); + goto ogg_out; + } + + ipipe->probe_info->magic=TC_MAGIC_OGG; + + memset(streams, 0, sizeof(streams)); + for (i = 0; i < (MAX_AUDIO_TRACKS + MAX_VIDEO_TRACKS); i++) + streams[i].serial = -1; + + ogg_sync_init(&sync); + + while (1) { + np = ogg_sync_pageseek(&sync, &page); + if (np < 0) { + tc_log_error(__FILE__, "ogg_sync_pageseek failed"); + goto ogg_out; + } + if (np == 0) { + buf = ogg_sync_buffer(&sync, BLOCK_SIZE); + if (!buf) { + tc_log_error(__FILE__, "ogg_sync_buffer failed"); + goto ogg_out; + } + + if ((nread = read(fdin, buf, BLOCK_SIZE)) <= 0) { + } + ogg_sync_wrote(&sync, nread); + continue; + } + + if (!ogg_page_bos(&page)) { + break; + } else { + ogg_stream_state sstate; + vorbis_info *inf = tc_malloc (sizeof(vorbis_info)); + vorbis_comment *com = tc_malloc (sizeof(vorbis_comment)); + + if (!inf || !com) { + tc_log_error(__FILE__, "Out of Memory at %d", __LINE__); + goto ogg_out; + } + sno = ogg_page_serialno(&page); + if (ogg_stream_init(&sstate, sno)) { + tc_log_error(__FILE__, "ogg_stream_init failed"); + goto ogg_out; + } + ogg_stream_pagein(&sstate, &page); + ogg_stream_packetout(&sstate, &pack); + + switch (ogm_packet_type(pack)) + { + case Vorbis: + vorbis_info_init(inf); + vorbis_comment_init(com); + + if(vorbis_synthesis_headerin(inf, com, &pack) < 0) { + tc_log_warn(__FILE__, "Could not decode vorbis header " + "packet - invalid vorbis stream ()"); + } else { +#ifdef OGM_DEBUG + tc_log_msg(__FILE__, "(a%d/%d) Vorbis audio; " + "rate: %ldHz, channels: %d, bitrate %3.2f kb/s", + natracks + 1, natracks + nvtracks + 1, inf->rate, + inf->channels, (double)inf->bitrate_nominal/1000.0); +#endif + + ipipe->probe_info->track[natracks].samplerate = inf->rate; + ipipe->probe_info->track[natracks].chan = inf->channels; + ipipe->probe_info->track[natracks].bits = 0; /* XXX --tibit*/ + ipipe->probe_info->track[natracks].format = TC_CODEC_VORBIS; + ipipe->probe_info->track[natracks].bitrate = (double)inf->bitrate_nominal/1000.0; + + ipipe->probe_info->track[natracks].tid=natracks; + if(ipipe->probe_info->track[natracks].chan>0) ++ipipe->probe_info->num_tracks; + + streams[natracks].serial = sno; + streams[natracks].vorbis = 1; + ac_memcpy(&streams[natracks].state, &sstate, sizeof(sstate)); + natracks++; + } + break; +#ifdef HAVE_THEORA + case Theora: + { + theora_info ti; + theora_comment tc; + + theora_decode_header(&ti, &tc, &pack); + + ipipe->probe_info->width = ti.width; + ipipe->probe_info->height = ti.height; + ipipe->probe_info->fps = (double)ti.fps_numerator/ti.fps_denominator; + tc_frc_code_from_ratio(&(ipipe->probe_info->frc), + ti.fps_numerator, ti.fps_denominator); + + ipipe->probe_info->codec=TC_CODEC_THEORA; + + idx = natracks + MAX_AUDIO_TRACKS; + + streams[idx].serial = sno; + ac_memcpy(&streams[idx].state, &sstate, sizeof(sstate)); + nvtracks++; + break; + } +#endif + case DirectShow: + if ((*(int32_t*)(pack.packet+96) == 0x05589f80) && + (pack.bytes >= 184)) { + tc_log_warn(__FILE__, "(v%d/%d) Found old video " + "header. Not supported.", nvtracks + 1, + natracks + nvtracks + 1); + } else if (*(int32_t*)pack.packet+96 == 0x05589F81) { + tc_log_warn(__FILE__, "(a%d/%d) Found old audio " + "header. Not supported.", natracks + 1, + natracks + nvtracks + 1); + } + break; + case StreamHeader: + sth = (ogm_stream_header *)(pack.packet + 1); + + if (!strncmp(sth->streamtype, "video", 5)) { +#ifdef OGM_DEBUG + unsigned long codec; + codec = (sth->subtype[0] << 24) + + (sth->subtype[1] << 16) + (sth->subtype[2] << 8) + sth->subtype[3]; + tc_log_msg(__FILE__, "(v%d/%d) video; fps: %.3f width height: %dx%d " + "codec: %p (%c%c%c%c)", nvtracks + 1, + natracks + nvtracks + 1, + (double)10000000 / (double)sth->time_unit, + sth->sh.video.width, sth->sh.video.height, (void *)codec, + sth->subtype[0], sth->subtype[1], sth->subtype[2], + sth->subtype[3]); +#endif + vid_codec[0] = sth->subtype[0]; + vid_codec[1] = sth->subtype[1]; + vid_codec[2] = sth->subtype[2]; + vid_codec[3] = sth->subtype[3]; + vid_codec[4] = '\0'; + + //ipipe->probe_info->frames = AVI_video_frames(avifile); + + ipipe->probe_info->width = sth->sh.video.width; + ipipe->probe_info->height = sth->sh.video.height; + ipipe->probe_info->fps = (double)10000000 / (double)sth->time_unit; + tc_frc_code_from_value(&(ipipe->probe_info->frc), + ipipe->probe_info->fps); + + ipipe->probe_info->codec=TC_CODEC_UNKNOWN; // gets rewritten + + if(strlen(vid_codec)==0) { + ipipe->probe_info->codec=TC_CODEC_RGB; + } else { + + if(strcasecmp(vid_codec,"dvsd")==0) + ipipe->probe_info->codec=TC_CODEC_DV; + + if(strcasecmp(vid_codec,"DIV3")==0) + ipipe->probe_info->codec=TC_CODEC_DIVX3; + + if(strcasecmp(vid_codec,"DIVX")==0) + ipipe->probe_info->codec=TC_CODEC_DIVX4; + + if(strcasecmp(vid_codec,"DX50")==0) + ipipe->probe_info->codec=TC_CODEC_DIVX5; + + if(strcasecmp(vid_codec,"XVID")==0) + ipipe->probe_info->codec=TC_CODEC_XVID; + + if(strcasecmp(vid_codec,"MJPG")==0) + ipipe->probe_info->codec=TC_CODEC_MJPEG; + } + + idx = natracks + MAX_AUDIO_TRACKS; + + streams[idx].serial = sno; + ac_memcpy(&streams[idx].state, &sstate, sizeof(sstate)); + nvtracks++; + } else if (!strncmp(sth->streamtype, "audio", 5)) { + int codec; + char buf[5]; + ac_memcpy(buf, sth->subtype, 4); + buf[4] = 0; + codec = strtoul(buf, NULL, 16); +#ifdef OGM_DEBUG + tc_log_msg(__FILE__, "(a%d/%d) codec: %d (0x%04x) (%s) bits per " + "sample: %d channels: %hd samples per second: %ld " + "avgbytespersec: %hd blockalign: %d", + natracks + 1, natracks + nvtracks + 1, + codec, codec, + codec == 0x1 ? "PCM" : codec == 55 ? "MP3" : + codec == 0x55 ? "MP3" : + codec == 0x2000 ? "AC3" : "unknown", + sth->bits_per_sample, sth->sh.audio.channels, + (long)sth->samples_per_unit, + sth->sh.audio.avgbytespersec, + sth->sh.audio.blockalign); +#endif + idx = natracks; + + ipipe->probe_info->track[natracks].samplerate = sth->samples_per_unit; + ipipe->probe_info->track[natracks].chan = sth->sh.audio.channels; + ipipe->probe_info->track[natracks].bits = + (sth->bits_per_sample<4)?sth->bits_per_sample*8:sth->bits_per_sample; + ipipe->probe_info->track[natracks].format = codec; + ipipe->probe_info->track[natracks].bitrate = 0; + + ipipe->probe_info->track[natracks].tid=natracks; + + + if(ipipe->probe_info->track[natracks].chan>0) ++ipipe->probe_info->num_tracks; + + streams[idx].serial = sno; + ac_memcpy(&streams[idx].state, &sstate, sizeof(sstate)); + natracks++; + } else { + tc_log_warn(__FILE__, "(%d) found new header of unknown/" + "unsupported type\n", nvtracks + natracks + 1); + } + break; + case none: + tc_log_warn(__FILE__, "OGG stream %d is of an unknown type " + "(bad header?)", nvtracks + natracks + 1); + break; + } /* switch type */ + free(inf); + free(com); + ogg_stream_clear(&sstate); + } /* beginning of page */ + } /* while (1) */ +ogg_out: + //close(fdin); + return; +} + +#else // (HAVE_OGG && HAVE_VORBIS) + +void probe_ogg(info_t *ipipe) +{ + tc_log_error(__FILE__, "No support for Ogg/Vorbis compiled in"); + ipipe->probe_info->codec=TC_CODEC_UNKNOWN; + ipipe->probe_info->magic=TC_MAGIC_UNKNOWN; +} + +#endif |
