ffmpeg2.1对HEVC/H.265视频进行解码的例子

简介: 新版的ffmpeg 2.1已经加入了对最新视频编解码标准H.265/HEVC的支持,因此可以解码该格式的视频了。这对视频产业来说将起到一种巨大的推动作用。

新版的ffmpeg 2.1已经加入了对最新视频编解码标准H.265/HEVC的支持,因此可以解码该格式的视频了。这对视频产业来说将起到一种巨大的推动作用。本文所示的demo是一个简单的H.265格式视频的playback程序,是在http://blog.csdn.net/mu399/article/details/5814859这篇文章的基础上针对新版ffmpeg2.1做了部分修改。与参考文章一样,这个demo同样没有加入播放延迟,所以视频的帧率是不正常的,随着学习的深入会逐渐解决这个问题。工程的下载地址为:http://download.csdn.net/detail/shaqoneal/6571657

这个工程需要用到ffmpeg和SDL的库,如何将这些库加入到工程中,有很多教程可以参考,就不在这里赘述了,上传到资源中的工程已经设置好了。

文件很简单,头文件如下:

//header.h
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"

#ifdef __cplusplus
}
#endif

源文件:

//main.cpp
#include "header.h"
#include <stdio.h>
#include "SDL/include/SDL.h"
#include <stdlib.h>   
#include <string.h>  
#include <math.h> 

static int sws_flags = SWS_BICUBIC; 

int main(int argc, char *argv[])
 {
	AVFormatContext *pFormatCtx = NULL;  
    int i, videoStream(-1);  
    AVCodecContext *pCodecCtx;  
    AVCodec *pCodec;  
    AVFrame *pFrame;  
    AVPacket packet;  
    int frameFinished;  
    float aspect_ratio;  
    AVCodecContext *aCodecCtx;  
    SDL_Overlay *bmp;  
    SDL_Surface *screen;  
    SDL_Rect rect;  
    SDL_Event event;  
    if(argc < 2)  
    {  
        fprintf(stderr, "Usage: test /n");  
        exit(1);  
    }  
  
    av_register_all();  
 
    if(avformat_open_input(&pFormatCtx,argv[1],NULL,NULL))  
        return -1; // Couldn't open file  
    if(av_find_stream_info(pFormatCtx)<0)  
        return -1; // Couldn't find stream information  
    // Dump information about file onto standard error  
//    dump_format(pFormatCtx, 0, argv[1], 0);  
  
    // Find the first video stream  
    for(i=0; i<pFormatCtx->nb_streams; i++)  
    {  
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO && videoStream<0)  
        {  
            videoStream=i;  
        }  
    }  
    if(videoStream==-1)  
      return -1; // Didn't find a video stream  
  
    // Get a pointer to the codec context for the video stream  
  
    pCodecCtx=pFormatCtx->streams[videoStream]->codec;  
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
    if(pCodec==NULL)  
    {  
        fprintf(stderr, "Unsupported codec!/n");  
        return -1; // Codec not found  
    }  
    // Open codec  
    if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)  
        return -1; // Could not open codec  
  
    // Allocate video frame  
    pFrame=avcodec_alloc_frame();  
  
    uint8_t *buffer;  
    int numBytes;  
    // Determine required buffer size and allocate buffer  
    numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);  
    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));  
  
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))  
    {  
        fprintf(stderr, "Could not initialize SDL - %s/n", SDL_GetError());  
        exit(1);  
    }  
  
#ifndef __DARWIN__  
    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);  
#else  
    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);  
#endif  
    if(!screen)  
    {  
        fprintf(stderr, "SDL: could not set video mode - exiting/n");  
        exit(1);  
    }  
  
    bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,  
        SDL_YV12_OVERLAY, screen);  
  
    static struct SwsContext *img_convert_ctx;  
    if (img_convert_ctx == NULL)  
    {  
        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
                                         pCodecCtx->pix_fmt,  
                                         pCodecCtx->width, pCodecCtx->height,  
                                         PIX_FMT_YUV420P,  
                                         sws_flags, NULL, NULL, NULL);  
        if (img_convert_ctx == NULL)  
        {  
            fprintf(stderr, "Cannot initialize the conversion context/n");  
            exit(1);  
        }  
    }  
    i=0;  
    while(av_read_frame(pFormatCtx, &packet)>=0)  
    {  
        // Is this a packet from the video stream?  
        if(packet.stream_index==videoStream)  
        {  
            // Decode video frame  
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

            // Did we get a video frame?  
            if(frameFinished)  
            {  
                // Convert the image from its native format to RGB  
                /*sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 
                      0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);*/  
                // Save the frame to disk  
                /*if(++i<=5) 
                    SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);*/  
                SDL_LockYUVOverlay(bmp);  
                AVPicture pict;  
                pict.data[0] = bmp->pixels[0];  
                pict.data[1] = bmp->pixels[2];  
                pict.data[2] = bmp->pixels[1];  
  
                pict.linesize[0] = bmp->pitches[0];  
                pict.linesize[1] = bmp->pitches[2];  
                pict.linesize[2] = bmp->pitches[1];  
  
                // Convert the image into YUV format that SDL uses  
                /*img_convert(&pict, PIX_FMT_YUV420P, 
                    (AVPicture *)pFrame, pCodecCtx->pix_fmt, 
                    pCodecCtx->width, pCodecCtx->height);*/  
                sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
                    0, pCodecCtx->height, pict.data, pict.linesize);  
                SDL_UnlockYUVOverlay(bmp);  
                rect.x = 0;  
                rect.y = 0;  
                rect.w = pCodecCtx->width;  
                rect.h = pCodecCtx->height;  
                SDL_DisplayYUVOverlay(bmp, &rect);  
                //Sleep(60);  
            }  
        }  
  
        // Free the packet that was allocated by av_read_frame  
        av_free_packet(&packet);  
  
        SDL_PollEvent(&event);  
        switch(event.type)  
        {  
        case SDL_QUIT:  
            SDL_Quit();  
            exit(0);  
            break;  
        default: break;  
        }  
    };  
    // Free the RGB image  
    av_free(buffer);  
    //av_free(pFrameRGB);  
    // Free the YUV frame  
    av_free(pFrame);  
    // Close the codec  
    avcodec_close(pCodecCtx);  
    // Close the video file  
    av_close_input_file(pFormatCtx);  
    return 0;  
};

