rkmpp 解碼 精簡mpi_dec_test.c例程

rkmpp 解碼流程(除 MPP_VIDEO_CodingMJPEG 之外)

解碼流程

源碼

輸入h264碼流 輸出nv12文件

/** Copyright 2015 Rockchip Electronics Co. LTD** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#if defined(_WIN32)
#include "vld.h"
#endif#define MODULE_TAG "mpi_dec_test"#include <string.h>#include "mpi_dec_utils.h"
#include "mpp_common.h"
#include "mpp_env.h"
#include "mpp_mem.h"
#include "mpp_time.h"
#include "rk_mpi.h"typedef struct {MpiDecTestCmd *cmd;MppCtx ctx;MppApi *mpi;RK_U32 quiet;/* end of stream flag when set quit the loop */RK_U32 loop_end;/* input and output */DecBufMgr buf_mgr;MppBufferGroup frm_grp;MppPacket packet;MppFrame frame;FILE *fp_output;RK_S32 frame_count;RK_S32 frame_num;RK_S64 first_pkt;RK_S64 first_frm;size_t max_usage;float frame_rate;RK_S64 elapsed_time;RK_S64 delay;FILE *fp_verify;FrmCrc checkcrc;
} MpiDecLoopData;int main(int argc, char **argv) {char *video_path = "/home/ido/chenFan/mpp/test/video/test.h264";// RK_S32 max_dec_frame_num = 100;  //最大解碼幀數RK_S32 max_dec_frame_num = 0;  //解碼完整個文件char *file_output = "/home/ido/chenFan/mpp/test/video/out.yuv";size_t max_usage;  //記錄解碼器最大使用內存MppCtx ctx = NULL;MppApi *mpi = NULL;// 1. 創建解碼器int ret = mpp_create(&ctx, &mpi);if (ret) {mpp_err("mpp_create failed\n");goto MPP_TEST_OUT;}// mpp_log("")// 2. 初始化解碼器MppCodingType video_type = MPP_VIDEO_CodingAVC;ret = mpp_init(ctx, MPP_CTX_DEC, video_type);if (ret) {mpp_err("%p mpp_init failed\n", ctx);goto MPP_TEST_OUT;}MppParam cfg = NULL;mpp_dec_cfg_init(&cfg);// 2.1 獲取默認配置ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);// 2.2 設置內部分幀模式uint32_t need_split = 1;ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);if (ret) {mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);goto MPP_TEST_OUT;}ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);if (ret) {mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);goto MPP_TEST_OUT;}//解碼碼流保存到文件FILE *fp_output = NULL;
#if 0fp_output = fopen(file_output, "w+b");if (NULL == fp_output) {mpp_err("failed to open output file %s\n", file_output);goto MPP_TEST_OUT;}
#endif//半內部模式配置MppDecBufMode buf_mode = MPP_DEC_BUF_HALF_INT;MppBufferGroup grp = NULL;DecBufMgr buf_mgr;ret = dec_buf_mgr_init(&buf_mgr);if (ret) {mpp_err("dec_buf_mgr_init failed\n");goto MPP_TEST_OUT;}// 配置輸入pktMppPacket packet = NULL;ret = mpp_packet_init(&packet, NULL, 0);if (ret) {mpp_err("mpp_packet_init failed\n");goto MPP_TEST_OUT;}// 3. 解碼/* end of stream flag when set quit the loop */RK_U32 loop_end = 0;RK_S32 frame_count = 0;RK_S64 first_pkt = 0;RK_S64 first_frm = 0;// 3.1 打開輸入碼流FileReader reader = NULL;reader_init(&reader, video_path, video_type);if (!reader) {mpp_err("input file %s reader_init failed\n");return -1;}mpp_log("input file %s size %ld\n", video_path, reader_size(reader));RK_S64 t_s, t_e;t_s = mpp_time();// 3.2 解碼循環while (!loop_end) {// 3.2.1 讀取輸入碼流FileBufSlot *slot = NULL;ret = reader_read(reader, &slot);if (ret < 0) {mpp_err("input file %s reader_read failed\n");return -1;}RK_U32 pkt_eos = 0;pkt_eos = slot->eos;if (pkt_eos) {//如果指定最大幀數小于0即一直解碼 或 碼流自身幀數小于指定最大解碼幀數,//則重載碼流繼續解碼if (max_dec_frame_num < 0 || max_dec_frame_num > frame_count) {mpp_log("%p loop again\n", ctx);reader_rewind(reader);pkt_eos = 0;} else {mpp_log("%p found last packet\n", ctx);loop_end = 1;}}// 3.2.2 配置輸入pktmpp_packet_set_data(packet, slot->data);mpp_packet_set_size(packet, slot->size);mpp_packet_set_pos(packet, slot->data);mpp_packet_set_length(packet, slot->size);if (pkt_eos) mpp_packet_set_eos(packet);RK_U32 pkt_done = 0;do {RK_S32 dec_frame_timeout = 30;RK_U32 frm_eos = 0;if (!pkt_done) {// 3.2.3 packet傳入解碼器ret = mpi->decode_put_packet(ctx, packet);if (ret == MPP_OK) {pkt_done = 1;if (!first_pkt) {first_pkt = mpp_time();  // 記錄第一個成功送入解碼器的時間戳}}}do {RK_S32 get_frm = 0;MppFrame frame = NULL;try_again:// 3.2.4 從解碼器獲取解碼后的幀ret = mpi->decode_get_frame(ctx, &frame);//超時等待if (ret == MPP_ERR_TIMEOUT) {if (dec_frame_timeout > 0) {dec_frame_timeout--;msleep(1);goto try_again;}mpp_err("%p decode_get_frame failed too much time\n", ctx);}if (ret) {mpp_err("%p decode_get_frame failed ret %d\n", ret, ctx);break;}if (frame) {// 3.2.5 配置MppBufferGroup 并 通知解碼器// MPP_DEC_SET_INFO_CHANGE_READY//半內部分配模式//可通過mpp_buffer_group_limit_config限制解碼器的內存使用量if (mpp_frame_get_info_change(frame)) {RK_U32 width = mpp_frame_get_width(frame);RK_U32 height = mpp_frame_get_height(frame);RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);RK_U32 buf_size = mpp_frame_get_buf_size(frame);mpp_log("%p decode_get_frame get info changed found\n", ctx);mpp_log("%p decoder require buffer w:h [%d:%d] stride [%d:%d] ""buf_size %d",ctx, width, height, hor_stride, ver_stride, buf_size);grp = dec_buf_mgr_setup(buf_mgr, buf_size, 24, buf_mode);/* Set buffer to mpp decoder */ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);if (ret) {mpp_err("%p set buffer group failed ret %d\n", ctx, ret);break;}ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);if (ret) {mpp_err("%p info change ready failed ret %d\n", ctx, ret);break;}} else {// 3.2.6 解碼所得幀char log_buf[256];RK_S32 log_size = sizeof(log_buf) - 1;RK_S32 log_len = 0;RK_U32 err_info = mpp_frame_get_errinfo(frame);RK_U32 discard = mpp_frame_get_discard(frame);if (!first_frm) first_frm = mpp_time();log_len += snprintf(log_buf + log_len, log_size - log_len,"decode get frame %d", frame_count);if (err_info || discard) {log_len += snprintf(log_buf + log_len, log_size - log_len," err %x discard %x", err_info, discard);}mpp_log("%p %s\n", ctx, log_buf);if (fp_output && !err_info)dump_mpp_frame_to_file(frame, fp_output);frame_count++;}frm_eos = mpp_frame_get_eos(frame);mpp_frame_deinit(&frame);get_frm = 1;}// try get runtime frame memory usageif (grp) {size_t usage = mpp_buffer_group_usage(grp);if (usage > max_usage) max_usage = usage;}// if last packet is send but last frame is not found continueif (pkt_eos && pkt_done && !frm_eos) {msleep(1);continue;}if (frm_eos) {mpp_log("%p found last packet\n", ctx);break;}//解碼指定幀數 或 解碼完一幀//注意:當前是內部分幀模式,一個 packet 不一定正好包含一個 frameif ((max_dec_frame_num > 0 && (frame_count >= max_dec_frame_num)) ||((max_dec_frame_num == 0) && frm_eos))break;//內部分幀模式if (get_frm) continue;break;} while (1);//解碼指定幀數 或 解碼完整個碼流if ((max_dec_frame_num > 0 && (frame_count >= max_dec_frame_num)) ||((max_dec_frame_num == 0) && frm_eos)) {loop_end = 1;break;}if (pkt_done) break;//休眠等待,避免傳入過快占滿解碼器內部隊列msleep(1);} while (1);}t_e = mpp_time();RK_S64 elapsed_time = t_e - t_s;float frame_rate = (float)frame_count * 1000000 / elapsed_time;RK_S64 delay = first_frm - first_pkt;mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n", frame_count,(RK_S64)(elapsed_time / 1000), (RK_S32)(delay / 1000), frame_rate);mpp_log("test success max memory %.2f MB\n", max_usage / (float)(1 << 20));// 4. 重置解碼器,恢復為正常初始化后的狀態, 用于循環解碼,// 解碼器在接收到eos之后不再接收碼流,需要reset重置ret = mpi->reset(ctx);if (ret) {mpp_err("%p mpi->reset failed\n", ctx);goto MPP_TEST_OUT;}MPP_TEST_OUT:// 5. 銷毀解碼器if (ctx) {mpp_destroy(ctx);ctx = NULL;}if (cfg) {mpp_dec_cfg_deinit(cfg);cfg = NULL;}if (packet) {mpp_packet_deinit(&packet);packet = NULL;}grp = NULL;if (buf_mgr) {dec_buf_mgr_deinit(buf_mgr);buf_mgr = NULL;}if (fp_output) {fclose(fp_output);fp_output = NULL;}return 0;
}

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

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

