ffmpeg 如何探测网络流格式/如何从内存中获取数据

一般ffmpeg都是直接从文件中读取或者从网络流中读取,比如rtp://xx.xx.xx.xx:xxxx。

事实上也支持从内存中获取。

函数avio_alloc_context()实现该功能。

[html] view plain copy

 
 print?

  1. AVIOContext *avio_alloc_context(  
  2.                   unsigned char *buffer,  
  3.                   int buffer_size,  
  4.                   int write_flag,  
  5.                   void *opaque,  
  6.                   int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),//重写该函数,指定从内存中读取的方法,将buf_size字节大小的数据保存到buf  
  7.                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),//对应的这是写内存的函数  
  8.                   int64_t (*seek)(void *opaque, int64_t offset, int whence));  

对于探测网络媒体流个格式,也可以用此种方法,先接收数据,然后探测。

 

下面贴出代码:

 

[cpp] view plain copy

 
 print?

  1. /* 
  2. *author tongli 
  3. */  
  4. extern "C"{  
  5. #include "libavformat/avformat.h"  
  6. #include "libavcodec/avcodec.h"  
  7. #include "libavutil/avutil.h"  
  8. }  
  9. #define BUF_SIZE 4096*500  
  10.   
  11. FILE* file;  
  12. //实现read_packet函数,从文件中读取模拟的是从内存中获取,同样可以实现为接收网络流  
  13. int read_packet(void *opaque, uint8_t *buf, int buf_size)  
  14. {  
  15.     int n = 0;  
  16.     if (!feof(file)){  
  17.         n = fread(buf, 1, buf_size, file);  
  18.         return n;  
  19.     }else  
  20.         return -1;  
  21. }  
  22.   
  23. int main(int argc, char** argv)  
  24. {  
  25.     file = fopen("2.mp4", "rb");  
  26.     if (file == NULL)  
  27.         return -1;  
  28.     av_register_all();  
  29.     AVIOContext* pb = NULL;  
  30.     AVInputFormat* piFmt = NULL;  
  31.     AVInputFormat* pFmt = NULL;  
  32.   
  33.     uint8_t* buf = (uint8_t*)av_mallocz(sizeof(uint8_t)* BUF_SIZE);  
  34.   
  35.     pb = avio_alloc_context(buf, BUF_SIZE, 0, NULL, read_packet, NULL, NULL);  
  36.     if (av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0) < 0)//探测从内存中获取到的媒体流的格式  
  37.     {  
  38.         fprintf(stderr, "probe format failed\n");  
  39.         return -1;   
  40.     }  
  41.     else{  
  42.         fprintf(stdout, "format:%s[%s]\n", piFmt->name, piFmt->long_name);  
  43.     }  
  44.     return 0;  
  45. }  

下面实现一个简单的例子,从内存中读取,然后播放。

 

 

 

