音視頻解封裝demo:將FLV文件解封裝(demux)得到文件中的H264數據和AAC數據(純手工,不依賴第三方開源庫)

1、README

前言

注意:flv是不支持h.265封裝的。目前解封裝功能正常,所得到的H.264文件與AAC文件均可正常播放。

a. demo使用
$ make clean && make DEBUG=1
$ 
$ $ ./flv_demux_h264_aac 
Usage: ./flv_demux_h264_aac avfile/test1.flv./flv_demux_h264_aac avfile/test2.flv
b. 參考鏈接

【參考文章】

  • FLV格式詳解_JT同學的博客-CSDN博客_flv格式**(推薦!!!)**

  • FLV封裝格式介紹及解析 - 簡書

  • 音視頻封裝:FLV格式詳解和打包H264、AAC方案(上) - 云+社區 - 騰訊云

  • 音視頻封裝:FLV格式詳解和打包H264、AAC方案(下) - 云+社區 - 騰訊云

【參考源碼】

  • https://github.com/ImSjt/H.264toFLV.git

  • https://github.com/rainfly123/flvmuxer

【工具下載】

  • SpecialAAAC.exe:https://sourceforge.net/projects/aacstreamanalysis/

  • H264BSAnalyzer.exe:https://github.com/latelee/H264BSAnalyzer/tree/master/release

  • FlvParse.exe:https://github.com/ty6815/AvStackDocs/tree/master/media%20format/flv

c. demo目錄架構
$ tree
.
├── aac_adts.c
├── aac_adts.h
├── avfile
│   ├── test1.aac
│   ├── test1.flv
│   ├── test1.h264
│   ├── test2.aac
│   ├── test2.flv
│   └── test2.h264
├── docs
│   ├── FLV封裝格式介紹及解析 - 簡書.mhtml
│   ├── FLV格式詳解_JT同學的博客-CSDN博客_flv格式.mhtml
│   ├── 筆記---H.264里的SEI - 簡書.mhtml
│   ├── 音視頻封裝:FLV格式詳解和打包H264、AAC方案(上) - 云+社區 - 騰訊云.mhtml
│   └── 音視頻封裝:FLV格式詳解和打包H264、AAC方案(下) - 云+社區 - 騰訊云.mhtml
├── flv.c
├── flv_format.h
├── flv.h
├── h264_nalu.h
├── main.c
├── Makefile
├── README.md
├── reference_code
│   └── Flv_to_h264_AAC_Demux.zip
└── tools├── FlvParse.exe├── H264BSAnalyzer.exe└── SpecialAAAC.exe

2、主要代碼片段

