FFMpeg对MPEG2 TS流解码的流程分析

合集下载

ffmpeg工作流程

ffmpeg工作流程

ffmpeg工作流程
FFmpeg是一个用于处理多媒体数据的开源软件,它可以用来录制、转换和流式传输音频和视频。

在本文中,我们将探讨FFmpeg的工作流程。

1. 输入多媒体数据。

FFmpeg的工作流程始于输入多媒体数据。

这些数据可以是来自摄像头、麦克风或文件的音频和视频流。

FFmpeg支持各种不同的输入格式,包括但不限于MP4、AVI、FLV、MP3和WAV。

2. 解码。

一旦输入多媒体数据被FFmpeg接收,它将进行解码处理。

这意味着数据将被解析成原始的音频和视频流。

FFmpeg将使用适当的解码器来解码数据,以便后续处理。

3. 处理。

在解码完成后,FFmpeg可以执行各种处理操作,例如裁剪、旋
转、调整音量、添加滤镜等。

这些处理操作可以通过命令行参数或
脚本来指定。

4. 编码。

处理完成后,音频和视频流将被编码成所需的输出格式。

编码
器将把处理过的数据重新打包成新的音频和视频文件,可以是MP4、AVI、FLV等格式。

5. 输出多媒体数据。

最后,编码后的多媒体数据将被输出到所需的目标,可以是文件、流媒体服务器或直接传输到网络。

FFmpeg支持多种输出选项,
包括保存到文件、实时流式传输等。

总结。

FFmpeg的工作流程涉及输入多媒体数据、解码、处理、编码和
输出多媒体数据。

它提供了丰富的功能和灵活的配置选项,使其成
为处理音频和视频的强大工具。

通过了解FFmpeg的工作流程,用户
可以更好地利用其功能,实现各种多媒体处理需求。

ts流解析原理

ts流解析原理

ts流解析原理TS流解析原理是指对TS(Transport Stream)流进行解析的过程,TS流是一种用于传输媒体数据的封装格式,常用于广播和卫星传输等领域。

TS流解析的主要步骤如下:1. TS包解析:TS流由一系列固定大小的TS包组成,每个TS包的大小为188字节。

TS包由头部和数据两部分组成,头部包含了一些基本的信息,如同步字节、计数器等。

解析器需要将每个TS包抽取出来,并解析其头部信息。

2. PID(Packet Identifier)解析:每个TS包中都包含一个PID字段,用于标识不同的数据包或流。

解析器需要根据PID字段的值将TS包中的数据分发到对应的处理模块。

3. PAT(Program Association Table)解析:PAT是TS流中的一个重要表格,用于指示包含在TS流中的其他表格的位置。

解析器首先需要解析出PAT表,获取到其他表格的PID值。

4. PMT(Program Map Table)解析:PMT表是TS流中的另一个重要表格,用于描述媒体流的相关信息,如音视频编码类型、PES(Packetized Elementary Stream)的PID等。

解析器需要根据PAT表获取到的PID值,解析出对应的PMT表。

5. PES解析:PES是TS流中常见的一种封装格式,用于封装音视频等媒体数据。

解析器需要根据PMT表中的PID值,解析出对应的PES数据。

6. 解码处理:解析器将解析出来的音视频等媒体数据交给相应的解码器进行解码,进一步处理和播放。

总的来说,TS流解析原理主要包括了对TS包、PID、PAT表、PMT表和PES数据的解析处理过程。

通过对TS流的解析,可以获取到媒体数据的相关信息,并进行进一步的处理和播放。

FFmpeg获取网络摄像头数据解码

FFmpeg获取网络摄像头数据解码

FFmpeg获取⽹络摄像头数据解码对USB摄像头实时编码,在前⾯已经探讨过了。

这次改变下思路,尝试去截取⽹络摄像头的H264码流,将其解码播放。

这⾥的测试代码,是在海康摄像头的基础上进⾏的。

解码的⼤致流程和以前的保持⼀致,只不过增加了部分函数。

FFmpeg打开媒体⽂件并查看媒体⽂件的信息,有三个步骤:avformat_open_input;avformat_find_stream_info;av_dump_format;依次调⽤三个函数后,我们可以很清楚的知道码流的各种信息。

