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

news/2024/7/10 22:23:01 标签: ffmpeg, 移动开发, git

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

最简单的基于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文件中,内容如下所示。

[cpp]  view plain  copy
 
  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.   
  19. #import "ViewController.h"  
  20. #include <libavcodec/avcodec.h>  
  21. #include <libavformat/avformat.h>  
  22. #include <libavutil/imgutils.h>  
  23. #include <libswscale/swscale.h>  
  24.   
  25. @interface ViewController ()  
  26.   
  27. @end  
  28.   
  29. @implementation ViewController  
  30.   
  31. - (void)viewDidLoad {  
  32.     [super viewDidLoad];  
  33.     // Do any additional setup after loading the view, typically from a nib.  
  34. }  
  35.   
  36. - (void)didReceiveMemoryWarning {  
  37.     [super didReceiveMemoryWarning];  
  38.     // Dispose of any resources that can be recreated.  
  39. }  
  40.   
  41. - (IBAction)clickDecodeButton:(id)sender {  
  42.     AVFormatContext *pFormatCtx;  
  43.     int             i, videoindex;  
  44.     AVCodecContext  *pCodecCtx;  
  45.     AVCodec         *pCodec;  
  46.     AVFrame *pFrame,*pFrameYUV;  
  47.     uint8_t *out_buffer;  
  48.     AVPacket *packet;  
  49.     int y_size;  
  50.     int ret, got_picture;  
  51.     struct SwsContext *img_convert_ctx;  
  52.     FILE *fp_yuv;  
  53.     int frame_cnt;  
  54.     clock_t time_start, time_finish;  
  55.     double  time_duration = 0.0;  
  56.       
  57.     char input_str_full[500]={0};  
  58.     char output_str_full[500]={0};  
  59.     char info[1000]={0};  
  60.       
  61.     NSString *input_str= [NSString stringWithFormat:@"resource.bundle/%@",self.inputurl.text];  
  62.     NSString *output_str= [NSString stringWithFormat:@"resource.bundle/%@",self.outputurl.text];  
  63.       
  64.     NSString *input_nsstr=[[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:input_str];  
  65.     NSString *output_nsstr=[[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:output_str];  
  66.       
  67.     sprintf(input_str_full,"%s",[input_nsstr UTF8String]);  
  68.     sprintf(output_str_full,"%s",[output_nsstr UTF8String]);  
  69.       
  70.     printf("Input Path:%s\n",input_str_full);  
  71.     printf("Output Path:%s\n",output_str_full);  
  72.       
  73.     av_register_all();  
  74.     avformat_network_init();  
  75.     pFormatCtx = avformat_alloc_context();  
  76.       
  77.     if(avformat_open_input(&pFormatCtx,input_str_full,NULL,NULL)!=0){  
  78.         printf("Couldn't open input stream.\n");  
  79.         return ;  
  80.     }  
  81.     if(avformat_find_stream_info(pFormatCtx,NULL)<0){  
  82.         printf("Couldn't find stream information.\n");  
  83.         return;  
  84.     }  
  85.     videoindex=-1;  
  86.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  87.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){  
  88.             videoindex=i;  
  89.             break;  
  90.         }  
  91.     if(videoindex==-1){  
  92.         printf("Couldn't find a video stream.\n");  
  93.         return;  
  94.     }  
  95.     pCodecCtx=pFormatCtx->streams[videoindex]->codec;  
  96.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  97.     if(pCodec==NULL){  
  98.         printf("Couldn't find Codec.\n");  
  99.         return;  
  100.     }  
  101.     if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){  
  102.         printf("Couldn't open codec.\n");  
  103.         return;  
  104.     }  
  105.       
  106.     pFrame=av_frame_alloc();  
  107.     pFrameYUV=av_frame_alloc();  
  108.     out_buffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,  pCodecCtx->width, pCodecCtx->height,1));  
  109.     av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize,out_buffer,  
  110.                          AV_PIX_FMT_YUV420P,pCodecCtx->width, pCodecCtx->height,1);  
  111.     packet=(AVPacket *)av_malloc(sizeof(AVPacket));  
  112.       
  113.     img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,  
  114.                                      pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);  
  115.       
  116.       
  117.     sprintf(info,   "[Input     ]%s\n", [input_str UTF8String]);  
  118.     sprintf(info, "%s[Output    ]%s\n",info,[output_str UTF8String]);  
  119.     sprintf(info, "%s[Format    ]%s\n",info, pFormatCtx->iformat->name);  
  120.     sprintf(info, "%s[Codec     ]%s\n",info, pCodecCtx->codec->name);  
  121.     sprintf(info, "%s[Resolution]%dx%d\n",info, pCodecCtx->width,pCodecCtx->height);  
  122.       
  123.       
  124.     fp_yuv=fopen(output_str_full,"wb+");  
  125.     if(fp_yuv==NULL){  
  126.         printf("Cannot open output file.\n");  
  127.         return;  
  128.     }  
  129.       
  130.     frame_cnt=0;  
  131.     time_start = clock();  
  132.       
  133.     while(av_read_frame(pFormatCtx, packet)>=0){  
  134.         if(packet->stream_index==videoindex){  
  135.             ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);  
  136.             if(ret < 0){  
  137.                 printf("Decode Error.\n");  
  138.                 return;  
  139.             }  
  140.             if(got_picture){  
  141.                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,  
  142.                           pFrameYUV->data, pFrameYUV->linesize);  
  143.                   
  144.                 y_size=pCodecCtx->width*pCodecCtx->height;  
  145.                 fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y  
  146.                 fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U  
  147.                 fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V  
  148.                 //Output info  
  149.                 char pictype_str[10]={0};  
  150.                 switch(pFrame->pict_type){  
  151.                     case AV_PICTURE_TYPE_I:sprintf(pictype_str,"I");break;  
  152.                     case AV_PICTURE_TYPE_P:sprintf(pictype_str,"P");break;  
  153.                     case AV_PICTURE_TYPE_B:sprintf(pictype_str,"B");break;  
  154.                     default:sprintf(pictype_str,"Other");break;  
  155.                 }  
  156.                 printf("Frame Index: %5d. Type:%s\n",frame_cnt,pictype_str);  
  157.                 frame_cnt++;  
  158.             }  
  159.         }  
  160.         av_free_packet(packet);  
  161.     }  
  162.     //flush decoder  
  163.     //FIX: Flush Frames remained in Codec  
  164.     while (1) {  
  165.         ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);  
  166.         if (ret < 0)  
  167.             break;  
  168.         if (!got_picture)  
  169.             break;  
  170.         sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,  
  171.                   pFrameYUV->data, pFrameYUV->linesize);  
  172.         int y_size=pCodecCtx->width*pCodecCtx->height;  
  173.         fwrite(pFrameYUV->data[0],1,y_size,fp_yuv);    //Y  
  174.         fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv);  //U  
  175.         fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv);  //V  
  176.         //Output info  
  177.         char pictype_str[10]={0};  
  178.         switch(pFrame->pict_type){  
  179.             case AV_PICTURE_TYPE_I:sprintf(pictype_str,"I");break;  
  180.             case AV_PICTURE_TYPE_P:sprintf(pictype_str,"P");break;  
  181.             case AV_PICTURE_TYPE_B:sprintf(pictype_str,"B");break;  
  182.             default:sprintf(pictype_str,"Other");break;  
  183.         }  
  184.         printf("Frame Index: %5d. Type:%s\n",frame_cnt,pictype_str);  
  185.         frame_cnt++;  
  186.     }  
  187.     time_finish = clock();   
  188.     time_duration=(double)(time_finish - time_start);  
  189.       
  190.     sprintf(info, "%s[Time      ]%fus\n",info,time_duration);  
  191.     sprintf(info, "%s[Count     ]%d\n",info,frame_cnt);  
  192.       
  193.     sws_freeContext(img_convert_ctx);  
  194.       
  195.     fclose(fp_yuv);  
  196.       
  197.     av_frame_free(&pFrameYUV);  
  198.     av_frame_free(&pFrame);  
  199.     avcodec_close(pCodecCtx);  
  200.     avformat_close_input(&pFormatCtx);  
  201.       
  202.     NSString * info_ns = [NSString stringWithFormat:@"%s", info];  
  203.     self.infomation.text=info_ns;  
  204.   
  205. }  
  206.   
  207.   
  208. @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