flv_format.h
/**************************************************************** describe: Flv file format description(Mainly for H.264 & AAC)* author: linriming* e-mail: linriming20@163.com***************************************************************/#ifndef __FLV_FORMAT_H__
#define __FLV_FORMAT_H__#include <stdint.h>#define AUDIO_SUPPORT(x)    (x << 2)    /* bit[2] in flvheader's type_flag */
#define VIDEO_SUPPORT(x)    (x << 0)    /* bit[0] in flvheader's type_flag */#define SIZE_FLV_HEADER         sizeof(struct flvHeader)    /* 9 Bytes */
#define SIZE_FLV_TAG_HEADER     sizeof(struct flvTagHeader) /* 11 Bytes */
#define SIZE_PREVIOUS_TAG_SIZE  sizeof(uint32_t)            /* 4 Bytes *//* FLV tag type */
typedef enum{FLVTAG_TYPE_AUDIO  = 0x08,FLVTAG_TYPE_VIDEO  = 0x09,FLVTAG_TYPE_SCRIPT = 0x12,
}flvTagType;/* AMF data type in <Script Tag> */
typedef enum{AMF_DATA_TYPE_NUMBER      = 0x00,AMF_DATA_TYPE_BOOL        = 0x01,AMF_DATA_TYPE_STRING      = 0x02,AMF_DATA_TYPE_OBJECT      = 0x03,AMF_DATA_TYPE_NULL        = 0x05,AMF_DATA_TYPE_UNDEFINED   = 0x06,AMF_DATA_TYPE_REFERENCE   = 0x07,AMF_DATA_TYPE_MIXEDARRAY  = 0x08,AMF_DATA_TYPE_OBJECT_END  = 0x09,AMF_DATA_TYPE_ARRAY       = 0x0a,AMF_DATA_TYPE_DATE        = 0x0b,AMF_DATA_TYPE_LONG_STRING = 0x0c,AMF_DATA_TYPE_UNSUPPORTED = 0x0d,
} amfDataType;/* audio tag */
typedef enum{SFI_LINEAR_PCM_PLATFORM_ENDIAN = 0,SFI_ADPCM                      = 1,SFI_MP3                        = 2,SFI_LINEAR_PCM_LITTLE_ENDIAN   = 3,SFI_NELLYMOSER_16KHZ_MONO      = 4,SFI_NELLYMOSER_8KHZ_MONO       = 5,SFI_NELLYMOSER                 = 6,SFI_G711A                      = 7,SFI_G711MU                     = 8,SFI_RESERVED                   = 9,SFI_AAC                        = 10,SFI_SPEEX                      = 11,SFI_MP3_8KHZ                   = 14,SFI_DEVIVE_SPECIFIC_SOUND      = 15,
}soundFormatIndex;typedef enum{SRI_5_5KHZ = 0,SRI_11KHZ  = 1,SRI_22KHZ  = 2,SRI_44KHZ  = 3,
}soundSamplerateIndex;typedef enum{SSI_8BIT  = 0,SSI_16BIT = 1,
}soundSizeIndex;typedef enum{STI_MONO   = 0,STI_STEREO = 1,
}soundTypeIndex;#define  AAC_PACKET_TYPE_SEQUENCE_HEADER 	(0)
#define  AAC_PACKET_TYPE_RAW 				(1)typedef enum{AAC_MAIN = 1,AAC_LC   = 2,AAC_SSR  = 3,
}aacProfileIndex;typedef enum{AAC_96KHz = 0x0,AAC_88_2KHz = 0x1,AAC_64KHz = 0x2,AAC_48KHz = 0x3,AAC_44_1KHz = 0x4,AAC_32KHz = 0x5,AAC_24KHz = 0x6,AAC_22_05KHz = 0x7,AAC_16KHz  = 0x8,AAC_12KHz  = 0x9,AAC_11_025KHz  = 0xa,AAC_8KHz  = 0xb,AAC_RESERVED = 0xc,
}aacSamplerateIndex;typedef enum{AAC_CHANNEL_SPECIAL = 0x0,AAC_CHANNEL_MONO = 0x1,AAC_CHANNEL_STEREO = 0x2,AAC_CHANNEL_3 = 0x3,AAC_CHANNEL_4 = 0x4,AAC_CHANNEL_5 = 0x5,AAC_CHANNEL_5_1 = 0x6,AAC_CHANNEL_7_1 = 0x7,AAC_CHANNELRESERVED = 0x8,
}aacChannelIndex;#define  AVC_PACKET_TYPE_SEQUENCE_HEADER 			 (0)
#define  AVC_PACKET_TYPE_NALU 						 (1)
#define  AVC_PACKET_TYPE_END_OF_SEQUENCE 			 (2)/* next for video tag */
#define  VIDEOTAG_FRAMETYPE_KEYFRAME                 (1)
#define  VIDEOTAG_FRAMETYPE_INTER_FRAME              (2)
#define  VIDEOTAG_FRAMETYPE_DISPOSABLE_INTER_FRAME   (3)
#define  VIDEOTAG_FRAMETYPE_GENERATED_KEYFRAME       (4)
#define  VIDEOTAG_FRAMETYPE_VIDEO_INFO_FRAME         (5)#define  VIDEOTAG_CODECID_JPEG                       (1)
#define  VIDEOTAG_CODECID_SORENSON_H263              (2)
#define  VIDEOTAG_CODECID_SCREEN_VIDEO               (3)
#define  VIDEOTAG_CODECID_ON2_VP6                    (4)
#define  VIDEOTAG_CODECID_ON2_VP6_WITH_ALPHA_CHANNEL (5)
#define  VIDEOTAG_CODECID_SCREEN_VIDEO_VERSION_2     (6)
#define  VIDEOTAG_CODECID_AVC                        (7)#pragma pack(push)
#pragma pack(1)   /* 1 bytes align */typedef struct flvHeader{uint8_t  signature[3]; 		/* signature bytes always 'F' 'L' 'V': 0x46 0x4C 0x56 */uint8_t  version; 			/* file version, always 0x01 */uint8_t  type_flag; 		/* bit[7:3] and bit[1] always 0, bit[2] for aduio, bit[0] for video */uint32_t data_offset; 		/* size of header, 00 00 00 09(big-endian) for version 1 */
}T_FlvHeader, *PT_FlvHeader;   	    /* 9 bytes totally */typedef struct flvTagHeader{uint8_t TagType; 					/* Type of this tag. Value are 8(audio), 9(video), 18(script), other(reserved). */uint8_t DataSize[3]; 				/* Length of the data in the Data filed. */uint8_t Timestamp[3]; 				/* Time in milliseconds at which the data in this applies. 0 in first tag in the FLV file. */uint8_t TimestampExtended; 			/* Extension of Timestamp field to form a SI32 value, it is upper 8 bits. */uint8_t StreamID[3]; 				/* Always 0 */
}T_FlvTagHeader, *PT_FlvTagHeader; 	/* 11 bytes total */typedef struct flvTag{T_FlvTagHeader flvheader; 	/* tag header */uint8_t flvdata[0]; 		/* tag data index */
}T_FlvTag, *PT_FlvTag;typedef struct avcVideoPacket{T_FlvTagHeader flvheader;uint8_t flvdata[0]; 		/* flv tag data index */
}T_AvcVideoPacket, *PT_AvcVideoPacket;#pragma pack(pop)#endif /* __FLV_FORMAT_H__ */
flv.c
#include "h264_nalu.h"
#include "aac_adts.h"
#include "flv.h"int flv_demux_h264_aac(const char *flvFileName)
{FILE *fpH264 = NULL;FILE *fpAAC  = NULL;FILE *fpFLV  = NULL;uint8_t *flvBuf = NULL;// note!!!: it maybe happen the 'Segmentation fault', as 1024 is too long for 'sps', but it maybe save the 'sei' or other unused data if first nalu isn't 'sps'.uint8_t spsBuf[64] = {0};uint8_t ppsBuf[64] = {0};uint32_t spsLen = 0;uint32_t ppsLen = 0;int ret = -1;uint32_t flvTagDataSize = 0;PT_FlvTag ptFlvTag = NULL;const char *h264FileName = "out_video.h264";const char *aacFileName = "out_audio.aac";/* open file */fpFLV  = fopen(flvFileName,  "rb");if (!fpFLV){printf("open %s error!\n", flvFileName);}fpH264 = fopen(h264FileName, "wb");if (!fpH264){printf("open %s error!\n", h264FileName);}fpAAC  = fopen(aacFileName,  "wb");if (!fpAAC){printf("open %s error!\n", aacFileName);}/* alloc memory */flvBuf = (uint8_t *)malloc(MAX_FLV_BUF_SIZE);if (!flvBuf){printf("malloc for 'flvBuf' error!\n");}/* parse and save some data first. */fread(flvBuf, SIZE_FLV_HEADER, 1, fpFLV);ret = strncmp((const char *)flvBuf, "FLV", 3);if(ret != 0){printf("\033[31m It's not a FLV file!\n\033[0m");return -1;}DEBUG("\033[32m""=====================================\n""Signature: '%c' '%c' '%c'\n""Version  : 0x%02x\n""Audio    : %s\n""Video    : %s\n""=====================================\n""\033[0m",flvBuf[0], flvBuf[1], flvBuf[2], flvBuf[3], (flvBuf[4] & 0x04) ? "yes" : "no", (flvBuf[4] & 0x01) ? "yes" : "no");fread(flvBuf, SIZE_PREVIOUS_TAG_SIZE, 1, fpFLV);DEBUG("\033[37m[Pre Tag Size]: %d \033[0m\n", (flvBuf[0] << 24) |\(flvBuf[1] << 16) |\(flvBuf[2] <<  8) |\flvBuf[3]);while(1){ret = fread(flvBuf, SIZE_FLV_TAG_HEADER, 1, fpFLV);if (ret <= 0){DEBUG(">>> FLV file end! <<<\n");break;}ptFlvTag = (PT_FlvTag)flvBuf;flvTagDataSize = (ptFlvTag->flvheader.DataSize[0] << 16) |\(ptFlvTag->flvheader.DataSize[1] << 8) |\ptFlvTag->flvheader.DataSize[2];fread(ptFlvTag->flvdata, flvTagDataSize, 1, fpFLV);switch (ptFlvTag->flvheader.TagType){case FLVTAG_TYPE_SCRIPT: {DEBUG("\033[34m[Script Tag] \033[0m\n");/* nothing to do! */break;}case FLVTAG_TYPE_AUDIO: {char *packetTypeStr = NULL;int aacPacketType = ptFlvTag->flvdata[1];switch(aacPacketType){case AAC_PACKET_TYPE_SEQUENCE_HEADER:packetTypeStr = "[AAC sequence header]";/* nothing to do! */break;case AAC_PACKET_TYPE_RAW:packetTypeStr = "[AAC raw]";uint8_t headerbuf[AAC_ADTS_HEADER_SIZE] = {0};uint32_t headerbufLen = 0;uint32_t datasize = ((ptFlvTag->flvheader.DataSize[0] << 16) |\(ptFlvTag->flvheader.DataSize[1] << 8) |\ptFlvTag->flvheader.DataSize[2]);generateAdtsHeader(AAC_ADTS_HEADER_SIZE + (datasize - 2), headerbuf, &headerbufLen);fwrite(headerbuf, headerbufLen, 1, fpAAC);fwrite(&ptFlvTag->flvdata[2], datasize - 2, 1, fpAAC);break;default:printf("[%s:%d] Unknown AAC packet type!", __FUNCTION__, __LINE__);goto exit;}DEBUG("\033[36m[Audio Tag] \t %s\033[0m\n", packetTypeStr);break;}case FLVTAG_TYPE_VIDEO: {char *packetTypeStr = NULL;char *frameTypeStr = NULL;uint8_t startCode[4] = {0x00, 0x00, 0x00, 0x01};int isKeyFrame = 0;int type = 0;isKeyFrame = (ptFlvTag->flvdata[0] & 0xF0) == 0x10 ? 1 : 0;type = ptFlvTag->flvdata[1];switch(type){case AVC_PACKET_TYPE_SEQUENCE_HEADER:packetTypeStr = "[AVC squence header]";frameTypeStr = "[key frame]";spsLen = ((ptFlvTag->flvdata[11] << 8) | ptFlvTag->flvdata[12]);memcpy(spsBuf, &ptFlvTag->flvdata[13], spsLen);//printf("spsLen: %d\n", spsLen);//for(int i = 0; i < spsLen; i++)//	printf("0x%02x ", spsBuf[i]);//printf("\n");ppsLen = ((ptFlvTag->flvdata[13 + spsLen + 1] << 8) | ptFlvTag->flvdata[13+spsLen+2]);memcpy(ppsBuf, &ptFlvTag->flvdata[13 + spsLen + 3], ppsLen);//printf("ppsLen: %d\n", ppsLen);//for(int i = 0; i < ppsLen; i++)//	printf("0x%02x ", ppsBuf[i]);//printf("\n");break;case AVC_PACKET_TYPE_NALU:packetTypeStr = "[AVC NALU]";/* one or more NALU. */uint32_t naluDataSize = 0;uint32_t curPos = 0;curPos = 5;naluDataSize = (ptFlvTag->flvdata[curPos + 0] << 24) |\(ptFlvTag->flvdata[curPos + 1] << 16) |\(ptFlvTag->flvdata[curPos + 2] << 8) |\ptFlvTag->flvdata[curPos + 3];if(isKeyFrame){frameTypeStr = "[key frame]";if((ptFlvTag->flvdata[curPos + 4] & 0x1f) == NALU_TYPE_SEI &&\(ptFlvTag->flvdata[curPos + 5] & 0x1f) == 0x05/* SEI: payloadType: user_data_unregistered() */){/* has SEI *//* SEI */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(&ptFlvTag->flvdata[curPos + 4], naluDataSize, 1, fpH264);/* SPS */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(spsBuf, spsLen, 1, fpH264);/* PPS */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(ppsBuf, ppsLen, 1, fpH264);/* update the second NALU data size. */curPos += (4 + naluDataSize);naluDataSize = (ptFlvTag->flvdata[curPos + 0] << 24) |\(ptFlvTag->flvdata[curPos + 1] << 16) |\(ptFlvTag->flvdata[curPos + 2] << 8) |\ptFlvTag->flvdata[curPos + 3];/* IDR */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(&ptFlvTag->flvdata[curPos + 4], naluDataSize, 1, fpH264);}else{/* SPS */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(spsBuf, spsLen, 1, fpH264);/* PPS */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(ppsBuf, ppsLen, 1, fpH264);/* IDR */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(&ptFlvTag->flvdata[curPos + 4], naluDataSize, 1, fpH264);}}else{frameTypeStr = "[inter frame]";/* SLICE */fwrite(startCode, sizeof(startCode), 1, fpH264);fwrite(&ptFlvTag->flvdata[curPos + 4], naluDataSize, 1, fpH264);}break;case AVC_PACKET_TYPE_END_OF_SEQUENCE:packetTypeStr = "[AVC end of squence]";frameTypeStr = "[key frame]";break;default:printf("[%s:%d] Unknown AVC packet type!", __FUNCTION__, __LINE__);goto exit;}DEBUG("\033[35m[Video Tag] \t %s \t %s\033[0m\n", packetTypeStr, frameTypeStr);break;}default: {printf("\033[33m[Unknown Tag]\033[0m\n");break;}}fread(flvBuf, SIZE_PREVIOUS_TAG_SIZE, 1, fpFLV);DEBUG("\033[37m[PreTagSize] \t %d\033[0m\n", (flvBuf[0] << 24) |\(flvBuf[1] << 16) |\(flvBuf[2] <<	8) |\flvBuf[3]);}exit:if(fpFLV) 	fclose(fpFLV);if(fpH264) 	{fflush(fpH264); fclose(fpH264);}if(fpAAC) 	{fflush(fpAAC); fclose(fpAAC);}if(flvBuf)  free(flvBuf);return 0;
}
main.c
#include <stdio.h>#include "flv.h"int main(int argc, char *argv[])
{if(argc == 1){printf("Usage: \n""   %s avfile/test1.flv\n""   %s avfile/test2.flv\n",argv[0], argv[0]);return -1;}flv_demux_h264_aac(argv[1]);printf("\033[32m""Success!\n""\033[0m");return 0;
}

