#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数据的更多相关文章

  1. 直播平台搭建之音视频开发:认识主流视频编码技术H.264

    H.264简介 什么是H.264?H.264是一种高性能的视频编解码技术.目前国际上制定视频编解码技术的组织有两个,一个是"国际电联",它制定的标准有H.261.H.263.H.2 ...

  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 ...

  3. FFMPEG学习----分离视音频里的PCM数据

    /** * 参考于:http://blog.csdn.net/leixiaohua1020/article/details/46890259 */ #include <stdio.h> # ...

  4. FFMPEG学习----打印视频信息

    FFMPEG学习资料少之又少,在此推荐雷神的博客: http://blog.csdn.net/leixiaohua1020 在这里,我们把打印视频里的相关信息作为学习FFMPEG的 Hello Wor ...

  5. 音视频开发之H.264 入门知识

    大家如果有做过音视频相关的项目,那么肯定对 H.264 相关的概念了解的比较通透,这里我为什么还要写这样一篇文章呢?一来是为了对知识的总结,二来是为了给刚入门音视频的同学一个参考. 基础概念 H.26 ...

  6. FFMPEG学习----解码视频

    基础概念 我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的容器格式规定了其中音视频数据的组织方式(也包括其他 ...

  7. 音视频入门-10-使用libyuv对YUV数据进行缩放、旋转、镜像、裁剪、混合

    * 音视频入门文章目录 * libyuv libyuv 是 Google 开源的实现各种 YUV 与 RGB 之间相互转换.旋转.缩放等的库.它是跨平台的,可在 Windows.Linux.Mac.A ...

  8. 用ffmpeg把视频编码格式转为h.264

    command: ffmpeg -i infile.mp4 -an -vcodec libx264 -crf 23 outfile.h264

  9. 黄聪:FFmpeg视频转码技巧之-crf参数(H.264篇)

    昨天,有个朋友给我出了个难题:他手上有一个视频,1080P的,49秒,200多兆:要求在确保质量的情况下把文件压缩到10M以内. 这是什么概念呢?按照文件大小10M来计算,码率是:10 x 8 / 4 ...

随机推荐

  1. Markdown数学符号

    上标 语法: x^2 效果: \(x^2\) 下标 语法: x_i 效果: \(x_i\) 整体 语法: x^{2y} 效果: \(x^{2y}\) 大括号 语法: \{\} 效果: \(\{\}\) ...

  2. Docker+Nginx使用流程(笔记)

    Docker+Nginx使用流程 本教程依据个人理解并经过实际验证为正确,特此记录下来,权当笔记. 注:基于linux操作系统 # uname -r 查看你当前的内核版本 # yum -y insta ...

  3. ThreadLocal解析:父线程的本地变量不能传递到子线程详解

    众所周知,ThreadLocal类是java提供线程本地变量的工具类.但父线程的本地变量却不能被子线程使用,代码如下: public static void main(String[] args) { ...

  4. Winform在控件内实现简单画笔功能

    using System.Drawing; using System.Windows.Forms; namespace ZhuoHuiSchoolroom.ZhuoHuiClass { /// < ...

  5. Spring HTTP invoker简介

    Spring HTTP invoker简介 Spring HTTP invoker是spring框架中的一个远程调用模型,执行基于HTTP的远程调用(意味着可以通过防火墙),并使用java的序列化机制 ...

  6. 三、JVM之方法区

    一.什么式方法区 方法区,也称非堆(Non-Heap),又是一个被线程共享的内存区域.其中主要存储加载的类字节码.class/method/field等元数据对象.static-final常量.sta ...

  7. 主席树 - 查询某区间第 K 大

    You are working for Macrohard company in data structures department. After failing your previous tas ...

  8. Gitlab应用——系统管理

    ​ 查看linux系统信息 ​ 查看日志 ​ ​ 创建账号 ​ 选择regular,这是一个普通账号,点击“create user”账号创建完成 ​ 点击“User”,然后点击“New user”.使 ...

  9. 10.JavaSE之包机制

    包机制: 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间 包语句的语法格式为: package pkg1[ . pkg2[ . pkg3...]]; package com.duan. ...

  10. [题解][Codeforces]Good Bye 2019 简要题解

    构造题好评,虽然这把崩了 原题解 A 题意 二人游戏,一个人有 \(k_1\) 张牌,另一个人 \(k_2\) 张,满足 \(2\le k_1+k_2=n\le 100\),每张牌上有一个数,保证所有 ...