详解FFMPEG API

认识FFmpeg

 

FFMPEG堪称自由软件中最完备的一套多媒体支持库,它几乎实现了所有当下常见的数据封装格式、多媒体传输协议以及音视频编解码器。因此,对于从事多媒体技术开发的工程师来说,深入研究FFMPEG成为一门必不可少的工作,可以这样说,FFMPEG之于多媒体开发工程师的重要性正如kernel之于嵌入式系统工程师一般。

几个小知识:

  • FFMPEG项目是由法国人Fabrice Bellard发起的,此人也是著名的CPU模拟器项目QEMU的发起者,同时还是圆周率算法纪录的保持者。

  • FF是Fast Forward的意思,翻译成中文是“快进”。

  • FFMPEG的LOGO是一个”Z字扫描”示意图,Z字扫描用于将图像的二维频域数据一维化,同时保证了一维化的数据具备良好的统计特性,从而提高其后要进行的一维熵编码的效率。

关于耻辱柱(Hall of Shame):FFMpeg大部分代码遵循LGPL许可证,如果使用者对FFMpeg进行了修改,要求公布修改的源代码;有少部分代码遵循GPL许可证,要求使用者同时公开使用FFMpeg的软件的源代码。实际上,除去部分大的系统软件开发商(Microsoft、Apple等)以及某些著名的音视频服务提供商(Divx、Real等)提供的自有播放器之外,绝大部分第三方开发的播放器都离不开FFMpeg的支持,像Linux桌面环境中的开源播放器VLC、MPlayer,Windows下的KMPlayer、暴风影音以及Android下几乎全部第三方播放器都是基于FFMpeg的。也有许多看似具备自主技术的播放器,其实也都不声不响地使用了FFMpeg,这种行为被称为“盗窃”,参与“盗窃”的公司的名字则被刻在耻辱柱上,国产播放器暴风影音、QQ影音于2009年上榜。

示例程序

 

