ffmpeg 接收h264+aac並解碼
阿新 • • 發佈:2019-02-07
ffmpeg一直更新所以執行時有些方法和庫對應不上,我用的是http://ffmpeg.zeranoe.com/builds/中:ffmpeg-20140305-git-d08bb06-win32-shared和ffmpeg-20140305-git-d08bb06-win32-dev;直接上程式碼了
#include "stdafx.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #ifdef __cplusplus extern "C"{ #include "libavformat\avformat.h" #include "libavcodec\avcodec.h" #include "libavutil\avutil.h" } #endif //__cplusplus #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 int _tmain(int argc, _TCHAR* argv[]) { const char* input = ""; AVInputFormat* pInForCtx = NULL; AVFormatContext* pFormatCtx = NULL; AVCodecContext *vpCodecCtx= NULL; AVCodecContext *apCodecCtx= NULL; AVCodec* video_codec = NULL; AVCodec* audio_codec = NULL; AVDictionary* pAVDictionary = NULL; AVFrame *pFrame = NULL; AVFrame *pFrameRGB = NULL; struct SwsContext *img_convert_ctx; int numBytes = 0; //uint8_t *buffer; int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100; uint8_t * inbuf = (uint8_t *)malloc(out_size); unsigned vframecount = 0; av_register_all(); avformat_network_init(); char szError[256] = {0}; CVCamSDKImpl* pVCam = NULL; pVCam = new CVCamSDKImpl(); //input可以是url int nRet = avformat_open_input(&pFormatCtx, input, pInForCtx, &pAVDictionary); if (nRet != 0) { av_strerror(nRet, szError, 256); printf(szError); printf("\n"); printf("Call avformat_open_input function failed!\n"); return 0; } if (av_find_stream_info(pFormatCtx) < 0) { printf("Call av_find_stream_info function failed!\n"); return 0; } int video_index = -1, audio_index = -1; for (unsigned int i = 0; i < pFormatCtx->nb_streams && (video_index < 0 || audio_index < 0); i++) { switch (pFormatCtx->streams[i]->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: video_index = i; pFormatCtx->streams[i]->discard = AVDISCARD_NONE; break; case AVMEDIA_TYPE_AUDIO: audio_index = i; pFormatCtx->streams[i]->discard = AVDISCARD_NONE; break; default: pFormatCtx->streams[i]->discard = AVDISCARD_ALL; break; } } //視訊解碼準備部分 if(video_index != -1){ vpCodecCtx = pFormatCtx->streams[video_index]->codec; video_codec = avcodec_find_decoder(vpCodecCtx->codec_id); if (video_codec == NULL) { printf("Call avcodec_find_decoder function failed!\n"); return 0; } if (avcodec_open2(vpCodecCtx, video_codec, &pAVDictionary) < 0) { printf("Call avcodec_open function failed !\n"); return 0; } pFrame= avcodec_alloc_frame(); pFrameRGB = avcodec_alloc_frame(); } if(audio_index != -1){ apCodecCtx = pFormatCtx->streams[audio_index]->codec; audio_codec = avcodec_find_decoder(apCodecCtx->codec_id); if (audio_codec == NULL) { printf("Call avcodec_find_decoder function failed!\n"); return 0; } if (avcodec_open2(apCodecCtx, audio_codec, &pAVDictionary) < 0) { printf("Call avcodec_open function failed !\n"); return 0; } } AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("h264_mp4toannexb"); if(bsfc == NULL) { return -1; } int decode_done = 0; int len = 0; uint8_t *buffer = NULL; do { double segment_time = 0; AVPacket packet; decode_done = av_read_frame(pFormatCtx, &packet);//Returns the next frame of a stream. if (decode_done < 0) break; if (av_dup_packet(&packet) < 0) { printf("Call av_dup_packet function failed\n"); av_free_packet(&packet); break; } if (packet.stream_index == video_index) { len = avcodec_decode_video2(vpCodecCtx, pFrame, &numBytes, &packet); if (numBytes != 0 ) { if(vframecount == 0) { numBytes=avpicture_get_size(PIX_FMT_RGB24, vpCodecCtx->width, vpCodecCtx->height); buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); // buffer = new uint8_t[numBytes]; avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24, vpCodecCtx->width, vpCodecCtx->height); img_convert_ctx = sws_getContext(vpCodecCtx->width, vpCodecCtx->height, vpCodecCtx->pix_fmt, vpCodecCtx->width, vpCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); if(img_convert_ctx == NULL) { } ++vframecount; } sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, vpCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); /*交換上下記憶體*/ for(;;){ int bytes_line = vpCodecCtx->width * 3; int rows = vpCodecCtx->height/2; int it=0; unsigned char* tmp = (unsigned char*)malloc(bytes_line); while(it<rows){ memcpy(tmp, pFrameRGB->data[0] + bytes_line*it, bytes_line); memcpy(pFrameRGB->data[0] + bytes_line*it, pFrameRGB->data[0] + (vpCodecCtx->height-1-it)*bytes_line, bytes_line); memcpy(pFrameRGB->data[0] + (vpCodecCtx->height-1-it)*bytes_line, tmp, bytes_line); it++; } free(tmp); break; } //然後就可以寫檔案或者用作其他 } }else if (packet.stream_index == audio_index)//音訊這塊我沒有測試,不知道有沒有問題,等測試了在更新 len = avcodec_decode_audio3(apCodecCtx, (short*)inbuf, &out_size, &packet); av_free_packet(&packet); }while(!decode_done); avcodec_free_frame(&pFrame); avcodec_free_frame(&pFrameRGB); av_bitstream_filter_close(bsfc); sws_freeContext(img_convert_ctx); if (pVCam != NULL) delete pVCam; free(inbuf); getchar(); return 0; }