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

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: flow.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.h"
  24. static const datatable FlowParams[] =
  25. {
  26. { FLOW_BUFFERED,TYPE_BOOL, DF_HIDDEN },
  27. DATATABLE_END(FLOW_CLASS)
  28. };
  29. int FlowEnum(void* p, int* No, datadef* Param)
  30. {
  31. return NodeEnumTable(No,Param,FlowParams);
  32. }
  33. static const nodedef Flow =
  34. {
  35. CF_ABSTRACT,
  36. FLOW_CLASS,
  37. NODE_CLASS,
  38. PRI_DEFAULT,
  39. };
  40. static const datatable OutParams[] =
  41. {
  42. { OUT_INPUT, TYPE_PACKET, DF_INPUT },
  43. { OUT_OUTPUT, TYPE_PACKET, DF_OUTPUT|DF_RDONLY },
  44. { OUT_TOTAL, TYPE_INT,  DF_HIDDEN },
  45. { OUT_DROPPED, TYPE_INT,  DF_HIDDEN },
  46. { OUT_KEEPALIVE,TYPE_BOOL,  DF_HIDDEN },
  47. DATATABLE_END(OUT_CLASS)
  48. };
  49. int OutEnum(void* p, int* No, datadef* Param)
  50. {
  51. return NodeEnumTable(No,Param,OutParams);
  52. }
  53. static const nodedef Out =
  54. {
  55. CF_ABSTRACT,
  56. OUT_CLASS,
  57. FLOW_CLASS,
  58. PRI_DEFAULT,
  59. };
  60. void Flow_Init()
  61. {
  62. NodeRegisterClass(&Flow);
  63. NodeRegisterClass(&Out);
  64. }
  65. void Flow_Done()
  66. {
  67. NodeUnRegisterClass(OUT_CLASS);
  68. NodeUnRegisterClass(FLOW_CLASS);
  69. }
  70. void Disconnect(node* Src,int SrcNo,node* Dst,int DstNo)
  71. {
  72. ConnectionUpdate(NULL,0,Dst,DstNo);
  73. ConnectionUpdate(Src,SrcNo,NULL,0);
  74. }
  75. int ConnectionUpdate(node* Src,int SrcNo,node* Dst,int DstNo)
  76. {
  77. int Result;
  78. pin Pin;
  79. packetformat Format;
  80. packetprocess Process;
  81. memset(&Format,0,sizeof(Format));
  82. // first setup connection via Pin, so when PIN_FORMAT is set the nodes can negotiate
  83. // ConnectionUpdate should not disconnect nodes even is something fails
  84. if (Dst && Dst->Get(Dst,DstNo,&Pin,sizeof(Pin))==ERR_NONE && (Pin.Node != Src || Pin.No != SrcNo))
  85. {
  86. Pin.Node = Src;
  87. Pin.No = SrcNo;
  88. Result = Dst->Set(Dst,DstNo,&Pin,sizeof(Pin));
  89. if (Result != ERR_NONE)
  90. return Result;
  91. }
  92. if (Src && Src->Get(Src,SrcNo,&Pin,sizeof(Pin))==ERR_NONE && (Pin.Node != Dst || Pin.No != DstNo))
  93. {
  94. Pin.Node = Dst;
  95. Pin.No = DstNo;
  96. Result = Src->Set(Src,SrcNo,&Pin,sizeof(Pin));
  97. if (Result != ERR_NONE)
  98. return Result;
  99. }
  100. if (Src && Dst)
  101. {
  102. Src->Get(Src,SrcNo|PIN_FORMAT,&Format,sizeof(Format));
  103. Result = Dst->Set(Dst,DstNo|PIN_FORMAT,&Format,sizeof(Format));
  104. if (Result != ERR_NONE)
  105. Dst->Set(Dst,DstNo|PIN_FORMAT,NULL,0);
  106. Dst->Get(Dst,DstNo|PIN_PROCESS,&Process,sizeof(packetprocess));
  107. Src->Set(Src,SrcNo|PIN_PROCESS,&Process,sizeof(packetprocess));
  108. if (Result != ERR_NONE)
  109. return Result;
  110. }
  111. else
  112. if (Dst)
  113. Dst->Set(Dst,DstNo|PIN_FORMAT,NULL,0);
  114. return ERR_NONE;
  115. }
  116. int DummyProcess(void* p, const packet* Packet, const flowstate* State)
  117. {
  118. if (State->CurrTime >= 0 && Packet && Packet->RefTime > State->CurrTime + SHOWAHEAD)
  119. return ERR_BUFFER_FULL;
  120. return ERR_NONE;
  121. }
  122. static bool_t ContentType(const packetformat* Format,tchar_t* Out,int OutLen)
  123. {
  124. tchar_t Id[16];
  125. switch (Format->Type)
  126. {
  127. case PACKET_VIDEO:
  128. FourCCToString(Id,TSIZEOF(Id),Format->Format.Video.Pixel.FourCC);
  129. stprintf_s(Out,OutLen,T("vcodec/%s"),Id);
  130. break;
  131. case PACKET_AUDIO:
  132. stprintf_s(Out,OutLen,T("acodec/0x%04x"),Format->Format.Audio.Format);
  133. break;
  134. case PACKET_SUBTITLE:
  135. FourCCToString(Id,TSIZEOF(Id),Format->Format.Subtitle.FourCC);
  136. stprintf_s(Out,OutLen,T("subtitle/%s"),Id);
  137. break;
  138. default:
  139. return 0;
  140. }
  141. return 1;
  142. }
  143. void PacketFormatEnumClass(array* List, const packetformat* Format)
  144. {
  145. tchar_t s[16];
  146. if (ContentType(Format,s,TSIZEOF(s)))
  147. NodeEnumClassEx(List,FLOW_CLASS,s,NULL,NULL,0);
  148. else
  149. memset(List,0,sizeof(array));
  150. }
  151. bool_t PacketFormatMatch(int Class, const packetformat* Format)
  152. {
  153. tchar_t s[16];
  154. const tchar_t* Supported = LangStr(Class,NODE_CONTENTTYPE);
  155. assert(Supported[0]!=0);
  156. if (Supported[0]==0)
  157. return 0;
  158. if (!ContentType(Format,s,TSIZEOF(s)))
  159. return 0;
  160. return CheckContentType(s,Supported);
  161. }
  162. bool_t PacketFormatSimilarAudio(const packetformat* Current, const packetformat* New)
  163. {
  164. return Current && Current->Type == PACKET_AUDIO && New && New->Type == PACKET_AUDIO &&
  165. Current->Format.Audio.Format == New->Format.Audio.Format &&
  166. Current->Format.Audio.Channels == New->Format.Audio.Channels &&
  167. Current->Format.Audio.SampleRate == New->Format.Audio.SampleRate;
  168. }
  169. bool_t PacketFormatRotatedVideo(const packetformat* Current, const packetformat* New,int Mask)
  170. {
  171. if (Current && Current->Type == PACKET_VIDEO && New && New->Type == PACKET_VIDEO &&
  172. (Current->Format.Video.Direction ^ New->Format.Video.Direction) & Mask)
  173. {
  174. video Tmp = New->Format.Video;
  175. Tmp.Pitch = Current->Format.Video.Pitch;
  176. if ((Current->Format.Video.Direction ^ Tmp.Direction) & DIR_SWAPXY)
  177. SwapInt(&Tmp.Width,&Tmp.Height);
  178. Tmp.Direction = Current->Format.Video.Direction;
  179. return EqVideo(&Current->Format.Video,&Tmp);
  180. }
  181. return 0;
  182. }
  183. bool_t EqPacketFormat(const packetformat* a, const packetformat* b)
  184. {
  185. if (!a || !b || a->Type != b->Type)
  186. return 0;
  187. switch (a->Type)
  188. {
  189. case PACKET_VIDEO: return EqVideo(&a->Format.Video,&b->Format.Video);
  190. case PACKET_AUDIO: return EqAudio(&a->Format.Audio,&b->Format.Audio);
  191. case PACKET_SUBTITLE: return EqSubtitle(&a->Format.Subtitle,&b->Format.Subtitle);
  192. }
  193. return 1;
  194. }
  195. int PacketFormatCopy(packetformat* Dst, const packetformat* Src)
  196. {
  197. PacketFormatClear(Dst);
  198. if (Src)
  199. {
  200. *Dst = *Src;
  201. if (Src->ExtraLength >= 0)
  202. {
  203. Dst->Extra = NULL;
  204. Dst->ExtraLength = 0;
  205. if (Src->ExtraLength && PacketFormatExtra(Dst,Src->ExtraLength))
  206. memcpy(Dst->Extra,Src->Extra,Dst->ExtraLength);
  207. if (Src->Type==PACKET_VIDEO && Src->Format.Video.Pixel.Palette == (rgb*)Src->Extra)
  208. Dst->Format.Video.Pixel.Palette = (rgb*)Dst->Extra;
  209. }
  210. }
  211. return ERR_NONE;
  212. }
  213. void PacketFormatCombine(packetformat* Dst, const packetformat* Src)
  214. {
  215. if (Dst->Type == Src->Type)
  216. {
  217. if (!Dst->ByteRate)
  218. Dst->ByteRate = Src->ByteRate;
  219. if (!Dst->PacketRate.Num)
  220. Dst->PacketRate = Src->PacketRate;
  221. switch (Dst->Type)
  222. {
  223. case PACKET_VIDEO:
  224. if (!Dst->Format.Video.Width && !Dst->Format.Video.Height)
  225. {
  226. Dst->Format.Video.Width = Src->Format.Video.Width;
  227. Dst->Format.Video.Height = Src->Format.Video.Height;
  228. Dst->Format.Video.Direction = Src->Format.Video.Direction;
  229. }
  230. if (!Dst->Format.Video.Aspect)
  231. Dst->Format.Video.Aspect = Src->Format.Video.Aspect;
  232. break;
  233. case PACKET_AUDIO:
  234. // force update
  235. Dst->Format.Audio.Channels = Src->Format.Audio.Channels;
  236. Dst->Format.Audio.SampleRate = Src->Format.Audio.SampleRate; 
  237. if (!Dst->Format.Audio.Bits)
  238. {
  239. Dst->Format.Audio.Bits = Src->Format.Audio.Bits;
  240. Dst->Format.Audio.FracBits = Src->Format.Audio.FracBits;
  241. }
  242. break;
  243. }
  244. }
  245. }
  246. void PacketFormatClear(packetformat* p)
  247. {
  248. if (p->ExtraLength>=0)
  249. free(p->Extra);
  250. memset(p,0,sizeof(packetformat));
  251. }
  252. bool_t PacketFormatExtra(packetformat* p, int Length)
  253. {
  254. if (Length<=0)
  255. {
  256. if (p->ExtraLength>=0)
  257. free(p->Extra);
  258. p->Extra = NULL;
  259. p->ExtraLength = 0;
  260. return 0;
  261. }
  262. else
  263. {
  264. void* Extra = realloc(p->Extra,Length);
  265. if (!Extra && Length)
  266. return 0;
  267. p->Extra = Extra;
  268. p->ExtraLength = Length;
  269. return 1;
  270. }
  271. }
  272. void PacketFormatPCM(packetformat* p, const packetformat* In, int Bits)
  273. {
  274. PacketFormatClear(p);
  275. p->Type = PACKET_AUDIO;
  276. p->Format.Audio.Format = AUDIOFMT_PCM;
  277. p->Format.Audio.Bits = Bits;
  278. p->Format.Audio.SampleRate = In->Format.Audio.SampleRate;
  279. p->Format.Audio.Channels = In->Format.Audio.Channels;
  280. if (p->Format.Audio.Channels > 2)
  281. p->Format.Audio.Channels = 2;
  282. PacketFormatDefault(p);
  283. }
  284. void PacketFormatDefault(packetformat* p)
  285. {
  286. switch (p->Type)
  287. {
  288. case PACKET_VIDEO:
  289. if (p->Format.Video.Pixel.FourCC==0) // DIB?
  290. {
  291. if (p->Format.Video.Pixel.BitCount <= 8)
  292. p->Format.Video.Pixel.Flags = PF_PALETTE;
  293. else
  294. switch (p->Format.Video.Pixel.BitCount)
  295. {
  296. case 16:
  297. DefaultRGB(&p->Format.Video.Pixel,p->Format.Video.Pixel.BitCount,5,5,5,0,0,0);
  298. break;
  299. case 24:
  300. case 32:
  301. DefaultRGB(&p->Format.Video.Pixel,p->Format.Video.Pixel.BitCount,8,8,8,0,0,0);
  302. break;
  303. }
  304. p->Format.Video.Direction = DIR_MIRRORUPDOWN;
  305. }
  306. else
  307. if (p->Format.Video.Pixel.FourCC==3)
  308. {
  309. p->Format.Video.Pixel.Flags = PF_RGB;
  310. p->Format.Video.Direction = DIR_MIRRORUPDOWN;
  311. }
  312. else
  313. {
  314. p->Format.Video.Pixel.Flags = PF_FOURCC;
  315. p->Format.Video.Pixel.FourCC = UpperFourCC(p->Format.Video.Pixel.FourCC);
  316. p->Format.Video.Direction = 0;
  317. }
  318. DefaultPitch(&p->Format.Video);
  319. if (p->Format.Video.Height<0)
  320. {
  321. p->Format.Video.Height = -p->Format.Video.Height;
  322. p->Format.Video.Direction ^= DIR_MIRRORUPDOWN;
  323. }
  324. break;
  325. case PACKET_AUDIO:
  326. // detect fake PCM
  327. if (p->Format.Audio.Format > 8192 && 
  328. p->Format.Audio.BlockAlign > 0 &&
  329. p->ByteRate > 0 &&
  330. p->Format.Audio.BlockAlign == ((p->Format.Audio.Channels * p->Format.Audio.Bits) >> 3) &&
  331. p->ByteRate == p->Format.Audio.SampleRate * p->Format.Audio.BlockAlign)
  332. p->Format.Audio.Format = AUDIOFMT_PCM;
  333. if (p->Format.Audio.Format == AUDIOFMT_PCM)
  334. {
  335. p->Format.Audio.FracBits = p->Format.Audio.Bits - 1;
  336. if (p->Format.Audio.Bits <= 8)
  337. p->Format.Audio.Flags |= PCM_UNSIGNED;
  338. p->Format.Audio.Bits = ALIGN8(p->Format.Audio.Bits);
  339. p->Format.Audio.BlockAlign = (p->Format.Audio.Channels * p->Format.Audio.Bits) >> 3;
  340. p->ByteRate = p->Format.Audio.SampleRate * p->Format.Audio.BlockAlign;
  341. }
  342. break;
  343. }
  344. }
  345. bool_t PacketFormatName(packetformat* p, tchar_t* Name, int NameLen)
  346. {
  347. tchar_t Id[8];
  348. switch (p->Type)
  349. {
  350. case PACKET_SUBTITLE:
  351. tcscpy_s(Name,NameLen,LangStr(p->Format.Subtitle.FourCC,0x4400));
  352. if (!Name[0])
  353. FourCCToString(Name,NameLen,p->Format.Subtitle.FourCC);
  354. return 1;
  355. case PACKET_AUDIO:
  356. if (p->Format.Audio.Format != AUDIOFMT_PCM)
  357. {
  358. stprintf_s(Id,TSIZEOF(Id),T("%04X"),p->Format.Audio.Format);
  359. tcscpy_s(Name,NameLen,LangStr(FOURCC(Id[0],Id[1],Id[2],Id[3]),0x4400));
  360. if (!Name[0])
  361. tcscpy_s(Name,NameLen,Id);
  362. }
  363. else
  364. tcscpy_s(Name,NameLen,T("PCM"));
  365. return 1;
  366. case PACKET_VIDEO:
  367. if (Compressed(&p->Format.Video.Pixel))
  368. {
  369. tcscpy_s(Name,NameLen,LangStr(p->Format.Video.Pixel.FourCC,0x4400));
  370. if (!Name[0])
  371. FourCCToString(Name,NameLen,p->Format.Video.Pixel.FourCC);
  372. }
  373. else
  374. if (AnyYUV(&p->Format.Video.Pixel))
  375. tcscpy_s(Name,NameLen,T("YUV"));
  376. else
  377. stprintf_s(Name,NameLen,T("RGB %d bits"),p->Format.Video.Pixel.BitCount);
  378. return 1;
  379. }
  380. return 0;
  381. }