[html] view plaincopy

  1. <span style="font-size:18px;">解码:</span>  
  2.   
  3. #include <stdio.h>  
  4. #include <string.h>  
  5. #include <stdlib.h>  
  6.    
  7. #include <sys/time.h>  
  8.    
  9. #include "libavutil/avstring.h"  
  10. #include "libavformat/avformat.h"  
  11. #include "libavdevice/avdevice.h"  
  12. #include "libavutil/opt.h"  
  13. #include "libswscale/swscale.h"  
  14.    
  15. #define DECODED_AUDIO_BUFFER_SIZE            192000  
  16.    
  17. struct options  
  18. {  
  19.     int streamId;  
  20.     int frames;  
  21.     int nodec;  
  22.     int bplay;  
  23.     int thread_count;  
  24.     int64_t lstart;  
  25.     char finput[256];  
  26.     char foutput1[256];  
  27.     char foutput2[256];  
  28. };  
  29.    
  30. int parse_options(struct options *opts, int argc, char** argv)  
  31. {  
  32.     int optidx;  
  33.     char *optstr;  
  34.    
  35.     if (argc < 2) return -1;  
  36.    
  37.     opts->streamId = -1;  
  38.     opts->lstart = -1;  
  39.     opts->frames = -1;  
  40.     opts->foutput1[0] = 0;  
  41.     opts->foutput2[0] = 0;  
  42.     opts->nodec = 0;  
  43.     opts->bplay = 0;  
  44.     opts->thread_count = 0;  
  45.     strcpy(opts->finput, argv[1]);  
  46.    
  47.     optidx = 2;  
  48.     while (optidx < argc)  
  49.     {  
  50.         optstr = argv[optidx++];  
  51.         if (*optstr++ != '-') return -1;  
  52.         switch (*optstr++)  
  53.         {  
  54.         case 's':  //< stream id  
  55.             opts->streamId = atoi(optstr);  
  56.             break;  
  57.         case 'f':  //< frames  
  58.             opts->frames = atoi(optstr);  
  59.             break;  
  60.         case 'k':  //< skipped  
  61.             opts->lstart = atoll(optstr);  
  62.             break;  
  63.         case 'o':  //< output  
  64.             strcpy(opts->foutput1, optstr);  
  65.             strcat(opts->foutput1, ".mpg");  
  66.             strcpy(opts->foutput2, optstr);  
  67.             strcat(opts->foutput2, ".raw");  
  68.             break;  
  69.         case 'n': //decoding and output options  
  70.             if (strcmp("dec", optstr) == 0)  
  71.                 opts->nodec = 1;  
  72.             break;  
  73.         case 'p':  
  74.             opts->bplay = 1;  
  75.             break;  
  76.         case 't':  
  77.             opts->thread_count = atoi(optstr);  
  78.             break;  
  79.         default:  
  80.             return -1;  
  81.         }  
  82.     }  
  83.    
  84.     return 0;  
  85. }  
  86.    
  87. void show_help(char* program)  
  88. {  
  89.     printf("Simple FFMPEG test program\n");  
  90.     printf("Usage: %s inputfile [-sstreamid [-fframes] [-kskipped] [-ooutput_filename(without extension)] [-ndec] [-p] [-tthread_count]]\n",  
  91.            program);  
  92.     return;  
  93. }  
  94.    
  95. static void log_callback(void* ptr, int level, const char* fmt, va_list vl)  
  96. {  
  97.     vfprintf(stdout, fmt, vl);  
  98. }  
  99.    
  100. /*  
  101. * audio renderer code (oss)  
  102. */  
  103. #include <sys/ioctl.h>  
  104. #include <unistd.h>  
  105. #include <fcntl.h>  
  106. #include <sys/soundcard.h>  
  107.    
  108. #define OSS_DEVICE "/dev/dsp0"  
  109.    
  110. struct audio_dsp  
  111. {  
  112.     int audio_fd;  
  113.     int channels;  
  114.     int format;  
  115.     int speed;  
  116. };  
  117. int map_formats(enum AVSampleFormat format)  
  118. {  
  119.     switch(format)  
  120.     {  
  121.         case AV_SAMPLE_FMT_U8:  
  122.             return AFMT_U8;  
  123.         case AV_SAMPLE_FMT_S16:  
  124.             return AFMT_S16_LE;  
  125.         default:  
  126.             return AFMT_U8;   
  127.     }  
  128. }  
  129. int set_audio(struct audio_dsp* dsp)  
  130. {  
  131.     if (dsp->audio_fd == -1)  
  132.     {  
  133.         printf("Invalid audio dsp id!\n");  
  134.         return -1;  
  135.     }      
  136.    
  137.     if (-1 == ioctl(dsp->audio_fd, SNDCTL_DSP_SETFMT, &dsp->format))  
  138.     {  
  139.         printf("Failed to set dsp format!\n");  
  140.         return -1;  
  141.     }  
  142.    
  143.     if (-1 == ioctl(dsp->audio_fd, SNDCTL_DSP_CHANNELS, &dsp->channels))  
  144.     {  
  145.         printf("Failed to set dsp format!\n");  
  146.         return -1;  
  147.     }  
  148.    
  149.     if (-1 == ioctl(dsp->audio_fd, SNDCTL_DSP_SPEED, &dsp->speed))  
  150.     {  
  151.         printf("Failed to set dsp format!\n");  
  152.         return -1;  
  153.     }      
  154.     return 0;  
  155. }  
  156.    
  157. int play_pcm(struct audio_dsp* dsp, unsigned char *buf, int size)  
  158. {  
  159.     if (dsp->audio_fd == -1)  
  160.     {  
  161.         printf("Invalid audio dsp id!\n");  
  162.         return -1;  
  163.     }  
  164.    
  165.     if (-1 == write(dsp->audio_fd, buf, size))  
  166.     {  
  167.         printf("Failed to write audio dsp!\n");  
  168.         return -1;  
  169.     }  
  170.    
  171.     return 0;  
  172. }  
  173. /* audio renderer code end */  
  174.    
  175. /* video renderer code*/  
  176. #include <linux/fb.h>  
  177. #include <sys/mman.h>  
  178.    
  179. #define FB_DEVICE "/dev/fb0"  
  180.    
  181. enum pic_format  
  182. {  
  183.     eYUV_420_Planer,  
  184. };  
  185. struct video_fb  
  186. {  
  187.     int video_fd;  
  188.     struct fb_var_screeninfo vinfo;  
  189.     struct fb_fix_screeninfo finfo;  
  190.     unsigned char *fbp;  
  191.     AVFrame *frameRGB;  
  192.     struct   
  193.     {  
  194.         int x;  
  195.         int y;  
  196.     } video_pos;  
  197. };  
  198.    
  199. int open_video(struct video_fb *fb, int x, int y)  
  200. {  
  201.     int screensize;  
  202.     fb->video_fd = open(FB_DEVICE, O_WRONLY);  
  203.     if (fb->video_fd == -1) return -1;  
  204.    
  205.     if (ioctl(fb->video_fd, FBIOGET_FSCREENINFO, &fb->finfo)) return -2;  
  206.     if (ioctl(fb->video_fd, FBIOGET_VSCREENINFO, &fb->vinfo)) return -2;  
  207.    
  208.    
  209.     printf("video device: resolution %dx%d, %dbpp\n", fb->vinfo.xres, fb->vinfo.yres, fb->vinfo.bits_per_pixel);  
  210.     screensize = fb->vinfo.xres * fb->vinfo.yres * fb->vinfo.bits_per_pixel / 8;  
  211.     fb->fbp = (unsigned char *) mmap(0, screensize, PROT_READ|PROT_WRITE, MAP_SHARED, fb->video_fd, 0);  
  212.     if (fb->fbp == -1) return -3;  
  213.    
  214.     if (x >= fb->vinfo.xres || y >= fb->vinfo.yres)  
  215.     {  
  216.         return -4;  
  217.     }  
  218.     else  
  219.     {  
  220.         fb->video_pos.x = x;  
  221.         fb->video_pos.y = y;  
  222.     }  
  223.    
  224.     fb->frameRGB = avcodec_alloc_frame();  
  225.     if (!fb->frameRGB) return -5;  
  226.    
  227.     return 0;  
  228. }  
  229.    
  230. /* only 420P supported now */  
  231. int show_picture(struct video_fb *fb, AVFrame *frame, int width, int height, enum pic_format format)  
  232. {  
  233.     struct SwsContext *sws;  
  234.     int i;  
  235.     unsigned char *dest;  
  236.     unsigned char *src;  
  237.    
  238.     if (fb->video_fd == -1) return -1;  
  239.     if ((fb->video_pos.x >= fb->vinfo.xres) || (fb->video_pos.y >= fb->vinfo.yres)) return -2;  
  240.    
  241.     if (fb->video_pos.x + width > fb->vinfo.xres)  
  242.     {  
  243.         width = fb->vinfo.xres - fb->video_pos.x;  
  244.     }  
  245.     if (fb->video_pos.y + height > fb->vinfo.yres)  
  246.     {  
  247.         height = fb->vinfo.yres - fb->video_pos.y;  
  248.     }  
  249.    
  250.     if (format == PIX_FMT_YUV420P)  
  251.     {  
  252.         sws = sws_getContext(width, height, format, width, height, PIX_FMT_RGB32, SWS_FAST_BILINEAR, NULL, NULL, NULL);  
  253.         if (sws == 0)  
  254.         {  
  255.             return -3;  
  256.         }  
  257.         if (sws_scale(sws, frame->data, frame->linesize, 0, height, fb->frameRGB->data, fb->frameRGB->linesize))  
  258.         {  
  259.             return -3;  
  260.         }  
  261.    
  262.         dest = fb->fbp + (fb->video_pos.x+fb->vinfo.xoffset) * (fb->vinfo.bits_per_pixel/8) +(fb->video_pos.y+fb->vinfo.yoffset) * fb->finfo.line_length;  
  263.         for (i = 0; i < height; i++)  
  264.         {  
  265.             memcpy(dest, src, width*4);  
  266.             src += fb->frameRGB->linesize[0];  
  267.             dest += fb->finfo.line_length;  
  268.         }  
  269.     }  
  270.     return 0;  
  271. }  
  272.    
  273. void close_video(struct video_fb *fb)  
  274. {  
  275.     if (fb->video_fd != -1)   
  276.     {  
  277.         munmap(fb->fbp, fb->vinfo.xres * fb->vinfo.yres * fb->vinfo.bits_per_pixel / 8);  
  278.         close(fb->video_fd);  
  279.         fb->video_fd = -1;  
  280.     }  
  281. }  
  282. /* video renderer code end */  
  283.    
  284. int main(int argc, char **argv)  
  285. {  
  286.     AVFormatContext* pCtx = 0;  
  287.     AVCodecContext *pCodecCtx = 0;  
  288.     AVCodec *pCodec = 0;  
  289.     AVPacket packet;  
  290.     AVFrame *pFrame = 0;  
  291.     FILE *fpo1 = NULL;  
  292.     FILE *fpo2 = NULL;  
  293.     int nframe;  
  294.     int err;  
  295.     int got_picture;  
  296.     int picwidth, picheight, linesize;  
  297.     unsigned char *pBuf;  
  298.     int i;  
  299.     int64_t timestamp;  
  300.     struct options opt;  
  301.     int usefo = 0;  
  302.     struct audio_dsp dsp;  
  303.     struct video_fb fb;  
  304.     int dusecs;  
  305.     float usecs1 = 0;  
  306.     float usecs2 = 0;  
  307.     struct timeval elapsed1, elapsed2;  
  308.     int decoded = 0;  
  309.    
  310.     av_register_all();  
  311.    
  312.     av_log_set_callback(log_callback);  
  313.     av_log_set_level(50);  
  314.    
  315.     if (parse_options(&opt, argc, argv) < 0 || (strlen(opt.finput) == 0))  
  316.     {  
  317.         show_help(argv[0]);  
  318.         return 0;  
  319.     }  
  320.  
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值