这里通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流,然后解码,最后再用opencv显示。用到的模块包括avformat、avcodec和avdevice。libavdevice库是libavformat的一个补充库(complementary library)。主要涉及到的接口函数包括:注:其中一些接口是被废弃的旧接口

1. avdevice_register_all:初始化libavdevice库并注册所有输入输出设备;

2. av_find_input_format:根据输入格式的名字查找AVInputFormat,在测试代码中,windows平台使用”vfwcap”(video for windows capture),linux平台使用”v4l2”(Video4Linux2);

3. avformat_alloc_context:分配AVFormatContext;

4. avformat_open_input:打开输入流并读取header;

5. avformat_find_stream_info:读取媒体文件的数据包以获取流信息;

6. 通过AVFormatContext中AVStream查找视频/音频流索引,这里在windows10下获取到的编码类型为mjpeg即AV_CODEC_ID_MJPEG,像素格式为yuv422p即AV_PIX_FMT_YUVJ422P;在linux或windows7下获取到的编码类型为rawvideo即AV_CODEC_ID_RAWVIDEO,像素格式yuyv422即AV_PIX_FMT_YUYV422;可见摄像头类型不同获取到的编码类型和像素格式可能也不同;

7. avcodec_find_decoder:由codec ID查找已注册的解码器;

8. avcodec_open2:初始化AVCodecContext;

9. av_frame_alloc:分配一个AVFrame并设置它的字段为默认值;

10. av_malloc:为一个AVPacket分配内存块;

11. sws_getContext:分配一个SwsContext;

12. av_read_frame:获取流即packet(AVPacket);

13. avcodec_decode_video2:解码视频帧,从流数据到图像数据;

14. sws_scale:转换图像格式;

15. av_free_packet:释放AVPacket;

16. av_frame_free:释放由av_frame_alloc分配的AVFrame;

17. sws_freeContext:释放由sws_getContext分配的SwsContext;

18. av_free:释放由av_malloc分配的AVPacket;

19. avformat_close_input:关闭打开的AVFormatContext并释放。

测试代码(test_ffmpeg_decode_show.cpp):

#include "funset.hpp"
#include <stdio.h>
#include <iostream>
#include <memory>
#include <fstream>#ifdef __cplusplus
extern "C" {
#endif#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/mem.h>
#include <libavutil/imgutils.h>#ifdef __cplusplus
}
#endif#include <opencv2/opencv.hpp>int test_ffmpeg_decode_show_old()
{avdevice_register_all();#ifdef _MSC_VERconst char* input_format_name = "vfwcap";const char* url = "";
#elseconst char* input_format_name = "video4linux2";const char* url = "/dev/video0";
#endifAVInputFormat* input_fmt = av_find_input_format(input_format_name);AVFormatContext* format_ctx = avformat_alloc_context();int ret = avformat_open_input(&format_ctx, url, input_fmt, nullptr);if (ret != 0) {fprintf(stderr, "fail to open url: %s, return value: %d\n", url, ret);return -1;}ret = avformat_find_stream_info(format_ctx, nullptr);if (ret < 0) {fprintf(stderr, "fail to get stream information: %d\n", ret);return -1;}int video_stream_index = -1;for (int i = 0; i < format_ctx->nb_streams; ++i) {const AVStream* stream = format_ctx->streams[i];if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream_index = i;fprintf(stdout, "type of the encoded data: %d, dimensions of the video frame in pixels: width: %d, height: %d, pixel format: %d\n",stream->codecpar->codec_id, stream->codecpar->width, stream->codecpar->height, stream->codecpar->format);}}if (video_stream_index == -1) {fprintf(stderr, "no video stream\n");return -1;}AVCodecContext* codec_ctx = format_ctx->streams[video_stream_index]->codec;AVCodec* codec = avcodec_find_decoder(codec_ctx->codec_id);if (!codec) {fprintf(stderr, "no decoder was found\n");return -1;}ret = avcodec_open2(codec_ctx, codec, nullptr);if (ret != 0) {fprintf(stderr, "fail to init AVCodecContext: %d\n", ret);return -1;}AVFrame* frame = av_frame_alloc();AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));SwsContext* sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_BGR24, 0, nullptr, nullptr, nullptr);if (!frame || !packet || !sws_ctx) {fprintf(stderr, "fail to alloc\n");return -1;}int got_picture = -1;std::unique_ptr<uint8_t[]> data(new uint8_t[codec_ctx->width * codec_ctx->height * 3]);cv::Mat mat(codec_ctx->height, codec_ctx->width, CV_8UC3);int width_new = 320, height_new = 240;cv::Mat dst(height_new, width_new, CV_8UC3);const char* winname = "usb video1";cv::namedWindow(winname);while (1) {ret = av_read_frame(format_ctx, packet);if (ret < 0) {fprintf(stderr, "fail to av_read_frame: %d\n", ret);continue;}if (packet->stream_index == video_stream_index) {ret = avcodec_decode_video2(codec_ctx, frame, &got_picture, packet);if (ret < 0) {fprintf(stderr, "fail to avcodec_decode_video2: %d\n", ret);av_free_packet(packet);continue;}if (got_picture) {uint8_t* p[1] = { data.get() };int dst_stride[1] = { frame->width * 3 };sws_scale(sws_ctx, frame->data, frame->linesize, 0, codec_ctx->height, p, dst_stride);mat.data = data.get();cv::resize(mat, dst, cv::Size(width_new, height_new));cv::imshow(winname, dst);}}av_free_packet(packet);int key = cv::waitKey(25);if (key == 27) break;}cv::destroyWindow(winname);av_frame_free(&frame);sws_freeContext(sws_ctx);av_free(packet);avformat_close_input(&format_ctx);fprintf(stdout, "test finish\n");return 0;
}