[cpp] view plain copy

 

 print?

    1. <pre name="code" class="cpp">/* 
    2. *author tongli 
    3. */  
    4. #include <stdio.h>  
    5. #include <direct.h>  
    6. #include <io.h>  
    7. extern "C"{  
    8. #include "libavformat/avformat.h"  
    9. #include "libavcodec/avcodec.h"  
    10. #include "libavutil/avutil.h"  
    11. #include "libswscale/swscale.h"  
    12. #include "libavformat/avio.h"  
    13. #include "sdl/SDL.h"  
    14. }  
    15. #define BUF_SIZE 4096 * 500  
    16. FILE* file;  
    17.   
    18. int read_data(void *opaque, uint8_t *buf, int buf_size)  
    19. {  
    20.     int n = 0;  
    21.     if (!feof(file)){  
    22.         n = fread(buf, 1, buf_size, file);  
    23.         return n;  
    24.     }  
    25.     else  
    26.         return -1;  
    27. }  
    28.   
    29. int main(int argc, char* argv[])  
    30. {  
    31.     av_register_all();  
    32.     //file = fopen("h2.dat", "rb");  
    33.     file = fopen("3.mp4", "rb+");  
    34.     if (file == NULL)  
    35.         return -1;  
    36.     AVFormatContext *pFormatCtx;  
    37.     int             i, videoindex;  
    38.     AVCodecContext  *pCodecCtx;  
    39.     AVCodec         *pCodec;  
    40.     AVIOContext* pb = NULL;  
    41.     AVInputFormat* piFmt = NULL;  
    42.   
    43.     uint8_t* buf = (uint8_t*)av_mallocz(sizeof(uint8_t)* BUF_SIZE);  
    44.   
    45.     pb = avio_alloc_context(buf, BUF_SIZE, 0, NULL, read_data, NULL, NULL);  
    46.     if (av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0) < 0)  
    47.     {  
    48.         fprintf(stderr, "probe format failed\n");  
    49.         return -1;  
    50.     }  
    51.     else{  
    52.         fprintf(stdout, "format:%s[%s]\n", piFmt->name, piFmt->long_name);  
    53.     }  
    54.     pFormatCtx = avformat_alloc_context();  
    55.     pFormatCtx->pb = pb;  
    56.   
    57.     if (avformat_open_input(&pFormatCtx, "", piFmt, NULL) != 0){//iformat,priv_data赋值,pb, nbstreams,streams为null  
    58.         printf("Couldn't open input stream.(无法打开输入流)\n");  
    59.         return -1;  
    60.     }  
    61.     if (avformat_find_stream_info(pFormatCtx, NULL)<0)//nbstreams,streams赋值, pb还是为null  
    62.     {  
    63.         printf("Couldn't find stream information.(无法获取流信息)\n");  
    64.         return -1;  
    65.     }  
    66.     videoindex = -1;  
    67.     for (i = 0; i<pFormatCtx->nb_streams; i++) //一般情况下,一个媒体只有两个流,视频和音频流即streams[0],stream[1]  
    68.     if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)  
    69.     {//找到视频流  
    70.         videoindex = i;//在nb_streams视频流的索引  
    71.         break;  
    72.     }  
    73.     if (videoindex == -1)  
    74.     {  
    75.         printf("Didn't find a video stream.(没有找到视频流)\n");  
    76.         return -1;  
    77.     }  
    78.     pCodecCtx = pFormatCtx->streams[videoindex]->codec;  
    79.     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);  
    80.     if (pCodec == NULL)  
    81.     {  
    82.         printf("Codec not found.(没有找到解码器)\n");  
    83.         return -1;  
    84.     }  
    85.     if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)  
    86.     {  
    87.         printf("Could not open codec.(无法打开解码器)\n");  
    88.         return -1;  
    89.     }  
    90.     AVFrame *pFrame, *pFrameYUV;  
    91.     pFrame = av_frame_alloc();  
    92.     pFrameYUV = av_frame_alloc();  
    93.   
    94.     uint8_t *out_buffer;  
    95.     out_buffer = new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];  
    96.       
    97.     avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);  
    98.     //------------SDL----------------  
    99.     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  
    100.         printf("Could not initialize SDL - %s\n", SDL_GetError());  
    101.         return -1;  
    102.     }  
    103.     SDL_Surface *screen;  
    104.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);  
    105.     if (!screen) {  
    106.         printf("SDL: could not set video mode - exiting\n");  
    107.         return -1;  
    108.     }  
    109.     SDL_Overlay *bmp;  
    110.     bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);  
    111.     SDL_Rect rect;  
    112.     //---------------  
    113.     int ret, got_picture;  
    114.     int y_size = pCodecCtx->width * pCodecCtx->height;  
    115.   
    116.     AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));  
    117.     av_new_packet(packet, y_size);  
    118.   
    119.     struct SwsContext *img_convert_ctx;  
    120.     img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
    121.         AV_PIX_FMT_YUVJ420P/*pCodecCtx->pix_fmt*/, pCodecCtx->width, pCodecCtx->height,  
    122.         PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);  
    123.     //------------------------------  
    124.     while (av_read_frame(pFormatCtx, packet) >= 0)  
    125.     {  
    126.         if (packet->stream_index == videoindex)  
    127.         {  
    128.             ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);  
    129.             if (ret < 0)  
    130.             {  
    131.                 printf("Decode Error.(解码错误)\n");  
    132.                 return -1;  
    133.             }  
    134.             if (got_picture)  
    135.             {  
    136.                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);  
    137.   
    138.                 SDL_LockYUVOverlay(bmp);  
    139.                 bmp->pixels[0] = pFrameYUV->data[0];  
    140.                 bmp->pixels[2] = pFrameYUV->data[1];  
    141.                 bmp->pixels[1] = pFrameYUV->data[2];  
    142.                 bmp->pitches[0] = pFrameYUV->linesize[0];  
    143.                 bmp->pitches[2] = pFrameYUV->linesize[1];  
    144.                 bmp->pitches[1] = pFrameYUV->linesize[2];  
    145.                 SDL_UnlockYUVOverlay(bmp);  
    146.                 rect.x = 0;  
    147.                 rect.y = 0;  
    148.                 rect.w = pCodecCtx->width;  
    149.                 rect.h = pCodecCtx->height;  
    150.                 SDL_DisplayYUVOverlay(bmp, &rect);  
    151.                 //延时40ms  
    152.                 SDL_Delay(40);  
    153.             }  
    154.         }  
    155.         av_free_packet(packet);  
    156.     }  
    157.     sws_freeContext(img_convert_ctx);  
    158.   
    159.     delete[] out_buffer;  
    160.     av_free(pFrameYUV);  
    161.     avcodec_close(pCodecCtx);  
    162.     avformat_close_input(&pFormatCtx);  
    163.   
    164.     return 0;  
    165. }  
