FFmpeg源代碼簡單分析-架構圖-解碼

參考鏈接

  • FFmpeg源代碼結構圖 - 解碼_雷霄驊的博客-CSDN博客_ffmpeg雷霄驊

函數背景色

  • 函數在圖中以方框的形式表現出來。不同的背景色標志了該函數不同的作用:
    • 粉紅色背景函數:FFmpeg的API函數。
    • 白色背景的函數:FFmpeg的內部函數。
    • 黃色背景的函數:URLProtocol結構體中的函數,包含處理協議(Protocol)的功能。
    • 綠色背景的函數:AVInputFormat結構體中的函數,包含處理封裝格式(Format)的功能。
    • 藍色背景的函數:AVCodec結構體中的函數,包含了編解碼器(Codec)的功能。
  • PS:URLProtocol,AVInputFormat,AVCodec在FFmpeg開始運行并且注冊完組件之后,都會分別被連接成一個個的鏈表。因此實際上是有很多的URLProtocol,AVInputFormat,AVCodec的。
  • 圖中畫出了解碼一個輸入協議是“文件”(其實就是打開一個文件。“文件”也被當做是一種廣義的協議),封裝格式為FLV,視頻編碼格式是H.264的數據的函數調用關系。?

區域

  • 整個架構圖可以分為以下幾個區域:
  • 左邊區域——架構函數區域:這些函數并不針對某一特定的視頻格式,通用架構,通用流程
  • 右上方黃色區域——協議處理函數區域:不同的協議(RTP,RTMP,FILE)會調用不同的協議處理函數。
  • 右邊中間綠色區域——封裝格式處理函數區域:不同的封裝格式(MKV,FLV,MPEGTS,AVI)會調用不同的封裝格式處理函數。
  • 右邊下方藍色區域——編解碼函數區域:不同的編碼標準(HEVC,H.264,MPEG2)會調用不同的編解碼函數。

箭頭線

  • 為了把調用關系表示的更明顯,圖中的箭頭線也使用了不同的顏色:
  • 黑色箭頭線:標志了函數之間的調用關系。
  • 紅色的箭頭線:標志了解碼的流程。
  • 其他顏色的箭頭線:標志了函數之間的調用關系。其中:
    • 調用URLProtocol結構體中的函數用黃色箭頭線標識;
    • 調用AVInputFormat結構體中的函數用綠色箭頭線標識;
    • 調用AVCodec結構體中的函數用藍色箭頭線標識。

函數所在的文件

  • 每個函數旁邊標識了它所在的文件的路徑。
  • 此外,還有一點需要注意的是,一些API函數內部也調用了另一些API函數。也就是說,API函數并不一定全部都調用FFmpeg的內部函數,他也有可能調用其他的API函數。
    • 例如從圖中可以看出來,avformat_close_input()調用了avformat_free_context()和avio_close()。這些在內部代碼中被調用的API函數也標記為粉紅色。

現在的執行流程

  • FFmpeg在avcodec.register_all被棄用后,新的流程_彌彥已死的博客-CSDN博客
  • 從學齡前開始解讀FFMPEG代碼 之 avcodec_register_all函數_zzyincsdn的博客-CSDN博客

模塊介紹?

右上區域(URLProtocol協議處理函數)

  • URLProtocol結構體包含如下協議處理函數指針:
    • url_open():打開
    • url_read():讀取
    • url_write():寫入
    • url_seek():調整進度
    • url_close():關閉
  • 結構體代碼
