Ffmpeg濾鏡

打開設備
添加濾鏡
循環錄制文件

#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libswscale/swscale.h"
#include "libavutil/pixdesc.h"
#include "libavutil/hash.h"
#include "libavutil/bswap.h"
#include "libavutil/opt.h"
#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavutil/pixfmt.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define DEVICE_NAME "/dev/video0"
#define OUTPUT_FILE "/root/output.mp4"
#define DURATION_SEC 10 // 全局變量AVFormatContext *in_fmt_ctx = NULL, *out_fmt_ctx = NULL;
AVCodecContext *dec_ctx = NULL, *enc_ctx = NULL;
AVFilterGraph *filter_graph = NULL;
AVFilterContext *buffersrc_ctx = NULL, *buffersink_ctx = NULL;
AVStream *in_stream = NULL, *out_stream = NULL;AVCodecParameters *codecParameters = NULL;
int video_stream_index = -1;int init_input_output()
{AVDictionary *opts = NULL;AVInputFormat *input_fmt = av_find_input_format("v4l2");av_dict_set(&opts, "video_size", "640x480", 0);av_dict_set(&opts, "framerate", "25", 0);av_dict_set(&opts, "input_format", "mjpeg", 0);if (avformat_open_input(&in_fmt_ctx, DEVICE_NAME, input_fmt, &opts) < 0){fprintf(stderr, "無法打開輸入設忇\n");return -1;}if (avformat_find_stream_info(in_fmt_ctx, NULL) < 0){printf("open input failed\n");return -1;}video_stream_index = av_find_best_stream(in_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, NULL);in_stream = in_fmt_ctx->streams[video_stream_index];codecParameters = in_stream->codecpar;printf("codecid = %d ; h = %d ; w = %d;\n", in_stream->codecpar->codec_id, codecParameters->height, codecParameters->width);AVCodec *decoder = avcodec_find_decoder(in_stream->codecpar->codec_id);if (!decoder){printf("upspoort decoder\n");return -1;}dec_ctx = avcodec_alloc_context3(decoder);avcodec_parameters_to_context(dec_ctx, codecParameters);if (avcodec_open2(dec_ctx, decoder, NULL) < 0){printf("decoder avcodec_open2 failed\n");return -1;}avformat_alloc_output_context2(&out_fmt_ctx, NULL, NULL, OUTPUT_FILE);const AVCodec *encoder = avcodec_find_encoder_by_name("mpeg4");; // avcodec_find_encoder(AV_CODEC_ID_H264);if (encoder == NULL){printf("unsporrt edcodec\n");return -1;}out_stream = avformat_new_stream(out_fmt_ctx, NULL);enc_ctx = avcodec_alloc_context3(encoder);enc_ctx->codec_type = AVMEDIA_TYPE_VIDEO;enc_ctx->codec_id = encoder->id;enc_ctx->width = 640;enc_ctx->height = 480;enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;enc_ctx->time_base = (AVRational){1, 25};enc_ctx->framerate = (AVRational){25, 1}; // in_stream->avg_frame_rate;//編碼幀率按照采集幀率板enc_ctx->has_b_frames = 0;enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;// av_opt_set(enc_ctx->priv_data, "tune", "zerolatency", 0);int ret = -1;ret = avcodec_open2(enc_ctx, encoder, NULL);printf("ret = %d\n", ret);if (ret < 0){printf(";;,,;encoder avcodec_open2 fialed\n");return -1;}out_stream->time_base = (AVRational){1, 25};avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);if (!(out_fmt_ctx->oformat->flags & AVFMT_NOFILE)){avio_open(&out_fmt_ctx->pb, OUTPUT_FILE, AVIO_FLAG_WRITE);}avformat_write_header(out_fmt_ctx, NULL);return 0;
}
int init_filter_graph()
{if (!dec_ctx){printf("dec_ctx is nullptr\n");return -1;}printf("----------->init_filter_graph\n");char args[512] = {0};char filter_descr[512] = {0};filter_graph = avfilter_graph_alloc();if (!filter_graph){printf("filter_graph  is nullptr\n");return -1;}const AVFilter *buffersrc = avfilter_get_by_name("buffer");const AVFilter *buffersink = avfilter_get_by_name("buffersink");if (!buffersrc || !buffersink){printf("buffersrc  or buffersink is nullptr\n");return -1;}snprintf(args, sizeof(args), "video_size=640x480:pix_fmt=%d:time_base=1/25:pixel_aspect=1/1", dec_ctx->pix_fmt);avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph);avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE};if (av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0){printf("set   buufersink gesgi failed\n");}sprintf(filter_descr, "%s", "drawtext=fontfile=/usr/share/fonts/msyh.ttf:text='%{localtime\\:%Y-%m-%d  %X}':fontcolor=white:fontsize=24:x=w-tw-10:y=10");// sprintf(filter_descr, "%s", "drawtext=fontfile=/usr/share/fonts/msyh.ttf:text='hello':fontcolor=white:fontsize=24:x=w-tw-10:y=10");// sprintf(filter_descr, "%s%s%s", "drawtext=fontfile=/usr/share/fonts/msyh.ttf:","text='%{localtime\:%Y-%m-%d  %X}':","fontcolor=white:fontsize=24:x=w-tw-10:y=10");printf("text -> %s\n", filter_descr);AVFilterInOut *outputs = avfilter_inout_alloc();AVFilterInOut *inputs = avfilter_inout_alloc();outputs->name = av_strdup("in");outputs->filter_ctx = buffersrc_ctx;outputs->pad_idx = 0;outputs->next = NULL;inputs->name = av_strdup("out");inputs->filter_ctx = buffersink_ctx;inputs->pad_idx = 0;inputs->next = NULL;if (avfilter_graph_parse_ptr(filter_graph, filter_descr, &inputs, &outputs, NULL) < 0){return -1;}if (avfilter_graph_config(filter_graph, NULL) < 0){return -1;}avfilter_inout_free(&inputs);avfilter_inout_free(&outputs);return 0;
}
int process_and_encode()
{AVPacket pkt;AVFrame *frame = av_frame_alloc();AVFrame *filt_frame = av_frame_alloc();int64_t start_time = av_gettime();while (av_gettime() - start_time < DURATION_SEC * 1000000){if (av_read_frame(in_fmt_ctx, &pkt) >= 0 && pkt.stream_index == video_stream_index){avcodec_send_packet(dec_ctx, &pkt);while (avcodec_receive_frame(dec_ctx, frame) == 0){av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF);while (av_buffersink_get_frame(buffersink_ctx, filt_frame) >= 0){avcodec_send_frame(enc_ctx, filt_frame);while (avcodec_receive_packet(enc_ctx, &pkt) == 0){pkt.stream_index = out_stream->index;pkt.pts = av_rescale_q(pkt.pts, enc_ctx->time_base, out_stream->time_base);pkt.dts = av_rescale_q(pkt.dts, enc_ctx->time_base, out_stream->time_base);pkt.duration = av_rescale_q(pkt.duration, enc_ctx->time_base, out_stream->time_base);av_interleaved_write_frame(out_fmt_ctx, &pkt);av_packet_unref(&pkt);}av_frame_unref(filt_frame);}av_frame_unref(frame);}av_packet_unref(&pkt);}}av_frame_free(&frame);av_frame_free(&filt_frame);return 0;
}int process_and_encode1()
{AVPacket pkt;AVFrame *frame = av_frame_alloc();AVFrame *filt_frame = av_frame_alloc();int64_t start_time = av_gettime();int frame_count = 0; // 新忞:用于設置 filt_frame->ptswhile (frame_count <= 250){// 1. 從輸入迻取 packetif (av_read_frame(in_fmt_ctx, &pkt) >= 0 && pkt.stream_index == video_stream_index){// 2. 解碼avcodec_send_packet(dec_ctx, &pkt);while (avcodec_receive_frame(dec_ctx, frame) == 0){// 3. 送入濾鏡(忿 drawtext_av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF);// 4. 從濾鏡輸鑿 filtered 帿while (av_buffersink_get_frame(buffersink_ctx, filt_frame) >= 0){// ? 顯式設置 filtered 幀的 PTS(避免編碼器無法計算時長_filt_frame->pts = frame_count++;// 5. 編碼avcodec_send_frame(enc_ctx, filt_frame);while (1){AVPacket out_pkt;av_init_packet(&out_pkt);out_pkt.data = NULL;out_pkt.size = 0;if (avcodec_receive_packet(enc_ctx, &out_pkt) != 0){break; // 暫無叿寫入數據}// ? 轎換時間基(防歿不合泿 time_base 導致時長錯迿_av_packet_rescale_ts(&out_pkt, enc_ctx->time_base, out_stream->time_base);out_pkt.stream_index = out_stream->index;av_interleaved_write_frame(out_fmt_ctx, &out_pkt);av_packet_unref(&out_pkt);}av_frame_unref(filt_frame);}av_frame_unref(frame);}av_packet_unref(&pkt);}}// ? 強制沖刷編碼器緩存(flush_avcodec_send_frame(enc_ctx, NULL); // 通知編碼噿:結束了while (1){AVPacket out_pkt;av_init_packet(&out_pkt);out_pkt.data = NULL;out_pkt.size = 0;if (avcodec_receive_packet(enc_ctx, &out_pkt) != 0)break;av_packet_rescale_ts(&out_pkt, enc_ctx->time_base, out_stream->time_base);out_pkt.stream_index = out_stream->index;av_interleaved_write_frame(out_fmt_ctx, &out_pkt);av_packet_unref(&out_pkt);}av_frame_free(&frame);av_frame_free(&filt_frame);return 0;
}int main()
{printf("this is ffmpeg drawtext test  mjpeg\n");av_register_all();avcodec_register_all();avdevice_register_all();avfilter_register_all();avformat_network_init();int ret = -1;ret = init_input_output();printf("reto = %d\n", ret);if (ret < 0){return -1;}ret = -1;ret = init_filter_graph();printf("ret1 = %d\n", ret);if (ret < 0){return -1;}ret = -1;ret = process_and_encode1();printf("ret2 = %d\n", ret);if (ret < 0){return -1;}// 清理資源av_write_trailer(out_fmt_ctx);if (!(out_fmt_ctx->oformat->flags & AVFMT_NOFILE)){avio_closep(&out_fmt_ctx->pb);avcodec_free_context(&dec_ctx);avcodec_free_context(&enc_ctx);avformat_close_input(&in_fmt_ctx);avformat_free_context(out_fmt_ctx);avfilter_graph_free(&filter_graph);}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91014.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91014.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91014.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HarmonyOS AI輔助編程工具(CodeGenie)UI生成

UI Generator基于BitFun Platform AI能力平臺&#xff0c;用于快速生成可編譯、可運行的HarmonyOS UI工程&#xff0c;支持基于已有UI布局文件&#xff08;XML&#xff09;&#xff0c;快速生成對應的HarmonyOS UI代碼&#xff0c;其中包含HarmonyOS基礎工程、頁面布局、組件及…

【第三節】ubuntu server配置遠程連接

首先在ubuntu server中查看ip&#xff0c;打開虛擬機&#xff0c;輸入ip addr show ,這個命令很好記&#xff0c;幾乎就是英文自然語言 下面我們準備遠程連接工具&#xff0c;我選擇的開源的ET&#xff0c;全稱是electerm,圈起來的是必須輸入的內容&#xff0c;輸入完成后點擊保…

CCS-MSPM0G3507-7-模塊篇-MPU6050的基本使用

前言本篇我們接收對MPU6050的基本使用&#xff0c;獲取ID&#xff0c;通過IIC協議獲取寄存器的值&#xff0c;至于高級濾波算法&#xff0c;比如卡爾曼濾波&#xff0c;或者上面的&#xff0c;后面再更新基本配置最好選擇PA0和PA1&#xff0c;5V開漏然后給上代碼MPU6050.c#incl…

spring-ai agent概念

目錄agent 概念理解記憶能力工具計劃agent 概念理解 agent 智能體&#xff0c;突出智能 大模型的感覺 告訴你怎么做&#xff08;也不一定正確&#xff09;不會幫你做 Agent的感覺 直接準確的幫你做完&#xff08;比如&#xff0c;告訴 AI Agent 幫忙下單一份外賣&#xff0c…

NO.4數據結構數組和矩陣|一維數組|二維數組|對稱矩陣|三角矩陣|三對角矩陣|稀疏矩陣

數組的儲存 【定義】 數組&#xff1a; 由 n&#xff08;≥1&#xff09; 個相同類型的數據元素構成的有限序列&#xff0c; 是線性表的推廣。 一旦被定義&#xff0c; 維數和長度就不可再改變&#xff0c; 一般對其只有元素的存取和修改操作。 一維數組 Arr[a0,…,an?1] Arr[…

如何把Arduino IDE中ESP32程序bin文件通過樂鑫flsah_download_tool工具軟件下載到ESP32中

目錄前言獲取Arduino IDE中ESP32程序bin文件flsah_download_tool工具軟件下載程序bin文件到ESP32中總結前言 Arduino IDE豐富的驅動庫給ESP32的開發帶來了很多便利&#xff0c;當我們下載程序的時候&#xff0c;直選選擇好ESP32開發板型號和端口號即可下載程序到開發板中&…

2025XYD Summer Camp 7.11 模考

T1TTT 組詢問&#xff0c;每組詢問給定 n,mn,mn,m&#xff0c;求 (nm)?1?∑i1n∑j1mlcm?(i,j) (nm)^{-1}\cdot\sum_{i1}^n\sum_{j1}^m\operatorname{lcm}(i,j) (nm)?1?i1∑n?j1∑m?lcm(i,j) 對 109710^971097 取模。 T≤20000T\le 20000T≤20000&#xff0c;n,m≤107n,m…

uniapp 微信小程序點擊開始倒計時

一、示例 當點擊按鈕時就開始倒計時代碼 <template><view class"sq_box"><button class"button" click"topay">按鈕</button><u-modal v-model"modalShow" :show-cancel-button"true" :content&…

【網絡】Linux 內核優化實戰 - net.netfilter.nf_conntrack_tcp_timeout_established

目錄一、核心概念1. **TCP 連接狀態跟蹤**2. **參數作用**二、默認值與典型場景1. **默認值**2. **典型場景**三、如何調整該參數1. **查看當前值**2. **臨時修改&#xff08;重啟后失效&#xff09;**3. **永久修改**四、相關參數與配合優化1. **其他 TCP 狀態超時參數**2. **…

鴻蒙app 開發中的Record<string,string>的用法和含義

Record<string, string> 在鴻蒙 App 開發中的用法在 TypeScript 中&#xff0c;Record<string, string> 是一個映射類型&#xff08;Mapped Type&#xff09;&#xff0c;用于描述一個對象的結構。在鴻蒙 App 開發中&#xff0c;它常用于定義接口、組件屬性或函數參…

Webpack、Vite配置技巧與CI/CD流程搭建全解析

Webpack、Vite配置技巧與CI/CD流程搭建全解析 在現代前端開發中&#xff0c;構建工具配置和自動化部署流程是提升開發效率和項目質量的關鍵環節。本文將深入探討Webpack和Vite這兩大構建工具的核心配置技巧&#xff0c;并詳細介紹CI/CD流程的搭建方法。 一、Webpack核心配置技巧…

輸入npm install后發生了什么

一、準備階段&#xff1a;配置與環境檢查讀取配置優先級npm install 首先加載多層級的配置&#xff08;優先級從高到低&#xff09;4&#xff1a;項目級 .npmrc用戶級 .npmrc&#xff08;如 ~/.npmrc&#xff09;全局 npmrcnpm 內置默認配置可通過 npm config ls -l 查看所有配…

SpringBoot集成Redis、SpringCache

1 Redis介紹 1.1 Redis作為緩存 由于Redis的存取效率非常高,在開發實踐中,通常會將一些數據從關系型數據庫(例如MySQL)中讀取出來,并寫入到Redis中,后續當需要訪問相關數據時,將優先從Redis中讀取所需的數據,以此,可以提高數據的讀取效率,并且對一定程度的保護關系型…

靜態路由綜合配置實驗報告

一、實驗拓撲二、實驗需求1.除了R5的環回地址固定5.5.5.0/24&#xff0c;其他網段基于192.168.1.0/24進行合理劃分&#xff1b;2.R1-R4每個路由器存在兩個環回接口&#xff0c;模擬PC&#xff0c;地址也在192.168.1.0/24網絡內&#xff1b;3.R1-R4不能直接編寫到達5.5.5.0/24的…

【一起來學AI大模型】PyTorch DataLoader 實戰指南

DataLoader 是 PyTorch 中處理數據的核心組件&#xff0c;它提供了高效的數據加載、批處理和并行處理功能。下面是一個全面的 DataLoader 實戰指南&#xff0c;包含代碼示例和最佳實踐。基礎用法&#xff1a;簡單數據加載import torch from torch.utils.data import Dataset, D…

SpringBoot單元測試類拿不到bean報空指針異常

原代碼package com.atguigu.gulimall.product;import com.aliyun.oss.OSSClient; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; impo…

持續集成 簡介環境搭建

1. 持續集成簡介 1.1 持續集成的作用 隨著互聯網的蓬勃發展,軟件生命周期模型也經歷了幾個比較大的階段,從最初的瀑布模型,到 V 模型,再到現在的敏捷或者 devops,不論哪個階段,項目從立項到交付幾乎都離不開以下幾個過程,開發、構建、測試和發布,而且一直都在致力于又…

關于 java:11. 項目結構、Maven、Gradle 構建系統

一、Java 項目目錄結構標準1.1 Java 項目標準目錄結構總覽標準 Java 項目目錄結構&#xff08;以 Maven / Gradle 通用結構為基礎&#xff09;&#xff1a;project-root/ ├── src/ │ ├── main/ │ │ ├── java/ # 主業務邏輯代碼&#xff08;核心…

大數據的安全挑戰與應對

在大數據時代&#xff0c;大數據安全問題已成為開發者最為關注的核心議題之一。至少五年來&#xff0c;大數據已融入各類企業的運營體系&#xff0c;而采用先進數據分析解決方案的組織數量仍在持續增長。本文將明確當前市場中最關鍵的大數據安全問題與威脅&#xff0c;概述企業…