欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    作為音視頻領域的開源工具,它幾乎可以實現所有針對音視頻的處理,本文主要利用 官方提供的 SDK 實現音視頻最簡單的幾個實例:編碼、解碼、封裝、解封裝、轉碼、縮放以及添加水印。

    接下來會由發現問題->分析問題->解決問題->實現方案,循序漸進的完成。

    參考代碼:

    編碼實現

    本例子實現的是將視頻域 YUV 數據編碼為壓縮域的幀數據,編碼格式包含了 H.264/H.265/MPEG1/MPEG2 四種 CODEC 類型。 實現的過程,可以大致用如下圖表示:

    從圖中可以大致看出視頻編碼的流程:

    根據流程可以推倒出大致的代碼實現:

    結構體的分配使用()函數,該函數會對 結構體的某些字段設置默認值,它會返回一個指向 的指針或 NULL指針(失敗)。 結構體的釋放只能通過()來完成。注意,該函數只能分配 結構體本身,不能分配它的 data 字段指向的內容,該字段的指向要根據視頻的寬高、像素格式信息手動分配,本例使用的是()函數。代碼實現大致如下:

    //allocate AVFrame struct
    AVFrame *frame = NULL;
    frame = av_frame_alloc();
    if(!frame){
    	printf("Alloc Frame Fail\n");
    	return -1;
    }
    //fill AVFrame struct fields
    frame->width = width;
    frame->height = height;
    frame->pix_fmt = AV_PIX_FMT_YUV420P;
    //allocate AVFrame data buffers field point
    ret = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, frame->pix_fmt, 32);
    if(ret < 0){
    	printf("Alloc Fail\n");
    	return -1;
    }
    //write input file data to frame->data buffer
    fread(frame->data[0], 1, frame->width*frame->height, pInput_File);
    ...
    av_frame_free(frame);
    

    解碼器相關的 結構體的分配使用 (enum id) 完成,該函數的作用是找到一個與 匹配的已注冊過得編碼器;成功則返回一個指向 ID 的指針,失敗返回 NULL 指針。該函數的作用是確定系統中是否有該編碼器,只是能夠使用編碼器進行特定格式編碼的最基本的條件,要想使用它,至少要完成兩個步驟:

    根據特定的視頻數據,對該編碼器進行特定的配置;打開該編碼器。

    針對第一步中關于編解碼器的特定參數, 提供了一個專門用來存放 所需要的配置參數的結構體 結構。它的分配使用t3(const *codec)完成,該函數根據特定的 CODEC 分配一個 結構體視頻解碼器有沒,并設置一些字段為默認參數,成功則返回指向 結構體的指針,失敗則返回 NULL 指針。分配完成后,根據視頻特性,手動指定與編碼器相關的一些參數,比如視頻寬高、像素格式、比特率、GOP 大小等。最后根據參數信息,打開找到的編碼器,此處使用()函數完成。代碼實現大致如下:

    AVCodec *codec = NULL;
    AVCodecContext *codecCtx = NULL;
    //register all encoder and decoder
    avcodec_register_all();
    //find the encoder
    codec = avcodec_find_encoder(codec_id);
    if(!codec){
    	printf("Could Not Find the Encoder\n");
    	return -1;
    }
    //allocate the AVCodecContext and fill it's fields
    codecCtx = avcodec_alloc_context3(codec);
    if(!codecCtx){
    

    佳能相機電池沒解碼_視頻解碼器有沒_2009年銳志的aux有解碼功能么

    printf("Alloc AVCodecCtx Fail\n"); return -1; } codecCtx->bit_rate = 4000000; codecCtx->width = frameWidth; codecCtx->height = frameHeight; codecCtx->time_base= (AVRational){1, 25}; //open the encoder if(avcodec_open2(codecCtx, codec, NULL) < 0){ printf("Open Encoder Fail\n"); }

    存放編碼數據的結構體為 ,使用之前要對該結構體進行初始化,初始化函數為( *pkt),該函數會初始化 結構體中一些字段為默認值,但它不會設置其中的 data 和 size 字段,需要單獨初始化,如果此處將 data 設為 NULL、size 設為 0,編碼器會自動填充這兩個字段。

    有了存放編碼數據的結構體后,我們就可以利用編碼器進行編碼了。 提供的用于視頻編碼的函數為2,它作用是編碼一幀視頻數據,該函數比較復雜,單獨列出如下:

    int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
                              const AVFrame *frame, int *got_packet_ptr);
    

    它會接收來自 ->data 的視頻數據,并將編碼數據放到 ->data 指向的位置,編碼數據大小為 ->size。

    其參數和返回值的意義:

    編碼完成后就可將->data內的編碼數據寫到輸出文件中;代碼實現大致如下:

    AVPacket pkt;
    //init AVPacket
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;
    //encode the image
    ret = avcodec_encode_video2(codecCtx, &pkt, frame, &got_output);
    if(ret < 0){
    	printf("Encode Fail\n");
    	return -1;
    
    if(got_output){
    	fwrite(pkt.data, 1, pkt.size, pOutput_File);
    }
    

    編碼的大致流程已經完成了,剩余的是一些收尾工作,比如釋放分配的內存、結構體等等。

    解碼實現

    解碼實現的是將壓縮域的視頻數據解碼為像素域的 YUV 數據。實現的過程,可以大致用如下圖所示。

    從圖中可以看出,大致可以分為下面三個步驟:

    根據流程可以推倒出大致的代碼實現:

    對于輸入數據,首先,通過 fread 函數實現將固定長度的輸入文件的數據存放到一塊 內。H.264中一個包的長度是不定的,讀取固定長度的碼流通常不可能剛好讀出一個包的長度;對此, 提供了一個 結構用于解析讀到 內的碼流信息,直到能夠取出一個完整的 H.264 包。為此, 提供的函數為,該函數比較復雜,定義如下:

    int av_parser_parse2(AVCodecParserContext *s,
                         AVCodecContext *avctx,
                         uint8_t **poutbuf, int *poutbuf_size,
                         const uint8_t *buf, int buf_size,
    

    視頻解碼器有沒_2009年銳志的aux有解碼功能么_佳能相機電池沒解碼

    int64_t pts, int64_t dts, int64_t pos);

    函數的參數和返回值含義如下:

    中為我們提供的該函數常用的使用方式為:

    while(in_len){
    	len = av_parser_parse2(myparser. AVCodecContext, &data, &size, in_data, in len, pts, dts, pos);
    	in_data += len;
    	in_len  -= len;
    	if(size)
    		decode_frame(data, size);
    }
    

    如果參數的值為0,那么應繼續解析緩存中剩余的碼流;如果緩存中的數據全部解析后依然未能找到一個完整的包,那么繼續從輸入文件中讀取數據到緩存,繼續解析操作,直到pkt.size不為0為止。

    因此,關于輸入數據的處理,代碼大致如下:

    //open input file
    FILE *pInput_File = fopen(Input_FileName, "rb+");
    if(!pInput_File){
    	printf("Open Input File Fail\n");
    	return -1;
    }
    //read compressed bitstream form file to buffer
    uDataSize = fread(inbuf, 1, INBUF_SIZE, pInput_File);
    if(uDataSize == 0){	//decode finish
    	return -1;
    }
    //decode the data in the buffer to AVPacket.data
    while(uDataSize > 0){
    	len = av_parser_parse2(pCodecParserCtx, codecCtx,
    							&(pkt.data), &(pkt.size),
    							pDataPtr, uDataSize,
    							AV_NOPTS_VALUE, AV_NOPTS_VALUE,
    							AV_NOPTS_VALUE);
    	uDataSize -= len;
    	uDataPtr  += len;
    	if(pkt.size == 0) continue;
    	decode_frame(pkt.data, pkt.size);
    }
    

    注意,上面提到的函數用的幾個參數,其實是與具體的編碼格式有關的,它們應該在之前已經分配好了,我們只是放到后面來講一下,因為它們是與具體的解碼器強相關的。

    對于解碼器。與上面提到的編碼實現類似,首先,根據 找到注冊的解碼器 , 為此提供的函數為();其次,根據找到的解碼器獲取與之相關的解碼器上下文結構體 ,使用的函數為編碼中提到的t3;再者,如上面提到的要獲取完整的一個 NALU,解碼器需要分配一個 結構,使用函數;最后,前面的準備工作完成后,打開解碼器,即可調用 提供的解碼函數2對輸入的壓縮域的碼流進行解碼,并將解碼數據存放到 ->data 中。代碼實現大致如下:

    AVFrame *frame = NULL;
    AVCodec *codec = NULL;
    AVCodecContext *codecCtx = NULL;
    AVCodecParserContext *pCodecParserCtx = NULL;
    

    視頻解碼器有沒_2009年銳志的aux有解碼功能么_佳能相機電池沒解碼

    //register all encoder and decoder avcodec_register_all(); //Allocate AVFrame to Store the Decode Data frame = av_frame_alloc(); if(!frame){ printf("Alloc Frame Fail\n"); return -1; } //Find the AVCodec Depending on the CODEC_ID codec = avcodec_find_decoder(AV_CODEC_ID_H264); if(!codec){ printf("Find the Decoder Fail\n"); return -1; } //Allocate the AVCodecContext codecCtx = avcodec_alloc_context3(codec); if(!codecCtx){ printf("Alloc AVCodecCtx Fail\n"); return -1; } //Allocate the AVCodecParserContext pCodecParserCtx = av_parser_init(AV_CODEC_ID_H264); if(!pCodecParserCtx){ printf("Alloc AVCodecParserContext Fail\n"); return -1; } //Open the Decoder if(avcodec_open2(codecCtx, codec, NULL) < 0){ printf("Could not Open the Decoder\n"); return -1; } //read compressed bitstream form file to buffer uDataSize = fread(inbuf, 1, INBUF_SIZE, pInput_File); if(uDataSize == 0){ //decode finish return -1; } //decode the data in the buffer to AVPacket.data while(uDataSize > 0){ len = av_parser_parse2(pCodecParserCtx, codecCtx, &(pkt.data), &(pkt.size), pDataPtr, uDataSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE); uDataSize -= len;

    視頻解碼器有沒_佳能相機電池沒解碼_2009年銳志的aux有解碼功能么

    uDataPtr += len; if(pkt.size == 0) continue; //decode start avcodec_decode_video2(codecCtx, frame, &got_frame, pkt); }

    注意,上面解碼的過程中,針對具體的實現,可能要做一些具體參數上的調整,此處只是理清解碼的流程。

    對于輸出數據。解碼完成后,解碼出來的像素域的數據存放在 的 data 字段內,只需要將該字段內存放的數據之間寫文件到輸出文件即可。解碼函數2函數完成整個解碼過程,對于它簡單介紹如下:

    int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                             int *got_picture_ptr,
                             const AVPacket *avpkt);
    

    該函數各個參數的意義:

    由此可見,當標識位為1時,代表解碼一幀結束,可以寫數據到文件中。代碼如下:

    pOutput_File = fopen(Output_FileName, "wb");
    if(!pOutput_File){
    	printf("Open Output File Fail\n");
    	return -1;
    }
    if(*got_picture_ptr){
    	fwrite(frame->data[0],1, Len, pOutput_File)
    }
    

    解碼的大致流程已經完成了,剩余的是一些收尾工作,比如釋放分配的內存、結構體等等。

    封裝實現

    本例子實現的是將視頻數據和音頻數據,按照一定的格式封裝為特定的容器,比如FLV、MKV、MP4、AVI等等。實現的過程,可以大致用如下圖表示:

    從圖中可以大致看出視頻封裝的流程:

    根據流程可以推倒出大致的代碼實現:

    對于由 YUV 數據得到編碼的視頻數據部分,不再重復。直接看與 Muxer 相關的部分,與特定的 Muxer 相關的信息, 提供了一個 的結構體描述,并用()函數來分配它。該函數的聲明如下:

    int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
                                       const char *format_name, const char *filename);
    

    其中:

    代碼如下:

    AVOutputFormat *fmt;
    AVFormatContext *oc;
    /* allocate the output media context */
    avformat_alloc_output_context2(&oc, NULL, NULL, filename);
    if (!oc) {
        printf("Could not deduce output format from file extension: using MPEG.\n");
        avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
    }
    if (!oc)
        return 1;
    fmt = oc->oformat;
    

    2009年銳志的aux有解碼功能么_視頻解碼器有沒_佳能相機電池沒解碼

    有了表示媒體文件格式的 結構后,就需要根據媒體格式來判斷是否需要往媒體文件中添加視頻流、音頻流(有的媒體文件,這兩種流并不是必須的);以 MP4 格式的媒體文件為例,我們需要一路視頻流、一路音頻流。因此需要創建一路流, 提供的創建流的函數為(),該函數完成向 結構體中所代碼的媒體文件中添加數據流,函數聲明如下:

    AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
    

    其中:

    注意:對于 Muxer,該函數必須在調用r()前調用。使用完成后視頻解碼器有沒,需要調用()和t()來清理由它分配的內容。

    該函數調用完成后,一個新的 便已經加入到輸出文件中,下面就需要設置 的 id 和 codec 等參數。以視頻流為例,代碼如下:

    OutputStream *ost;
    AVFormatContext *oc;
    AVCodec **codec;
    AVCodecContext *c;
    AVStream *st;
    st = avformat_new_stream(oc, *codec);
    if(!st){
        fprintf(stderr, "Could not allocate stream\n");
        exit(1);
    }
    st->id = oc->nb_streams-1;
    c = st->codec;
    

    參數設置完成后,就可以打開編碼器并為編碼器分配必要的內存。步驟跟之前的類似,以視頻為例,示例代碼如下:

    //open the codec
    ret = avcodec_open(c, codec, &opt);
    if(ret < 0){
        fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
        exit(1);
    }
    //allocate and init a re-usable frame
    ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
    

    接下來進行真正的封裝:首先,為媒體文件添加頭部信息, 為此提供的函數為r()。其次,將編碼好的音視頻 包添加到媒體文件中去, 為此提供的函數為()。最后,寫入文件尾的數據, 為此提供的函數為()。

    封裝的大致流程已經完成了,剩余的是一些收尾工作,比如釋放分配的內存、結構體等等。

    轉碼的實現 視頻縮放實現

    針對視頻的縮放, 提供了 庫,可以輕松實現視頻的分辨率轉換功能。除此之外, 庫還可以 實現顏色空間轉換的功能。

    中針對視頻的縮放提供了一個示例代碼,位于doc\\.c中。分析該程序的流程大致分為如下幾部分:

    解析命令行參數,獲取縮放的視頻寬高,視頻文件名。創建結構體。分配源圖像和目標圖像的內存。將源圖像進行轉換為目標圖像的大小。將縮放的圖像寫到輸出文件中。收尾工作,釋放分配的內存,關閉打開的文件。

    首先解析期望的視頻寬高,示例代碼中使用的是函數,該函數的聲明如下:

    int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str);
    

    解析 str,并將解析出來的寬高信息賦值給 , ;其中:

    之后,創建結構體,示例代碼中使用的是函數,該函數聲明如下:

    struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                                      int dstW, int dstH, enum AVPixelFormat dstFormat,
                                      int flags, SwsFilter *srcFilter,
                                      SwsFilter *dstFilter, const double *param);
    

    該函數的作用是分配并返回一個結構,后面如果需要實現縮放/轉換操作時,需要使用函數。其中:

    編譯時用make 后生成 可執行文件。命令行如下:

    $ /scaling_video 001_bit_rv8_64P_352x288.yuv hd1080
    

    注意,輸入時 YUV 數據,輸出時 RGB 數據,會根據后面的 size 生成不同分辨率的數據。

    //RTMP/NDK/音視頻流媒體高級開發 學習資料、教學視頻和學習路線圖

    有需要的可以自行添加學習交流群

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有