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

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: oggembedded.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 file format embedded inside an audio stream
  28. typedef struct oggembedded
  29. {
  30. codec Codec;
  31. int OggStreamNo;
  32. ogg_sync_state*  OggSync;
  33. ogg_stream_state* OggStream;
  34. ogg_page         OggPage;
  35. ogg_packet       OggPacket;
  36. vorbis_info      Info;
  37. vorbis_comment   Comment;
  38. // output data
  39. tick_t RefTime;
  40. bool_t Reset;
  41. bool_t NeedMorePage;
  42. int Bytes;   // bytes in Sync buffer
  43. int PageNo;
  44. } oggembedded;
  45. static int UpdateInput( oggembedded* p )
  46. {
  47. vorbis_comment_clear(&p->Comment);
  48. vorbis_info_clear(&p->Info);
  49. ogg_packet_release(&p->OggPacket);
  50. ogg_page_release(&p->OggPage);
  51. if (p->OggStream)
  52. ogg_stream_destroy(p->OggStream);
  53. if (p->OggSync)
  54. ogg_sync_destroy(p->OggSync);
  55. p->OggSync = NULL;
  56. p->OggStream = NULL;
  57. if (p->Codec.In.Format.Type == PACKET_AUDIO)
  58. {
  59. PacketFormatClear(&p->Codec.Out.Format);
  60. p->Codec.Out.Format.Type = PACKET_AUDIO;
  61. p->Codec.Out.Format.Format.Audio.Format = AUDIOFMT_VORBIS_INTERNAL_VIDEO;
  62. p->Codec.Packet.Data[0] = &p->OggPacket;
  63. p->Codec.Packet.Length = sizeof(p->OggPacket);
  64. p->RefTime = TIME_UNKNOWN;
  65. p->Bytes = 0;
  66. p->OggStreamNo = 0;
  67. p->NeedMorePage = 1;
  68. p->PageNo = 0;
  69. p->OggSync = ogg_sync_create();
  70. vorbis_info_init(&p->Info);
  71. vorbis_comment_init(&p->Comment);
  72. }
  73. return ERR_NONE;
  74. }
  75. static int Process( oggembedded* p, const packet* Packet, const flowstate* State )
  76. {
  77. if (Packet)
  78. {
  79. void* Ptr;
  80. // set new reftime (rewind with bytes already buffered)
  81. if (Packet->RefTime >= 0)
  82. p->RefTime = Packet->RefTime - Scale(p->Bytes,TICKSPERSEC,p->Codec.Out.Format.ByteRate);
  83. // add new packet to oggsync
  84. Ptr = ogg_sync_bufferin(p->OggSync,Packet->Length);
  85. if (Ptr)
  86. {
  87. p->Bytes += Packet->Length;
  88. memcpy(Ptr,Packet->Data[0],Packet->Length);
  89. ogg_sync_wrote(p->OggSync,Packet->Length);
  90. }
  91. p->NeedMorePage = 1;
  92. }
  93. for (;;)
  94. {
  95. while (p->NeedMorePage)
  96. {
  97. int StreamNo;
  98. do
  99. {
  100. int Bytes = ogg_sync_pageseek(p->OggSync,&p->OggPage);
  101. if (Bytes == 0)
  102. return ERR_NEED_MORE_DATA; // missing data
  103. if (Bytes < 0) 
  104. {
  105. // corrupt data
  106. p->Bytes += Bytes; //sub skipped bytes 
  107. StreamNo = -1;
  108. }
  109. else
  110. {
  111. p->Bytes -= Bytes;
  112. StreamNo = ogg_page_serialno(&p->OggPage);
  113. if (!p->OggStream)
  114. {
  115. //add stream
  116. p->OggStream = ogg_stream_create(StreamNo);
  117. p->OggStreamNo = StreamNo;
  118. }
  119. }
  120. }
  121. while (StreamNo != p->OggStreamNo);
  122. if (ogg_stream_pagein(p->OggStream,&p->OggPage) >= 0)
  123. p->NeedMorePage = 0;
  124. }
  125. while (!p->NeedMorePage)
  126. {
  127. int Result = ogg_stream_packetout(p->OggStream,&p->OggPacket);
  128. if (Result == 0)
  129. p->NeedMorePage = 1; // set need more page
  130. else
  131. if (Result > 0) 
  132. {
  133. // valid packet
  134. if (p->PageNo < 3) // need 3 header packets
  135. {
  136. // first page is vital
  137. if (vorbis_synthesis_headerin(&p->Info,&p->Comment,&p->OggPacket)>=0 || p->PageNo>0)
  138. {
  139. if (++p->PageNo == 3)
  140. {
  141. tchar_t Comment[256];
  142. int No;
  143. if (p->Codec.Comment.Node)
  144. for (No=0;No<p->Comment.comments;++No)
  145. {
  146. StrToTcs(Comment,TSIZEOF(Comment),p->Comment.user_comments[No]);
  147. p->Codec.Comment.Node->Set(p->Codec.Comment.Node,p->Codec.Comment.No,Comment,sizeof(Comment));
  148. }
  149. p->Codec.Out.Format.Extra = &p->Info;
  150. p->Codec.Out.Format.ExtraLength = -1;
  151. p->Codec.In.Format.ByteRate = p->Codec.Out.Format.ByteRate = p->Info.bitrate_nominal >> 3;
  152. p->Codec.In.Format.Format.Audio.SampleRate = p->Codec.Out.Format.Format.Audio.SampleRate = p->Info.rate;
  153. p->Codec.In.Format.Format.Audio.Channels = p->Codec.Out.Format.Format.Audio.Channels = p->Info.channels;
  154. ConnectionUpdate(&p->Codec.Node,CODEC_OUTPUT,p->Codec.Out.Pin.Node,p->Codec.Out.Pin.No);
  155. }
  156. }
  157. }
  158. else
  159. {
  160. p->Codec.Packet.RefTime = p->RefTime;
  161. if (p->RefTime >= 0)
  162. {
  163. if (p->Codec.Out.Format.ByteRate)
  164. p->RefTime += Scale(p->OggPacket.bytes,TICKSPERSEC,p->Codec.Out.Format.ByteRate);
  165. else
  166. p->RefTime = TIME_UNKNOWN;
  167. }
  168. return ERR_NONE; 
  169. }
  170. }
  171. }
  172. }
  173. return ERR_NEED_MORE_DATA;
  174. }
  175. static int Flush(oggembedded* p)
  176. {
  177. if (p->OggSync)
  178. ogg_sync_reset(p->OggSync);
  179. if (p->OggStream)
  180. ogg_stream_reset_serialno(p->OggStream,p->OggStreamNo);
  181. p->Bytes = 0;
  182. return ERR_NONE;
  183. }
  184. static int Create(oggembedded* p)
  185. {
  186. p->Codec.UpdateInput = (nodefunc)UpdateInput;
  187. p->Codec.Flush = (nodefunc)Flush;
  188. p->Codec.Process = (packetprocess)Process;
  189. p->Codec.UseComment = 1;
  190. return ERR_NONE;
  191. }
  192. static const nodedef OGGEmbedded =
  193. {
  194. sizeof(oggembedded),
  195. OGGEMBEDDED_ID,
  196. CODEC_CLASS,
  197. PRI_DEFAULT,
  198. (nodecreate)Create,
  199. };
  200. void OGGEmbedded_Init()
  201. {
  202. NodeRegisterClass(&OGGEmbedded);
  203. }
  204. void OGGEmbedded_Done()
  205. {
  206. NodeUnRegisterClass(OGGEMBEDDED_ID);
  207. }