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. }  
目录
相关文章
|
1天前
|
安全 算法 网络安全
网络安全与信息安全:保护你的数据,保障你的安全
【5月更文挑战第3天】在数字化时代,网络安全和信息安全已经成为我们生活中不可或缺的一部分。本文将深入探讨网络安全漏洞、加密技术以及安全意识等方面的问题,以期帮助读者更好地理解和应对网络安全挑战。
|
2天前
|
SQL 安全 算法
网络安全与信息安全:保护您的数据和隐私
【5月更文挑战第2天】本文将深入探讨网络安全与信息安全的重要性,分析常见的网络安全漏洞,介绍加密技术的应用,并强调提高安全意识的必要性。通过阅读本文,您将了解如何保护自己的数据和隐私,防范网络攻击。
|
2天前
|
安全 算法 网络安全
网络安全与信息安全:保护您的数据和隐私
【5月更文挑战第2天】随着互联网的普及和技术的快速发展,网络安全和信息安全已经成为我们日常生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术以及安全意识等方面的知识,帮助读者更好地保护自己的数据和隐私。
12 3
|
2天前
|
安全 算法 网络安全
网络安全与信息安全:保护您的数据和隐私
【5月更文挑战第2天】随着互联网的普及和技术的快速发展,网络安全和信息安全已经成为我们日常生活中不可或缺的一部分。了解网络安全漏洞、加密技术和安全意识等方面的知识,可以帮助我们更好地保护自己的数据和隐私。本文将为您分享有关网络安全的关键技术和方法,以及如何提高自己的安全意识,确保在网络世界中的安全。
11 3
|
2天前
|
SQL 安全 网络安全
网络安全与信息安全:保护您的数据和隐私
【5月更文挑战第2天】随着互联网的普及和技术的快速发展,网络安全和信息安全已成为我们日常生活中不可或缺的一部分。本文将探讨网络安全漏洞、加密技术和安全意识等方面,以帮助您更好地了解如何保护自己的数据和隐私。
|
3天前
|
存储 安全 算法
网络安全与信息安全:保护数据的关键策略
【4月更文挑战第30天】在数字化时代,数据成为了新的货币。然而,随之而来的是对数据安全的威胁和挑战。本文将深入探讨网络安全漏洞的概念、加密技术的重要性以及提升安全意识的必要性。通过对这些关键领域的分析,我们旨在为读者提供一套综合的网络安全和信息保护策略。
|
3天前
|
安全 算法 网络安全
网络安全与信息安全:保护你的数据,保护你的未来
【4月更文挑战第30天】在数字化的世界中,网络安全和信息安全已经成为我们生活的重要组成部分。本文将深入探讨网络安全漏洞、加密技术以及安全意识等方面的问题,以期帮助读者更好地理解和应对网络安全挑战。
|
4天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:保护你的数据,保护你的世界
【4月更文挑战第30天】在数字化的世界中,网络安全和信息安全已经成为我们生活的重要组成部分。本文将深入探讨网络安全漏洞、加密技术以及安全意识等方面的问题,帮助读者更好地理解和保护自己的数据。
|
4天前
|
机器学习/深度学习 数据可视化
R语言逻辑回归、决策树、随机森林、神经网络预测患者心脏病数据混淆矩阵可视化(下)
R语言逻辑回归、决策树、随机森林、神经网络预测患者心脏病数据混淆矩阵可视化
11 0
|
4天前
|
机器学习/深度学习 数据采集 数据可视化
R语言逻辑回归、决策树、随机森林、神经网络预测患者心脏病数据混淆矩阵可视化(上)
R语言逻辑回归、决策树、随机森林、神经网络预测患者心脏病数据混淆矩阵可视化
12 0