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

最简单的基于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. 【HDOJ】4612 Warm up

    双连通缩点+求树的直径,图论基础题目. /* 4612 */ #pragma comment(linker, "/STACK:1024000000,1024000000") #in ...

  2. [LeetCode#252] Meeting Rooms

    Problem: Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2] ...

  3. Win32中常用消息

    一 .WM_PAINT消息 1 WM_PAINT的产生   由于窗口的互相覆盖等,产生需要绘制的区域,那么会产生WM_PAINT消息. 一般情况下,不直接发送WM_PAINT消息,通过API声明需要绘 ...

  4. Linux给用户增加sudo权限

    有时候我们在Linux下执行sudo的时候,出现 xxx is not int the sudoers file 告诉我们当前用户不是sudoer,所以我们要把当前用户添加进去,步骤如下: 1.进入超 ...

  5. GPUImage实现过程

    GPUImage就是一个函数的类库,用于对图片实现滤镜的效果. 下面是实现一个最简单的GPUImage的程序和讲解: 首先新建一个项目,导入GPUImage类库(导入过程在我的另一个博客里面有写). ...

  6. Intersection - POJ 1410(线段与矩形是否相交)

    题目大意:给一个线段和一个矩形,判断线段是否和矩形有公共点.   分析:用矩形的四个边当线段判断与所给的线段是否有交点,需要注意的是给的矩形是不标准的,需要自己转换,还需要注意线段有可能在矩形内部. ...

  7. 用Autohotkey让powerpoint幻灯片一直播放

    有台电脑专门接了个大电视循环播放一个幻灯片,但是有时候会弹出一些对话框,比如windows要更新之类的,这样的话powerpoint就不是active的进城了,这样幻灯片就会停下来,还需要人去手动点一 ...

  8. ios面试题整理

    (1).weak 和assign的区别? assign: 用于非指针变量 (2).IOS开发之----#import.#include和@class的区别? 1. 如果不是c/c++,尽量用#impo ...

  9. 基于Visual C++2012拆解世界五百强面试题--题3

    请用C语言实现 输入N,打印N*N矩阵 比如 N = 3, 打印: 1 2 3 8 9 4 7 6 5 N = 4, 打印 1   2    3   4 12  13   14  5 11  16   ...

  10. otg线是什么,otg线和数据线的区别介绍

    OTG是什么? OTG主要应用于各种不同的设备或移动设备间的联接,进行数据交换.USB技术的发展,使得PC和周边设备能够通过简单方式.适度的制造成本将各种数 据传输速度的设备连接在一起.上述我们的应用 ...