3、demo下載地址(任選一個)

  • https://download.csdn.net/download/weixin_44498318/89526743
  • https://gitee.com/linriming/av_flv_demux_h264_aac.git
  • https://github.com/linriming20/av_flv_demux_h264_aac.git

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

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

相關文章

壓縮感知1——算法簡介

傳統的數據采集 傳統的數字信號采樣定律就是有名的香農采樣定理&#xff0c;又稱那奎斯特采樣定律定理內容如下&#xff1a;為了不失真地恢復模擬信號&#xff0c;采樣頻率應該不小于模擬信號頻譜中最高頻率的2倍 上述步驟得到的數字信號的數據量比較大&#xff0c;一方面不利…

C語言程序題(一)

一.三個整數從大到小輸出 首先做這個題目需要知道理清排序的思路&#xff0c;通過比較三個整數的值&#xff0c;使之從大到小輸出。解這道題有很多方法我就總結了兩種方法&#xff1a;一是通過中間變量比較和交換&#xff0c;二是可以用冒泡排序法&#xff08;雖然三個數字排序…

車載聚合路由器應用場景分析

乾元通QYT-X1z車載式1U多卡聚合路由器&#xff0c;支持最多8路聚合&#xff0c;無論是應急救援&#xff0c;還是車載交通&#xff0c;任何寬帶服務商無法覆蓋的區域&#xff0c;聚合路由器可提供現場需要的穩定、流暢、安全的視頻傳輸網絡&#xff0c;聚合路由器可無縫接入應急…