完整的代码:#include <stdio.h>#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <windows.h>#include "queue.h"extern "C"{#include <libavformat/avformat.h>#include <libavcodec/avcodec.h>#include <libswscale/swscale.h>}#pragma comment(lib, "avcodec.lib")#pragma comment(lib, "avformat.lib")#pragma comment(lib, "avutil.lib")#pragma comment(lib ,"swscale.lib")using namespace std;using namespace cv;DWORD WINAPI opencv_imshow(LPVOID lparam){result_link_type* result_link = (result_link_type*)lparam;struct result_node_datatype *result_node2 = NULL;while (1){result_node2 = result_pop(result_link);if (result_node2 == NULL){Sleep(1);continue;}imshow("frame", result_node2->result);waitKey(1);}}int main(int argc, const char * argv[]){HANDLE thread1;result_link_type *result_link = new result_link_type;result_link->head = result_link->end = NULL;result_link->result_num = 0;thread1 = CreateThread(NULL, 0, opencv_imshow, (LPVOID)result_link, 0, NULL);int i;int videoStream;int frameFinished;int numBytes;int ret;int got_picture;long prepts = 0;bool first_time = true;AVCodec *pCodec;AVFrame *pFrame;AVFrame *pFrameRGB;AVPacket packet;AVCodecContext *pCodecCtx;AVFormatContext *pFormatCtx = NULL;//结构体AVFormatContext:包含码流参数较多static struct SwsContext *img_convert_ctx;uint8_t *buffer;Mat pCvMat;char filepath[] = "rtsp://admin:jdh123456@10.170.6.187/axis-media/media.amp?camera=2";//码流的获取路径av_register_all();//注册编解码器avformat_network_init();//加载socket库以及⽹络加密协议相关的库if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)//打开多媒体数据并且获得信息{return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0)//读取视⾳频数据并且获得信息{return -1;}av_dump_format(pFormatCtx, 0, argv[1], false);//⼿⼯调试函数,看到pFormatCtx->streams的内容videoStream = -1;for (i = 0; i < pFormatCtx->nb_streams; i++){if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){videoStream = i;break;}}if (videoStream == -1){return -1;}pCodecCtx = pFormatCtx->streams[videoStream]->codec;pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//查找解码器if (pCodec == NULL){return -1;}if (avcodec_open2(pCodecCtx, pCodec, 0) < 0)//初始化AVCodecContext{return -1;}if (pCodecCtx->time_base.num > 1000 && pCodecCtx->time_base.den == 1){pCodecCtx->time_base.den = 1000;}pFrame = av_frame_alloc();//分配内存pFrameRGB = av_frame_alloc();i = 0;while (1){if (av_read_frame(pFormatCtx, &packet) >= 0)//读取码流中的⾳频若⼲帧或者视频⼀帧{if (packet.stream_index == videoStream){ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);//开始解码if (ret < 0){printf("Decode Error.(解码错误)\n");return ret;}if (got_picture)//解码成功,got_picture返回任意⾮零值{if (first_time){//初始化SwsContextimg_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); if (img_convert_ctx == NULL){fprintf(stderr, "Cannot initialize the conversion context!\n");exit(1);}numBytes = avpicture_get_size(AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);buffer = (uint8_t *)av_malloc(numBytes);avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); // allocator memory for BGR bufferpCvMat.create(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3);first_time = false;}//处理图像数据sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);memcpy(pCvMat.data, buffer, numBytes);struct result_node_datatype *result_node = new struct result_node_datatype;result_node->result = pCvMat;result_push(result_link, result_node);}}av_free_packet(&packet);}}//free(buffer);av_free(buffer);av_free(pFrameRGB);av_free(pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);system("Pause");return 0;}队列函数:#include "queue.h"#include <iostream>using namespace std;void result_push(result_link_type* result_link, result_node_datatype * result_node) //⼊队操作{if (result_link->head == NULL){result_link->head = result_node;result_link->end = result_link->head;result_link->result_num++;}else{result_link->end->next = result_node;result_link->end = result_node;result_link->result_num++;}}struct result_node_datatype* result_pop(result_link_type* result_link) //出队操作{struct result_node_datatype* tmp_node;if (result_link->head == NULL)return NULL;else if (result_link->head == result_link->end){return NULL;}else{tmp_node = result_link->head;result_link->head = result_link->head->next;result_link->result_num--;return tmp_node;}}队列函数的头⽂件:#ifndef QUEUE_H#define QUEUE_H#include <stdio.h>#include <stdlib.h>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>using namespace cv;typedef struct result_link_datatype{struct result_node_datatype *head;struct result_node_datatype *end;int result_num;}result_link_type;struct result_node_datatype{Mat result;struct result_node_datatype* next;};void result_push(result_link_type* result_link, result_node_datatype * result_node); //⼊队操作struct result_node_datatype* result_pop(result_link_type* result_link);//出队操作#endif解码后的数据进⼊队列,再从队列中取出,利⽤opencv将其显⽰(opencv显⽰是另外开的⼀个线程函数)。