相關文章

用一個實際例子快速理解MCP應用的工作步驟

已經有很多的文章介紹MCP server&#xff0c;MCP Client工作原理&#xff0c;這里不做太多介紹。但是很多介紹都只是側重介紹概念&#xff0c;實際的工作原理理解起來對初學者還是不太友好。本文以一個智能旅游咨詢系統為例&#xff0c;詳細說明在利用 Model Context Protocol&…

【LeetCode 題解】數據庫:1321.餐館營業額變化增長

一、問題描述 本題給定了一個名為 Customer 的表&#xff0c;記錄了餐館顧客的交易數據&#xff0c;包括顧客 ID、姓名、訪問日期和消費金額。作為餐館老板&#xff0c;我們的任務是分析營業額的變化增長情況&#xff0c;具體來說&#xff0c;就是計算以 7 天&#xff08;某日…

【Python】讀取xlsb或xlsx的單一或連續單元格工具類

代碼主要來自Kimi.ai&#xff0c;有修改。 優先使用工作表序號索引工作表&#xff0c;序號從1開始。 運行需要先安裝openpyxl和pyxlsb兩個第三方庫。 import openpyxl from openpyxl.utils import range_boundaries from pyxlsb import open_workbook as open_xlsbclass Exc…

【藍橋杯】動態規劃:背包問題