转载于:https://www.cnblogs.com/haohao-developer/p/5417264.html


http://www.niftyadmin.cn/n/1420574.html

相关文章

Unity WebGL发布无法运行问题

问题1&#xff1a; It seems your browser does not support running Unity WebGL content from file:// urls. Please upload it to an http server, or try a different browser. 解决方案&#xff1a; 在 火狐浏览器里面设置&#xff1a; Mozilla firefox&#xff08;火…

安装Appium

1.Appium官方网站&#xff1a;http://appium.io/ 拉到页面底端显示下面一段描述&#xff1a; > brew install node # get node.js > npm install -g appium # get appium > npm install wd # get appium client > appium & # star…

html2canvas 阿里云图片没显示_最强markdown编辑器typora图床教程- 阿里云版

史上最稳定的图床工具 - 阿里云 之 typora图床教程最终篇之前陆续更新了typora图床教程的smms版和七牛云版&#xff0c;本着做事做全套的精神&#xff0c;我又来更新了。这次更新的是用阿里云作为图床。 保证是全中国最稳的图床工具人了。我估计等我敲不动代码了&#xff0c;阿…

Windows平台下搭建自己的Git服务器

实测 真实可用&#xff1a; 如何在windows上搭建私有git服务器_xyq54的博客-CSDN博客_服务器上搭建git服务 注意&#xff1a; 执行netstat -ano可以看到所有被占用的端口&#xff0c;执行netstat -ano | findstr 1010 可以看到1010端口是否被占用 文章转载&#xff1a;Windows…

Android——自定义视图(一)转

首先&#xff0c;建立一个Android工程&#xff0c;命名MyView。 然后&#xff0c;自定义一个类myView&#xff0c;继承View类。代码如下 package com.android.randy.viewDemo; import android.content.Context; import android.graphics.Canvas; import android.graphics.…

如何打开sln文件并显示窗口_在本机打开别人的sln文件

sln:在开发环境中使用的解决方案文件。它将一个或多个项目的所有元素组织到单个的解决方案中。此文件存储在父项目目录中.解决方案文件&#xff0c;他是一个或多个.proj(项目)的集合呵呵&#xff0c;今天没带书&#xff0c;就去网上找了个ASP.NET的源代码&#xff0c;叫简单实用…

git 与tortoiseGit 相关知识和概念

master &#xff1a;代表主分支 head :每一个分支都有一个head&#xff0c;代表指向当前分支的引用&#xff0c;每次提交或者推送&#xff0c;都会生成一个版本&#xff0c;然后head就指向新生成的版本&#xff0c; 一般都是将其他分支合并到master主分支上 注意&#xff1a…

Linux 命令的举例需求及解答步骤

1.在/usr/local/创建3个文件夹以1.2.3命名&#xff0c;在1下面有a,a下面有b,b下面有c&#xff0c;c下面有个文件叫做2.txt,里面是一句歌词&#xff1a;姐是老中医&#xff0c;专治吹牛逼。查询创建递归创建文件vim编辑器---设计输入法或者远程字符集编码的问题保存2.把1文件目录…