ts流 标准 -回复

ts流 标准 -回复

ts流标准-回复什么是TS流(Transport Stream)?如何实现TS流的传输和播放?如今TS流在数字视频广播和流媒体传输中有何应用?接下来,我们将一步一步回答这些问题。

TS流(Transport Stream)是一种用于数字视频广播和流媒体传输的标准流媒体格式。

它是MPEG-2标准中定义的一种封装格式,用于将视频、音频和其他元数据按照特定的规则打包成一系列的数据包,以进行高效的传输和播放。

首先,我们需要了解TS流的基本结构和特点。

TS流采用分层和多路复用的方式来组织数据。

它由多个PID(Packet Identifier)所对应的数据包组成,每个PID可以承载不同类型(如视频、音频、字幕等)的数据。

这种分层结构使得TS流可以同时传输、解码和显示多路音视频流。

为了实现TS流的传输和播放,需要使用一些特定的工具和协议。

首先,需要一个流媒体服务器来提供TS流的分发和传输。

常用的流媒体服务器软件包括Wowza、Kurento、NGINX等。

这些服务器软件可以根据客户端的请求,向其发送相应的TS流数据。

在传输层,TS流一般使用TCP或UDP协议进行传输。

TCP协议可提供可靠的数据传输,适用于对数据完整性要求较高的场景;而UDP协议则提供了更低的延迟和更高的传输效率,适用于实时性要求较高的场景。

在播放端,需要使用支持TS流的播放器来解析和显示数据。

常见的TS流播放器有VLC、FFmpeg、Windows Media Player等。

这些播放器能够将接收到的TS流进行解封装,并按照其中的PID进行数据提取和解码。

然后,根据需要将视频画面和音频声音同步输出到屏幕和音箱上,实现完整的播放效果。

TS流在数字视频广播和流媒体传输中有着广泛的应用。

在数字电视广播领域,TS流被用于将多路电视频道同时通过有线或无线传输到电视机上。

利用TS流的分层和多路复用特点,可以在一个通道内传输多个节目,大大提高了频谱利用率。

TS流系统解码层架

TS流系统解码层架

TS系统解码TS系统解码 (1)1 TS流的内容 (2)1.1 ES (2)1.2 PES (2)1.3 TS (4)2 TS流的解码过程(只考虑本地文件,解码只涉及到系统层打包的解码,不涉及到编码的解码) (5)2.1 PAT解码: (5)2.2 PMT解码 (6)2.3 音视频解码 (6)3 TS流解码 (7)3.1 总用例图 (7)3.2 各解码类的UML图 (8)3.2.1 解码主类 (8)3.2.2 事件管理类 (9)3.2.3 各类包解析的关系图 (10)3.2.4 输入输出类 (11)3.2.5 解析PA T、PMT、私有数据等 (12)3.2.6 解析TS 包 (13)3.2.7 解析PES包 (14)3.2.8 PCR时钟类 (15)3.2.9 CRC校验类 (15)3.3 解码流程图 (16)3.3.1 TS包解析流程图 (16)3.3.2 Section解码流程图 (17)3.3.3 PES解码流程图 (18)4 TS流合成(编码) (19)4.1 各编码类的UML图 (19)4.1.1 编码主类 (19)4.1.2 合成各类之间的关系 (20)4.2 编码主要流程 (21)4.2.1 TS编码流程图 (21)4.2.2 负载(pes、section)打包过程 (22)附表一: (23)附表二: (25)1TS流的内容TS->PES->ES->NAL1.1 ESAn elementary stream (ES) is defined by MPEG communication protocol is usually the output of an audio or video encoder.1.2 PESallows an Elementary stream to be divided into packets.图一:PES结构图PES结构各字段的具体含义见附表一。