這篇文章主要記錄動態規劃方面的學習。 動態規劃的核心思想: 把大問題分解成小問題,記住小問題的解,避免重復計算。 動態規劃(DP)的三大特點: ①最優子結構:大問題的最優解可以由小問題的最優解推導出來 ②重疊子問題:在求解過程中會反復遇到相同的小問題 ③無后效…

華為數字芯片機考2025合集1已校正

單選 1&#xff0e;以下低功耗措施中&#xff0c;哪種不是降低電路翻轉率的方法? A.在不進行算術運算的時候&#xff0c;使這些模塊的輸入保持不變&#xff0c;不讓新的操作數進來 B.采用Gray 碼或One‐hot 碼作為狀態機編碼 C.減少電路中的glitch D.重新安排“if‐else”表達…

React 列表渲染

開發環境&#xff1a;Reacttsantd 你可能經常需要通過 JavaScript 的數組方法 來操作數組中的數據&#xff0c;從而將一個數據集渲染成多個相似的組件。在這篇文章中&#xff0c;你將學會如何在 React 中使用 filter() 篩選需要渲染的組件和使用 map() 把數組轉換成組件數組。 …

力扣刷題DAY11(動態規劃-線性DP)

一、最長上升子序列 300. 最長遞增子序列 &#xff08;一&#xff09;初版代碼 class Solution { public:int lengthOfLIS(vector<int>& nums) {int n nums.size();vector<int> f(n 1, 1); //初始化為1&#xff0c;因為每個數至少可以作為一個單獨的序列in…

DFS--

數字的全排列 #include <bits/stdc.h> using namespace std;//最大的排列數目 const int N10; int n; //存儲排列的路徑 int path[N]; //標記數字是否已經被使用 bool st[N];void dfs(int u){//到達遞歸邊界&#xff0c;輸出一個排列if(un){//輸出循環for(int i0; i<…

棧與隊列及其基礎應用

一.棧 1.棧的定義 棧是一種特殊的線性表&#xff0c;其只允許在固定的一端進行插入和刪除元素操作。進行數據插入和刪除操作的一端稱為棧頂&#xff0c;另一端稱為棧底。棧中的數據元素遵守后進先出LIFO&#xff08;Last In First Out&#xff09;的原則。其結構可以參考羽毛…

openEuler-22.03-LTS-SP3 編譯安裝 Greenplum-db 6.20.0