时间: 2024-09-25 00:35:47

ffmpeg 如何探测网络流格式/如何从内存中获取数据的相关文章

ffmpeg 从内存中读取数据(或将数据输出到内存)

更新记录(2014.7.24): 1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开. 2.增加了将数据输出到内存的方法.   从内存中读取数据 ffmpeg一般情况下支持打开一个本地文件,例如"C:\test.avi" 或者是一个流媒体协议的URL,例如"rtmp://222.31.64.208/vod/test.flv" 其打开文件的函数是avformat_open_input(),直接将文件路径或者流媒体URL的字符串传递给该函数就可以了. 但其

EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载

原文:EF如何操作内存中的数据以及加载相关联表的数据:延迟加载.贪婪加载.显示加载 之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过ObjectContext来操作数据库的,一看是Object打头的,自然相当庞大,方法也比较多.到了经典的4.1版本,EF小组推出了一些更简单好用的API,就是DbContext,它包括更常用的方法.看看EF小组是怎么说

游戏外挂技术:编程实现内存检索(检索内存中指定数据)

1.目标,通过程序检索植物大战僵尸雪的值,并将雪的值修改(这个时候得使用dll的方式才能够实现): 2.打开MemSearch工具.截图如下: 上面(0x20337520)是通过MemSearch累计查找到的地址值 3.新建项目,项目截图如下: 内存检索代码: #include <stdio.h> #include <stdlib.h> #include <Windows.h>   /*******************************************

【POI】导出excel文件,不生成中间文件,直接将内存中的数据创建对象下载到浏览器

 不是从InputStream中read,然后outputStream再write @RequestMapping("download4Excel") public void download4Excel(HttpServletResponse response){ XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("测试Sheet"); sheet.

从内存中偷取未加密的 SSH-agent 密钥 【已翻译100%】

如果你曾使用SSH密钥来管理多台机器,那么你可能使用过SSH-agent.这个工具使SSH密钥在内存中持续化,这样用户就不用每次都输入口令.然而,这会导致一些安全风险.root用户可能有权限从内存中取出解密后的SSH密钥,并重构它. 由于需要root权限,这种攻击看起来没什么用.例如,一个攻击者可能安装一个Keylogger并使用它来获得SSH密钥的口令.然而,这要等待肉鸡输入它们的口令.这取决于肉鸡掉线的频度,可能需要几个小时,几天或几周.在快速攻击方法中,这也是为什么从内存中获取SSH密钥对

如何定位并删除内存中的内容?

问题描述 如何定位并删除内存中的内容? 例如剪切板中的内容是存储在内存中的,那么我该怎样才知道它到底存储在哪一部分并且删除它呢? 解决方案 内存中的数据,你如果能够知道地址,那么可以访问地址来修改数据等.但是还要看地址是否允许写 解决方案二: 删除它很简单,清空剪贴板或者设置点别的就可以了.

生命周期-java数据在内存中的存放问题

问题描述 java数据在内存中的存放问题 谢谢查看. 问题是这样的,作为java新手,最近老搞不明白数据在内存中到底存放位置的问题.查了许多资料后,得出个结论,请有错误的帮忙指正,谢谢. 基本类型的数值会存放在栈中,执行效率高:引用对象(不包括String类型)的数据放在堆中,堆灵活性高,容量可变长. 但是编译器在编译时候,基本类型中部分,称为直接量会为了效率高会直接生成放在常量区,其他都会在栈中生成,而且经过优化,如果是同一生命周期内栈数据是可以共享的,也就是有相同的数据的变量可以指向同个栈地

IBM Informix Warehouse Accelerator为内存中分析处理提供卓越性能

数据的快速增长增加了http://www.aliyun.com/zixun/aggregation/8302.html">数据仓库和分析引擎的压力,致使执行商业智能查询极为耗时.但大多数企业都承担不起等待的代价,需要立即获得答案. 利用内存中处理提升性能 IBM® Informix® Warehouse Accelerator (IWA) 能凭借专有的压缩.可伸缩的处理器缓存敏感型算法以及高度可访问的内存中数据显著缩短了响应时间.IWA 能够将数据仓库中的数据以压缩形式完全载入系统内存.I

配置内存中OLTP文件组提高性能

原文:配置内存中OLTP文件组提高性能 在今天的文章里,我想谈下使用内存中OLTP的内存优化文件组来获得持久性,还有如何配置它来获得高性能.在进入正题前,我想简单介绍下使用你数据库里这个特定文件组,内存OLTP是如何获得持久性的. 内存中OLTP的持久性 早些天对内存中OLTP(代号Hekaton)的一个大误解是,人们认为内存中OLTP是不具有ACID属性的--只有ACI属性,没有D属性(Durability).但这不是真的,因为在内存中OLTP里,每个在内存中的操作都是完全日志的.如果你的数据