=====================================================

最简单的基于FFmpeg的移动端例子系列文章列表:

最简单的基于FFmpeg的移动端例子:Android HelloWorld

最简单的基于FFmpeg的移动端例子:Android 视频解码器

最简单的基于FFmpeg的移动端例子:Android 视频解码器-单个库版

最简单的基于FFmpeg的移动端例子:Android 推流器

最简单的基于FFmpeg的移动端例子:Android 视频转码器

最简单的基于FFmpeg的移动端例子附件:Android 自带播放器

最简单的基于FFmpeg的移动端例子附件:SDL Android HelloWorld

最简单的基于FFmpeg的移动端例子:IOS HelloWorld

最简单的基于FFmpeg的移动端例子:IOS 视频解码器

最简单的基于FFmpeg的移动端例子:IOS 推流器

最简单的基于FFmpeg的移动端例子:IOS 视频转码器

最简单的基于FFmpeg的移动端例子附件:IOS自带播放器

最简单的基于FFmpeg的移动端例子:Windows Phone HelloWorld

=====================================================

本文记录iOS平台下基于FFmpeg的视频解码器。该示例C语言的源代码来自于《最简单的基于FFMPEG+SDL的视频播放器》。相关的概念就不再重复记录了。

源代码

项目的目录结构如图所示。