openEuler-22.03-LTS-SP3 編譯安裝 Greenplum-db 6.20.0 1、配置 yum 華為源2、安裝依賴3、源碼安裝 openssl 1.0.1u3.1、openssl 1.1.1 降級到 openssl 1.0.1 4、源碼安裝 python 2.75、使用 pip3 安裝 Python 相關依賴6、編譯安裝 Greenplum-db 6.20.06.1、修改配置6.2、基于…

機器學習02——概要

一、簡介 機器學習是一門在沒有明確編程的情況下讓計算機學習的科學。 監督學習是有目標的&#xff0c;輸入數據對應明確的輸出&#xff1b;無監督學習則是“探索”型的&#xff0c;模型的目標是從數據中發現潛在的模式或結構&#xff0c;而不需要預先知道標簽。 二、機器學…

swift-08-屬性、匯編分析inout本質

一、Swift中跟實例相關的屬性可以分為2大類 1.1 存儲屬性&#xff08; Stored Property&#xff09; 類似于成員變量這個概念 存儲在實例的內存中 結構體、類可以定義存儲屬性 枚舉不可以定義存儲屬性&#xff08;因為枚舉只存儲關聯值和case&#xff09; 1.2 計算屬性&am…

【HarmonyOS Next之旅】DevEco Studio使用指南(十二)

目錄 1 -> Code Linter代碼檢查 2 -> 配置代碼檢查規則 3 -> 查看/處理代碼檢查結果 1 -> Code Linter代碼檢查 Code Linter針對ArkTS/TS代碼進行最佳實踐/編程規范方面的檢查。 可根據掃描結果中告警提示手工修復代碼缺陷&#xff0c;或者執行一鍵式自動修復…

前端vue項目打包成桌面端exe應用

主要 使用 Electron將 vue項目打包為 exe 1.首先下載Electron git clone https://github.com/electron/electron-quick-start cd electron-quick-start npm install安裝完依賴之后 npm start運行成功 注意&#xff1a;如果你的項目使用了VueRouter&#xff0c;那么切記&…

基于springcloud的“微服務架構的巡游出租管理平臺”的設計與實現(源碼+數據庫+文檔+PPT)

基于springcloud的“微服務架構的巡游出租管理平臺”的設計與實現&#xff08;源碼數據庫文檔PPT) 開發語言&#xff1a;Java 數據庫&#xff1a;MySQL 技術&#xff1a;springcloud 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系統展示 系統總體結構圖 E-R實體關系圖…

新一代達夢官方管理工具SQLark:可視化建表操作指南

在數據庫管理工作中&#xff0c;新建表是一項基礎且頻繁的操作。SQLark 的可視化建表功能為我們提供了一種高效、便捷且絲滑流暢的建表新體驗。一起來了解下吧。 SQLark 官方下載鏈接&#xff1a;www.sqlark.com 新建表作為常見的功能&#xff0c;相比其他管理工具&#xff0c;…

Scala相關知識學習總結6

1、集合計算高級函數說明 - 過濾&#xff1a;遍歷集合&#xff0c;提取滿足特定條件的元素組成新集合。 - 轉化/映射&#xff08;map&#xff09;&#xff1a;將集合里的每個元素應用到指定函數進行轉換。 - 扁平化&#xff1a;文檔未詳細闡述其具體含義和操作。 - 扁平化映射&…

pandas.DataFrame.dtypes--查看和驗證 DataFrame 列的數據類型!

查看每列的數據類型&#xff0c;方便分析是否需要數據類型轉換 property DataFrame.dtypes[source] Return the dtypes in the DataFrame. This returns a Series with the data type of each column. The result’s index is the original DataFrame’s columns. Columns with…

計算機中的單位

在計算機科學中&#xff0c;單位用于衡量數據存儲、內存、數據傳輸速率等。以下是一些常見的計算機單位及其含義&#xff1a; ### **1. 數據存儲單位** 數據存儲單位用于衡量計算機存儲設備&#xff08;如硬盤、內存、閃存等&#xff09;的容量。 | 單位 | 符號 | 含義…

Spring Boot 自定義配置類(包含字符串、數字、布爾、小數、集合、映射、嵌套對象)實現步驟及示例

Spring Boot 自定義配置類實現步驟及示例 步驟說明 創建配置類&#xff1a;定義一個 POJO 類&#xff0c;使用 ConfigurationProperties 注解指定配置前綴。啟用配置綁定&#xff1a;在啟動類或配置類上添加 EnableConfigurationProperties 注解。配置文件寫法&#xff1a;在 …