FFMPEG学习----分离视频里的H.264与YUV数据
#include <stdio.h> extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}; #pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "avutil.lib") int main(int argc, char* argv[])
{
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL, *pFrameYUV = NULL;
unsigned char *out_buffer = NULL;
AVPacket packet;
struct SwsContext *img_convert_ctx = NULL;
int y_size;
int got_picture;
int i, videoIndex;
int frame_cnt = 1; char filepath[] = "Titanic.ts"; FILE *fp_yuv = fopen("film.yuv", "wb+");
FILE *fp_h264 = fopen("film.h264", "wb+");
if (fp_yuv == NULL || fp_h264 == NULL)
{
printf("FILE open error");
return -1;
} av_register_all(); if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0){
printf("Couldn't open an input stream.\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0){
printf("Couldn't find stream information.\n");
return -1;
}
videoIndex = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
videoIndex = i;
break;
} if (videoIndex == -1){
printf("Couldn't find a video stream.\n");
return -1;
} pCodecCtx = pFormatCtx->streams[videoIndex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL){
printf("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
printf("Could not open codec.\n");
return -1;
} pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
if (pFrame == NULL || pFrameYUV == NULL)
{
printf("memory allocation error\n");
return -1;
}
out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));
av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer,
AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); while (av_read_frame(pFormatCtx, &packet) >= 0)
{
if (packet.stream_index == videoIndex)
{
//分离出h.264数据
fwrite(packet.data, 1, packet.size, fp_h264); if (avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet) < 0)
{
printf("Decode Error.\n");
return -1;
}
if (got_picture)
{
sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameYUV->data, pFrameYUV->linesize); //分离出YUV数据
y_size = pCodecCtx->width * pCodecCtx->height;
fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); //Y
fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); //U
fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); //V printf("Succeed to decode %d frame!\n", frame_cnt);
frame_cnt++;
}
}
av_free_packet(&packet);
} fclose(fp_yuv);
fclose(fp_h264);
sws_freeContext(img_convert_ctx);
av_frame_free(&pFrameYUV);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx); return 0;
}
压缩率大于100倍了。
当av_read_frame()循环退出的时候,实际上解码器中可能还包含剩余的几帧数据。因此需要通过“flush_decoder”将这几帧数据输出。“flush_decoder”功能简而言之即直接调用avcodec_decode_video2()获得AVFrame,而不再向解码器传递AVPacket。参考代码如下:
//FIX: Flush Frames remained in Codec
while (1) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
break;
if (!got_picture)
break;
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
//处理...
}
FFMPEG学习----分离视频里的H.264与YUV数据的更多相关文章
- 直播平台搭建之音视频开发:认识主流视频编码技术H.264
H.264简介 什么是H.264?H.264是一种高性能的视频编解码技术.目前国际上制定视频编解码技术的组织有两个,一个是"国际电联",它制定的标准有H.261.H.263.H.2 ...
- Wireshark Lua: 一个从RTP抓包里导出H.264 Payload,变成264裸码流文件(xxx.264)的Wireshark插件
Wireshark Lua: 一个从RTP抓包里导出H.264 Payload,变成264裸码流文件(xxx.264)的Wireshark插件 在win7-64, wireshark Version ...
- FFMPEG学习----分离视音频里的PCM数据
/** * 参考于:http://blog.csdn.net/leixiaohua1020/article/details/46890259 */ #include <stdio.h> # ...
- FFMPEG学习----打印视频信息
FFMPEG学习资料少之又少,在此推荐雷神的博客: http://blog.csdn.net/leixiaohua1020 在这里,我们把打印视频里的相关信息作为学习FFMPEG的 Hello Wor ...
- 音视频开发之H.264 入门知识
大家如果有做过音视频相关的项目,那么肯定对 H.264 相关的概念了解的比较通透,这里我为什么还要写这样一篇文章呢?一来是为了对知识的总结,二来是为了给刚入门音视频的同学一个参考. 基础概念 H.26 ...
- FFMPEG学习----解码视频
基础概念 我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的容器格式规定了其中音视频数据的组织方式(也包括其他 ...
- 音视频入门-10-使用libyuv对YUV数据进行缩放、旋转、镜像、裁剪、混合
* 音视频入门文章目录 * libyuv libyuv 是 Google 开源的实现各种 YUV 与 RGB 之间相互转换.旋转.缩放等的库.它是跨平台的,可在 Windows.Linux.Mac.A ...
- 用ffmpeg把视频编码格式转为h.264
command: ffmpeg -i infile.mp4 -an -vcodec libx264 -crf 23 outfile.h264
- 黄聪:FFmpeg视频转码技巧之-crf参数(H.264篇)
昨天,有个朋友给我出了个难题:他手上有一个视频,1080P的,49秒,200多兆:要求在确保质量的情况下把文件压缩到10M以内. 这是什么概念呢?按照文件大小10M来计算,码率是:10 x 8 / 4 ...
随机推荐
- WeihanLi.Npoi 1.7.0 更新
WeihanLi.Npoi 1.7.0 更新介绍 Intro 昨天晚上发布了 WeihanLi.Npoi 1.7.0 版本,增加了 ColumnInputFormatter/ColumnOutputF ...
- Wireshark抓包,带你快速入门
前言 关于抓包我们平时使用的最多的可能就是Chrome浏览器自带的Network面板了(浏览器上F12就会弹出来).另外还有一大部分人使用Fiddler,Fiddler也是一款非常优秀的抓包工具.但是 ...
- delphi7 如何描述窗体上的全部控件
在delphi开发中,经常需要用到窗体中控件的name名来进行对象方法或属性的调用,所以如何对delphi窗体进行简洁,清楚,完整的描述就很重要.最好能不看界面也能进行界面编码,具体如下表所示: xx ...
- 「Luogu P2015」二叉苹果树 解题报告
题面 一个二叉树,边数为n\((2<n\le 100)\),每条边有一个权值,求剪枝后剩下p\((1<p<n)\)条边,使p条边的权值和最大 还看不懂?-- 2 5 input:5 ...
- win10下使用mklink命令给C盘软件搬家
在windows下,大多数软件会默认安装在C盘,即使小心翼翼地点开“自定义”->“安装路径”,然后把软件安装到其他盘,还是会有很多软件用到的数据文件被塞到C盘,虽然可以到注册表修改软件默认安装路 ...
- surging 社区版本支持.net core 3.1
简介 surging 经过两年多的研发,微服务引擎已经略有雏形,也承蒙各位的厚爱, GitHub上收获了将近2800星,fork 811,付费用户企业也有十几家,还有咨询培训, 在2020年,我们将依 ...
- 【Javaweb学习笔记】XML和约束模式
一.XML语法 xml 可扩展标记语言,w3c组织发布的,用于保存有关系的数据,作为配置文件,描述程序模块之间的关系 xml 文件开头必须包括下面的标签: <?xml version=" ...
- Java ArrayList类的简单介绍
ArrayList类的说明: ArrayList类是List接口的实现类,java.util.ArrayList集合数据存储的结构是数组结构. 特点: 元素增删慢,查找快.(由于日常开发中使用最多的功 ...
- C# 根据年月日计算周次
//day:要判断的日期,WeekStart:1 周一为一周的开始, 2 周日为一周的开始 public static int WeekOfMonth(DateTime day, int WeekSt ...
- webpack进阶用法你都get到了么?
如何消除无用代码:打包自己的私有js库:实现代码分割和动态import提升初次加载速度:配置eslint规范团队代码规范:打包异常抓捕你都get到了么? 摇树优化:Tree Shaking webpa ...