执行结果如下:

GitHub:https://github.com//fengbingchun/OpenCV_Test

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(旧接口)相关推荐

  1. FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(新接口)

    在https://blog.csdn.net/fengbingchun/article/details/93975325 中给出了通过旧接口即FFmpeg中已废弃的接口实现通过摄像头获取视频流然后解码 ...

  2. FFmpeg中编码类型为rawvideo无须解码直接显示测试代码

    在 https://blog.csdn.net/fengbingchun/article/details/93975325 中介绍过通过FFmpeg可以直接获取usb视频流并解码显示的测试代码,当时通 ...

  3. FFmpeg中一个线程获取视频流一个线程执行scale测试代码

    在https://blog.csdn.net/fengbingchun/article/details/94712986 中介绍过如果usb视频流编码类型为rawvideo则无需进行解码,可直接通过a ...

  4. FFmpeg在Windows上通过dshow编解码方式设置为mjpeg并实时显示测试代码

    Windows上默认的内置摄像头一般支持两种编解码格式:rawvideo和mjpeg.在调用FFmpeg接口时默认的采用rawvideo.这里通过DirectShow实现为mjpeg进行编解码. 通过 ...

  5. FFmpeg在Windows上设置dshow mjpeg编码+libyuv解码显示测试代码

    之前在https://blog.csdn.net/fengbingchun/article/details/103444891中介绍过在Windows上通过ffmpeg dshow设置为mjpeg编解 ...

  6. FFmpeg中拉取rtsp视频流并缩放显示测试代码

    之前在https://blog.csdn.net/fengbingchun/article/details/92198857中给出过仅拉取rtsp视频流的测试代码,这里在此代码的基础上进行扩充,包括设 ...

  7. ffmpeg+nvidia解码SDK+GPU实现视频流硬解码成Mat

    方法原理 rtsp流解码方式分为两种:硬解码和软解码.软解码一般通过ffmpeg编解码库实现,但是cpu占用率很高,解码一路1080p视频cpu占用率达到70%左右,对实际应用来说,严重影响机器最大解 ...

  8. FFmpeg实现获取USB摄像头视频流测试代码

    通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流用到的模块包括avformat和avdevice.头文件仅include ...

  9. FFMPEG采集摄像头图像SDL渲染+MP4格式视频编码

    FFMPEG采集摄像头图像SDL渲染+MP4格式视频编码 FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音 ...

最新文章

  1. VS Code 1.47 发布!官方版 Settings Sync 终于来了!
  2. 侦听127.0.01_Spring 4.2中由注释驱动的事件侦听器
  3. 想用Python爬小姐姐图片?那你得先搞定分布式进程
  4. 4012最长的最短路径的求解(C++,迪杰斯特拉算法,注释全,附迪杰斯特拉算法详解文章)
  5. 方法调用中的别名问题
  6. 一文带你了解传统手工特征的骨龄评估方法的发展历史
  7. 【原创源码】(05):C#-计算绝对路径。
  8. STM32学习第二课:STM32c语言基础2
  9. Shell脚本中计算字符串长度的5种方法
  10. python uwsgi_uwsgi的多站点配置
  11. js 函数节流和防抖
  12. 城市记忆:(一)灵洲----河奇;(二)富平三迁
  13. Python手机App数据抓取实战:抖音用户的抓取
  14. 清理浏览器html缓存图片吗,在JSP或Javascript中清除浏览器缓存中的图像
  15. 科技大停滞--过去已逝,未来未来
  16. puts 和 printf %s
  17. 1.什么是方法 2.方法定义俩变量求和打印 3.改进上面的 (在调用里面改值相加) 4.形参与实参 5.计算长方形周长 定义一个方法并打印出来 6.定义一个方法 计算圆的面积打印出来
  18. XtraReport 填补空白行,生成空白行
  19. 浅析信息系统架构的应用架构与数据架构
  20. 美摄科技推出桌面端专业视频编辑解决方案——美映PC版

热门文章

  1. 图像识别-opencv
  2. 【机器视觉案例】(9) AI视觉,手势控制电脑键盘,附python完整代码
  3. 修改vscode的语言
  4. 在VirtualBox 5.0.12 for Linux版本上安装CentOS 6.6 x86_64系统
  5. 使用libevent多线程验证Linux上的服务器惊群现象
  6. 虚幻引擎5(UE5)实时VFX游戏特效制作入门到精通
  7. C#和Unity游戏开发者大师班2021 (2D,3D和FPS)
  8. leetcode-20 有效的括号匹配
  9. Ubuntu 18.04时间同步
  10. 我是如何有效的避免测试漏测?