ffmpeg简单解码

ffmpeg简单解码

ffmpeg简单解码FFmpeg是一个非常强大的开源多媒体处理库,可以用于处理音频、视频和其他类型的多媒体数据。

下面是一个简单的FFmpeg解码示例:c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<libavcodec/avcodec.h>#include<libavformat/avformat.h>int main(int argc, char **argv){AVFormatContext *format_ctx = NULL;AVCodec *codec;AVCodecContext *codec_ctx = NULL;FILE *file;int ret;// 打开输入文件ret = avformat_open_input(&format_ctx, argv[1], NULL, NULL);if (ret < 0) {fprintf(stderr, "无法打开输入文件:%s\n", argv[1]);return-1;}// 获取视频流信息ret = avformat_find_stream_info(format_ctx, NULL);if (ret < 0) {fprintf(stderr, "无法获取流信息:%s\n", av_err2str(ret));return-1;}// 查找解码器codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);if (!codec) {fprintf(stderr, "找不到解码器\n");return-1;// 初始化解码器上下文ret = avcodec_alloc_context3(codec);if (ret < 0) {fprintf(stderr, "无法分配解码器上下文:%s\n", av_err2str(ret)); return-1;}ret = avcodec_open2(codec_ctx, codec, NULL);if (ret < 0) {fprintf(stderr, "无法打开解码器:%s\n", av_err2str(ret)); return-1;}// 开始解码过程while (1) {AVPacket *packet = av_packet_alloc();if (!packet) {fprintf(stderr, "无法分配包\n");return-1;}ret = av_read_frame(format_ctx, packet);if (ret < 0) {fprintf(stderr, "读取帧错误:%s\n", av_err2str(ret));return-1;}if (packet->stream_index == -1) {break; // 已经读取到文件末尾,退出循环} else { // 开始解码一帧数据ret = avcodec_send_packet(codec_ctx, packet);if (ret < 0) {fprintf(stderr, "发送包到解码器错误:%s\n", av_err2str(ret)); return-1;}while (1) { // 循环接收解码后的帧数据,直到没有更多帧数据可接收为止AVFrame *frame = av_frame_alloc();if (!frame) {fprintf(stderr, "无法分配帧\n");return-1;ret = avcodec_receive_frame(codec_ctx, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { // 没有更多帧数据可接收,退出循环break;} else if (ret < 0) { // 错误处理,返回错误代码或退出程序,具体取决于应用程序的设计和需求。

ffmpeg库使用流程

ffmpeg库使用流程
FFmpeg库的使用流程如下:
调用av_register_all()函数,用于注册所有的文件格式和编解码库。

调用avformat_network_init()函数,用于打开网络视频流。

调用av_open_input_file()函数,用于读取文件头部信息,并将其保存到AVFormatContext结构体中。

调用av_find_stream_info()函数,用于为pFormatCtx->streams填充正确的信息。

根据需要判断是否为视频流,例如通过判断CODEC_TYPE_VIDEO。

调用avcodec_find_decoder()函数,用于查找解码器。

调用avcodec_open()函数,用于打开编解码器。

调用avcodec_alloc_frame()函数,用于分配空间以保存解码后的帧数据。

调用av_read_frame()函数,用于不断从流中提取帧数据。

调用avcodec_decode_video()函数,用于解码视频流。

以上步骤是使用FFmpeg库的一般流程,根据实际需求和环境可能需要适当调整。

此外,建议查阅FFmpeg官方文档或相关教程以获取更详细和准确的信息。

TS码流分析

MPEG组织于1994年推出MPEG-2压缩标准,以实现视/音频服务与应用互操作的可能性,MPEG-2标准是针对标准数字电视和高清晰度电视在各种应用下的压缩方案和系统层的详细规定。

