更新记录(2014.7.24):
1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开。
2.增加了将数据输出到内存的方法。
从内存中读取数据
ffmpeg一般情况下支持打开一个本地文件,例如“C:\test.avi”
或者是一个流媒体协议的URL,例如“rtmp://222.31.64.208/vod/test.flv”
其打开文件的函数是avformat_open_input(),直接将文件路径或者流媒体URL的字符串传递给该函数就可以了。
但其是否支持从内存中读取数据呢?这个问题困扰了我很长时间。当时在做项目的时候,通过Winpcap抓取网络上的RTP包,打算直接送给ffmpeg进行解码。一直没能找到合适的方法。因为抓取的数据包是存在内存中的,所以无法传递给avformat_open_input()函数其路径(根本没有路径= =)。当然也可以将抓取的数据报存成文件,然后用ffmpeg打开这个文件,但是这样的话,程序的就太难控制了。
后来经过分析ffmpeg的源代码,发现其竟然是可以从内存中读取数据的,代码很简单,如下所示:
AVFormatContext *ic = NULL; ic = avformat_alloc_context();
unsigned char * iobuffer=(unsigned char *)av_malloc(32768); AVIOContext *avio =avio_alloc_context(iobuffer, 32768,0,NULL,fill_iobuffer,NULL,NULL); ic->pb=avio; err = avformat_open_input(&ic, "nothing", NULL, NULL);
关键要在avformat_open_input()之前初始化一个AVIOContext,而且将原本的AVFormatContext的指针pb(AVIOContext类型)指向这个自行初始化AVIOContext。当自行指定了AVIOContext之后,avformat_open_input()里面的URL参数就不起作用了。示例代码开辟了一块空间iobuffer作为AVIOContext的缓存。
fill_iobuffer则是将数据读取至iobuffer的回调函数。fill_iobuffer()形式(参数,返回值)是固定的,是一个回调函数,如下所示(只是个例子,具体怎么读取数据可以自行设计)。示例中回调函数将文件中的内容通过fread()读入内存。
//读取数据的回调函数------------------------- //AVIOContext使用的回调函数! //注意:返回值是读取的字节数 //手动初始化AVIOContext只需要两个东西:内容来源的buffer,和读取这个Buffer到FFmpeg中的函数 int fill_iobuffer(void * buffer,uint8_t *iobuf, int bufsize){ if(!feof(fp_open)){ int true_size=fread(buf,1,buf_size,fp_open); return true_size; }else{ return -1; } }
整体结构大致如下:
FILE *fp_open; int fill_iobuffer(void * buffer,uint8_t *iobuf, int bufsize){ ... } int main(){ ... fp_open=fopen("test.h264","rb+"); AVFormatContext *ic = NULL; ic = avformat_alloc_context(); unsigned char * iobuffer=(unsigned char *)av_malloc(32768); AVIOContext *avio =avio_alloc_context(iobuffer, 32768,0,NULL,fill_iobuffer,NULL,NULL); ic->pb=avio; err = avformat_open_input(&ic, "nothing", NULL, NULL); ...//解码 }
将数据输出到内存
和从内存中读取数据类似,ffmpeg也可以将处理后的数据输出到内存。
回调函数如下示例,可以将输出到内存的数据写入到文件中。
//写文件的回调函数 int write_buffer(void *opaque, uint8_t *buf, int buf_size){ if(!feof(fp_write)){ int true_size=fwrite(buf,1,buf_size,fp_write); return true_size; }else{ return -1; } }
主函数如下所示,也是先初始化AVIOContext。
FILE *fp_write; int write_buffer(void *opaque, uint8_t *buf, int buf_size){ ... } main(){ ... fp_write=fopen("src01.h264","wb+"); //输出文件 ... AVFormatContext* ofmt_ctx=NULL; avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL); unsigned char* outbuffer=(unsigned char*)av_malloc(32768); AVIOContext *avio_out =avio_alloc_context(outbuffer, 32768,0,NULL,NULL,write_buffer,NULL); ofmt_ctx->pb=avio_out; ofmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO; ... }
相关推荐
本程序实现了FFmpeg对内存中的视频数据的读写。包含两个工程: simplest_ffmpeg_mem_player:播放内存中视频数据的播放器。 simplest_ffmpeg_mem_transcoder:转码内存中数据的转码器。
2. 使用FFmpeg命令行工具,通过管道(pipe)或内存映射(memory mapping)将内存中的数据传递给FFmpeg。 - 例如,`echo "你的内存数据" | ffmpeg -i - -f lavfi -i anullsrc -c copy output.mp4` 这个命令会将标准...
在处理内存中的数据时,你需要自定义`AVInputFormat`,并使用`avio_open_dyn_buf()`创建一个动态缓冲区,以供FFMPEG读取。 对于读取网络摄像头的视频,通常会涉及到网络协议,如RTSP(Real Time Streaming Protocol...
在本文中,我们将深入探讨如何使用FFmpeg库通过C语言从USB摄像头捕获视频并将其编码为H264的TS(Transport Stream)流。FFmpeg是一个强大的多媒体处理框架,支持多种格式的音视频编码、解码、转换和流媒体功能。 ...
这个"simplest_ffmpeg_mem_player"项目提供了一个学习FFmpeg内存播放器的起点,通过阅读和理解源码,开发者可以深入了解FFmpeg的内部工作原理,以及如何处理内存中的多媒体数据。对于任何希望在没有磁盘I/O的情况下...
8. **读取和编码帧**:使用`av_read_frame()`从摄像头读取一帧数据,然后调用`avcodec_send_frame()`将该帧发送到编码器。编码器处理后,通过`avcodec_receive_packet()`接收编码后的数据包。 9. **写入输出文件**...
本主题聚焦于如何使用C++与FFmpeg库来将H264、H265编码的视频流和MP3音频流合并并写入到MP4文件中。H264和H265是两种高效的视频编码标准,而MP3是一种广泛接受的音频编码格式。MP4文件格式则允许同时存储视频和音频...
在FFmpeg中,`AVFormatContext`是处理多媒体文件的核心结构,它包含了关于输入或输出文件的各种信息,如流、时钟、选项等。`AVStream`则代表了文件中的一个特定音视频流,包含了编码器上下文、解码器上下文以及...
解码后的数据可以在内存中处理,例如裁剪、缩放或调整格式。 复用阶段,需要创建一个新的`AVFormatContext`,用`avformat_alloc_output_context2()`指定输出格式和文件名。对于每个输入流,找到相应的编码器,创建`...
`-s WxH`设置视频分辨率,`-i -`表示从标准输入读取数据,`-c:v libx264`指定使用H264编码器,`-preset slow`和`-crf 23`分别设置编码预设和质量参数,最后`-f flv -`表示输出为FLV格式并发送到标准输出。...
本文将详细阐述FFmpeg库中一些关键的数据结构和函数,以及它们在实际应用中的作用。 1. 数据结构: - AVFormatContext:这是FFmpeg的核心数据结构,包含了输入或输出的多媒体文件格式上下文,如流信息、元数据、...
在C++环境中,使用FFmpeg库可以实现从RTSP(Real Time Streaming Protocol)视频流中捕获数据,并将其保存为本地的MP4文件。这个过程涉及到了网络协议处理、多媒体数据解析和文件封装等多个技术点。 首先,RTSP是一...
在本文中,我们将深入探讨如何使用Qt框架结合FFmpeg API来实现摄像头视频流的读取、推流、拉流以及视频播放功能。Qt是一个强大的C++图形用户界面库,而FFmpeg则是一个开源的多媒体处理工具集,包含了音视频编码、...
这可以通过NuGet包管理器安装第三方库如`Xabe.FFmpeg`或者手动下载FFmpeg库文件并将其添加到项目引用中。 2. **初始化FFmpeg**:在C#代码中,需要进行必要的初始化工作,如设置全局配置、打开日志等。 3. **创建...
本手册将以中文形式详细介绍了FFMpeg SDK的核心概念、数据结构、重要函数以及如何使用这些组件进行音视频处理。 首先,FFMpeg SDK中定义了一系列核心的数据结构,这些结构是进行多媒体处理的基础。 1. ...
在本示例中,我们将探讨如何使用C++通过FFmpeg库从RTMP流中提取音频,并将其转换为16KHz、16位的PCM(脉冲编码调制)格式。这个过程对于音频处理、语音识别或者实时通信应用非常常见。 首先,我们需要在项目中集成...
6. **封装数据**:循环读取输入流的数据包(`AVPacket`),使用适当的编码器对数据进行编码(如果需要),然后将编码后的数据封装到MP4容器中。这个过程可能涉及`av_interleaved_write_frame()`或`av_write_frame()`...
1. **初始化上下文**:创建`AVFormatContext`,它是FFmpeg的核心上下文结构,包含了关于输入或输出文件的所有信息。 2. **打开输入文件**:使用`avformat_open_input`函数打开AAC文件,并通过`avformat_find_stream_...
读取水印图片到内存中,将其解码为`AVFrame`。这可以通过`avcodec_decode_video2()`函数实现,该函数将字节流解码为`AVFrame`。 2. **处理水印内存数据**:一旦水印图像被解码,你需要将其像素数据复制到一个内存...