C代码位于ViewController.m文件中,内容如下所示。

  1. /**
  2. * 最简单的基于FFmpeg的视频解码器-IOS
  3. * Simplest FFmpeg IOS Decoder
  4. *
  5. * 雷霄骅 Lei Xiaohua
  6. * leixiaohua1020@126.com
  7. * 中国传媒大学/数字电视技术
  8. * Communication University of China / Digital TV Technology
  9. * http://blog.csdn.net/leixiaohua1020
  10. *
  11. * 本程序是IOS平台下最简单的基于FFmpeg的视频解码器。
  12. * 它可以将输入的视频数据解码成YUV像素数据。
  13. *
  14. * This software is the simplest decoder based on FFmpeg in IOS.
  15. * It can decode video stream to raw YUV data.
  16. *
  17. */
  18. #import "ViewController.h"
  19. #include <libavcodec/avcodec.h>
  20. #include <libavformat/avformat.h>
  21. #include <libavutil/imgutils.h>
  22. #include <libswscale/swscale.h>
  23. @interface ViewController ()
  24. @end
  25. @implementation ViewController
  26. - (void)viewDidLoad {
  27. [super viewDidLoad];
  28. // Do any additional setup after loading the view, typically from a nib.
  29. }
  30. - (void)didReceiveMemoryWarning {
  31. [super didReceiveMemoryWarning];
  32. // Dispose of any resources that can be recreated.
  33. }
  34. - (IBAction)clickDecodeButton:(id)sender {
  35. AVFormatContext *pFormatCtx;
  36. int             i, videoindex;
  37. AVCodecContext  *pCodecCtx;
  38. AVCodec         *pCodec;
  39. AVFrame *pFrame,*pFrameYUV;
  40. uint8_t *out_buffer;
  41. AVPacket *packet;
  42. int y_size;
  43. int ret, got_picture;
  44. struct SwsContext *img_convert_ctx;
  45. FILE *fp_yuv;
  46. int frame_cnt;
  47. clock_t time_start, time_finish;
  48. double  time_duration = 0.0;
  49. char input_str_full[500]={0};
  50. char output_str_full[500]={0};
  51. char info[1000]={0};
  52. NSString *input_str= [NSString stringWithFormat:@"resource.bundle/%@",self.inputurl.text];
  53. NSString *output_str= [NSString stringWithFormat:@"resource.bundle/%@",self.outputurl.text];
  54. NSString *input_nsstr=[[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:input_str];
  55. NSString *output_nsstr=[[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:output_str];
  56. sprintf(input_str_full,"%s",[input_nsstr UTF8String]);
  57. sprintf(output_str_full,"%s",[output_nsstr UTF8String]);
  58. printf("Input Path:%s\n",input_str_full);
  59. printf("Output Path:%s\n",output_str_full);
  60. av_register_all();
  61. avformat_network_init();
  62. pFormatCtx = avformat_alloc_context();
  63. if(avformat_open_input(&pFormatCtx,input_str_full,NULL,NULL)!=0){
  64. printf("Couldn't open input stream.\n");
  65. return ;
  66. }
  67. if(avformat_find_stream_info(pFormatCtx,NULL)<0){
  68. printf("Couldn't find stream information.\n");
  69. return;
  70. }
  71. videoindex=-1;
  72. for(i=0; i<pFormatCtx->nb_streams; i++)
  73. if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
  74. videoindex=i;
  75. break;
  76. }
  77. if(videoindex==-1){
  78. printf("Couldn't find a video stream.\n");
  79. return;
  80. }
  81. pCodecCtx=pFormatCtx->streams[videoindex]->codec;
  82. pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  83. if(pCodec==NULL){
  84. printf("Couldn't find Codec.\n");
  85. return;
  86. }
  87. if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){
  88. printf("Couldn't open codec.\n");
  89. return;
  90. }
  91. pFrame=av_frame_alloc();
  92. pFrameYUV=av_frame_alloc();
  93. out_buffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,  pCodecCtx->width, pCodecCtx->height,1));
  94. av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize,out_buffer,
  95. AV_PIX_FMT_YUV420P,pCodecCtx->width, pCodecCtx->height,1);
  96. packet=(AVPacket *)av_malloc(sizeof(AVPacket));
  97. img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
  98. pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
  99. sprintf(info,   "[Input     ]%s\n", [input_str UTF8String]);
  100. sprintf(info, "%s[Output    ]%s\n",info,[output_str UTF8String]);
  101. sprintf(info, "%s[Format    ]%s\n",info, pFormatCtx->iformat->name);
  102. sprintf(info, "%s[Codec     ]%s\n",info, pCodecCtx->codec->name);
  103. sprintf(info, "%s[Resolution]%dx%d\n",info, pCodecCtx->width,pCodecCtx->height);
  104. fp_yuv=fopen(output_str_full,"wb+");
  105. if(fp_yuv==NULL){
  106. printf("Cannot open output file.\n");
  107. return;
  108. }
  109. frame_cnt=0;
  110. time_start = clock();
  111. while(av_read_frame(pFormatCtx, packet)>=0){
  112. if(packet->stream_index==videoindex){
  113. ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
  114. if(ret < 0){
  115. printf("Decode Error.\n");
  116. return;
  117. }
  118. if(got_picture){
  119. sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
  120. pFrameYUV->data, pFrameYUV->linesize);
  121. y_size=pCodecCtx->width*pCodecCtx->height;
  122. fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y
  123. fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U
  124. fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V
  125. //Output info
  126. char pictype_str[10]={0};
  127. switch(pFrame->pict_type){
  128. case AV_PICTURE_TYPE_I:sprintf(pictype_str,"I");break;
  129. case AV_PICTURE_TYPE_P:sprintf(pictype_str,"P");break;
  130. case AV_PICTURE_TYPE_B:sprintf(pictype_str,"B");break;
  131. default:sprintf(pictype_str,"Other");break;
  132. }
  133. printf("Frame Index: %5d. Type:%s\n",frame_cnt,pictype_str);
  134. frame_cnt++;
  135. }
  136. }
  137. av_free_packet(packet);
  138. }
  139. //flush decoder
  140. //FIX: Flush Frames remained in Codec
  141. while (1) {
  142. ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
  143. if (ret < 0)
  144. break;
  145. if (!got_picture)
  146. break;
  147. sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
  148. pFrameYUV->data, pFrameYUV->linesize);
  149. int y_size=pCodecCtx->width*pCodecCtx->height;
  150. fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y
  151. fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U
  152. fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V
  153. //Output info
  154. char pictype_str[10]={0};
  155. switch(pFrame->pict_type){
  156. case AV_PICTURE_TYPE_I:sprintf(pictype_str,"I");break;
  157. case AV_PICTURE_TYPE_P:sprintf(pictype_str,"P");break;
  158. case AV_PICTURE_TYPE_B:sprintf(pictype_str,"B");break;
  159. default:sprintf(pictype_str,"Other");break;
  160. }
  161. printf("Frame Index: %5d. Type:%s\n",frame_cnt,pictype_str);
  162. frame_cnt++;
  163. }
  164. time_finish = clock();
  165. time_duration=(double)(time_finish - time_start);
  166. sprintf(info, "%s[Time      ]%fus\n",info,time_duration);
  167. sprintf(info, "%s[Count     ]%d\n",info,frame_cnt);
  168. sws_freeContext(img_convert_ctx);
  169. fclose(fp_yuv);
  170. av_frame_free(&pFrameYUV);
  171. av_frame_free(&pFrame);
  172. avcodec_close(pCodecCtx);
  173. avformat_close_input(&pFormatCtx);
  174. NSString * info_ns = [NSString stringWithFormat:@"%s", info];
  175. self.infomation.text=info_ns;
  176. }
  177. @end