typedef struct URLProtocol {const char *name;int     (*url_open)( URLContext *h, const char *url, int flags);/*** This callback is to be used by protocols which open further nested* protocols. options are then to be passed to ffurl_open_whitelist()* or ffurl_connect() for those nested protocols.*/int     (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options);int     (*url_accept)(URLContext *s, URLContext **c);int     (*url_handshake)(URLContext *c);/*** Read data from the protocol.* If data is immediately available (even less than size), EOF is* reached or an error occurs (including EINTR), return immediately.* Otherwise:* In non-blocking mode, return AVERROR(EAGAIN) immediately.* In blocking mode, wait for data/EOF/error with a short timeout (0.1s),* and return AVERROR(EAGAIN) on timeout.* Checking interrupt_callback, looping on EINTR and EAGAIN and until* enough data has been read is left to the calling function; see* retry_transfer_wrapper in avio.c.*/int     (*url_read)( URLContext *h, unsigned char *buf, int size);int     (*url_write)(URLContext *h, const unsigned char *buf, int size);int64_t (*url_seek)( URLContext *h, int64_t pos, int whence);int     (*url_close)(URLContext *h);int (*url_read_pause)(URLContext *h, int pause);int64_t (*url_read_seek)(URLContext *h, int stream_index,int64_t timestamp, int flags);int (*url_get_file_handle)(URLContext *h);int (*url_get_multi_file_handle)(URLContext *h, int **handles,int *numhandles);int (*url_get_short_seek)(URLContext *h);int (*url_shutdown)(URLContext *h, int flags);const AVClass *priv_data_class;int priv_data_size;int flags;int (*url_check)(URLContext *h, int mask);int (*url_open_dir)(URLContext *h);int (*url_read_dir)(URLContext *h, AVIODirEntry **next);int (*url_close_dir)(URLContext *h);int (*url_delete)(URLContext *h);int (*url_move)(URLContext *h_src, URLContext *h_dst);const char *default_whitelist;
} URLProtocol;

?注意事項:

  • 【例子】不同的協議對應著上述接口有不同的實現函數,舉幾個例子:
  • File協議(即文件)對應的URLProtocol結構體ff_file_protocol:
  • ff_file_protocol結構體的文件在<libavformat/file.c>
    • url_open() -> file_open() -> open()
    • url_read() -> file_read() -> read()
    • url_write() -> file_write() -> write()
    • url_seek() -> file_seek() -> lseek()
    • url_close() -> file_close() -> close()
const URLProtocol ff_file_protocol = {.name                = "file",.url_open            = file_open,.url_read            = file_read,.url_write           = file_write,.url_seek            = file_seek,.url_close           = file_close,.url_get_file_handle = file_get_handle,.url_check           = file_check,.url_delete          = file_delete,.url_move            = file_move,.priv_data_size      = sizeof(FileContext),.priv_data_class     = &file_class,.url_open_dir        = file_open_dir,.url_read_dir        = file_read_dir,.url_close_dir       = file_close_dir,.default_whitelist   = "file,crypto,data"
};
  • RTMP協議(libRTMP)對應的URLProtocol結構體ff_librtmp_protocol:
  • ff_librtmp_protocol結構體的文件在<libavformat/protocol>
    • url_open() -> rtmp_open() -> RTMP_Init(), RTMP_SetupURL(), RTMP_Connect(), RTMP_ConnectStream()
    • url_read() -> rtmp_read() -> RTMP_Read()
    • url_write() -> rtmp_write() -> RTMP_Write()
    • url_seek() -> rtmp_read_seek() -> RTMP_SendSeek()
    • url_close() -> rtmp_close() -> RTMP_Close()
RTMP_CLASS(rtmp)
const URLProtocol ff_librtmp_protocol = {.name                = "rtmp",.url_open            = rtmp_open,.url_read            = rtmp_read,.url_write           = rtmp_write,.url_close           = rtmp_close,.url_read_pause      = rtmp_read_pause,.url_read_seek       = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size      = sizeof(LibRTMPContext),.priv_data_class     = &librtmp_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};
  • UDP協議對應的URLProtocol結構體ff_udp_protocol:
  • ff_udp_protocol結構體位于<libavformat/udp.c>
    • url_open() -> udp_open()
    • url_read() -> udp_read()
    • url_write() -> udp_write()
    • url_seek() -> udp_close()
    • url_close() -> udp_close()
const URLProtocol ff_udp_protocol = {.name                = "udp",.url_open            = udp_open,.url_read            = udp_read,.url_write           = udp_write,.url_close           = udp_close,.url_get_file_handle = udp_get_file_handle,.priv_data_size      = sizeof(UDPContext),.priv_data_class     = &udp_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};

右中區域(AVInputFormat封裝格式處理函數)

  • AVInputFormat包含如下封裝格式處理函數指針:
    • read_probe():檢查格式
    • read_header():讀取文件頭
    • read_packet():讀取一幀數據
    • read_seek():調整進度
    • read_close():關閉

