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

简介: 一般ffmpeg都是直接从文件中读取或者从网络流中读取,比如rtp://xx.xx.xx.xx:xxxx。 事实上也支持从内存中获取。 函数avio_alloc_context()实现该功能。 [html] view plain copy    print? AVIOC...

一般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. }  
目录
相关文章
|
11天前
|
数据采集 存储 API
网络爬虫与数据采集:使用Python自动化获取网页数据
【4月更文挑战第12天】本文介绍了Python网络爬虫的基础知识,包括网络爬虫概念(请求网页、解析、存储数据和处理异常)和Python常用的爬虫库requests(发送HTTP请求)与BeautifulSoup(解析HTML)。通过基本流程示例展示了如何导入库、发送请求、解析网页、提取数据、存储数据及处理异常。还提到了Python爬虫的实际应用,如获取新闻数据和商品信息。
|
4天前
|
存储 NoSQL Oracle
Oracle 12c的内存列存储:数据的“闪电侠”
【4月更文挑战第19天】Oracle 12c的内存列存储以超高速度革新数据处理,结合列存储与内存技术,实现快速查询与压缩。它支持向量化查询和并行处理,提升效率,但需合理配置以平衡系统资源。作为数据管理员,应善用此功能,适应业务需求和技术发展。
|
6天前
|
机器学习/深度学习 数据可视化 测试技术
深度学习:Keras使用神经网络进行简单文本分类分析新闻组数据
深度学习:Keras使用神经网络进行简单文本分类分析新闻组数据
19 0
|
6天前
|
机器学习/深度学习 API 算法框架/工具
R语言深度学习:用keras神经网络回归模型预测时间序列数据
R语言深度学习:用keras神经网络回归模型预测时间序列数据
16 0
|
6天前
|
机器学习/深度学习 数据采集 TensorFlow
R语言KERAS深度学习CNN卷积神经网络分类识别手写数字图像数据(MNIST)
R语言KERAS深度学习CNN卷积神经网络分类识别手写数字图像数据(MNIST)
23 0
|
6天前
|
存储 算法 前端开发
R语言中贝叶斯网络(BN)、动态贝叶斯网络、线性模型分析错颌畸形数据
R语言中贝叶斯网络(BN)、动态贝叶斯网络、线性模型分析错颌畸形数据
26 0
|
7天前
|
机器学习/深度学习 数据可视化 网络架构
matlab使用长短期记忆(LSTM)神经网络对序列数据进行分类
matlab使用长短期记忆(LSTM)神经网络对序列数据进行分类
12 0
|
8天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android&#39;s AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
9 0
|
8天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
8 0
|
10天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:保护数据的关键策略
【4月更文挑战第14天】在数字化时代,网络安全与信息安全已成为维护个人隐私和企业资产的重要组成部分。本文深入探讨了网络安全漏洞的概念、加密技术的应用以及提升安全意识的重要性。通过分析当前网络威胁的常见形式,文章提供了防御策略,旨在帮助读者构建一个更加安全的网络环境。

热门文章

最新文章