对应于不同的应用,符合MPEG-2标准的码流又分为传送流和程序流,本文主要讲解了传送流有关的部分数据结构,从实际应用的传送流码流中截取了部分码流做了说明,并给出了部分解析传送流码流的实例程序。

在MPEG-II标准中,为了将一个或更多的音频、视频或其他的基本数据流合成单个或多个数据流,以适应于存储和传送,必须对其重新进行打包编码,在码流中还需插入各种时间标记、系统控制等信息,最后送到信道编码与调制器。

这样可以形成两种数据流——传送流(TS)和程序流(PS),分别适用于不同的应用,图1给出了单路节目的视音频数据流的复用框图。

传送流(Transport Stream)简称TS流,它是根据ITU-T Rec.H.222.0|ISO/IEC 13818-2 和ISO/IEC 13818-3协议而定义的一种数据流,其目的是为了在有可能发生严重错误的情况下进行一道或多道程序编码数据的传送和存储。

这种错误表现为比特值错误或分组丢失。

传送流由一道或多道节目组成,每道节目由一个或多个原始流和一些其他流复合在一起,包括视频流、音频流、节目特殊信息流(PSI)和其他数据包。

其中PSI表有4种类型:节目关联表(PAT)、节目映射表(PMT)、网络信息表和条件访问表。

传送流应用比较广泛,如视音频资料的保存、电视节目的非线性编辑系统及其网络等。

在开发机顶盒以及视频设备时有时需要对码流的编码知识有比较清楚地了解,这样才能在遇到问题时做出全面的分析。

TS流结构分析如图2所示,TS包的长度是固定的,为188字节。

包括同步字节(sync_byte)0x47和数据包识别号PID 等。

PID为13位字段,指示存储于分组有效负载中数据的类型,PID值0x0000为程序关联表保留,而0x0001为条件访问表保留,0x1FFF为空分组保留。

ffmpeg ts名称获得的参数

一、引言在视频处理中,使用ffmpeg工具可以完成各种复杂的任务,而ts流媒体是常见的视频格式之一。

在使用ffmpeg处理ts流媒体时,需要获取一些参数进行设置,以实现对视频的操作和处理。

本文将就ffmpeg获取ts流媒体名称的参数进行详细介绍,方便读者在使用ffmpeg工具时能够准确获取所需的参数,从而更好地完成视频处理任务。

二、ts流媒体格式介绍1. ts流媒体格式是一种常见的视频传输格式,常用于网络视频的传输和播放。

2. ts格式的特点是可以将视频数据和音频数据进行分离,并且支持多种编码格式和多路复用。

三、ffmpeg工具简介1. ffmpeg是一款开源的跨评台多媒体处理工具,可以用于对音频、视频等多媒体数据进行编解码、转换、处理等操作。

2. 使用ffmpeg工具可以对多种格式的音视频文件进行处理,并且支持丰富的参数设置和功能扩展。

四、获取ts流媒体名称的参数在使用ffmpeg处理ts流媒体时,需要获取一些参数进行设置,以便于对视频进行操作和处理。

以下是获取ts流媒体名称的参数的方法:1. 使用ffprobe工具ffprobe是ffmpeg工具中用于查看多媒体文件信息的工具,可以用于获取ts流媒体文件的名称参数。

命令格式如下:```shellffprobe -show_streams -print_format json {ts流媒体文件名}```执行以上命令可以获取ts流媒体文件中的多路流信息,包括名称参数。

2. 使用ffmpeg工具ffmpeg工具本身也可以用于获取ts流媒体文件的名称参数,具体命令如下:```shellffmpeg -i {ts流媒体文件名}```执行以上命令可以获取ts流媒体文件中的音视频流信息,包括名称参数。

3. 解析输出信息在获取ts流媒体文件的名称参数后,需要进行输出信息的解析,以便于获取所需的参数。

使用json解析工具可以将ffprobe或ffmpeg命令的输出结果进行解析,从而获取ts流媒体文件的名称参数。

ffmpeg库使用流程 -回复

