`

最简单的基于FFMPEG的封装格式转换器(无编解码)

 
阅读更多

本文介绍一个基于FFMPEG的封装格式转换器。所谓的封装格式转换,就是在AVI,FLV,MKV,MP4这些格式之间转换(对应.avi,.flv,.mkv,.mp4文件)。需要注意的是,本程序并不进行视音频的编码和解码工作。而是直接将视音频压缩码流从一种封装格式文件中获取出来然后打包成另外一种封装格式的文件。传统的转码程序工作原理如下图所示:

上图例举了一个举例:FLV(视频:H.264,音频:AAC)转码为AVI(视频:MPEG2,音频MP3)的例子。可见视频转码的过程通俗地讲相当于把视频和音频重新“录”了一遍。
本程序的工作原理如下图所示:

由图可见,本程序并不进行视频和音频的编解码工作,因此本程序和普通的转码软件相比,有以下两个特点:
处理速度极快。视音频编解码算法十分复杂,占据了转码的绝大部分时间。因为不需要进行视音频的编码和解码,所以节约了大量的时间。
视音频质量无损。因为不需要进行视音频的编码和解码,所以不会有视音频的压缩损伤。

下面贴上代码,代码是从FFmpeg的例子改编的,平台是VC2010。

 

/*
*最简单的基于FFmpeg的封装格式转换器
*Simplest FFmpeg Remuxer
*
*雷霄骅 Lei Xiaohua
*leixiaohua1020@126.com
*中国传媒大学/数字电视技术
*Communication University of China / Digital TV Technology
*http://blog.csdn.net/leixiaohua1020
*
*本程序实现了视频封装格式之间的转换。
*需要注意的是本程序并不改变视音频的编码格式。
*
* This software converts a media file from one container format
* to another container format without encoding/decoding video files.
*/

#include "stdafx.h"

extern "C"
{
#include "libavformat/avformat.h"
};


int _tmain(int argc, _TCHAR* argv[])
{
 AVOutputFormat *ofmt = NULL;
 //输入对应一个AVFormatContext,输出对应一个AVFormatContext
 //(Input AVFormatContext and Output AVFormatContext)
 AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
 AVPacket pkt;
 const char *in_filename, *out_filename;
 int ret, i;
 if (argc < 3) {
 printf("usage: %s input output\n"
 "Remux a media file with libavformat and libavcodec.\n"
 "The output format is guessed according to the file extension.\n"
 "Modified by Lei Xiaohua, leixiaohua1020@126.com\n"
 "Communication University of China / Digital TV Technology\n"
 "http://blog.csdn.net/leixiaohua1020", argv[0]);
 return 1;
 }
 in_filename = argv[1];//输入文件名(Input file URL)
 out_filename = argv[2];//输出文件名(Output file URL)
 av_register_all();
 //输入(Input)
 if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
 printf( "Could not open input file.");
 goto end;
 }
 if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
 printf( "Failed to retrieve input stream information");
 goto end;
 }
 av_dump_format(ifmt_ctx, 0, in_filename, 0);
 //输出(Output)
 avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
 if (!ofmt_ctx) {
 printf( "Could not create output context\n");
 ret = AVERROR_UNKNOWN;
 goto end;
 }
 ofmt = ofmt_ctx->oformat;
 for (i = 0; i < ifmt_ctx->nb_streams; i++) {
 //根据输入流创建输出流(Create output AVStream according to input AVStream)
 AVStream *in_stream = ifmt_ctx->streams[i];
 AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
 if (!out_stream) {
 printf( "Failed allocating output stream\n");
 ret = AVERROR_UNKNOWN;
 goto end;
 }
 //复制AVCodecContext的设置(Copy the settings of AVCodecContext)
 ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
 if (ret < 0) {
 printf( "Failed to copy context from input to output stream codec context\n");
 goto end;
 }
 out_stream->codec->codec_tag = 0;
 if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
 out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
 }
 //输出一下格式------------------
 av_dump_format(ofmt_ctx, 0, out_filename, 1);
 //打开输出文件(Open output file)
 if (!(ofmt->flags & AVFMT_NOFILE)) {
 ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
 if (ret < 0) {
 printf( "Could not open output file '%s'", out_filename);
 goto end;
 }
 }
 //写文件头(Write file header)
 ret = avformat_write_header(ofmt_ctx, NULL);
 if (ret < 0) {
 printf( "Error occurred when opening output file\n");
 goto end;
 }
 int frame_index=0;
 while (1) {
 AVStream *in_stream, *out_stream;
 //获取一个AVPacket(Get an AVPacket)
 ret = av_read_frame(ifmt_ctx, &pkt);
 if (ret < 0)
 break;
 in_stream = ifmt_ctx->streams[pkt.stream_index];
 out_stream = ofmt_ctx->streams[pkt.stream_index];
 /* copy packet */
 //转换PTS/DTS(Convert PTS/DTS)
 pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
 pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
 pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
 pkt.pos = -1;
 //写入(Write)
 ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
 if (ret < 0) {
 printf( "Error muxing packet\n");
 break;
 }
 printf("Write %8d frames to output file\n",frame_index);
 av_free_packet(&pkt);
 frame_index++;
 }
 //写文件尾(Write file trailer)
 av_write_trailer(ofmt_ctx);
end:
 avformat_close_input(&ifmt_ctx);
 /* close output */
 if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
 avio_close(ofmt_ctx->pb);
 avformat_free_context(ofmt_ctx);
 if (ret < 0 && ret != AVERROR_EOF) {
 printf( "Error occurred.\n");
 return -1;
 }
 return 0;
}


调试的时候,只需要“右键工程->调试->命令行参数”里面设置输入的文件名和输出的文件名就可以了。

 

下图显示了一个测试的输入文件的视音频参数。

下图显示了输出文件的视音频参数。可以看出除了视频的封装格式从flv转换成了mp4,其他有关视音频编码的参数没有任何变化。

 

完整工程下载地址:

http://download.csdn.net/detail/leixiaohua1020/7323491

分享到:
评论

相关推荐

    最简单的基于FFmpeg的封装格式转换器(源代码)

    本程序是一个基于FFMPEG的封装格式转换器的源代码。可以用于学习FFMPEG的开发相关知识。 需要注意的是,本程序并不进行视音频的编码和解码工作。而是直接将视音频压缩码流从一种封装格式文件中获取出来然后打包成...

    ffmpeg解码器

    FFmpeg是一款强大的开源多媒体处理工具,它包含了众多的编解码器、容器格式支持和转换功能。在FFmpeg中,解码器是用于解析特定编码格式的组件,将压缩的媒体数据转换为原始的、可播放的位流。在本案例中,我们将深入...

    基于ffmpeg的封装成MP4文件源代码

    在本示例中,"基于ffmpeg的封装成MP4文件源代码"指的是利用FFmpeg库来将不同格式的音视频数据封装成MP4格式的文件。MP4(MPEG-4 Part 14)是一种广泛使用的多媒体容器格式,它能够包含视频、音频、字幕、图像等多种...

    FFmpeg视频格式转换.zip

    FFmpeg是一款强大的开源多媒体处理工具,它包含了音视频编解码、封装、转换、流媒体等一系列功能。在iOS开发中,使用FFmpeg进行视频格式转换是常见的需求,尤其是在处理用户上传或下载的视频时,可能需要将视频转换...

    文库首页后端C++最简单的基于FFMPEG的音频编码器 1.1最简单的基于FFMPEG的音频编码器 1.1

    在C++中使用FFmpeg可以实现音频编码器,本文将详细介绍如何构建一个最简单的基于FFMPEG的音频编码器。 FFmpeg 包含了多种音频和视频编解码库,如libavcodec(编解码)、libavformat(容器格式处理)和libavutil...

    ffmpeg+fdk-aac编解码

    它包含了各种工具,如ffmpeg命令行工具,可以进行格式转换、编码、解码、剪辑、合并等多种操作。FDK-AAC(Fraunhofer Development Kit for Advanced Audio Coding)是来自Fraunhofer IIS的AAC编解码器,它是高质量...

    ffmpeg编解码,解封装封装

    FFmpeg是一款强大的开源工具,主要用于音频和视频的处理,包括编解码、解封装和过滤等操作。在本文中,我们将深入探讨FFmpeg的核心概念及其在实际应用中的使用。 首先,我们要理解“编解码”这个术语。编解码是指将...

    FFMpeg编解码测试Demo

    FFmpeg是一款强大的开源多媒体处理工具,它包含了音视频编解码、封装、转换以及流处理等功能。本项目“FFmpeg编解码测试Demo”旨在帮助开发者理解和应用FFmpeg进行二进制封装,以便更便捷地进行YUV编码和H264解码...

    FFMPEG实现视频格式转换组件-源代码

    FFMPEG的核心是其库,包括libavcodec(用于编解码)、libavformat(用于容器格式处理)和libavfilter(用于滤镜和特效)。这些库提供API,使得开发者能够轻松地在自己的应用程序中集成视频处理功能。通过调用这些API...

    FFMPEG C++封装库使用示例之初始化

    它包含了各种编解码器、工具和库,能够进行编码、解码、转换、流媒体操作等。FFmpeg 提供了 C 和 C++ 接口,允许开发者在自己的应用程序中集成 FFmpeg 的功能。在这个"FFMPEG C++封装库使用示例之初始化"中,我们将...

    ffmpeg编解码库

    FFmpeg是一个开源项目,它包含了多种音视频处理工具,主要用于音视频的编码、解码、转换、流媒体处理等任务。在开发过程中,为了实现这些功能,FFmpeg依赖于一系列的第三方库。以下是对压缩包文件中包含的第三方库的...

    ffmpeg编解码

    本资料包显然针对的是FFmpeg的学习者,包含了解码器的源码和相关文档,这对于深入理解FFmpeg的工作原理以及如何实际操作编解码过程非常有价值。 首先,FFmpeg 的编解码流程主要包括以下几个步骤: 1. **捕获**:...

    封装的使用FFMPEG的DXVA2解码显示H264和H265码流的库

    FFmpeg是一款强大的开源多媒体处理工具,它包含了各种编解码器、过滤器和转换功能,广泛应用于音视频处理领域。在FFmpeg中,DXVA2(DirectX Video Acceleration 2)是微软提供的一个硬件加速技术,用于减轻CPU在处理...

    基于FFmpeg的格式转封装.rar

    本资源"基于FFmpeg的格式转封装.rar"着重讲解了如何利用FFmpeg进行多媒体文件的格式转换和封装操作。通过访问提供的博客链接 cn-yixiaonaihe.blog.csdn.net,你可以找到更详细的步骤和示例。 在多媒体领域,格式转...

    基于FFMpeg的软解码库

    FFmpeg是一个开源项目,它提供了一套强大的工具和库,用于处理音频和视频内容,包括编码、解码、转换、流媒体等。在本压缩包中,我们关注的是"基于FFmpeg的软解码库",它特别强调了对多路播放和多路混音的支持,这...

    c#基于FFMPEG的视频转码(视频转音频)

    当进行视频转音频操作时,FFMPEG首先读取视频文件中的音频流,然后使用合适的解码器解码音频数据,最后用编码器将解码后的音频数据编码为目标音频格式,如MP3、AAC或WAV。 C#结合FFMPEG: C#本身并不直接支持FFMPEG...

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

    FFmpeg是一款强大的开源多媒体处理工具,它包含了音视频编解码、封装格式转换、流媒体处理等多种功能。在本项目中,我们将探讨如何利用FFmpeg获取网络摄像头的数据并进行解码播放,以此来理解FFmpeg在实时视频处理中...

    简单的FFmpeg解码,OpenCV显示

    FFmpeg库包含了许多预定义的解码器,能够处理各种常见的视频编码格式,如H.264、VP9等。通过初始化一个解码器上下文(`AVCodecContext`),我们可以指定我们要解码的编码类型,并加载相应的解码器。 ```c++ ...

    FFMPEG解码视频流

    FFmpeg是一款强大的开源多媒体处理工具,它包含了音视频编解码、封装、转换以及播放等功能。在VC(Visual C++)环境下,通过FFmpeg库,我们可以实现对各种视频流的解码,包括H264和MPEG4等常见的编码格式。 首先,...

    FFMPEG实现PCM编码AAC和MP3(采用封装格式实现)

    FFmpeg是一款强大的开源多媒体处理工具,它包含了音视频编解码、封装、转换以及流媒体服务等功能。在本文中,我们将深入探讨如何使用FFmpeg将PCM(脉冲编码调制)编码转换为AAC和MP3两种常见的音频编码格式,同时...

Global site tag (gtag.js) - Google Analytics