FFmpeg中编码类型为rawvideo无须解码直接显示测试代码
生活随笔
收集整理的這篇文章主要介紹了
FFmpeg中编码类型为rawvideo无须解码直接显示测试代码
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在?https://blog.csdn.net/fengbingchun/article/details/93975325 中介紹過通過FFmpeg可以直接獲取usb視頻流并解碼顯示的測試代碼,當(dāng)時通過usb獲取到的視頻流編碼類型為AV_CODEC_ID_RAWVIDEO,像素格式為AV_PIX_FMT_YUYV422,其實編碼類型為rawvideo的視頻流可以不經(jīng)過解碼操作直接就可進(jìn)行顯示,測試代碼如下:
#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_stream_show()
{avdevice_register_all();#ifndef _MSC_VERconst char* input_format_name = "video4linux2";const char* url = "/dev/video0";AVInputFormat* 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 (unsigned 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;}AVCodecParameters* codecpar = format_ctx->streams[video_stream_index]->codecpar;const AVCodec* codec = avcodec_find_decoder(codecpar->codec_id);if (!codec) {fprintf(stderr, "fail to avcodec_find_decoder\n");return -1;}AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "fail to avcodec_alloc_context3\n");return -1;}codec_ctx->pix_fmt = AVPixelFormat(codecpar->format);codec_ctx->height = codecpar->height;codec_ctx->width = codecpar->width;codec_ctx->thread_count = 16;ret = avcodec_open2(codec_ctx, codec, nullptr);if (ret != 0) {fprintf(stderr, "fail to avcodec_open2: %d\n", ret);return -1;}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 (!packet || !sws_ctx) {fprintf(stderr, "fail to alloc\n");return -1;}uint8_t *bgr_data[4], *yuyv422_data[4];int bgr_linesize[4], yuyv422_linesize[4];av_image_alloc(bgr_data, bgr_linesize, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_BGR24, 1);av_image_alloc(yuyv422_data, yuyv422_linesize, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_YUYV422, 1);cv::Mat mat(codec_ctx->height, codec_ctx->width, CV_8UC3);const char* winname = "usb video";cv::namedWindow(winname);const uint8_t *srcSlice[1];while (1) {ret = av_read_frame(format_ctx, packet);if (ret >= 0 && packet->stream_index == video_stream_index) {srcSlice[0] = packet->data;sws_scale(sws_ctx, srcSlice, yuyv422_linesize, 0, codec_ctx->height, bgr_data, bgr_linesize);mat.data = bgr_data[0];cv::imshow(winname, mat);}av_packet_unref(packet);int key = cv::waitKey(25);if (key == 27) break;}cv::destroyWindow(winname);sws_freeContext(sws_ctx);avformat_close_input(&format_ctx);av_freep(packet);av_freep(&bgr_data[0]);av_freep(&yuyv422_data[0]);fprintf(stdout, "test finish\n");return 0;
#elsefprintf(stderr, "Error: this interface only support usb camera: encode type: rawvideo\n");return -1;
#endif
}
執(zhí)行結(jié)果如下:
GitHub:https://github.com//fengbingchun/OpenCV_Test
總結(jié)
以上是生活随笔為你收集整理的FFmpeg中编码类型为rawvideo无须解码直接显示测试代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开源库libuuid简介及使用
- 下一篇: FFmpeg中一个线程获取视频流一个线程