今后一段时间里讲尽可能详细地解析上面的每一个类、语句的结构和作用,最终的目的是彻底搞通ffmpeg进行视频处理的原理,可以方便地完成基于ffmpeg的各种开发。一起加油吧!
目录
相关文章
|
5月前
|
编解码 Linux
CentOS安装ffmpeg并转码视频为mp4
CentOS安装ffmpeg并转码视频为mp4
174 0
|
2月前
|
编解码 监控 网络协议
如何使用FFmpeg实现RTSP推送H.264和H.265(HEVC)编码视频
本文详细介绍了如何使用FFmpeg实现RTSP推送H.264和H.265(HEVC)编码视频。内容涵盖环境搭建、编码配置、服务器端与客户端实现等方面,适合视频监控系统和直播平台等应用场景。通过具体命令和示例代码,帮助读者快速上手并实现目标。
598 6
|
7月前
|
Python
Python使用ffmpeg下载m3u8拼接为视频
Python使用ffmpeg下载m3u8拼接为视频
|
3月前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
259 1
|
3月前
|
计算机视觉 Python
FFMPEG学习笔记(一): 提取视频的纯音频及无声视频
本文介绍了如何使用FFmpeg工具从视频中提取纯音频和无声视频。提供了具体的命令行操作,例如使用`ffmpeg -i input.mp4 -vn -c:a libmp3lame output.mp3`来提取音频,以及`ffmpeg -i input.mp4 -c:v copy -an output.mp4`来提取无声视频。此外,还包含了一个Python脚本,用于批量处理视频文件,自动提取音频和生成无声视频。
143 1
|
3月前
FFmpeg学习笔记(二):多线程rtsp推流和ffplay拉流操作,并储存为多路avi格式的视频
这篇博客主要介绍了如何使用FFmpeg进行多线程RTSP推流和ffplay拉流操作,以及如何将视频流保存为多路AVI格式的视频文件。
465 0
|
6月前
|
数据采集 大数据 Python
FFmpeg 在爬虫中的应用案例:流数据解码详解
在大数据背景下,网络爬虫与FFmpeg结合,高效采集小红书短视频。需准备FFmpeg、Python及库如Requests和BeautifulSoup。通过设置User-Agent、Cookie及代理IP增强隐蔽性,解析HTML提取视频链接,利用FFmpeg下载并解码视频流。示例代码展示完整流程,强调代理IP对避免封禁的关键作用,助你掌握视频数据采集技巧。
FFmpeg 在爬虫中的应用案例:流数据解码详解
|
7月前
|
Web App开发 安全 Linux
FFmpeg开发笔记(二十六)Linux环境安装ZLMediaKit实现视频推流
《FFmpeg开发实战》书中介绍轻量级流媒体服务器MediaMTX,但其功能有限,不适合生产环境。推荐使用国产开源的ZLMediaKit,它支持多种流媒体协议和音视频编码标准。以下是华为欧拉系统下编译安装ZLMediaKit和FFmpeg的步骤,包括更新依赖、下载源码、配置、编译、安装以及启动MediaServer服务。此外,还提供了通过FFmpeg进行RTSP和RTMP推流,并使用VLC播放器拉流的示例。
369 3
FFmpeg开发笔记(二十六)Linux环境安装ZLMediaKit实现视频推流
|
6月前
|
语音技术 C语言 Windows
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
|
7月前
|
编解码 Linux 计算机视觉
python 调用ffmpeg使用usb摄像头录制视频,输出h264格式,自动获取摄像头的最佳帧率和最大画面尺寸
使用 Python 调用 FFmpeg 进行 USB 摄像头视频录制,需先确保安装 FFmpeg 和 Python 的 `subprocess` 模块。代码示例展示了如何自动获取摄像头的最佳帧率和最大分辨率,然后录制视频。首先通过 FFmpeg 列出摄像头格式获取信息,解析出帧率和分辨率,选择最优值。之后调用 FFmpeg 命令录制视频,设置帧率、分辨率等参数。注意 `/dev/video0` 是 Linux 的摄像头设备路径,Windows 系统需相应调整。代码中未直接实现自动获取最佳参数,通常需要借助其他库如 OpenCV。

热门文章

最新文章