?注意事項:

  • 【例子】不同的封裝格式對應著上述接口有不同的實現函數,舉幾個例子:
  • FLV封裝格式對應的AVInputFormat結構體ff_flv_demuxer:
    • read_probe() -> flv_probe() –> probe()
    • read_header() -> flv_read_header() -> create_stream() -> avformat_new_stream()
    • read_packet() -> flv_read_packet()
    • read_seek() -> flv_read_seek()
    • read_close() -> flv_read_close()
  • FFmpeg: libavformat/flvdec.c File Reference
= {.name           = "flv",.long_name      = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),.priv_data_size = sizeof(FLVContext),.read_probe     = flv_probe,.read_header    = flv_read_header,.read_packet    = flv_read_packet,.read_seek      = flv_read_seek,.read_close     = flv_read_close,.extensions     = "flv",.priv_class     = &flv_class,
}
  • MKV封裝格式對應的AVInputFormat結構體ff_matroska_demuxer:
    • read_probe() -> matroska_probe()
    • read_header() -> matroska_read_header()
    • read_packet() -> matroska_read_packet()
    • read_seek() -> matroska_read_seek()
    • read_close() -> matroska_read_close()
  • 參考鏈接:FFmpeg: libavformat/matroskadec.c File Reference
= {.name           = "matroska,webm",.long_name      = NULL_IF_CONFIG_SMALL("Matroska / WebM"),.extensions     = "mkv,mk3d,mka,mks",.priv_data_size = sizeof(MatroskaDemuxContext),.read_probe     = matroska_probe,.read_header    = matroska_read_header,.read_packet    = matroska_read_packet,.read_close     = matroska_read_close,.read_seek      = matroska_read_seek,.mime_type      = "audio/webm,audio/x-matroska,video/webm,video/x-matroska"
}
  • MPEG2TS封裝格式對應的AVInputFormat結構體ff_mpegts_demuxer:
    • read_probe() -> mpegts_probe()
    • read_header() -> mpegts_read_header()
    • read_packet() -> mpegts_read_packet()?
    • read_close() -> mpegts_read_close()
  • 參考鏈接:FFmpeg: libavformat/mpegts.c File Reference
= {.name           = "mpegts",.long_name      = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"),.priv_data_size = sizeof(MpegTSContext),.read_probe     = mpegts_probe,.read_header    = mpegts_read_header,.read_packet    = mpegts_read_packet,.read_close     = mpegts_read_close,.read_timestamp = mpegts_get_dts,.flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,.priv_class     = &mpegts_class,
}
  • AVI封裝格式對應的AVInputFormat結構體ff_avi_demuxer:
    • read_probe() -> avi_probe()
    • read_header() -> avi_read_header()
    • read_packet() -> avi_read_packet()
    • read_seek() -> avi_read_seek()
    • read_close() -> avi_read_close()
  • 參考鏈接:FFmpeg: libavformat/avidec.c File Reference
= {.name           = "avi",.long_name      = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),.priv_data_size = sizeof(AVIContext),.extensions     = "avi",.read_probe     = avi_probe,.read_header    = avi_read_header,.read_packet    = avi_read_packet,.read_close     = avi_read_close,.read_seek      = avi_read_seek,.priv_class = &demuxer_class,
}

右下區域(AVCodec編解碼函數)

  • AVCodec包含如下編解碼函數指針:
    • init():初始化
    • decode():解碼一幀數據
    • close():關閉
  • 參考鏈接:FFmpeg: AVCodec Struct Reference
  • 上述參考鏈接里面包含的結構體包含上述編解碼函數指針
  • 但是新版本好像沒有了
