<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### 基礎:顯示過程 1) 設定顯示區域,//video mode 2) Yuv覆蓋 // 3) 顯示圖像//rgb格式轉yuv,操作力實際操作用 yv12來填充yuv420, 4) 繪制圖像//位置,高度,寬度,縮放大小的矩陣參數。 一屆理解:桌子,白底桌布,原始花紋,變化的花紋。 【待補充 SDL 顯示過程 csdn】 ### 關于播放聲音的小結 1) 聲音的回調函數,尤其那個參數的設置過程(get decode...) 2) Event事件,聯系到消費者、生產者問題。**其他處理比如為了預防死循環,自己sleep讓系統調度,以方便做其他事 **3) 一個數據結構,audioq,隊列。 4) 聲音播放對應的函數。 ### 關于播放圖像的小結 1) 程序的調用框架 Video_thread? ----call--->?????可能? queue_picture(分配空間 等)...............???????? send event............收到事件,執行 alloc_picture; ??????????????????????????--->(空間分配好后的事件處理)???????? 【待補充】 Main timer--->????? schedule_refresh ----> send event......................... 收到事件,執行?video_refresh_timer--->播放函數video_play 待更新一個函數調用框架 2) 大量的使用事件機制 > a) 刷新事件(細心的話,你會發現schedule_refresh觸發了timer事件,而后者又調用了schedule_refresh,所謂的形成回路;在此我推斷這里的定時器一般情形只能執行一次) b) 退出事件 c) 處理 生產者 消費者 問題(細心的話,**會發現針對 video_q有兩處上鎖,有兩處解鎖,**具體的情景后續分析) 3) 圖像的處理過程在這里 “形散而神不散”,說句俗話,就是跟tutorial 2不一樣,這里 buffer 申請,yuv覆蓋申請,拷貝buffer 到yuv覆蓋 等等都獨立成函數; 4) 有一個全局的數據結構,videoState ,所謂的大數據結構,這個結構涵蓋大部分的信息; 5) 在使用音頻隊列的基礎上,同時普及視頻隊列; ### 場景分析 簡要交互過程 Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3197C video_thread,【wait】while (!vp->allocated && !is->quit) Function: alloc_picture(void *), Thread: 0x31844 主線程,【signal】,分配ok Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3197C video_thread,驗證一下,寫到滿? Function: video_display(VideoState *), Thread: 0x31844 主線程,play core,SDL_DisplayYUVOverlay Function: video_refresh_timer(void *), Thread: 0x31844 主線程, size=1,驗證 是否會 消費到底 Function: video_refresh_timer(void *), Thread: 0x31844 主線程,【signal】timer中 隊列數目減少 Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3197C video_thread,【wait】while (!vp->allocated && !is->quit) Function: alloc_picture(void *), Thread: 0x31844 主線程,【signal】,分配ok Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3197C video_thread,驗證一下,寫到滿? **【線程調度,再次發現沒有分配,下一條記錄可以發現】** //Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3197C video_thread,【wait】while (!vp->allocated && !is->quit) Function: video_display(VideoState *), Thread: 0x31844 主線程,play core,SDL_DisplayYUVOverlay Function: video_refresh_timer(void *), Thread: 0x31844 主線程, size=1,驗證 是否會 消費到底 Function: video_refresh_timer(void *), Thread: 0x31844 主線程,【signal】timer中 隊列數目減少 我在下面的圖片,對每一幀的過程 進行了標示,細心甚至會發現第4幀出現時? 有一個申請內存的小插曲。 ### ![](https://box.kancloud.cn/2016-02-22_56cae4b7e4165.jpg) 場景分析二:一個完整的交互過程 直接上圖。 ![](https://box.kancloud.cn/2016-02-22_56cae4b80e031.jpg) //分析如上,不同,主要就是timer 還沒有觸發,所以就執行下一次的wait. //其實場景切換,不過與vedio_thread,主線程的分配,還有timer的播放; . ps:如果wait滿足的話,那么下一次還是在原來線程里執行; 鑒定真實的wait就是下一次執行不在這個線程里; 一句話,這里的wait表示執行到這塊代碼,并不表示一定會wait. **隊列的數目,從來沒有超過1,這就是作者說的有了就要用,沒有就要取;想起這里使用的同步量是mutex;** 其他:程序中有2個wait, 但下面這個wait從來沒有執行過,后續可以增加分析 ~~~ while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !is->quit) { SDL_CondWait(is->pictq_cond, is->pictq_mutex); } ~~~ 唯一長期執行的wait是如下代碼: ~~~ /* wait until we have a picture allocated */ SDL_LockMutex(is->pictq_mutex); while (!vp->allocated && !is->quit) { SDL_CondWait(is->pictq_cond, is->pictq_mutex); } SDL_UnlockMutex(is->pictq_mutex); ~~~ ### 最后一幀的處理 那就是當所有的12幀圖像播放完畢后,代碼的行為。以下是log 經過分析,這是圖像的最后一幀,當前的vedio picture已經分配,所以不會出現分配的情景。 Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3AD14 video_thread, 隊列增加 size=1 Function: video_display(VideoState *), Thread: 0x3ABEC 主線程,play core,SDL_DisplayYUVOverlay Function: video_refresh_timer(void *), Thread: 0x3ABEC 主線程, size=1,驗證 是否會 消費到底 Function: video_refresh_timer(void *), Thread: 0x3ABEC 主線程,【signal】timer中 隊列數目減少 Function: queue_picture(VideoState *, AVFrame *), Thread: 0x3AD14 video_thread, 隊列增加 size=1 Function: video_display(VideoState *), Thread: 0x3ABEC 主線程,play core,SDL_DisplayYUVOverlay Function: video_refresh_timer(void *), Thread: 0x3ABEC 主線程, size=1,驗證 是否會 消費到底 Function: video_refresh_timer(void *), Thread: 0x3ABEC 主線程,【signal】timer中 隊列數目減少 ### 其他問題 (有同事提出,可能哪個鎖沒有打開,此時待后續分析) 具體說,就是上鎖的位置就是那個vp 沒有分配的情形, 解鎖就是alloc 完畢,或者播放完畢的情形;至于播放完畢會導致鎖解開的情形待分析。 解決方案:就是在上鎖的位置打log,看上鎖代碼的log和后續的關鍵區log 是否會相繼出現。\ 如果是相繼出現,就證明queue_picture里沒有出現 鎖mutex等待的情形;//mutex要么0要么1 視頻刷新的時間 可能會打亂播放的順序。待考證 解決方案:那就是修改播放刷新的時間, ### 小結: 這是第一次使用日志的方式處理異步調試 針對關鍵區域的斷點放置,是個學問,針對讀取變量或者鎖的輪詢有不同的方案; 一個視頻流完整的對應過程(忽略細節不同),如下代碼:,一句話,找到開頭和結尾。 Function: queue_picture(VideoState *, AVFrame *), Thread: 0x48CB0 video_thread,【wait】while (!vp->allocated && !is->quit) ...忽略 Function: video_refresh_timer(void *), Thread: 0x48AEC 主線程,【signal】timer中 隊列數目減少 附件:完整的調試log(待補充,將會在csdn網盤補充)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看