Dify中的weaviate向量數據庫操作

一.安裝weaviate客戶端 1.Dify 0.6.9中weaviate信息 在Dify 0.6.9版本中weaviate容器信息如下: # The Weaviate vector store. weaviate:image: semitechnologies/weaviate:1.19.0restart: alwaysvolumes:# Mount the Weaviate data directory to the container.- ./volume…

【操作系統】進程管理——信號量機制(個人筆記)

學習日期&#xff1a;2024.7.9 內容摘要&#xff1a;信號量機制&#xff0c;用信號量實現進程的同步與互斥 信號量機制 信號量的概念 在上節內容中&#xff0c;我們學習了進程互斥的軟件和硬件解決方案&#xff0c;但這些方案都有各自的問題&#xff0c;雙標志法都因為檢查和…

【自用】【高昆輪概率論與數理統計筆記】2.1 分布函數的概念與性質

不定期更新&#xff0c;前面的章節會在學完后補回來&#xff0c;重新學學概率&#xff0c;當年考研考的數學二&#xff0c;沒有概率基礎&#xff0c;想自己補補&#xff0c;視頻課是高昆輪老師講的浙大四版概率論教材的視頻課&#xff0c;地址&#xff1a; 第一章&#xff1a;h…

數據庫MySQL---基礎篇