typedef struct AVCodec {/*** Name of the codec implementation.* The name is globally unique among encoders and among decoders (but an* encoder and a decoder can share the same name).* This is the primary way to find a codec from the user perspective.*/const char *name;/*** Descriptive name for the codec, meant to be more human readable than name.* You should use the NULL_IF_CONFIG_SMALL() macro to define it.*/const char *long_name;enum AVMediaType type;enum AVCodecID id;/*** Codec capabilities.* see AV_CODEC_CAP_**/int capabilities;uint8_t max_lowres;                     ///< maximum value for lowres supported by the decoderconst AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}const enum AVPixelFormat *pix_fmts;     ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
#if FF_API_OLD_CHANNEL_LAYOUT/*** @deprecated use ch_layouts instead*/attribute_deprecatedconst uint64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
#endifconst AVClass *priv_class;              ///< AVClass for the private contextconst AVProfile *profiles;              ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}/*** Group name of the codec implementation.* This is a short symbolic name of the wrapper backing this codec. A* wrapper uses some kind of external implementation for the codec, such* as an external library, or a codec implementation provided by the OS or* the hardware.* If this field is NULL, this is a builtin, libavcodec native codec.* If non-NULL, this will be the suffix in AVCodec.name in most cases* (usually AVCodec.name will be of the form "<codec_name>_<wrapper_name>").*/const char *wrapper_name;/*** Array of supported channel layouts, terminated with a zeroed layout.*/const AVChannelLayout *ch_layouts;
} AVCodec;

?注意事項:

  • 【例子】不同的編解碼器對應著上述接口有不同的實現函數,舉幾個例子:
  • HEVC解碼對應的AVCodec結構體ff_hevc_decoder:
    • init() -> hevc_decode_init()
    • decode() -> hevc_decode_frame() -> decode_nal_units()
    • close() -> hevc_decode_free()
  • 參考鏈接:FFmpeg: libavcodec/hevc.c File Reference
= {.name                  = "hevc",.long_name             = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"),.type                  = AVMEDIA_TYPE_VIDEO,.id                    = AV_CODEC_ID_HEVC,.priv_data_size        = sizeof(HEVCContext),.priv_class            = &hevc_decoder_class,.init                  = hevc_decode_init,.close                 = hevc_decode_free,.decode                = ,.flush                 = hevc_decode_flush,.update_thread_context = hevc_update_thread_context,.init_thread_copy      = hevc_init_thread_copy,.capabilities          = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,.profiles              = NULL_IF_CONFIG_SMALL(profiles),
}
  • H.264解碼對應的AVCodec結構體ff_h264_decoder:
    • init() -> ff_h264_decode_init()
    • decode() -> h264_decode_frame() -> decode_nal_units()
    • close() -> h264_decode_end()
  • 參考鏈接:FFmpeg: libavcodec/h264.c File Reference
= {.name                  = "h264",.long_name             = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),.type                  = AVMEDIA_TYPE_VIDEO,.id                    = AV_CODEC_ID_H264,.priv_data_size        = sizeof(H264Context),.init                  = ff_h264_decode_init,.close                 = h264_decode_end,.decode                = h264_decode_frame,.capabilities          =  AV_CODEC_CAP_DR1 |AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |AV_CODEC_CAP_FRAME_THREADS,.flush                 = flush_dpb,.init_thread_copy      = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context),.profiles              = NULL_IF_CONFIG_SMALL(profiles),.priv_class            = &h264_class,
}
  • VP8解碼(libVPX)對應的AVCodec結構體ff_libvpx_vp8_decoder:
    • init() -> vpx_init() -> vpx_codec_dec_init()
    • decode() -> vp8_decode() -> vpx_codec_decode(), vpx_codec_get_frame()
    • close() -> vp8_free() -> vpx_codec_destroy()
  • 版本差異
  • 參考鏈接:FFmpeg: libavcodec/libvpxdec.c Source File
AVCodec ff_libvpx_vp8_decoder = {.name           = "libvpx",.type           = AVMEDIA_TYPE_VIDEO,.id             = AV_CODEC_ID_VP8,.priv_data_size = sizeof(VP8Context),.init           = vp8_init,.close          = vp8_free,.decode         = vp8_decode,.capabilities   = CODEC_CAP_AUTO_THREADS | CODEC_CAP_DR1,.long_name      = NULL_IF_CONFIG_SMALL("libvpx VP8"),
};
  • MPEG2解碼對應的AVCodec結構體ff_mpeg2video_decoder:
    • init() -> mpeg_decode_init()
    • decode() -> mpeg_decode_frame()
    • close() -> mpeg_decode_end()
  • 參考鏈接:FFmpeg: libavcodec/mpeg12dec.c File Reference
