ogg.cpp
上传用户:chn_coc
上传日期:2007-12-20
资源大小:563k
文件大小:11k
源码类别:

P2P编程

开发平台:

Windows_Unix

  1. // ------------------------------------------------
  2. // File : mp3.cpp
  3. // Date: 28-may-2003
  4. // Author: giles
  5. //
  6. // (c) 2002-3 peercast.org
  7. // ------------------------------------------------
  8. // This program is free software; you can redistribute it and/or modify
  9. // it under the terms of the GNU General Public License as published by
  10. // the Free Software Foundation; either version 2 of the License, or
  11. // (at your option) any later version.
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. // GNU General Public License for more details.
  16. // ------------------------------------------------
  17. #include "channel.h"
  18. #include "ogg.h"
  19. static int test=0;
  20. // ------------------------------------------
  21. void OGGStream::readHeader(Stream &,Channel *)
  22. {
  23. test = 0;
  24. }
  25. // ------------------------------------------
  26. void OGGStream::readEnd(Stream &,Channel *)
  27. {
  28. }
  29. // ------------------------------------------
  30. int OGGStream::readPacket(Stream &in,Channel *ch)
  31. {
  32. OggPage ogg;
  33. ChanPacket pack;
  34. ogg.read(in);
  35. if (ogg.isBOS())
  36. {
  37. if (!vorbis.needHeader() && !theora.needHeader())
  38. {
  39. ch->headPack.len = 0;
  40. }
  41. if (ogg.detectVorbis())
  42. vorbis.bos(ogg.getSerialNo());
  43. if (ogg.detectTheora())
  44. theora.bos(ogg.getSerialNo());
  45. }
  46. if (ogg.isEOS())
  47. {
  48. if (ogg.getSerialNo() == vorbis.serialNo)
  49. {
  50. LOG_CHANNEL("Vorbis stream: EOS");
  51. vorbis.eos();
  52. }
  53. if (ogg.getSerialNo() == theora.serialNo)
  54. {
  55. LOG_CHANNEL("Theora stream: EOS");
  56. theora.eos();
  57. }
  58. }
  59. if (vorbis.needHeader() || theora.needHeader())
  60. {
  61. if (ogg.getSerialNo() == vorbis.serialNo)
  62. vorbis.readHeader(ch,ogg);
  63. else if (ogg.getSerialNo() == theora.serialNo)
  64. theora.readHeader(ch,ogg);
  65. else
  66. throw StreamException("Bad OGG serial no.");
  67. if (!vorbis.needHeader() && !theora.needHeader())
  68. {
  69. ch->info.bitrate = 0;
  70. if (vorbis.isActive())
  71. ch->info.bitrate += vorbis.bitrate;
  72. if (theora.isActive())
  73. {
  74. ch->info.bitrate += theora.bitrate;
  75. ch->info.contentType = ChanInfo::T_OGM;
  76. }
  77. ch->headPack.type = ChanPacket::T_HEAD;
  78. ch->headPack.pos = ch->streamPos;
  79. ch->startTime = sys->getDTime();
  80. ch->streamPos += ch->headPack.len;
  81. ch->newPacket(ch->headPack);
  82. LOG_CHANNEL("Got %d bytes of headers",ch->headPack.len);
  83. }
  84. }else
  85. {
  86. pack.init(ChanPacket::T_DATA,ogg.data,ogg.headLen+ogg.bodyLen,ch->streamPos);
  87. ch->newPacket(pack);
  88. ch->streamPos+=pack.len;
  89. if (theora.isActive())
  90. {
  91. if (ogg.getSerialNo() == theora.serialNo)
  92. {
  93. ch->sleepUntil(theora.getTime(ogg));
  94. }
  95. }else if (vorbis.isActive())
  96. {
  97. if (ogg.getSerialNo() == vorbis.serialNo)
  98. {
  99. ch->sleepUntil(vorbis.getTime(ogg));
  100. }
  101. }
  102. }
  103. return 0;
  104. }
  105. // -----------------------------------
  106. void OggSubStream::readHeader(Channel *ch,OggPage &ogg)
  107. {
  108. if ((pack.bodyLen + ogg.bodyLen) >= OggPacket::MAX_BODYLEN)
  109. throw StreamException("OGG packet too big");
  110. if (ch->headPack.len+(ogg.bodyLen+ogg.headLen) >= ChanMeta::MAX_DATALEN)
  111. throw StreamException("OGG packet too big for headMeta");
  112. // copy complete packet into head packet
  113. memcpy(&ch->headPack.data[ch->headPack.len],ogg.data,ogg.headLen+ogg.bodyLen);
  114. ch->headPack.len += ogg.headLen+ogg.bodyLen;
  115. // add body to packet
  116. memcpy(&pack.body[pack.bodyLen],&ogg.data[ogg.headLen],ogg.bodyLen);
  117. pack.bodyLen += ogg.bodyLen;
  118. pack.addLacing(ogg);
  119. if (pack.numPackets >= maxHeaders)
  120. procHeaders(ch);
  121. }
  122. // -----------------------------------
  123. void OggVorbisSubStream::procHeaders(Channel *ch)
  124. {
  125. unsigned int packPtr=0;
  126. for(int i=0; i<pack.numPackets; i++)
  127. {
  128. MemoryStream vin(&pack.body[packPtr],pack.packetSizes[i]);
  129. packPtr += pack.packetSizes[i];
  130. char id[8];
  131. vin.read(id,7);
  132. id[7]=0;
  133. switch (id[0])
  134. {
  135. case 1: // ident
  136. LOG_CHANNEL("OGG Vorbis Header: Ident (%d bytes)",vin.len);
  137. readIdent(vin,ch->info);
  138. break;
  139. case 3: // comment
  140. {
  141. LOG_CHANNEL("OGG Vorbis Header: Comment (%d bytes)",vin.len);
  142. ChanInfo newInfo = ch->info;
  143. readComment(vin,newInfo);
  144. ch->updateInfo(newInfo);
  145. }
  146. break;
  147. case 5: // setup
  148. LOG_CHANNEL("OGG Vorbis Header: Setup (%d bytes)",vin.len);
  149. //readSetup(vin);
  150. break;
  151. default:
  152. throw StreamException("Unknown Vorbis packet header type");
  153. break;
  154. }
  155. }
  156. }
  157. // -----------------------------------
  158. double OggTheoraSubStream::getTime(OggPage &ogg)
  159. {
  160.     int64_t iframe=ogg.granPos>>granposShift;
  161.     int64_t pframe=ogg.granPos-(iframe<<granposShift);
  162.     return (iframe+pframe)*frameTime;
  163. }
  164. // -----------------------------------
  165. void OggTheoraSubStream::readInfo(Stream &in, ChanInfo &info)
  166. {
  167. int verMaj = in.readBits(8);
  168. int verMin = in.readBits(8);
  169. int verSub = in.readBits(8);
  170. int encWidth = in.readBits(16) << 4;
  171. int encHeight = in.readBits(16) << 4;
  172. in.readBits(24+24+8+8);
  173. int fpsNum = in.readBits(32);
  174. int fpsDen = in.readBits(32);
  175. float fps = (float)fpsNum/(float)fpsDen;
  176. frameTime = (double)fpsDen/(double)fpsNum;
  177. in.readBits(24+24+8);
  178. bitrate = in.readBits(24) / 1000;
  179. int quality = in.readBits(6);
  180. granposShift = in.readBits(5);
  181. LOG_CHANNEL("OGG Theora Info: %dx%dx%.1ffps %dkbps %dQ %dG",encWidth,encHeight,fps,bitrate,quality,granposShift);
  182. }
  183. // -----------------------------------
  184. void OggTheoraSubStream::procHeaders(Channel *ch)
  185. {
  186. unsigned int packPtr=0;
  187. for(int i=0; i<pack.numPackets; i++)
  188. {
  189. MemoryStream vin(&pack.body[packPtr],pack.packetSizes[i]);
  190. packPtr += pack.packetSizes[i];
  191. unsigned char id[8];
  192. vin.read(id,7);
  193. id[7]=0;
  194. switch (id[0] & 0xff)
  195. {
  196. case 128: // info
  197. LOG_CHANNEL("OGG Theora Header: Info (%d bytes)",vin.len);
  198. readInfo(vin,ch->info);
  199. break;
  200. default:
  201. LOG_CHANNEL("OGG Theora Header: Unknown %d (%d bytes)",id[0] & 0xff,vin.len);
  202. break;
  203. }
  204. }
  205. }
  206. // -----------------------------------
  207. double OggVorbisSubStream::getTime(OggPage &ogg)
  208. {
  209. return (double)ogg.granPos / (double)samplerate;
  210. }
  211. // -----------------------------------
  212. void OggVorbisSubStream::readIdent(Stream &in, ChanInfo &info)
  213. {
  214. int ver = in.readLong();
  215. int chans = in.readChar();
  216. samplerate = in.readLong();
  217. int brMax = in.readLong();
  218. int brNom = in.readLong();
  219. int brLow = in.readLong();
  220. in.readChar(); // skip blocksize 0+1
  221. LOG_CHANNEL("OGG Vorbis Ident: ver=%d, chans=%d, rate=%d, brMax=%d, brNom=%d, brLow=%d",
  222. ver,chans,samplerate,brMax,brNom,brLow);
  223. bitrate = brNom/1000;
  224. char frame = in.readChar(); // framing bit
  225. if (!frame)
  226. throw StreamException("Bad Indent frame");
  227. }
  228.  
  229. // -----------------------------------
  230. void OggVorbisSubStream::readSetup(Stream &in)
  231. {
  232. // skip everything in packet
  233. int cnt=0;
  234. while (!in.eof())
  235. {
  236. cnt++;
  237. in.readChar();
  238. }
  239. LOG_CHANNEL("Read %d bytes of Vorbis Setup",cnt);
  240. }
  241. // -----------------------------------
  242. void OggVorbisSubStream::readComment(Stream &in, ChanInfo &info)
  243. {
  244. int vLen = in.readLong(); // vendor len
  245. in.skip(vLen);
  246. char argBuf[8192];
  247. info.track.clear();
  248. int cLen = in.readLong(); // comment len
  249. for(int i=0; i<cLen; i++)
  250. {
  251. int l = in.readLong();
  252. if (l > sizeof(argBuf))
  253. throw StreamException("Comment string too long");
  254. in.read(argBuf,l);
  255. argBuf[l] = 0;
  256. LOG_CHANNEL("OGG Comment: %s",argBuf);
  257. char *arg;
  258. if ((arg=stristr(argBuf,"ARTIST=")))
  259. {
  260. info.track.artist.set(arg+7,String::T_ASCII);
  261. info.track.artist.convertTo(String::T_UNICODE);
  262. }else if ((arg=stristr(argBuf,"TITLE=")))
  263. {
  264. info.track.title.set(arg+6,String::T_ASCII);
  265. info.track.title.convertTo(String::T_UNICODE);
  266. }else if ((arg=stristr(argBuf,"GENRE=")))
  267. {
  268. info.track.genre.set(arg+6,String::T_ASCII);
  269. info.track.genre.convertTo(String::T_UNICODE);
  270. }else if ((arg=stristr(argBuf,"CONTACT=")))
  271. {
  272. info.track.contact.set(arg+8,String::T_ASCII);
  273. info.track.contact.convertTo(String::T_UNICODE);
  274. }else if ((arg=stristr(argBuf,"ALBUM=")))
  275. {
  276. info.track.album.set(arg+6,String::T_ASCII);
  277. info.track.album.convertTo(String::T_UNICODE);
  278. }
  279. }
  280. char frame = in.readChar(); // framing bit
  281. if (!frame)
  282. throw StreamException("Bad Comment frame");
  283. // updateMeta();
  284. }
  285. // -----------------------------------
  286. bool OggPage::isBOS()
  287. {
  288. return (data[5] & 0x02) != 0;
  289. }
  290. // -----------------------------------
  291. bool OggPage::isEOS()
  292. {
  293. return (data[5] & 0x04) != 0;
  294. }
  295. // -----------------------------------
  296. bool OggPage::isNewPacket()
  297. {
  298. return (data[5] & 0x01) == 0;
  299. }
  300. // -----------------------------------
  301. bool OggPage::isHeader()
  302. {
  303. return ((*(unsigned int *)&data[6]) || (*(unsigned int *)&data[10])) == 0;
  304. }
  305. // -----------------------------------
  306. unsigned int OggPage::getSerialNo()
  307. {
  308. return *(unsigned int *)&data[14];
  309. }
  310. // -----------------------------------
  311. void OggPage::read(Stream &in)
  312. {
  313. // skip until we get OGG capture pattern
  314. bool gotOgg=false;
  315. while (!gotOgg)
  316. {
  317. if (in.readChar() == 'O')
  318. if (in.readChar() == 'g')
  319. if (in.readChar() == 'g')
  320. if (in.readChar() == 'S')
  321. gotOgg = true;
  322. if (!gotOgg)
  323. LOG_CHANNEL("Skipping OGG packet");
  324. }
  325. memcpy(&data[0],"OggS",4);
  326. in.read(&data[4],27-4);
  327. int numSegs = data[26];
  328. bodyLen = 0;
  329. // read segment table
  330. in.read(&data[27],numSegs);
  331. for(int i=0; i<numSegs; i++)
  332. bodyLen += data[27+i];
  333. if (bodyLen >= MAX_BODYLEN)
  334. throw StreamException("OGG body too big");
  335. headLen = 27+numSegs;
  336. if (headLen > MAX_HEADERLEN)
  337. throw StreamException("OGG header too big");
  338. in.read(&data[headLen],bodyLen);
  339. granPos = *(unsigned int *)&data[10];
  340. granPos <<= 32;
  341. granPos |= *(unsigned int *)&data[6];
  342. #if 0
  343. LOG_DEBUG("OGG Packet - page %d, id = %x - %s %s %s - %d:%d - %d segs, %d bytes",
  344. *(unsigned int *)&data[18],
  345. *(unsigned int *)&data[14],
  346. data[5]&0x1?"cont":"new",
  347. data[5]&0x2?"bos":"",
  348. data[5]&0x4?"eos":"",
  349. (unsigned int)(granPos>>32),
  350. (unsigned int)(granPos&0xffffffff),
  351. numSegs,
  352. headLen+bodyLen);
  353. #endif
  354. }
  355. // -----------------------------------
  356. bool OggPage::detectVorbis()
  357. {
  358. return memcmp(&data[headLen+1],"vorbis",6) == 0;
  359. }
  360. // -----------------------------------
  361. bool OggPage::detectTheora()
  362. {
  363. return memcmp(&data[headLen+1],"theora",6) == 0;
  364. }
  365. // -----------------------------------
  366. void OggPacket::addLacing(OggPage &ogg)
  367. {
  368. int numSegs = ogg.data[26];
  369. for(int i=0; i<numSegs; i++)
  370. {
  371. int seg = ogg.data[27+i];
  372. packetSizes[numPackets]+=seg;
  373. if (seg < 255)
  374. {
  375. numPackets++;
  376. if (numPackets >= MAX_PACKETS)
  377. throw StreamException("Too many OGG packets");
  378. packetSizes[numPackets]=0;
  379. }
  380. }
  381. }