• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            string

            string
            posts - 27, comments - 177, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
            上面一節是從使用者的角度看Protocol ,這一節從Protocol提供者的角度來看Protocol。
            作為提供者,我們要了解三個問題:
            1. Protocol是什么?
            2. Protocol安裝到什么地方。
            3. 怎么安裝Protocol。
            前兩個問題上一節已經講述,那么我們現在看第三個問題。
            BootService 提供了InstallProtocolInterface幫我們把Protocol安裝到Controller Handle上。
            EFI_STATUS
            InstallProtocolInterface (
                IN OUT EFI_HANDLE *Handle,                 // Protocol將安裝到這兒
                IN EFI_GUID *Protocol,                         // GUID
                IN EFI_INTERFACE_TYPE InterfaceType,  // 通常為EFI_NATIVE_INTERFACE
                IN VOID *Interface                              // Protocol實例
            );

            我們希望我們的Protocol能常駐內存以提供服務。 我們知道Application 是不能常駐內存的,只有Driver可以常駐內存。那么我們就要用driver的形式來提供服務。但我們的服務與通常的driver不同,driver需要特定硬件支持,而我們的服務不需要。這就使得我們的driver變的簡單,driver需要安裝到特定的controller上,我們的服務安裝到任何controller都可以。
            那么還有一個不是問題的問題,何時安裝Protocol。作為驅動的Protocol有特定的規范,將在下一節講述。通常一個driver被load到內存后會執行InstallProtocolInterface 將 Driver Binding Protocol 和Component Name Protocol安裝到自身Handle(或者其它handle)上。 相比driver我們的服務要簡單許多,我們在Image初始化的時候將Protocol安裝到自身Handle即可。

            通過上面的分析,我們決定使用driver來提供服務,Image初始化的時候安裝Protocol。具體到我們將要提供的視頻解碼服務,我們還要分析一下我們需要提供哪些函數。我們需要OpenVideo來打開視頻,QueryFrame取得一幀,CloseFrame關閉視頻,還需要一個函數來獲取視頻信息。下面讓我們一步步來產生這個Protocol吧。
            頭文件ffdecoder.h
            首先我們要定義我們Protocol的GUID
            #define EFI_FFDECODER_PROTOCOL_GUID \
            { \
                0xce345171, 0xabcd, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
            }

            //
            ///// Protocol GUID name defined in EFI1.1.
            // 
            #define FFDECODER_PROTOCOL  EFI_FFDECODER_PROTOCOL_GUID
            然后定義Protocol里服務的函數原型
            /**
              Open the video 
              @param  This       Indicates a pointer to the calling context.
              @param  FileName   File name of the video under current dir. 
              @retval EFI_SUCCESS           The video is opened successfully. 
              @retval EFI_NOT_FOUND         There is no such file.
            **/
            typedef 
            EFI_STATUS
            (EFIAPI* EFI_OPEN_VIDEO)(
                    IN EFI_FFDECODER_PROTOCOL* This,
                    IN CHAR16* FileName
                    );

            /**
              Close the video 
              @param  This       Indicates a pointer to the calling context.
              @retval EFI_SUCCESS           The video is closed successfully. 
            **/
            typedef 
            EFI_STATUS
            (EFIAPI* EFI_CLOSE_VIDEO)(
                    IN EFI_FFDECODER_PROTOCOL* This
                    );

            /**
              Query a frame from the video. 
              @param  This       Indicates a pointer to the calling context.
              @param  pFrame     Points to the current Frame.  
              @retval EFI_SUCCESS          The video is opened successfully. 
              @retval EFI_NO_MEDIA         There is no opened video. 
              @retval EFI_END_OF_MEDIA     There is no more Frame. 
            **/
            typedef 
            EFI_STATUS
            (EFIAPI* EFI_QUARY_FRAME)(
                    IN  EFI_FFDECODER_PROTOCOL  *This,
                    OUT AVFrame                 **pFrame
                    );

            /**
              Query the Width and height of a frame. 
              @param  This       Indicates a pointer to the calling context.
              @param  Width      Width(in pixels) of a frame.
              @param  Height     Height(in pixels) of a frame.
              @retval EFI_SUCCESS          Return the Size successfully. 
              @retval EFI_NO_MEDIA         There is no opened video. 
            **/
            typedef 
            EFI_STATUS
            (EFIAPI* EFI_QUARY_FRAME_SIZE)(
                    IN  EFI_FFDECODER_PROTOCOL  *This,
                    OUT UINT32                  *Width,
                    OUT UINT32                  *Height 
                    );
            下面就要定義Protocol本身了, 按照EDK2的規則,我們的Protocol取名為EFI_FFDECODER_PROTOCOL . 
            struct _EFI_FFDECODER_PROTOCOL{
             UINT64          Revision;
             EFI_OPEN_VIDEO  OpenVideo;
             EFI_CLOSE_VIDEO CloseVideo;
             EFI_QUARY_FRAME QueryFrame;
             EFI_QUARY_FRAME_SIZE QueryFrameSize;
            };
            typedef struct _EFI_FFDECODER_PROTOCOL EFI_FFDECODER_PROTOCOL;
            typedef EFI_FFDECODER_PROTOCOL  EFI_FFDECODER;

            頭文件ffdecoder.h最后要提供給用戶使用。下面進入EFI_FFDECODER_PROTOCOL 的實現部分ffdecoder.c
            ffdecoder.c中我們要提供EFI_FFDECODER_PROTOCOL 的四個成員函數,以及一個Image初始化函數, 一個Private數據結構,用于存放EFI_FFDECODER_PROTOCOL 的上下文。
            首先看Private數據結構,如果你對ffmpeg比較熟悉,那么你很快就會明白我們需要在Private中存放什么
            #define FFDECODER_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('V', 'I', 'D', 'O')
            /**
              @member     Signature         The signature of the Protocol Context
              @member     FFDecoder        The EFI_FFDECODER_PROTOCOL   
              @member     pFormatCtx       Video Format Context
              @member    videoStream       The index of Video Stream in all the streams.
              @member     pCodecCtx        Codec context
              @member     pFrame             The yuv Frame
              @member     pFrameRGBA      The RGBA Frame
              @member     buffer               internal used
              @member     img_convert_ctx  The Context of converting from yuv to rgba.
             **/
            typedef struct {
                UINTN                 Signature;
                EFI_FFDECODER_PROTOCOL  FFDecoder; 
                AVFormatContext    *pFormatCtx;
                int                        videoStream;
                AVCodecContext     *pCodecCtx;
                AVFrame               *pFrame; 
                AVFrame               *pFrameRGBA;
                uint8_t                  *buffer;
                struct SwsContext  *img_convert_ctx ;

            } FFDECODER_PRIVATE_DATA;

            static FFDECODER_PRIVATE_DATA gFFDecoderPrivate;

            我們還定義了一個變量gFFDecoderPrivate, 同時我們就得到了 EFI_FFDECODER_PROTOCOL 的一個實例。下面我們要定義4個函數,對應EFI_FFDECODER_PROTOCOL 的四個成員函數。
            EFI_STATUS
            OpenVideo(
                    IN EFI_FFDECODER_PROTOCOL* This,
                    IN CHAR16* FileName
                    )
            {
                FFDECODER_PRIVATE_DATA* Private;
                Private = FFDECODER_PRIVATE_DATA_FROM_THIS(This);
                ...
            }

            EFI_STATUS
            CloseVideo(
                    IN EFI_FFDECODER_PROTOCOL* This
                    )
            {
                FFDECODER_PRIVATE_DATA* Private;
                Private = FFDECODER_PRIVATE_DATA_FROM_THIS(This);
                ...
            }

            EFI_STATUS
            QueryFrame(
                    IN  EFI_FFDECODER_PROTOCOL  *This,
                    OUT AVFrame                 **ppFrame
                    )
            {
                FFDECODER_PRIVATE_DATA* Private;
                Private = FFDECODER_PRIVATE_DATA_FROM_THIS(This);
                ...
            }

            EFI_STATUS
            QueryFrameSize(
                    IN  EFI_FFDECODER_PROTOCOL  *This,
                    OUT UINT32                  *Width,
                    OUT UINT32                  *Height
                    )
            {
                FFDECODER_PRIVATE_DATA* Private;
                Private = FFDECODER_PRIVATE_DATA_FROM_THIS(This);
                ...
            }
            宏FFDECODER_PRIVATE_DATA_FROM_THIS(This) 用于根據Protocol指針取得Protocol的上下文, 定義如下:
            #define FFDECODER_PRIVATE_DATA_FROM_THIS(a) CR (a, FFDECODER_PRIVATE_DATA, FFDecoder, FFDECODER_PRIVATE_DATA_SIGNATURE)
            本篇重點講述Protocol,所以這個四個函數細節不再詳述,感興趣的話可以看附件中的源碼。

            下面我們看最重要的部分,Image的初始化函數,回憶一下,我們會記得,在初始化函數中我們將要安裝Protocol。
            EFI_STATUS
            EFIAPI
            InitFFdecoder (
                    IN EFI_HANDLE        ImageHandle,
                    IN EFI_SYSTEM_TABLE  *SystemTable
                    )
            {
                EFI_STATUS Status;
                FFDECODER_PRIVATE_DATA* Private = &gFFDecoderPrivate;
                //初始化ShellProtocol
                ShellLibConstructorWorker2(NULL,NULL,NULL,NULL);
                //初始化StdLib
                (void) DriverInitMain(0, NULL);

                //設置Protocol上下文的Signature.
                //初始化Protocol,設置Protocol成員函數。
                Private-> Signature= FFDECODER_PRIVATE_DATA_SIGNATURE  ; 
                Private->FFDecoder.OpenVideo = OpenVideo; 
                Private->FFDecoder.CloseVideo = CloseVideo; 
                Private->FFDecoder.QueryFrame= QueryFrame;  
                Private->FFDecoder.QueryFrameSize= QueryFrameSize; 

                //將
            EFI_FFDECODER_PROTOCOL的實例 
            &(Private->FFDecoder )安裝到自身Handle中。
                Status = gBS->InstallProtocolInterface (
                        &ImageHandle,
                        &gEfiFFDecoderProtocolGUID ,
                        EFI_NATIVE_INTERFACE,
                        &Private->FFDecoder
                        );

            }

            在.inf文件中我們把InitFFdecoder 設為Entrypoint,當Image被load到內存后InitFFdecoder 會自動執行。
            [Defines]
              INF_VERSION                    = 0x00010006
              BASE_NAME                      = ffdecoder
              FILE_GUID                        = 33a97c46-7491-4dfd-b442-74798713ce5f
              #ENTRY_POINT                 = ShellCEntryLib
              #MODULE_TYPE                = UEFI_APPLICATION 
              VERSION_STRING              = 0.1
              MODULE_TYPE                  = UEFI_DRIVER 
              ENTRY_POINT                   = InitFFdecoder 

            #
            #  VALID_ARCHITECTURES           = IA32 X64 IPF
            #

            [Sources]
              ffdecoder.c 
              math.c
              InitShell.c
            [Packages]
              StdLib/StdLib.dec
              MdePkg/MdePkg.dec
              MdeModulePkg/MdeModulePkg.dec
              ShellPkg/ShellPkg.dec
              ffmpeg/ffmpeg.dec
              StdLibPrivateInternalFiles/DoNotUse.dec

            [LibraryClasses]
              UefiDriverEntryPoint
              LibC
              LibStdio
              LibMath
              LibString
              BsdSocketLib
              EfiSocketLib
              UseSocketDxe
              DevShell
              zlib
              libavcodec
              libavutil
              libswscale
              libavformat

              LibUefi
              LibNetUtil
            啊哈,編譯得到ffdecoder.efi. 使用命令 load ffdecoder.efi 加載之后就可以像使用其它Protocol一樣使用EFI_FFDECODER_PROTOCOL了。
            下面是一個簡單的例子 fplayer.c 用于播放視頻
            #ifdef __cplusplus
            extern "C"{
            #endif
            #include 
            <Uefi.h> 
            #include 
            <Base.h> 
            #include 
            <Library/DebugLib.h>
            #include 
            <Library/PrintLib.h>
            #include 
            <Protocol/GraphicsOutput.h>
            EFI_GRAPHICS_OUTPUT_PROTOCOL         
            *GraphicsOutput;
            #ifdef __cplusplus
            }
            #endif
            #include 
            "ffdecoder.h"

            EFI_STATUS LocateGraphicsOutput()
            {
                EFI_STATUS Status 
            = gBS->LocateProtocol(
                        
            &gEfiGraphicsOutputProtocolGuid,
                        NULL,
                        (VOID 
            **)&GraphicsOutput);
                
            if (EFI_ERROR(Status)) {
                    Print(L
            "LocateProtocol %r\n", Status);
                }
                
            return Status;
            }
            void ShowFrame(AVFrame *pFrame, int width, int height, int iFrame)
            {
                
            if(GraphicsOutput)
                    GraphicsOutput
            ->Blt(
                            GraphicsOutput,
                            (EFI_GRAPHICS_OUTPUT_BLT_PIXEL 
            *)pFrame->data[0],
                            EfiBltBufferToVideo,
                            
            0,0,
                            
            0,0,
                            width, height,
                            
            0
                            );
            }

            int main(int argc, char *argv[])
            {
                AVFrame         
            *pFrame; 
                EFI_GUID gEfiFFDecoderProtocolGUID 
            = EFI_FFDECODER_PROTOCOL_GUID ;
                EFI_FFDECODER_PROTOCOL 
            *FFDecoder; 
                UINT32 Width, Height;
                CHAR16
            * FileName = 0;

                
            // Locate the Protocol
                EFI_STATUS Status = gBS->LocateProtocol(
                        
            &gEfiFFDecoderProtocolGUID ,
                        NULL,
                        (VOID 
            **)&FFDecoder );
                
            if (EFI_ERROR(Status)) {
                    Print(L
            "LocateProtocol %r\n", Status);
                    
            return Status;
                }
                LocateGraphicsOutput();

                
            // Open Video
                Status =  gBS->AllocatePool(EfiLoaderData, AsciiStrLen(argv[1]) *2 + 2, (VOID**)&FileName );
                AsciiStrToUnicodeStr(argv[
            1], FileName);
                Status 
            = FFDecoder -> OpenVideo( FFDecoder, FileName);
                (
            void) gBS->FreePool ( FileName);
                
            if (EFI_ERROR(Status)) {
                    Print(L
            "Open %r\n", Status);
                    
            return Status;
                }
                
            // Query Frame Size(Width height)
                Status = FFDecoder-> QueryFrameSize(FFDecoder, &Width, &Height);
                
            // Query Frame 
                while!EFI_ERROR( FFDecoder-> QueryFrame(FFDecoder, &pFrame)))
                {
                    ShowFrame(pFrame, Width, Height, 
            0);
                }
                
            // Close Video
                Status = FFDecoder -> CloseVideo(FFDecoder );
                
            return 0;
            }
            在shell里面執行
            f0:/>ffplayer test.avi                                     
            就可以播放視頻了
             下載EFI_FFDECODER_PROTOCOL 附近包含了32-bit的ffdecoder.efi 以及ffdecoder.c fplayer.c

            Feedback

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-03-27 03:58 by djx_zh
            下載EFI_FFDECODER_PROTOCOL
            http://codelibrarydzh.googlecode.com/files/EFI_FFDECODER_PROTOCOL_1.0.zip

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-07-14 22:56 by djx_zh
            @djx_zh
            https://codelibrarydzh.googlecode.com/files/EFI_FFDECODER_PROTOCOL_1.1.zip
            修正一個bug: 顯示的時候應采用BGRA格式。
            增加了timer用于控制播放。按'q'退出播放

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-08-23 15:44 by Amin
            ffdecoder.efi 的driver存放在U盤中,要在shell下運行Load,老是無法成功
            指令 fs0:\ Load ffdecoder.efi
            都只會顯示Load : fs0:\ffdecoder.efi is not a image

            請問是否哪邊有錯誤?

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-08-23 17:02 by Amin
            請問ffdecoder.efi 與ffplayer.efi是否有X64版本可以提供?

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-08-23 17:50 by Amin
            我無法找出以下的LibraryClasses
            zlib
            libavcodec
            libavutil
            libswscale
            libavformat
            請問可從哪里獲取?

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務[未登錄]  回復  更多評論   

            2012-08-24 08:54 by djx_zh
            @Amin
            X64的仍有些技術問題沒有解決。解碼速度已經足夠了,但是GraphOutputProtocol的顯示速度太慢。 你可以留個email給我,我發給你。

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-08-24 09:28 by Amin
            我的mail : white_5168@hotmail.com
            請問我在build x64時有很多的LIB加得很辛苦,請問有什麼方法可以include一個文檔就可以build成功
            我的環境只有用X64的,所以32位元的ffdecoder與ffplayer都無法執行

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-08-24 10:08 by djx_zh
            @Amin
            你是說編譯ffdecoder很辛苦嗎? ffdecoder的編譯比較麻煩,需要修改EDK2的源碼和ffmpeg源碼。除非你很有興趣去學習EDK2, 否則沒必要去編譯ffdecoder.
            ffplayer編譯非常簡單。
            X64的.efi文件已經發給你了。

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2012-09-19 10:38 by Amin
            不是編譯ffdecoder很辛苦,而是你所附上的附檔,里面真的缺了很多文檔,光是要找出來與引用就需要很費時間,不知是否能提供的完整,如libavcodec.inf,libavutil.inf,libswscale.inf,libavformat.inf,ffmpeg/ffmpeg.dec

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務[未登錄]  回復  更多評論   

            2013-05-06 10:52 by 張揚
            博主,你好,請問有什么方法可以直接調用shellpkg這個包里面的函數呢,比如讀寫文件,可以用simple_file_protocol,但是shellpkg里面的方法如何調用?
            還有關于視屏播放的源碼能否分享?(如果不涉及您的版權的前提下)
            多謝!

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務[未登錄]  回復  更多評論   

            2013-05-06 10:53 by 張揚
            我的Email:1102878561@qq.com

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2013-12-19 09:18 by lingming
            有X64的嗎?麻煩給我一份,saillimited@hotmail.com,謝謝。

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2014-07-17 17:41 by 李波
            您好,非常希望能繼續拜讀您的大作,請問一下哪里能買到你的書???
            另外,能不能把這份源碼發給我,我是新手,有些地方不是很清楚。我的郵箱 lumia361@hotmail.com ,謝謝。

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2014-11-12 21:41 by Xexerse
            你好,能把代碼發給我一份嗎,314018436@qq.com,那個鏈接不能用了。還有你的書出版了嗎?叫什么名字啊,現在在學UEFI,想買來參考下

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2015-05-25 15:43 by 周彬彬
            您好,能給我發一份完整的整個代碼嗎?1146625664@qq.com,謝謝

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務[未登錄]  回復  更多評論   

            2015-06-02 22:23 by djx_zh
            ffmpeg的源代碼可到此處下載
            https://github.com/zhenghuadai/uefi-programming/releases/download/1.0/ffmpeg-0.10.2-for-UEFI.tgz

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2015-12-29 11:06 by Zafir
            樓主,可否給我也發一份64位的。511599737@qq.com萬分感謝

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2016-02-17 17:55 by pingl
            樓主,可否發一份64位的給我,謝謝。568900705@qq.com

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2016-02-17 17:57 by pingl
            @Amin

            樓主,可否發一份64位的給我,謝謝。568900705@qq.com

            # re: UEFI 實戰(4) protocol 之利用Protocol提供視頻解碼服務  回復  更多評論   

            2016-02-25 03:11 by djxzh
            @pingl

            http://pan.baidu.com/s/1pKwBzy7
            久久精品二区| 亚洲AV无码久久精品成人| 久久综合给久久狠狠97色| 久久午夜免费视频| 2021国内久久精品| 2021久久精品免费观看| 久久精品中文字幕一区| 国产成人无码精品久久久性色| 中文成人久久久久影院免费观看| 伊人久久大香线蕉无码麻豆| 久久福利片| 狠狠色丁香久久婷婷综合蜜芽五月| 久久精品桃花综合| 人妻精品久久无码区| 久久精品国产亚洲AV电影 | 伊人丁香狠狠色综合久久| 国产成人精品三上悠亚久久| 一本一本久久aa综合精品| 久久久久久亚洲AV无码专区| 999久久久免费精品国产| 久久se精品一区精品二区国产| 亚洲国产成人久久综合区| 久久亚洲精品国产精品| 国产真实乱对白精彩久久| 久久亚洲精品无码VA大香大香| 久久精品国产亚洲AV麻豆网站 | 午夜天堂精品久久久久| 狠狠色丁香久久婷婷综| 四虎国产精品免费久久| 久久亚洲精精品中文字幕| 国产亚州精品女人久久久久久| 亚洲国产精品无码久久青草| 国产精品女同久久久久电影院| 久久综合九色综合97_久久久| 日韩电影久久久被窝网| 久久99精品久久久久久动态图| 国产精自产拍久久久久久蜜| 蜜臀久久99精品久久久久久小说| 精品综合久久久久久97超人| 国产精品久久久久久久app| 品成人欧美大片久久国产欧美...|