= {.name           = "mpeg2video",.long_name      = NULL_IF_CONFIG_SMALL("MPEG-2 video"),.type           = AVMEDIA_TYPE_VIDEO,.id             = AV_CODEC_ID_MPEG2VIDEO,.priv_data_size = sizeof(Mpeg1Context),.init           = mpeg_decode_init,.close          = mpeg_decode_end,.decode         = mpeg_decode_frame,.capabilities   = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY |AV_CODEC_CAP_SLICE_THREADS,.flush          = flush,.max_lowres     = 3,.profiles       = NULL_IF_CONFIG_SMALL(mpeg2_video_profiles),
}

?注意事項

  • FFmpeg (libav*) 開發踩過的坑 - 嗶哩嗶哩

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

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

相關文章

JUnit單元測試筆記

#01 JUnit簡介 1.在項目工程中的Library,add 一個JUnit的Jar包&#xff0c;按需要添加JUnit 3 或 JUnit 4&#xff08;分為被測試類與測試類較佳&#xff09;。 2.單元測試是由程序員完成的。 3.Java 5 之前的版本只能 用JUnit 4前的版本&#xff08;因為JUnit 4用到Java 5的…

jqery獲取每個月天數_三年級《年、月、日》單元重要知識點整理匯總,以及難點題型解析...

昨天給大家分享了《計算經過的時間》問題&#xff0c;今天給大家分享的是《年、月、日》單元中重要的幾個知識點&#xff0c;以及難點題型解析。知識點1 感知年、月、日一、結合生活實際&#xff0c;看看下面事情需要經過多少時間。跑完100米大約需要經過十幾(秒)。2.打一場籃球…

FFmpeg源代碼簡單分析-架構圖-編碼

參考鏈接 FFmpeg源代碼結構圖 - 編碼_雷霄驊的博客-CSDN博客_ffmpeg 源碼函數背景色 函數在圖中以方框的形式表現出來。不同的背景色標志了該函數不同的作用&#xff1a; 粉紅色背景函數&#xff1a;FFmpeg的API函數。白色背景的函數&#xff1a;FFmpeg的內部函數。黃色背景的…

為革命,保護視力——為Eclipse更換暗黑皮膚及編輯頁面的字體顏色主題

1.在Eclipse中的菜單欄的Help -> Eclipse Market 的 Search欄中輸入 Eclipse Moonrise UI Theme &#xff0c;之后自己執生啦&#xff08;確保上網配置正確&#xff09;。 2.與上面操作類似&#xff0c;輸入 Eclipse Color Theme&#xff0c;選擇安裝。 3.選擇菜單欄的Win…

python函數可以作為容器對象嗎_正確理解Python函數是第一類對象

正確理解 Python函數&#xff0c;能夠幫助我們更好地理解 Python 裝飾器、匿名函數(lambda)、函數式編程等高階技術。函數(Function)作為程序語言中不可或缺的一部分&#xff0c;太稀松平常了。但函數作為第一類對象(First-Class Object)卻是 Python 函數的一大特性。那到底什么…

FFmpeg源代碼簡單分析-通用- av_register_all()

參考鏈接 ffmpeg 源代碼簡單分析 &#xff1a; av_register_all()_雷霄驊的博客-CSDN博客_av_register_all()從學齡前開始解讀FFMPEG代碼 之 avcodec_register_all函數_zzyincsdn的博客-CSDN博客

@suppressWarnings(unchecked)及其相關屬性在Java中意思

首先suppressWarnings("unchecked")是JDK1.5中新加入的Annotation語法&#xff0c;用來壓制警告信息的。 編寫代碼時&#xff0c;有時會提示一些警告&#xff08;例如&#xff1a;使用已經廢棄的類&#xff0c;沒有加入泛型等&#xff09;&#xff0c;如果不想讓程序…

FFmpeg源代碼簡單分析-通用-avcodec_register_all()

參考鏈接 ffmpeg 源代碼簡單分析 &#xff1a; avcodec_register_all()_雷霄驊的博客-CSDN博客

pythonsklearn乳腺癌數據集_Python的Sklearn庫中的數據集

一、Sklearn介紹scikit-learn是Python語言開發的機器學習庫&#xff0c;一般簡稱為sklearn&#xff0c;目前算是通用機器學習算法庫中實現得比較完善的庫了。其完善之處不僅在于實現的算法多&#xff0c;還包括大量詳盡的文檔和示例。其文檔寫得通俗易懂&#xff0c;完全可以當…

FFmpeg源代碼簡單分析-通用- 內存的分配和釋放(av_malloc()、av_free()等)