存儲和管理數據的倉庫 MySQL概述 數據庫相關概念 數據庫&#xff08;DataBase&#xff09;---數據存儲的倉庫&#xff0c;數據是有組織的進行存儲 數據庫管理系統&#xff08;DBMS&#xff09;-----操縱和管理數據庫的大型軟件 SQL----操作關系型數據庫的編程語言&#xff…

Python:安裝/Mac

之前一直陸陸續續有學python&#xff01;今天開始&#xff01;正式開肝&#xff01;&#xff01;&#xff01; 進入網站&#xff1a;可能會有點慢&#xff0c;多開幾個網頁 https://www.python.org 點擊下載&#xff0c;然后進入新的頁面&#xff0c;往下滑 來到File&#xff0…

實時溫濕度監測系統:Micropython編碼ESP32與DHT22模塊的無線數據傳輸與PC端接收項目

實時溫濕度監測系統 前言項目目的項目材料項目步驟模擬ESP32接線連接測試搭建PC端ESP32拷錄環境對ESP32進行拷錄PC端搭建桌面組件本地數據接收桌面小組件部分 實驗總結 前言 人生苦短&#xff0c;我用Python。 由于我在日常工作中經常使用Python&#xff0c;因此在進行該項目…

基于java+springboot+vue實現的校園二手書交易平臺(文末源碼+Lw)287