运行结果

App在手机上运行后的结果如下图所示。单击“Decode”,将会把位于resource.bundle中的“sintel.mov”文件解码为“sintel.yuv”文件并存储于相同的目录下。

生成的文件如下图所示。

 

下载

simplest ffmpeg mobile

项目主页

Github:https://github.com/leixiaohua1020/simplest_ffmpeg_mobile

开源中国:https://git.oschina.net/leixiaohua1020/simplest_ffmpeg_mobile

SourceForge:https://sourceforge.net/projects/simplestffmpegmobile/

CSDN工程下载地址:http://download.csdn.net/detail/leixiaohua1020/8924391

本解决方案包含了使用FFmpeg在移动端处理多媒体的各种例子:

转至:http://blog.csdn.net/leixiaohua1020/article/details/47072257

最简单的基于FFmpeg的移动端例子:IOS 视频解码器-保存的更多相关文章

  1. 最简单的基于FFmpeg的移动端例子:IOS 视频转码器

    ===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...

  2. 最简单的基于FFmpeg的移动端例子:IOS 推流器

    转至:http://blog.csdn.net/leixiaohua1020/article/details/47072519   ================================== ...

  3. 最简单的基于FFmpeg的移动端例子:Android 视频转码器

    http://blog.csdn.net/leixiaohua1020/article/details/47056365

  4. 最简单的基于FFmpeg的移动端样例:Android 视频解码器-单个库版

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  5. 最简单的基于FFmpeg的移动端样例:IOS 视频解码器

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  6. 最简单的基于FFmpeg的移动端样例附件:Android 自带播放器

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  7. 最简单的基于FFmpeg的移动端样例附件:SDL Android HelloWorld

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  8. 最简单的基于FFmpeg的移动端样例:IOS 视频转码器

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  9. 最简单的基于FFmpeg的移动端样例:Android HelloWorld

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

随机推荐

  1. LeetCode 面试:Add Binary

    1 题目 Given two binary strings, return their sum (also a binary string). For example,a = "11&quo ...

  2. poj3580

    区间操作的究极题,我们一个个来分析其实只有insert,delete,revolve三种没讲过insert 先把x旋到根,一开始我比较SB的,准备把新节点插入到右子树的最左节点,这显然很烦 好的方法是 ...

  3. poj2482

    (题外话:这题这是ACMer的福利啊……)我非常不擅长做矩形类的数据结构一般来说,二维的问题我们要转化为一维来考虑感觉一般的手法是对一维排序,并且线性扫描这一维,然后用各种数据结构维护另一维上的最优值 ...

  4. 【转】MFC下拉列表框的用法

    原文网址:http://blog.csdn.net/kinglimy/article/details/6452239 Combo Box (组合框)控件很简单,可以节省空间.从用户角度来看,这个控件是 ...

  5. NVIDIA CG语言 函数之所有数学类函数(Mathematical Functions)

    数学类函数(Mathematical Functions) abs(x) 返回标量和向量x的绝对值 如果x是向量,则返回每一个成员的绝对值 acos(x) 返回标量和向量x的反余弦 x的范围是[-1, ...

  6. 基于Processing的数据可视化

    虽然数据可视化领域有很多成熟.界面友好.功能强大的软件产品(例如Tableau.VIDI.NodeXL等),但是借助Processing我们可以基于Java语言框架进行丰富多元的可视化编程,熟悉了Pr ...

  7. ClientScriptManager与ScriptManager向客户端注册脚本的区别

    使用ClientScriptManager向客户端注册脚本 ClientScriptManager在非异步(就是说非AJAX)环境下使用的.如果要在异步环境下注册脚本应该使用ScriptManager ...

  8. YUV像素和ycbcr

    一幅彩色图像的基本要素是什么? 说白了,一幅图像包括的基本东西就是二进制数据,其容量大小实质即为二进制数据的多少.一幅1920x1080像素的YUV422的图像,大小是1920X1080X2=4147 ...

  9. Java 操作 EXCEL

    今天帮朋友写了一段用来处理EXCEL内容的程序,在这里记录下自己的学习过程.主要是对EXCEL表格中的内容做分类和统计,使用计算机来做这种重复的机械性地工作再好不过了.首先,我们需要下载一个java操 ...

  10. poj 1228 凸包

    题目链接:http://poj.org/problem?id=1228 #include<cstdio> #include<cstring> #include<cmath ...