參考鏈接 FFmpeg源代碼簡單分析&#xff1a;內存的分配和釋放&#xff08;av_malloc()、av_free()等&#xff09;_雷霄驊的博客-CSDN博客_av_malloc 內容介紹 內存操作的常見函數位于libavutil\mem.c中本文記錄最常使用的幾個函數&#xff1a; av_malloc()av_realloc()av_mal…

面試題——死鎖的實現

public class DeadLock {public static Object Chopstick_1 new Object();public static Object Chopstick_2 new Object();public static void main(String[] args) {final DeadLock deadLock new DeadLock();// 第一個線程 new Thread(new Runnable() {public void run()…

python回歸分析實驗_python線性回歸實驗

實驗算法python線性回歸實驗【實驗名稱】Python線性回歸實驗【實驗要求】掌握Python線性回歸模型應用過程&#xff0c;根據模型要求進行數據預處理&#xff0c;建模&#xff0c;評價與應用&#xff1b;【背景描述】線性回歸是利用數理統計中回歸分析&#xff0c;來確定兩種或兩…

FFmpeg源代碼簡單分析-通用-結構體分析-AVFormatContext

參考鏈接 FFMPEG結構體分析&#xff1a;AVFormatContext_雷霄驊的博客-CSDN博客_avformatcontext AVFormatContext AVFormatContext是包含碼流參數較多的結構體結構體的定義位于libavformat/avformat.h/*** Format I/O context.//格式化 I/O 上下文* New fields can be added…

log4j詳解與實戰

log4j詳解與實戰 http://www.iteye.com/topic/378077

plsql如何顯示表結構圖_【論文攻略】排版技巧——如何用 Word 編輯參考文獻

每個需要寫畢業論文的朋友都會發現&#xff0c;修改文獻是一件非常痛苦的事情&#xff0c;雖然現在也有很多軟件可以編排參考文獻&#xff0c;其實 word 本身就可以。采用合適的編輯方法會方便地做到整齊,規范, 自動排序和交叉引用。 1. 以尾注的方式插入第一個參考文獻將光標定…

FFmpeg源代碼簡單分析-通用-結構體分析-AVCodecContext

參考鏈接 FFMPEG結構體分析&#xff1a;AVCodecContext_雷霄驊的博客-CSDN博客_avcodeccontext AVCodecContext AVCodecContext是包含變量較多的結構體&#xff08;感覺差不多是變量最多的結構體&#xff09;結構體的定義位于avcodec.h關鍵的變量如下所示&#xff08;僅僅考慮…

Hello OpenGL——OpenGL在Visual c++6.0安裝和配置

1、下載并安裝glut庫opengl的glut庫 GLUT不是OpenGL所必須的&#xff0c;但它會給我們的學習帶來一定的方便&#xff0c;推薦安裝。 Windows環境下的GLUT下載地址&#xff1a;&#xff08;大小約為150k&#xff09; http://www.opengl.org/resources/libraries/glut/glutdlls37…

FFmpeg源代碼簡單分析-通用-結構體分析-AVIOContext

參考鏈接 FFMPEG結構體分析&#xff1a;AVIOContext_雷霄驊的博客-CSDN博客_aviocontext AVIOContext AVIOContext是FFMPEG管理輸入輸出數據的結構體結構體的定義位于位于avio.h關鍵的變量如下所示 unsigned char *buffer&#xff1a;緩存開始位置int buffer_size&#xff1…

初聞動態規劃

前言 本文以一道常見的算法面試題開篇&#xff0c;引入動態規劃的基礎概念&#xff0c; 介紹其思考過程。 正文 一、常見的一道算法面試題——上臺階 有一個樓梯總共n個臺階&#xff0c;只能往上走&#xff0c;每次只能上1個、2個臺階&#xff0c;總共有多少種走法。 解決…

FFmpeg源代碼簡單分析-通用-結構體分析-AVCodec

參考鏈接 FFMPEG結構體分析&#xff1a;AVCodec_雷霄驊的博客-CSDN博客_avcodec AVCodec AVCodec是存儲編解碼器信息的結構體結構體的定義位于avcodec.h文件中最主要的幾個變量 const char *name&#xff1a;編解碼器的名字&#xff0c;比較短const char *long_name&#xff…