摘 要 信息數據從傳統到當代&#xff0c;是一直在變革當中&#xff0c;突如其來的互聯網讓傳統的信息管理看到了革命性的曙光&#xff0c;因為傳統信息管理從時效性&#xff0c;還是安全性&#xff0c;還是可操作性等各個方面來講&#xff0c;遇到了互聯網時代才發現能補上自…

Vue中v-for和v-if優先級(2、3)

Vue中v-for和v-if優先級&#xff08;2、3&#xff09; Vue2 在Vue2當中,v-for優先級要優于v-if,也就是說&#xff0c;當它倆同時沿用時&#xff0c;v-for先遍歷&#xff0c;v-if再判斷。 Vue2源碼位置 \vue-dev\src\compiler\codegen\index.js export function genElement…

如何構建數據驅動的企業?爬蟲管理平臺是關鍵橋梁嗎?

一、數據驅動時代&#xff1a;為何選擇爬蟲管理平臺&#xff1f; 在信息爆炸的今天&#xff0c;數據驅動已成為企業發展的核心戰略之一。爬蟲管理平臺&#xff0c;作為數據采集的第一站&#xff0c;它的重要性不言而喻。這類平臺通過自動化手段&#xff0c;從互聯網的各個角落…

windows的遠程桌面連接docker