ffmpeg库使用流程-回复FFmpeg 是一个开源的多媒体处理库,用于处理音视频文件。

它提供了一套丰富的功能和工具,可以进行音频、视频的解码、编码、转码、剪辑以及流媒体传输等操作。

本文将一步一步地介绍使用FFmpeg 的流程。

第一步:下载和安装FFmpeg要使用FFmpeg,首先需要下载并安装它。

在FFmpeg 的官方网站(用户可以下载编译好的可执行文件,而Linux 和macOS 用户可以通过源码编译安装。

第二步:查看FFmpeg 的帮助文档在安装好FFmpeg 后,可以使用命令行工具(例如Windows 的命令提示符或macOS 的终端)来运行FFmpeg。

输入"ffmpeg" 命令,可以查看到FFmpeg 的帮助文档,其中包含了所有可用的命令和参数的说明。

第三步:检查FFmpeg 的可用功能通过运行"ffmpeg -version" 命令,可以查看FFmpeg 的版本信息和支持的功能列表。

确保所安装的FFmpeg 版本包含了所需的功能,例如是否支持音频和视频编码、解码,以及是否支持所需的文件格式等。

第四步:使用基本命令FFmpeg 提供了一些基本的命令,用于常见的音视频处理操作。

以下是一些常用的命令示例:1. 转码:"ffmpeg -i input.mp4 output.avi"上述命令会将名为input.mp4 的视频文件转码为output.avi 格式的文件。

2. 剪辑:"ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4"该命令将从input.mp4 视频文件中剪辑出从1 分钟到2 分钟的部分,并输出到output.mp4 文件中。

3. 提取音频:"ffmpeg -i input.mp4 -vn -acodec copy output.mp3"通过上述命令,可以将input.mp4 视频文件中的音频提取出来,并保存为output.mp3 文件。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、FFMPEG中MPEG2 TS流解码的流程分析 (1)二、mpegts.c文件分析 (11)一、 FFMPEG中MPEG2 TS流解码的流程分析说道具体的音频或者视频格式,一上来就是理论,那是国内混资历的所谓教授的做为,对于我们,不合适,还是用自己的方式理解这些晦涩不已的理论吧。

其实MPEG2是一族协议,至少已经成为ISO标准的就有以下几部分:ISO/IEC-13818-1:系统部分;ISO/IEC-13818-2:视频编码格式;ISO/IEC-13818-3:音频编码格式;ISO/IEC-13818-4:一致性测试;ISO/IEC-13818-5:软件部分;ISO/IEC-13818-6:数字存储媒体命令与控制;ISO/IEC-13818-7:高级音频编码;ISO/IEC-13818-8:系统解码实时接口;我不是很想说实际的音视频编码格式,毕竟协议已经很清楚了,我主要想说说这些部分怎么组合起来在实际应用中工作的。

第一部分(系统部分)很重要,是构成以MPEG2为基础的应用的基础. 很绕口,是吧,我简单解释一下:比如DVD实际上是以系统部分定义的PS流为基础,加上版权管理等其他技术构成的。

而我们的故事主角,则是另外一种流格式,TS流,它在现阶段最大的应用是在数字电视节目的传输与存储上,因此,你可以理解TS实际上是一种传输协议,与实际传输的负载关系不大,只是在TS中传输了音频,视频或者其他数据。

先说一下为什么会有这两种格式的出现,PS适用于没有损耗的环境下面存储,而TS则适用于可能出现损耗或者错误的各种物理网络环境,比如你在公交上看到的电视,很有可能就是基于TS的DVB-T 的应用:)我们再来看MPEG2协议中的一些概念,为理解代码做好功课:l ES(Elementary Stream):wiki上说“An elementary stream (ES) is defined by MPEG communication protocol is usually the output of an audio or video encoder”恩,很简单吧,就是编码器编出的一组数据,可能是音频的,视频的,或者其他数据。

说到着,其实可以对编码器的流程思考一下,无非是执行:采样,量化,编码这3个步骤中的编码而已(有些设备可能会包含前面的采样和量化)。

关于视频编码的基本理论,还是请参考其它的资料。

