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

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: ffmpeg.c 603 2006-01-19 13:00:33Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common/common.h"
  24. #include "ffmpeg.h"
  25. #undef malloc
  26. #undef realloc
  27. #undef free
  28. #include "libavcodec/avcodec.h"
  29. typedef struct ffmpeg_video
  30. {
  31. codec Codec;
  32. buffer Buffer;
  33.     AVCodecContext *Context;
  34.     AVFrame *Picture;
  35. AVRational Aspect;
  36. int PixelFormat;
  37. int SkipToKey;
  38. int DropToKey;
  39. bool_t Dropping;
  40. int CodecId;
  41. tick_t FrameTime;
  42.     AVPaletteControl Palette;
  43. } ffmpeg_video;
  44. typedef struct codecinfo
  45. {
  46. int Id;
  47. int CodecId;
  48. const tchar_t* Name;
  49. const tchar_t* ContentType;
  50. } codecinfo;
  51. #define FFMPEG_VIDEO_CLASS FOURCC('F','F','M','V')
  52. static const codecinfo Info[] = 
  53. {
  54. {FOURCC('F','C','I','N'),CODEC_ID_CINEPAK,T("FFmpeg Cinepak"),
  55. T("vcodec/cvid")},
  56. {FOURCC('F','T','S','C'),CODEC_ID_TSCC,T("FFmpeg TSCC"),
  57. T("vcodec/tscc")},
  58. {FOURCC('F','M','S','0'),CODEC_ID_MSVIDEO1,T("FFmpeg Microsoft Video 1"),
  59. T("vcodec/cram,vcodec/msvc")},
  60. {FOURCC('F','M','P','G'),CODEC_ID_MPEG2VIDEO,T("FFmpeg MPEG1/2"),
  61. T("vcodec/mpeg,vcodec/mpg1")},
  62. {FOURCC('F','2','6','3'),CODEC_ID_H263,T("FFmpeg h.263"),
  63. T("vcodec/h263,vcodec/u263,vcodec/x263,vcodec/s263")},
  64. {FOURCC('F','A','V','C'),CODEC_ID_H264,T("FFmpeg AVC"),
  65. T("vcodec/avc1,vcodec/h264,vcodec/x264,vcodec/vssh")},
  66. {FOURCC('F','W','V','1'),CODEC_ID_WMV1,T("FFmpeg WMV1"),
  67. T("vcodec/wmv1")},
  68. {FOURCC('F','W','V','2'),CODEC_ID_WMV2,T("FFmpeg WMV2"),
  69. T("vcodec/wmv2")},
  70. // {FOURCC('F','W','V','3'),CODEC_ID_WMV3,T("FFmpeg WMV3"),
  71. // T("vcodec/wmv3")},
  72. // {FOURCC('F','S','V','1'),CODEC_ID_SVQ1,T("FFmpeg SVQ1"),
  73. // T("vcodec/svq1")},
  74. {FOURCC('F','S','V','3'),CODEC_ID_SVQ3,T("FFmpeg SVQ3"),
  75. T("vcodec/svq3")},
  76. {FOURCC('F','M','S','1'),CODEC_ID_MSMPEG4V1,T("FFmpeg MSMPEG1"),
  77. T("vcodec/mpg4,vcodec/mp41,vcodec/div1")},
  78. {FOURCC('F','M','S','2'),CODEC_ID_MSMPEG4V2,T("FFmpeg MSMPEG2"),
  79. T("vcodec/mp42,vcodec/div2")},
  80. {FOURCC('F','M','S','3'),CODEC_ID_MSMPEG4V3,T("FFmpeg MSMPEG3"),
  81. T("vcodec/mp43,vcodec/mpg3,vcodec/div3,vcodec/div4,vcodec/div5,vcodec/div6,vcodec/ap41,vcodec/col0,vcodec/col1,vcodec/3ivd")},
  82. {FOURCC('F','M','P','4'),CODEC_ID_MPEG4,T("FFmpeg MPEG4"),
  83. T("vcodec/divx,vcodec/dx50,vcodec/xvid,vcodec/mrs2,vcodec/3iv2,vcodec/mp4s,vcodec/pm4v,vcodec/blz0,vcodec/ump4,vcodec/m4s2,vcodec/mp4v,vcodec/fmp4")},
  84. {0},
  85. };
  86. static bool_t BuildOutputFormat(ffmpeg_video* p)
  87. {
  88. int pix_fmt = p->Context->pix_fmt;
  89. if (pix_fmt<0)
  90. pix_fmt = PIX_FMT_YUV420P; // is this needed?
  91. PacketFormatClear(&p->Codec.Out.Format);
  92. p->Codec.Out.Format.Type = PACKET_VIDEO;
  93. switch (pix_fmt)
  94. {
  95. case PIX_FMT_YUV410P:
  96. p->Codec.Out.Format.Format.Video.Pixel.Flags = PF_YUV410;
  97. break;
  98. case PIX_FMT_YUV420P:
  99. p->Codec.Out.Format.Format.Video.Pixel.Flags = PF_YUV420;
  100. break;
  101. case PIX_FMT_BGR24:
  102. DefaultRGB(&p->Codec.Out.Format.Format.Video.Pixel,24,8,8,8,0,0,0);
  103. break;
  104. case PIX_FMT_RGBA32:
  105. DefaultRGB(&p->Codec.Out.Format.Format.Video.Pixel,32,8,8,8,0,0,0);
  106. break;
  107. case PIX_FMT_RGB555:
  108. DefaultRGB(&p->Codec.Out.Format.Format.Video.Pixel,16,5,5,5,0,0,0);
  109. break;
  110. case PIX_FMT_PAL8:
  111. p->Codec.Out.Format.Format.Video.Pixel.Flags = PF_PALETTE;
  112. p->Codec.Out.Format.Format.Video.Pixel.BitCount = 8;
  113. p->Codec.Out.Format.Format.Video.Pixel.Palette = p->Codec.In.Format.Format.Video.Pixel.Palette;
  114. break;
  115. default:
  116. return 0;
  117. }
  118. p->Aspect = p->Context->sample_aspect_ratio;
  119. p->Codec.Out.Format.Format.Video.Aspect = p->Codec.In.Format.Format.Video.Aspect;
  120. if (p->Context->sample_aspect_ratio.num>0 && !p->Codec.Out.Format.Format.Video.Aspect)
  121. p->Codec.Out.Format.Format.Video.Aspect = Scale(ASPECT_ONE,p->Context->sample_aspect_ratio.num,p->Context->sample_aspect_ratio.den);
  122. p->Codec.In.Format.Format.Video.Width = p->Codec.Out.Format.Format.Video.Width = p->Context->width;
  123. p->Codec.In.Format.Format.Video.Height = p->Codec.Out.Format.Format.Video.Height = p->Context->height;
  124. if (p->Picture->linesize[0])
  125. p->Codec.Out.Format.Format.Video.Pitch = p->Picture->linesize[0];
  126. else
  127. DefaultPitch(&p->Codec.Out.Format.Format.Video);
  128. p->PixelFormat = p->Context->pix_fmt;
  129. if (p->Context->bit_rate > 0 && p->Context->bit_rate < 100000000)
  130. p->Codec.In.Format.ByteRate = p->Context->bit_rate/8;
  131. if (p->Context->time_base.num > 0)
  132. {
  133. p->Codec.In.Format.PacketRate.Num = p->Context->time_base.den;
  134. p->Codec.In.Format.PacketRate.Den = p->Context->time_base.num;
  135. p->FrameTime = Scale(TICKSPERSEC,p->Codec.In.Format.PacketRate.Den,p->Codec.In.Format.PacketRate.Num);
  136. }
  137. else
  138. p->FrameTime = TIME_UNKNOWN;
  139. //ShowMessage("","%d %d %d",p->Context->pix_fmt,p->Context->width,p->Context->height);
  140. return 1;
  141. }
  142. static void UpdateSettings(ffmpeg_video* p)
  143. {
  144. p->Context->skip_loop_filter = QueryAdvanced(ADVANCED_NODEBLOCKING)? AVDISCARD_ALL : AVDISCARD_DEFAULT;
  145. }
  146. static int UpdateInput( ffmpeg_video* p )
  147. {
  148. if (p->Context)
  149. avcodec_close(p->Context);
  150.     av_free(p->Context);
  151.     av_free(p->Picture);
  152. p->Context = NULL;
  153. p->Picture = NULL;
  154. BufferClear(&p->Buffer);
  155. if (p->Codec.In.Format.Type == PACKET_VIDEO)
  156. {
  157.     AVCodec *Codec;
  158. const codecinfo *i;
  159. for (i=Info;i->Id;++i)
  160. if (i->Id == p->Codec.Node.Class)
  161. break;
  162. if (!i->Id)
  163. return ERR_INVALID_DATA;
  164. Codec = avcodec_find_decoder(i->CodecId);
  165. if (!Codec)
  166. return ERR_INVALID_DATA;
  167. p->Context = avcodec_alloc_context();
  168. p->Picture = avcodec_alloc_frame();
  169. if (!p->Context || !p->Picture)
  170. return ERR_OUT_OF_MEMORY;
  171.     if ((p->Codec.In.Format.Format.Video.Pixel.Flags & PF_FRAGMENTED) && 
  172. (Codec->capabilities & CODEC_CAP_TRUNCATED))
  173. p->Context->flags|= CODEC_FLAG_TRUNCATED;
  174. UpdateSettings(p);
  175. p->Context->palctrl = NULL;
  176.     p->Context->bit_rate = 0;
  177. p->Context->extradata = p->Codec.In.Format.Extra;
  178. p->Context->extradata_size = p->Codec.In.Format.ExtraLength;
  179. p->Context->width = p->Codec.In.Format.Format.Video.Width;
  180. p->Context->height = p->Codec.In.Format.Format.Video.Height;
  181. p->Context->bits_per_sample = p->Codec.In.Format.Format.Video.Pixel.BitCount;
  182. if (p->Codec.In.Format.Format.Video.Pixel.Palette && 
  183. p->Codec.In.Format.Format.Video.Pixel.BitCount<=8)
  184. {
  185. int i,n = 1 << p->Codec.In.Format.Format.Video.Pixel.BitCount;
  186. for (i=0;i<n;++i)
  187. p->Palette.palette[i] = INT32LE(p->Codec.In.Format.Format.Video.Pixel.Palette[i].v);
  188. p->Palette.palette_changed = 1;
  189. p->Context->palctrl = &p->Palette;
  190. }
  191. p->CodecId = i->CodecId;
  192.     if (avcodec_open(p->Context,Codec)<0)
  193. {
  194. // avoid calling avcodec_close at next UpdateInput
  195.     av_free(p->Context);
  196. p->Context = NULL;
  197. return ERR_INVALID_DATA;
  198. }
  199. if (!BuildOutputFormat(p))
  200. return ERR_INVALID_DATA;
  201. p->SkipToKey = 1;
  202. p->DropToKey = 1;
  203. p->Dropping = 0;
  204. }
  205. return ERR_NONE;
  206. }
  207. static INLINE bool_t SupportDrop( ffmpeg_video* p )
  208. {
  209. return p->CodecId != CODEC_ID_H264 && (!p->Context->has_b_frames || p->CodecId != CODEC_ID_SVQ3);
  210. }
  211. static int Process( ffmpeg_video* p, const packet* Packet, const flowstate* State )
  212. {
  213. int Picture;
  214. int Len;
  215. if (Packet)
  216. {
  217. if (State->DropLevel)
  218. {
  219. if (State->DropLevel>1)
  220. {
  221. p->SkipToKey = 1;
  222. p->DropToKey = 1;
  223. p->Dropping = 1;
  224. p->Context->hurry_up = 5;
  225. }
  226. else
  227. p->Context->hurry_up = 1;
  228. if (!SupportDrop(p))
  229. p->Context->hurry_up = 0;
  230. }
  231. else
  232. p->Context->hurry_up = 0;
  233. if (!Packet->Key && p->DropToKey)
  234. {
  235. if (p->Dropping)
  236. {
  237. flowstate DropState;
  238. DropState.CurrTime = TIME_UNKNOWN;
  239. DropState.DropLevel = 1;
  240. p->Codec.Out.Process(p->Codec.Out.Pin.Node,NULL,&DropState);
  241. }
  242. if (SupportDrop(p))
  243. avcodec_flush_buffers(p->Context);
  244. return ERR_DROPPING;
  245. }
  246. if (p->DropToKey)
  247. p->DropToKey = 0;
  248. if (Packet->RefTime >= 0)
  249. p->Codec.Packet.RefTime = Packet->RefTime;
  250. BufferPack(&p->Buffer,0);
  251. BufferWrite(&p->Buffer,Packet->Data[0],Packet->Length,2048);
  252. }
  253. else
  254. {
  255. if (p->FrameTime<0)
  256. p->Codec.Packet.RefTime = TIME_UNKNOWN;
  257. else
  258. if (!State)
  259. p->Codec.Packet.RefTime += p->FrameTime;
  260. if (!State && p->Buffer.WritePos == p->Buffer.ReadPos)
  261. return ERR_NEED_MORE_DATA;
  262. }
  263. if (p->SkipToKey)
  264. p->Picture->pict_type = 0;
  265. Len = avcodec_decode_video(p->Context, p->Picture, &Picture, p->Buffer.Data + p->Buffer.ReadPos, 
  266. p->Buffer.WritePos - p->Buffer.ReadPos);
  267. if (Len < 0)
  268. {
  269. BufferDrop(&p->Buffer);
  270. return ERR_INVALID_DATA;
  271. }
  272. p->Buffer.ReadPos += Len;
  273. if (!Picture)
  274. {
  275. if (p->SkipToKey>1 && p->Picture->pict_type)
  276. --p->SkipToKey;
  277. return ERR_NEED_MORE_DATA;
  278. }
  279. if (p->SkipToKey>0)
  280. {
  281. if ((!p->Picture->key_frame && p->Picture->pict_type) || p->SkipToKey>1)
  282. {
  283. if (p->SkipToKey>1)
  284. --p->SkipToKey;
  285. if (p->Dropping)
  286. {
  287. flowstate DropState;
  288. DropState.CurrTime = TIME_UNKNOWN;
  289. DropState.DropLevel = 1;
  290. p->Codec.Out.Process(p->Codec.Out.Pin.Node,NULL,&DropState);
  291. }
  292. return ERR_DROPPING;
  293. }
  294. p->SkipToKey = 0;
  295. }
  296. if (p->Context->pix_fmt != p->PixelFormat ||
  297. p->Context->sample_aspect_ratio.num != p->Aspect.num ||
  298. p->Context->sample_aspect_ratio.den != p->Aspect.den ||
  299. p->Context->width != p->Codec.Out.Format.Format.Video.Width ||
  300. p->Context->height != p->Codec.Out.Format.Format.Video.Height ||
  301. p->Picture->linesize[0] != p->Codec.Out.Format.Format.Video.Pitch)
  302. {
  303. if (!BuildOutputFormat(p))
  304. return ERR_INVALID_DATA;
  305. ConnectionUpdate(&p->Codec.Node,CODEC_OUTPUT,p->Codec.Out.Pin.Node,p->Codec.Out.Pin.No);
  306. }
  307. p->Codec.Packet.Data[0] = p->Picture->data[0];
  308. p->Codec.Packet.Data[1] = p->Picture->data[1];
  309. p->Codec.Packet.Data[2] = p->Picture->data[2];
  310. return ERR_NONE;
  311. }
  312. static int ReSend( ffmpeg_video* p )
  313. {
  314. flowstate State;
  315. if (p->SkipToKey || !p->Codec.Out.Pin.Node || !p->Picture->data[0])
  316. return ERR_NEED_MORE_DATA;
  317. State.CurrTime = TIME_RESEND;
  318. State.DropLevel = 0;
  319. p->Codec.Packet.RefTime = TIME_UNKNOWN;
  320. p->Codec.Packet.Data[0] = p->Picture->data[0];
  321. p->Codec.Packet.Data[1] = p->Picture->data[1];
  322. p->Codec.Packet.Data[2] = p->Picture->data[2];
  323. return p->Codec.Out.Process(p->Codec.Out.Pin.Node,&p->Codec.Packet,&State);
  324. }
  325. static int Flush( ffmpeg_video* p )
  326. {
  327. p->SkipToKey = 1;
  328. p->DropToKey = 1;
  329. p->Dropping = 0;
  330. if (p->Context)
  331. {
  332. if (SupportDrop(p))
  333. avcodec_flush_buffers(p->Context);
  334. if (p->Context->has_b_frames && p->Context->frame_number>0)
  335. p->SkipToKey = 2;
  336. }
  337. BufferDrop(&p->Buffer);
  338. return ERR_NONE;
  339. }
  340. static int Set(ffmpeg_video* p, int No, const void* Data, int Size)
  341. {
  342. int Result = CodecSet(&p->Codec,No,Data,Size);
  343. switch (No)
  344. {
  345. case NODE_SETTINGSCHANGED: 
  346. if (p->Context)
  347. UpdateSettings(p);
  348. break;
  349. }
  350. return Result;
  351. }
  352. static int Create( ffmpeg_video* p )
  353. {
  354. p->Codec.Node.Set = (nodeset)Set;
  355. p->Codec.Process = (packetprocess)Process;
  356. p->Codec.UpdateInput = (nodefunc)UpdateInput;
  357. p->Codec.Flush = (nodefunc)Flush;
  358. p->Codec.ReSend = (nodefunc)ReSend;
  359. p->Codec.NoHardDropping = 1;
  360. return ERR_NONE;
  361. }
  362. static const nodedef FFMPEGVideo =
  363. {
  364. sizeof(ffmpeg_video)|CF_ABSTRACT,
  365. FFMPEG_VIDEO_CLASS,
  366. CODEC_CLASS,
  367. PRI_DEFAULT,
  368. (nodecreate)Create,
  369. NULL,
  370. };
  371. void FFMPEG_Init()
  372. {
  373. nodedef Def;
  374. const codecinfo* i;
  375. avcodec_init();
  376. register_avcodec(&mpeg1video_decoder);
  377. register_avcodec(&mpeg2video_decoder);
  378. register_avcodec(&mpegvideo_decoder);
  379. // register_avcodec(&svq1_decoder);
  380. register_avcodec(&svq3_decoder);
  381. register_avcodec(&h263_decoder);
  382. register_avcodec(&mpeg4_decoder);
  383. register_avcodec(&msmpeg4v1_decoder);
  384. register_avcodec(&msmpeg4v2_decoder);
  385. register_avcodec(&msmpeg4v3_decoder);
  386. register_avcodec(&wmv1_decoder);
  387. register_avcodec(&wmv2_decoder);
  388. // register_avcodec(&wmv3_decoder);
  389. register_avcodec(&h264_decoder);
  390. register_avcodec(&cinepak_decoder);
  391. register_avcodec(&msvideo1_decoder);
  392. register_avcodec(&tscc_decoder);
  393. NodeRegisterClass(&FFMPEGVideo);
  394. memset(&Def,0,sizeof(Def));
  395. for (i=Info;i->Id;++i)
  396. {
  397. StringAdd(1,i->Id,NODE_NAME,i->Name);
  398. StringAdd(1,i->Id,NODE_CONTENTTYPE,i->ContentType);
  399. Def.Class = i->Id;
  400. Def.ParentClass = FFMPEG_VIDEO_CLASS;
  401. Def.Priority = PRI_DEFAULT-10; // do not override ARM optimized codecs by default
  402. Def.Flags = 0; // parent size
  403. if ((i->CodecId == CODEC_ID_WMV1 && QueryPlatform(PLATFORM_WMPVERSION)!=10) || //WMP10 RGB only output -> prefer ffmpeg
  404. i->CodecId == CODEC_ID_WMV2 ||
  405. i->CodecId == CODEC_ID_WMV3)
  406. Def.Priority -= 100; // prefer DMO, WMV2 J-frames are not supported by ffmpeg, WMMX support by MS codecs are faster
  407. NodeRegisterClass(&Def);
  408. }
  409. NodeRegisterClass(&WMVF);
  410. }
  411. void FFMPEG_Done()
  412. {
  413. NodeUnRegisterClass(FFMPEG_VIDEO_CLASS);
  414. NodeUnRegisterClass(WMVF_ID);
  415. av_free_static();
  416. }
  417. //only function needed from imgconvert.c
  418. void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
  419. {
  420. switch (pix_fmt)
  421. {
  422.     case PIX_FMT_YUV420P:
  423.     case PIX_FMT_YUVJ420P:
  424. *h_shift = 1;
  425. *v_shift = 1;
  426. break;
  427.     case PIX_FMT_YUVJ422P:
  428.     case PIX_FMT_YUV422P:
  429.     case PIX_FMT_YUV422:
  430.     case PIX_FMT_UYVY422:
  431. *h_shift = 1;
  432. *v_shift = 0;
  433. break;
  434.     case PIX_FMT_YUV410P:
  435. *h_shift = 2;
  436. *v_shift = 2;
  437. break;
  438.     case PIX_FMT_YUV411P:
  439.     case PIX_FMT_UYVY411:
  440. *h_shift = 2;
  441. *v_shift = 0;
  442. break;
  443. default:
  444. *h_shift = 0;
  445. *v_shift = 0;
  446. break;
  447. }
  448. }
  449. int avpicture_fill(AVPicture *picture, uint8_t *ptr, int pix_fmt, int width, int height)
  450. {
  451. int h,v;
  452.     int size = width*height;
  453.     int sizeuv;
  454.     switch (pix_fmt) 
  455. {
  456.     case PIX_FMT_YUV410P:
  457.     case PIX_FMT_YUV411P:
  458.     case PIX_FMT_YUV420P:
  459.     case PIX_FMT_YUV422P:
  460.     case PIX_FMT_YUV444P:
  461. avcodec_get_chroma_sub_sample(pix_fmt,&h,&v);
  462.         sizeuv = RSHIFT_ROUND(width,h)*RSHIFT_ROUND(height,v);
  463.         picture->data[0] = ptr;
  464.         picture->data[1] = ptr + size;
  465.         picture->data[2] = ptr + size + sizeuv;
  466.         picture->linesize[0] = width;
  467.         picture->linesize[1] = RSHIFT_ROUND(width,h);
  468.         picture->linesize[2] = RSHIFT_ROUND(width,h);
  469.         return size + 2*sizeuv;
  470. default:
  471. assert(0);
  472. return -1;
  473.     }
  474. }
  475. int avpicture_get_size(int pix_fmt, int width, int height)
  476. {
  477.     AVPicture i;
  478.     return avpicture_fill(&i, NULL, pix_fmt, width, height);
  479. }