ogg.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:24k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: ogg.c 543 2006-01-07 22:06:24Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common/common.h"
  24. #include "vorbis.h"
  25. #include "tremor/ogg.h"
  26. #include "tremor/ivorbiscodec.h"
  27. // OGG and OGM file format
  28. #define PACKET_TYPE_HEADER 0x01
  29. #define PACKET_TYPE_COMMENT 0x03
  30. #define PACKET_TYPE_CODEBOOK 0x05
  31. #define PACKET_TYPE_BITS 0x07
  32. #define PACKET_IS_SYNCPOINT 0x08
  33. #define PACKET_LEN_BITS01 0xc0
  34. #define PACKET_LEN_BITS2 0x02
  35. static const char MT_Video[] = "video";
  36. static const char MT_Audio[] = "audio";
  37. static const char MT_Text[] = "text";
  38. typedef struct oggstream
  39. {
  40. format_stream Stream;
  41. bool_t Invalid; // not vorbis and not ogm
  42. bool_t Vorbis; // sending direct oggpackets (not the merged binary data)
  43. bool_t Native; // speex
  44. int PacketNo;
  45. int64_t MediaTime; // in units
  46. int64_t MediaRateNum; // in units/tick
  47. int64_t MediaRateDen;
  48. int DefaultLen;
  49. bool_t NeedMorePage;
  50. ogg_stream_state* OggStream;
  51. ogg_packet       OggPacket;
  52. vorbis_info      Info;
  53. vorbis_comment   Comment;
  54. } oggstream;
  55. typedef struct ogg
  56. {
  57. format_base Format;
  58. ogg_sync_state* OggSync;
  59. ogg_page        OggPage;
  60. } ogg;
  61. typedef struct ogm_header_video
  62. {
  63. int32_t width;
  64. int32_t height;
  65. } ogm_header_video;
  66. typedef struct ogm_header_audio
  67. {
  68. int16_t channels;
  69. int16_t blockalign;
  70. int32_t avgbytespersec;
  71. } ogm_header_audio;
  72. typedef struct ogm_header
  73. {
  74. char streamtype[8];
  75. char subtype[4];
  76. int32_t size;
  77. int64_t time_unit;
  78. int64_t samples_per_unit;
  79. int32_t default_len;
  80. int32_t buffersize;
  81. int16_t bits_per_sample;
  82. union
  83. {
  84. ogm_header_video video;
  85. ogm_header_audio audio;
  86. } format;
  87. } ogm_header;
  88. extern int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb,int eop);
  89. static void FreeStream(ogg* p,oggstream* Stream)
  90. {
  91. vorbis_comment_clear(&Stream->Comment);
  92. vorbis_info_clear(&Stream->Info);
  93. ogg_packet_release(&Stream->OggPacket);
  94. if (Stream->OggStream)
  95. {
  96. ogg_stream_destroy(Stream->OggStream);
  97. Stream->OggStream = NULL;
  98. }
  99. }
  100. static void Done(ogg* p)
  101. {
  102. ogg_page_release(&p->OggPage);
  103. if (p->OggSync)
  104. {
  105. ogg_sync_destroy(p->OggSync);
  106. p->OggSync = NULL;
  107. }
  108. }
  109. static int AddBuffer(ogg* p,format_buffer* Buffer)
  110. {
  111. if (!Buffer)
  112. return ERR_NEED_MORE_DATA;
  113. if (Buffer->Length)
  114. {
  115. ogg_buffer* Ptr = ogg_sync_bufferinext(p->OggSync);
  116. if (!Ptr)
  117. {
  118. Format_BufferRelease(&p->Format,Buffer);
  119. return ERR_OUT_OF_MEMORY;
  120. }
  121. Ptr->ext = &p->Format;
  122. Ptr->extdata = Buffer;
  123. Ptr->data = Buffer->Block.Ptr;
  124. Ptr->size = Buffer->Length;
  125. ogg_sync_wrote(p->OggSync,Buffer->Length);
  126. }
  127. else
  128. Format_BufferRelease(&p->Format,Buffer);
  129. return ERR_NONE;
  130. }
  131. static int Init(ogg* p)
  132. {
  133. format_reader* Reader = p->Format.Reader;
  134. format_buffer* Buffer;
  135. int i;
  136. memset(&p->OggPage,0,sizeof(ogg_page));
  137. p->OggSync = ogg_sync_create();
  138. p->Format.TimeStamps = 1;
  139. if (!p->OggSync)
  140. return ERR_OUT_OF_MEMORY;
  141. Format_ReadBuffer(Reader,0);
  142. Buffer = Format_BufferRemove(Reader);
  143. if (!Buffer)
  144. return ERR_INVALID_DATA;
  145. // search for 'OggS' pattern
  146. for (i=3;i<Buffer->Length;++i)
  147. if (Buffer->Block.Ptr[i-3]=='O' &&
  148. Buffer->Block.Ptr[i-2]=='g' &&
  149. Buffer->Block.Ptr[i-1]=='g' &&
  150. Buffer->Block.Ptr[i-0]=='S')
  151. break;
  152. if (i==Buffer->Length)
  153. {
  154. Format_BufferRelease(&p->Format,Buffer);
  155. return ERR_INVALID_DATA;
  156. }
  157. return AddBuffer(p,Buffer);
  158. }
  159. static void AfterSeek(ogg* p)
  160. {
  161. ogg_sync_reset(p->OggSync);
  162. }
  163. static void ReleaseStream(ogg* p,oggstream* Stream)
  164. {
  165. ogg_stream_reset_serialno(Stream->OggStream,Stream->Stream.Id);
  166. Stream->NeedMorePage = 1;
  167. Stream->MediaTime = Stream->Stream.Reader->FilePos>0 && Stream->PacketNo>3 ? -1:0;
  168. }
  169. extern void oggext_release(void* ext,void* ext2)
  170. {
  171. if (ext && ext2)
  172. Format_BufferRelease((format_base*)ext,(format_buffer*)ext2);
  173. }
  174. static int ReadPacketTime( ogg* p, format_reader* Reader, format_packet* Packet )
  175. {
  176. // only called by CalcDuration
  177. format_buffer* Buffer;
  178. int Bytes;
  179. ogg_buffer* Ptr;
  180. ogg_sync_state* Sync = ogg_sync_create();
  181. ogg_page Page;
  182. if (!Sync)
  183. return ERR_OUT_OF_MEMORY;
  184. while ((Buffer = Format_BufferRemove(Reader))!=NULL)
  185. {
  186. Ptr = ogg_sync_bufferinext(Sync);
  187. if (Ptr)
  188. {
  189. Ptr->ext = &p->Format;
  190. Ptr->extdata = Buffer;
  191. Ptr->data = Buffer->Block.Ptr;
  192. Ptr->size = Buffer->Length;
  193. ogg_sync_wrote(Sync,Buffer->Length);
  194. }
  195. else
  196. Format_BufferRelease(&p->Format,Buffer);
  197. }
  198. memset(&Page,0,sizeof(Page));
  199. while ((Bytes = ogg_sync_pageseek(Sync,&Page)) != 0)
  200. {
  201. if (Bytes > 0)
  202. {
  203. int64_t MediaTime = ogg_page_granulepos(&Page);
  204. int Id = ogg_page_serialno(&Page);
  205. int i;
  206. if (MediaTime != -1)
  207. for (i=0;i<p->Format.StreamCount;++i)
  208. if (p->Format.Streams[i]->Id == Id)
  209. {
  210. oggstream* s = (oggstream*) p->Format.Streams[i];
  211. if (s->MediaRateNum)
  212. {
  213. tick_t RefTime = (tick_t)((MediaTime * s->MediaRateDen) / s->MediaRateNum);
  214. if (RefTime > Packet->RefTime)
  215. {
  216. Packet->Stream = &s->Stream;
  217. Packet->RefTime = RefTime;
  218. }
  219. }
  220. break;
  221. }
  222. }
  223. }
  224. ogg_page_release(&Page);
  225. ogg_sync_destroy(Sync);
  226. return ERR_NONE;
  227. }
  228. static void FrameRate( fraction* f, int64_t Num, int64_t Den )
  229. {
  230. while (Num > MAX_INT || Den > MAX_INT)
  231. {
  232. Num >>= 1;
  233. Den >>= 1;
  234. }
  235. f->Num = (int)Num;
  236. f->Den = (int)Den;
  237. }
  238. static bool_t SpeexHeader(ogg* p, oggstream* s, const char* Data, int Length )
  239. {
  240. if (Length<80 && strncmp(Data,"Speex   ",8)!=0)
  241. return 0;
  242. PacketFormatClear(&s->Stream.Format);
  243. s->Stream.Format.Type = PACKET_AUDIO;
  244. s->Stream.Format.Format.Audio.Format = AUDIOFMT_SPEEX;
  245. s->Stream.Format.Format.Audio.Channels = INT32LE(*(int32_t*)(Data+48));
  246. s->Stream.Format.ByteRate = INT32LE(*(int32_t*)(Data+52))/8;
  247. s->Stream.Format.Format.Audio.SampleRate = INT32LE(*(int32_t*)(Data+36));
  248. s->MediaRateDen = TICKSPERSEC;
  249. s->MediaRateNum = s->Stream.Format.Format.Audio.SampleRate;
  250. s->Native = 1;
  251. if (PacketFormatExtra(&s->Stream.Format,Length))
  252. memcpy(s->Stream.Format.Extra,Data,s->Stream.Format.ExtraLength);
  253. return 1;
  254. }
  255. static bool_t OGMHeader(ogg* p, oggstream* s, const char* Data, int Length )
  256. {
  257. int i;
  258. if (Length<40 || (*Data & PACKET_TYPE_BITS) != PACKET_TYPE_HEADER)
  259. return 0;
  260. if (strncmp(Data+1, "Direct Show Samples embedded in Ogg", 35) == 0)
  261. {
  262. // old header
  263. if (INT32LE(*(int32_t*)(Data+96)) == 0x05589F80)
  264. {
  265. PacketFormatClear(&s->Stream.Format);
  266. s->Stream.Format.Type = PACKET_VIDEO;
  267. s->Stream.Format.Format.Video.Width = INT32LE(*(int32_t*)(Data+176));
  268. s->Stream.Format.Format.Video.Height = INT32LE(*(int32_t*)(Data+180));
  269. s->Stream.Format.Format.Video.Pixel.FourCC = INT32LE(*(int32_t*)(Data+68));
  270. s->Stream.Format.Format.Video.Pixel.BitCount = INT16LE(*(int16_t*)(Data+182));
  271. i = INT16LE(*(int16_t*)(Data+136)); // extrasize
  272. if (i && PacketFormatExtra(&s->Stream.Format,i))
  273. memcpy(s->Stream.Format.Extra,Data+142,s->Stream.Format.ExtraLength);
  274. s->MediaRateDen = INT64LE(*(int32_t*)(Data+164))*TICKSPERSEC;
  275. s->MediaRateNum = 10000000;
  276. s->DefaultLen = 1;
  277. FrameRate(&s->Stream.Format.PacketRate,s->MediaRateNum,s->MediaRateDen/TICKSPERSEC);
  278. return 1;
  279. }
  280. if (INT32LE(*(int32_t*)(Data+96)) == 0x05589F81)
  281. {
  282. PacketFormatClear(&s->Stream.Format);
  283. s->Stream.Format.Type = PACKET_AUDIO;
  284. s->Stream.Format.Format.Audio.Format = INT16LE(*(int16_t*)(Data+124));
  285. s->Stream.Format.Format.Audio.Channels = INT16LE(*(int16_t*)(Data+126));
  286. s->Stream.Format.Format.Audio.BlockAlign = INT16LE(*(int16_t*)(Data+136));
  287. s->Stream.Format.Format.Audio.Bits = INT16LE(*(int16_t*)(Data+138));
  288. s->Stream.Format.Format.Audio.SampleRate = INT32LE(*(int32_t*)(Data+128));
  289. s->Stream.Format.ByteRate = INT32LE(*(int32_t*)(p+132));
  290. i = INT16LE(*(int16_t*)(Data+136)); // extrasize
  291. if (i && PacketFormatExtra(&s->Stream.Format,i))
  292. memcpy(s->Stream.Format.Extra,Data+142,s->Stream.Format.ExtraLength);
  293. s->MediaRateDen = TICKSPERSEC;
  294. s->MediaRateNum = INT32LE(*(int32_t*)(Data+128));
  295. s->DefaultLen = 1;
  296. return 1;
  297. }
  298. }
  299. else
  300. if (Length >= sizeof(ogm_header)+1)
  301. {
  302. ogm_header Head;
  303. memcpy(&Head,Data+1,sizeof(Head));
  304. // new header
  305. if (strncmp(Head.streamtype, MT_Video, strlen(MT_Video)) == 0)
  306. {
  307. PacketFormatClear(&s->Stream.Format);
  308. s->Stream.Format.Type = PACKET_VIDEO;
  309. s->Stream.Format.Format.Video.Width = INT32LE(Head.format.video.width);
  310. s->Stream.Format.Format.Video.Height = INT32LE(Head.format.video.height);
  311. s->Stream.Format.Format.Video.Pixel.FourCC = INT32LE(*(int32_t*)Head.subtype);
  312. s->Stream.Format.Format.Video.Pixel.BitCount = INT16LE(Head.bits_per_sample);
  313. s->MediaRateDen = INT64LE(Head.time_unit)*TICKSPERSEC;
  314. s->MediaRateNum = INT64LE(Head.samples_per_unit) * 10000000;
  315. s->DefaultLen = INT32LE(Head.default_len);
  316. FrameRate(&s->Stream.Format.PacketRate,s->MediaRateNum,s->MediaRateDen/TICKSPERSEC);
  317. i = Length - (sizeof(ogm_header)+1);
  318. if (i && PacketFormatExtra(&s->Stream.Format,i))
  319. memcpy(s->Stream.Format.Extra,Data+1+sizeof(ogm_header),s->Stream.Format.ExtraLength);
  320. return 1;
  321. }
  322. if (strncmp(Head.streamtype, MT_Audio, strlen(MT_Audio)) == 0)
  323. {
  324. PacketFormatClear(&s->Stream.Format);
  325. s->Stream.Format.Type = PACKET_AUDIO;
  326. s->Stream.Format.Format.Audio.Format = 0;
  327. for (i=0;i<4;++i)
  328. if (Head.subtype[i])
  329. s->Stream.Format.Format.Audio.Format = s->Stream.Format.Format.Audio.Format*16+Hex(Head.subtype[i]);
  330. s->Stream.Format.Format.Audio.Channels = INT16LE(Head.format.audio.channels);
  331. s->Stream.Format.Format.Audio.Bits = INT16LE(Head.bits_per_sample);
  332. s->Stream.Format.Format.Audio.BlockAlign = INT16LE(Head.format.audio.blockalign);
  333. s->Stream.Format.ByteRate = INT32LE(Head.format.audio.avgbytespersec);
  334. s->Stream.Format.Format.Audio.SampleRate = (int)INT64LE(Head.samples_per_unit);
  335. s->MediaRateDen = INT64LE(Head.time_unit)*TICKSPERSEC;
  336. s->MediaRateNum = INT64LE(Head.samples_per_unit) * 10000000;
  337. s->DefaultLen = INT32LE(Head.default_len);
  338. i = Length - (sizeof(ogm_header)+1);
  339. if (i && PacketFormatExtra(&s->Stream.Format,i))
  340. memcpy(s->Stream.Format.Extra,Data+1+sizeof(ogm_header),s->Stream.Format.ExtraLength);
  341. return 1;
  342. }
  343. if (strncmp(Data+1, MT_Text,  strlen(MT_Text)) == 0)
  344. {
  345. PacketFormatClear(&s->Stream.Format);
  346. s->Stream.Format.Type = PACKET_SUBTITLE;
  347. s->Stream.Format.Format.Subtitle.FourCC = SUBTITLE_OEM; //???
  348. s->MediaRateDen = INT64LE(Head.time_unit)*TICKSPERSEC;
  349. s->MediaRateNum = INT64LE(Head.samples_per_unit) * 10000000;
  350. s->DefaultLen = INT32LE(Head.default_len);
  351. i = Length - (sizeof(ogm_header)+1);
  352. if (i && PacketFormatExtra(&s->Stream.Format,i))
  353. memcpy(s->Stream.Format.Extra,Data+1+sizeof(ogm_header),s->Stream.Format.ExtraLength);
  354. return 1;
  355. }
  356. }
  357. return 0;
  358. }
  359. static void SendComments(oggstream* Stream)
  360. {
  361. tchar_t s[256];
  362. if (Stream->Stream.Comment.Node)
  363. {
  364. int No;
  365. for (No=0;No<Stream->Comment.comments;++No)
  366. {
  367. UTF8ToTcs(s,TSIZEOF(s),Stream->Comment.user_comments[No]);
  368. Stream->Stream.Comment.Node->Set(Stream->Stream.Comment.Node,Stream->Stream.Comment.No,s,sizeof(s));
  369. }
  370. }
  371. }
  372. static bool_t VorbisHeader(ogg* p,oggstream* s)
  373. {
  374. tchar_t URL[MAXPATH];
  375. if (vorbis_synthesis_headerin(&s->Info,&s->Comment,&s->OggPacket)<0)
  376. return 0;
  377. PacketFormatClear(&s->Stream.Format);
  378. s->Stream.Format.Type = PACKET_AUDIO;
  379. s->Stream.Format.Format.Audio.Channels = s->Info.channels;
  380. s->Stream.Format.Format.Audio.SampleRate = s->Info.rate;
  381. s->Stream.Format.ByteRate = s->Info.bitrate_nominal >> 3;
  382. if (p->Format.Reader->Input->Get(p->Format.Reader->Input,STREAM_URL,URL,sizeof(URL))==ERR_NONE &&
  383. CheckExts(URL,T("ogg:A")) != 0)
  384. s->Stream.Format.Format.Audio.Format = AUDIOFMT_VORBIS_INTERNAL_AUDIO;
  385. else
  386. s->Stream.Format.Format.Audio.Format = AUDIOFMT_VORBIS_INTERNAL_VIDEO;
  387. s->Vorbis = 1;
  388. s->MediaRateDen = TICKSPERSEC;
  389. s->MediaRateNum = s->Info.rate;
  390. return 1;
  391. }
  392. static int FillQueue(ogg* p,format_reader* Reader)
  393. {
  394. for (;;)
  395. {
  396. int Bytes = ogg_sync_pageseek(p->OggSync,&p->OggPage);
  397. if (Bytes == 0) // need more data
  398. {
  399. int Result;
  400. format_buffer* Buffer;
  401. if (!Reader->BufferAvailable && (!p->Format.SyncMode || p->Format.SyncRead<=0))
  402. return ERR_NEED_MORE_DATA;
  403. Buffer = Format_BufferRemove(Reader);
  404. if (!Buffer && p->Format.SyncMode && p->Format.SyncRead>0 && Format_ReadBuffer(Reader,0))
  405. Buffer = Format_BufferRemove(Reader);
  406. Result = AddBuffer(p,Buffer);
  407. if (Result != ERR_NONE)
  408. return Result;
  409. }
  410. else
  411. if (Bytes < 0)
  412. Reader->FilePos -= Bytes;
  413. else
  414. if (Bytes > 0)
  415. {
  416. int StreamNo;
  417. oggstream* s;
  418. int Id;
  419. Reader->FilePos += Bytes;
  420. Id = ogg_page_serialno(&p->OggPage);
  421. DEBUG_MSG4(DEBUG_FORMAT,T("OGG Page id:%d size:%d gran:%d filepos:%d"),Id,p->OggPage.body_len,(int)ogg_page_granulepos(&p->OggPage),Reader->FilePos - Bytes);
  422. for (StreamNo=0;StreamNo<p->Format.StreamCount;++StreamNo)
  423. if (p->Format.Streams[StreamNo]->Id == Id)
  424. break;
  425. if (StreamNo==p->Format.StreamCount)
  426. {
  427. // check for restarted audio http streaming (comments changed)
  428. if (p->Format.StreamCount==1 && 
  429. p->Format.Streams[0]->Format.Type == PACKET_AUDIO &&
  430. p->Format.Streams[0]->LastTime>0)
  431. {
  432. StreamNo = 0;
  433. s = (oggstream*) p->Format.Streams[0];
  434. if (s->Vorbis)
  435. {
  436. // vorbis decoder have to release s->Info
  437. s->Stream.Format.Extra = NULL;
  438. s->Stream.Format.ExtraLength = 0;
  439. ConnectionUpdate((node*)&p->Format,FORMAT_STREAM+0,s->Stream.Pin.Node,s->Stream.Pin.No);
  440. }
  441. FreeStream(p,s);
  442. }
  443. else
  444. {
  445. s = (oggstream*) Format_AddStream(&p->Format,sizeof(oggstream));
  446. if (!s) continue;
  447. }
  448. // init stream
  449. s->Stream.Id = Id;
  450. s->OggStream = ogg_stream_create(Id);
  451. s->NeedMorePage = 1;
  452. s->MediaTime = 0;
  453. s->Invalid = 0;
  454. s->Vorbis = 0;
  455. s->Native = 0;
  456. s->PacketNo = 0;
  457. vorbis_info_init(&s->Info);
  458. vorbis_comment_init(&s->Comment);
  459. }
  460. s = (oggstream*) p->Format.Streams[StreamNo];
  461. if (s->Invalid) // drop invalid streams
  462. continue;
  463. if (s->PacketNo>=3)
  464. {
  465. if (!s->Stream.Pin.Node) // drop unused streams
  466. continue;
  467. if (p->Format.InSeek)
  468. {
  469. // reftime needed for SeekByPacket
  470. if ((s->MediaTime = ogg_page_granulepos(&p->OggPage)) != -1)
  471. {
  472. // no need for GlobalOffset here
  473. s->Stream.LastTime = (tick_t)(s->MediaTime * s->MediaRateDen / s->MediaRateNum);
  474. if (s->Stream.Format.Type == PACKET_AUDIO)
  475. {
  476. s->Stream.LastTime += p->Format.AVOffset;
  477. if (s->Stream.LastTime < 0)
  478. s->Stream.LastTime = 0;
  479. }
  480. }
  481. }
  482. }
  483. // add page to stream
  484. if (ogg_stream_pagein(s->OggStream,&p->OggPage) >= 0)
  485. {
  486. if (s->PacketNo<3) // header packet needed?
  487. {
  488. int i = ogg_stream_packetout(s->OggStream,&s->OggPacket);
  489. if (i == 0) // stream needs more pages
  490. continue;
  491. if (++s->PacketNo==1) // first packet?
  492. {
  493. ogg_reference* Ref;
  494. const void* Data;
  495. int Length;
  496. if (i < 0)
  497. {
  498. // first header packet is a must have
  499. s->Invalid = 1;
  500. continue;
  501. }
  502. if (p->Format.UseBufferBlock)
  503. {
  504. for (Length=0,Ref=s->OggPacket.packet;Ref;Ref=Ref->next)
  505. Length += Ref->length;
  506. if (s->Stream.BufferBlockLength<Length && !Format_AllocBufferBlock(&p->Format,&s->Stream,Length))
  507. {
  508. Length = 0;
  509. Data = NULL;
  510. }
  511. else
  512. {
  513. for (Length=0,Ref=s->OggPacket.packet;Ref;Ref=Ref->next)
  514. {
  515. WriteBlock(&s->Stream.BufferBlock,Length,Ref->buffer->data + Ref->begin,Ref->length);
  516. Length += Ref->length;
  517. }
  518. Data = s->Stream.BufferBlock.Ptr;
  519. }
  520. }
  521. else
  522. {
  523. BufferDrop(&s->Stream.BufferMem);
  524. for (Ref=s->OggPacket.packet;Ref;Ref=Ref->next)
  525. BufferWrite(&s->Stream.BufferMem,Ref->buffer->data + Ref->begin, Ref->length, 16384);
  526. Data = s->Stream.BufferMem.Data;
  527. Length = s->Stream.BufferMem.WritePos;
  528. }
  529. if (OGMHeader(p,s,(char*)Data,Length) || SpeexHeader(p,s,(char*)Data,Length))
  530. {
  531. PacketFormatDefault(&s->Stream.Format);
  532. s->PacketNo = 3; // no more headers
  533. }
  534. else
  535. if (!VorbisHeader(p,s))
  536. {
  537. s->Invalid = 1;
  538. continue;
  539. }
  540. while (s->MediaRateNum > (1<<30))
  541. {
  542. s->MediaRateDen >>= 1;
  543. s->MediaRateNum >>= 1;
  544. }
  545. Format_PrepairStream(&p->Format,&s->Stream);
  546. continue;
  547. }
  548. else
  549. {
  550. assert(s->Vorbis);
  551. // error in second or third header packet will not cause fatal error
  552. vorbis_synthesis_headerin(&s->Info,&s->Comment,&s->OggPacket); 
  553. if (s->PacketNo == 3)
  554. {
  555. // got the three header packets: reinit codec with vorbis_info
  556. s->Stream.Format.Extra = &s->Info;
  557. s->Stream.Format.ExtraLength = -1;
  558. ConnectionUpdate((node*)&p->Format,FORMAT_STREAM+StreamNo,s->Stream.Pin.Node,s->Stream.Pin.No);
  559. SendComments(s);
  560. }
  561. continue;
  562. }
  563. }
  564. s->NeedMorePage = 0;
  565. break;
  566. }
  567. }
  568. }
  569. return ERR_NONE;
  570. }
  571. static int Process(ogg* p,oggstream* Stream)
  572. {
  573. int Result;
  574. int No;
  575. int Burst = 1;
  576. if (Stream->Invalid)
  577. return ERR_NONE;
  578. if (Stream->Stream.Pending)
  579. {
  580. Result = Format_Send(&p->Format,&Stream->Stream);
  581. if (Result == ERR_BUFFER_FULL || Result == ERR_SYNCED)
  582. return Result;
  583. }
  584. // process a limited number of packets at once (other streams need cpu time too)
  585. Result = ERR_NONE;
  586. Burst = Stream->Stream.PacketBurst;
  587. for (No=0;No<Burst;++No)
  588. {
  589. while (Stream->NeedMorePage)
  590. {
  591. Result = FillQueue(p,Stream->Stream.Reader);
  592. if (Result == ERR_NEED_MORE_DATA && Stream->Stream.Reader->NoMoreInput)
  593. Result = Format_CheckEof(&p->Format,&Stream->Stream);
  594. if (Result != ERR_NONE || (p->Format.Bench && Stream->NeedMorePage))
  595. return Result;
  596. }
  597. // sync: only SyncStream is processed
  598. if (p->Format.SyncMode && Stream != (oggstream*)p->Format.SyncStream)
  599. return ERR_NEED_MORE_DATA;
  600. Result = ogg_stream_packetout(Stream->OggStream,&Stream->OggPacket);
  601. if (Result == 0)
  602. {
  603. // stream needs more pages
  604. Stream->NeedMorePage = 1;
  605. if (p->Format.Bench) break; // benchmark mode: no additional pages are added in this loop
  606. --No;
  607. continue;
  608. }
  609. if (Result < 0) // packet hole or span
  610. continue;
  611. DEBUG_MSG3(DEBUG_FORMAT,T("OGG Packet id:%d size:%d gran:%d"),Stream->Stream.Id,Stream->OggPacket.bytes,(int)Stream->OggPacket.granulepos);
  612. if (!Stream->Vorbis && Stream->PacketNo==3)
  613. {
  614. // non vorbis: second packet can be a comment (after first header)
  615. ++Stream->PacketNo;
  616. if (Stream->Native)
  617. {
  618. oggpack_buffer opb;
  619.     oggpack_readinit(&opb,Stream->OggPacket.packet);
  620. if (_vorbis_unpack_comment(&Stream->Comment,&opb,0)>=0)
  621. SendComments(Stream);
  622. continue; // always assume comment packet
  623. }
  624. else
  625. {
  626. Stream->Info.rate=1;
  627. if (vorbis_synthesis_headerin(&Stream->Info,&Stream->Comment,&Stream->OggPacket) >= 0)
  628. {
  629. SendComments(Stream);
  630. continue;
  631. }
  632. }
  633. }
  634. // build output packet
  635. if (Stream->OggPacket.granulepos >= 0)
  636. Stream->MediaTime = Stream->OggPacket.granulepos;
  637. if (Stream->MediaTime >= 0)
  638. {
  639. tick_t t = (tick_t)((Stream->MediaTime * Stream->MediaRateDen) / Stream->MediaRateNum);
  640. t += p->Format.GlobalOffset;
  641. if (Stream->Stream.Format.Type == PACKET_AUDIO)
  642. {
  643. t += p->Format.AVOffset;
  644. if (t<0) t=0;
  645. }
  646. if (Stream->Stream.LastTime>t && t-p->Format.GlobalOffset<TICKSPERSEC)
  647. Format_TimeStampRestarted(&p->Format,&Stream->Stream,&t);
  648. Stream->Stream.LastTime = Stream->Stream.Packet.RefTime = t;
  649. }
  650. else
  651. {
  652. if (Stream->Stream.LastTime < 0)
  653. continue;
  654. Stream->Stream.Packet.RefTime = TIME_UNKNOWN;
  655. }
  656. if (!Stream->Vorbis)
  657. {
  658. ogg_reference* Ref;
  659. const uint8_t* Data;
  660. int Length;
  661. int Len;
  662. int PacketTime;
  663. // merge buffers
  664. if (p->Format.UseBufferBlock)
  665. {
  666. for (Length=0,Ref=Stream->OggPacket.packet;Ref;Ref=Ref->next)
  667. Length += Ref->length;
  668. if (Stream->Stream.BufferBlockLength<Length && !Format_AllocBufferBlock(&p->Format,&Stream->Stream,Length))
  669. {
  670. Length = 0;
  671. Data = NULL;
  672. }
  673. else
  674. {
  675. for (Length=0,Ref=Stream->OggPacket.packet;Ref;Ref=Ref->next)
  676. {
  677. WriteBlock(&Stream->Stream.BufferBlock,Length,Ref->buffer->data + Ref->begin,Ref->length);
  678. Length += Ref->length;
  679. }
  680. Data = Stream->Stream.BufferBlock.Ptr;
  681. }
  682. }
  683. else
  684. {
  685. BufferDrop(&Stream->Stream.BufferMem);
  686. for (Ref=Stream->OggPacket.packet;Ref;Ref=Ref->next)
  687. BufferWrite(&Stream->Stream.BufferMem,Ref->buffer->data + Ref->begin, Ref->length, 16384);
  688. Data = (const uint8_t*)Stream->Stream.BufferMem.Data;
  689. Length = Stream->Stream.BufferMem.WritePos;
  690. }
  691. if (Stream->Native)
  692. {
  693. Stream->Stream.Packet.Data[0] = Data;
  694. Stream->Stream.Packet.Length = Length;
  695. Stream->MediaTime = -1;
  696. }
  697. else
  698. {
  699. // process OGM information
  700. if (*Data & PACKET_TYPE_HEADER)
  701. continue; // not data packet
  702. Len = (*Data & PACKET_LEN_BITS01) >> 6;
  703. Len |= (*Data & PACKET_LEN_BITS2) << 1;
  704. Stream->Stream.Packet.Key = (*Data & PACKET_IS_SYNCPOINT) != 0;
  705. Stream->Stream.Packet.Data[0] = Data + 1 + Len;
  706. Stream->Stream.Packet.Length = Length - 1 - Len;
  707. if (!Len)
  708. PacketTime = Stream->DefaultLen;
  709. else
  710. for (PacketTime=0;Len;--Len)
  711. {
  712. PacketTime <<= 8;
  713. PacketTime |= Data[Len];
  714. }
  715. Stream->MediaTime += PacketTime;
  716. }
  717. }
  718. else
  719. {
  720. // send oggpacket directly 
  721. if (!Stream->OggPacket.packet)
  722. continue;
  723. Stream->Stream.Packet.Data[0] = &Stream->OggPacket;
  724. Stream->Stream.Packet.Length = sizeof(Stream->OggPacket);
  725. Stream->MediaTime = -1;
  726. }
  727. Stream->Stream.Pending = 1;
  728. Result = Format_Send(&p->Format,&Stream->Stream);
  729. if (Result == ERR_BUFFER_FULL || Result == ERR_SYNCED)
  730. break;
  731. if (Stream->Stream.State.DropLevel==2)
  732. Burst = Stream->Stream.PacketBurst*2; // try to catch up
  733. }
  734. // buffer full: there was possibly some processing so don't allow sleeping
  735. // need data: burst count exceeded, but it doesn't mean there is no data left in buffers
  736. if (Result == ERR_BUFFER_FULL || Result == ERR_NEED_MORE_DATA)
  737. Result = ERR_NONE;
  738. return Result;
  739. }
  740. static int Create(ogg* p)
  741. {
  742. p->Format.Init = (fmtfunc)Init;
  743. p->Format.Done = (fmtvoid)Done;
  744. p->Format.Seek = (fmtseek)Format_SeekByPacket;
  745. p->Format.FillQueue = (fmtfill)FillQueue;
  746. p->Format.ReadPacket = (fmtreadpacket)ReadPacketTime;
  747. p->Format.ReleaseStream = (fmtstream)ReleaseStream;
  748. p->Format.AfterSeek = (fmtvoid)AfterSeek;
  749. p->Format.FreeStream = (fmtstream)FreeStream;
  750. p->Format.Process = (fmtstreamprocess)Process;
  751. p->Format.DisableReader = 1;
  752. p->Format.Sended = NULL;
  753. return ERR_NONE;
  754. }
  755. static const nodedef OGG = 
  756. {
  757. sizeof(ogg),
  758. OGG_ID,
  759. FORMATBASE_CLASS,
  760. PRI_DEFAULT,
  761. (nodecreate)Create,
  762. };
  763. void OGG_Init()
  764. {
  765. NodeRegisterClass(&OGG);
  766. }
  767. void OGG_Done()
  768. {
  769. NodeUnRegisterClass(OGG_ID);
  770. }