l PES(Packetized Elementary Stream):wiki上说“allows an Elementary stream to be divided into packets”其实可以理解成,把一个源源不断的数据(音频,视频或者其他)流,打断成一段一段,以便处理.l TS(Transport Stream):l PS(Program Stream):这两个上面已经有所提及,后面会详细分析TS,我对PS格式兴趣不大.步入正题才进入正题,恩,看来闲话太多了:(,直接看Code.前面说过,TS是一种传输协议,因此,对应到FFmpeg,可以认为他是一种封装格式。

因此,对应的代码应该先去libavformat里面找,很容易找到,就是mpegts.c:)。

还是逐步看过来:[libavformat/utils.c]int av_open_input_file(A VFormatContext **ic_ptr, const char *filename,A VInputFormat *fmt,int buf_size,A VFormatParameters *ap){int err, probe_size;A VProbeData probe_data, *pd = &probe_data;ByteIOContext *pb = NULL;pd->filename = "";if (filename)pd->filename = filename;pd->buf = NULL;pd->buf_size = 0;#########################################################################【1】这段代码其实是为了针对不需要Open文件的容器Format的探测,其实就是使用A VFMT_NOFILE标记的容器格式单独处理,现在只有使用了该标记的Demuxer很少,只有image2_demuxer,rtsp_demuxer,因此我们分析TS时候可以不考虑这部分#########################################################################if (!fmt) {/* guess format if no file can be opened */fmt = av_probe_input_format(pd, 0);}/* Do not open file if the format does not need it. XXX: specifichack needed to handle RTSP/TCP */if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {/* if no file needed do not try to open one */#####################################################################【2】这个函数似乎很好理解,无非是带缓冲的IO的封装,不过我们既然到此了,不妨跟踪下去,看看别人对带缓冲的IO操作封装的实现:)#####################################################################if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0) {goto fail;}if (buf_size > 0) {url_setbufsize(pb, buf_size);}for(probe_size= PROBE_BUF_MIN; probe_size<=PROBE_BUF_MAX && !fmt; probe_size<<=1){int score= probe_size < PROBE_BUF_MAX ? AVPROBE_SCORE_MAX/4 : 0;/* read probe data */pd->buf= av_realloc(pd->buf, probe_size + AVPROBE_PADDING_SIZE);##################################################################【3】真正将文件读入到pd的buffer的地方,实际上最终调用FILE protocol的file_read(),将内容读入到pd的buf,具体代码如果有兴趣可以自己跟踪##################################################################pd->buf_size = get_buffer(pb, pd->buf, probe_size);memset(pd->buf+pd->buf_size, 0, A VPROBE_PADDING_SIZE);if (url_fseek(pb, 0, SEEK_SET) < 0) {url_fclose(pb);if (url_fopen(&pb, filename, URL_RDONLY) < 0) {pb = NULL;err = A VERROR(EIO);goto fail;}}##################################################################【4】此时的pd已经有了需要分析的原始文件,只需要查找相应容器format的Tag比较,以判断读入的究竟为什么容器格式,这里##################################################################/* guess file format */fmt = av_probe_input_format2(pd, 1, &score);}av_freep(&pd->buf);}/* if still no format found, error */if (!fmt) {err = AVERROR_NOFMT;goto fail;}/* check filename in case an image number is expected */if (fmt->flags & AVFMT_NEEDNUMBER) {if (!av_filename_number_test(filename)) {err = AVERROR_NUMEXPECTED;goto fail;}}err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);if (err)goto fail;return 0;fail:av_freep(&pd->buf);if (pb)url_fclose(pb);*ic_ptr = NULL;return err;}【2】带缓冲IO的封装的实现[liavformat/aviobuf.c]int url_fopen(ByteIOContext **s, const char *filename, int flags){URLContext *h;int err;err = url_open(&h, filename, flags);if (err < 0)return err;err = url_fdopen(s, h);if (err < 0) {url_close(h);return err;}return 0;}可以看到,下面的这个函数,先查找是否是FFmpeg支持的protocol的格式,如果文件名不符合,则默认是FILE protocol格式,很显然,这里protocol判断是以URL的方式判读的,因此基本上所有的IO接口函数都是url_xxx的形式。

相关文档
最新文档