1. Docker容器中運行遠程桌面服務 (RDP)&#xff1a;您的Docker容器需要安裝和運行遠程桌面服務。通常&#xff0c;遠程桌面服務在Windows操作系統上可用。如果您使用的是Linux容器&#xff0c;則需要安裝一個支持RDP協議的桌面環境和RDP服務器。 2. 開放RDP端口&#xff1a;通…

什么是RPC?有哪些RPC框架?

定義 RPC&#xff08;Remote Procedure Call&#xff0c;遠程過程調用&#xff09;是一種允許運行在一臺計算機上的程序調用另一臺計算機上子程序的技術。這種技術屏蔽了底層的網絡通信細節&#xff0c;使得程序間的遠程通信如同本地調用一樣簡單。RPC機制使得開發者能夠構建分…

【常見開源庫的二次開發】一文學懂CJSON

簡介&#xff1a; JSON&#xff08;JavaScript Object Notation&#xff09;是一種輕量級的數據交換格式。它基于JavaScript的一個子集&#xff0c;但是JSON是獨立于語言的&#xff0c;這意味著盡管JSON是由JavaScript語法衍生出來的&#xff0c;它可以被任何編程語言讀取和生成…

Django 實現子模版繼承父模板

背景 Django的占位符&#xff0c;如果不繼承父模板的內容&#xff0c;會被子模版所覆蓋&#xff0c;有些業務場景子模版也需要使用到父模板中的內容 可以使用Django自帶的標簽{% block super %}來實現此效果 base.html 最基礎html&#xff0c;相當于第一層html&#xff0c;bl…

代碼隨想錄算法訓練營day76 | Floyd 算法精講、A * 算法精講

本次題目來自于卡碼網 ??97. 小明逛公園 &#xff08;Floyd 算法精講&#xff09; 1、確定dp數組以及下標的含義 grid[i][j][k] m&#xff0c;表示 節點i 到 節點j 以[1...k] 集合為中間節點的最短距離為m 2、確定遞推公式 分兩種情況&#xff1a; 節點i 到 節點j 的最…

01 | 基礎架構:一條SQL查詢語句是如何執行的?

此系列文章為極客時間課程《MySQL 實戰 45 講》的學習筆記&#xff01; 引言 在了解 SQL 查詢語句如何執行之前&#xff0c;先了解下MySQL 的基本架構示意圖。 MySQL 分為 Server 層和引擎層。 Server 層包括連接器、查詢緩存、分析器、優化器、執行器等&#xff0c;涵蓋 M…

微球無菌篩分技術的巔峰之作:納維加特PV系列

在醫藥行業中&#xff0c;對微球的制備和篩分要求極高&#xff0c;納維加特&#xff08;Navector&#xff09;憑借其自主創新的PV系列微球無菌旋振篩&#xff0c;成功突破這一領域的技術壁壘。該產品不僅擁有高效率、高精度的篩分能力&#xff0c;同時還兼顧了高衛生級別的要求…

uniapp自動升級

一、創建云服務空間&#xff08;https://unicloud.dcloud.net.cn&#xff09; 云空間用于關聯需要版本控制升級的項目&#xff0c;如果已擁有云空間則省略此步驟。 二、搭建 uni升級中心 - 后臺管理系統&#xff08;升級中心 uni-upgrade-center - Admin&#xff09; uni-adm…