- int OpenAVFile(const char* szFileName)
- {
- char errbuf[256] = { 0 };
- int iRes = 0;
- int vindex = -1;
- AVFormatContext* pFmtCtx = NULL;
- AVCodecContext* vCodecCtx = NULL;
- AVCodec* vCodec = NULL;
- AVPacket* pkt = NULL;
- AVFrame* pfe = NULL;
- AVFrame* YUV = NULL;
- uint8_t* buf = NULL;
- struct SwsContext* img_ctx = NULL;
- SDL_Window* window = NULL;
- SDL_Renderer* renderer = NULL;
- SDL_Texture* texture = NULL;
- SDL_Rect rect= { 0 };
- av_register_all();
- if(SDL_Init(SDL_INIT_VIDEO) != 0)
- return ERROR_INIT;
- pFmtCtx = avformat_alloc_context();
- if ((iRes = avformat_open_input(&pFmtCtx, szFileName, NULL, NULL)) != 0)
- return ERROR_OPEN;
- if (avformat_find_stream_info(pFmtCtx, NULL) streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
- vindex = i;
- }
- if (vindex == -1)
- return ERROR_FIND;
- vCodecCtx = avcodec_alloc_context3(NULL);
- if(avcodec_parameters_to_context(vCodecCtx, pFmtCtx->streams[vindex]->codecpar) codec_id);
- if (!vCodec)
- return ERROR_FIND;
- if(avcodec_open2(vCodecCtx, vCodec, NULL) != 0)
- return ERROR_OPEN;
- window = SDL_CreateWindow("video", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 680, 540, SDL_WINDOW_OPENGL);
- renderer = SDL_CreateRenderer(window, -1, 0);
- texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, vCodecCtx->width, vCodecCtx->height);
- if (!window || !renderer || !texture)
- return ERROR_CREATE;
- rect.w = vCodecCtx->width;
- rect.h = vCodecCtx->height;
- img_ctx = sws_getContext(vCodecCtx->width, vCodecCtx->height, vCodecCtx->pix_fmt,
- vCodecCtx->width, vCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL,NULL);
- if (!img_ctx)
- return ERROR_GET;
- pkt = av_packet_alloc();
- pfe = av_frame_alloc();
- YUV = av_frame_alloc();
- buf = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, vCodecCtx->width, vCodecCtx->height,1));
- av_image_fill_arrays(YUV->data, YUV->linesize, buf, AV_PIX_FMT_YUV420P, vCodecCtx->width, vCodecCtx->height, 1);
- while (av_read_frame(pFmtCtx, pkt) >= 0)
- {
- if (pkt->stream_index == vindex)
- {
- if ((iRes = avcodec_send_packet(vCodecCtx, pkt)) != 0)
- av_strerror(iRes, errbuf, 256);//return -5;
- if ((iRes= avcodec_receive_frame(vCodecCtx, pfe)) != 0)
- av_strerror(iRes, errbuf, 256); //return -6;
- sws_scale(img_ctx, pfe->data, pfe->linesize, 0, vCodecCtx->height, YUV->data, YUV->linesize);
- SDL_UpdateTexture(texture, &rect, YUV->data[0], YUV->linesize[0]);
- SDL_RenderClear(renderer);
- SDL_RenderCopy(renderer, texture, NULL, NULL);
- SDL_RenderPresent(renderer);
- }
- }
- av_free(buf);
- av_frame_free(&YUV);
- av_frame_free(&pfe);
- av_packet_free(&pkt);
- sws_freeContext(img_ctx);
- SDL_DestroyTexture(texture);
- SDL_DestroyRenderer(renderer);
- SDL_DestroyWindow(window);
- SDL_Quit();
- avcodec_free_context(&vCodecCtx);
- avformat_close_input(&pFmtCtx);
- avformat_free_context(pFmtCtx);
- return 0;
- }
[cpp] view plain copy
- uint8_t* g_buf = NULL;
- int g_MaxLen = 0;
- int g_CurPos = 0;
- void aCallback(void *userdata, Uint8 * stream, int len)
- {
- SDL_memset(stream, 0, len);//important
- SDL_MixAudio(stream, g_buf, len, SDL_MIX_MAXVOLUME);//memcpy(stream, g_buf, len);
- g_CurPos += len;
- g_MaxLen -= len;
- }
- int OpenAVFile(const char* szFileName)
- {
- char errbuf[256] = { 0 };
- int iRes = 0;
- int aindex = -1;
- AVFormatContext* pFmtCtx = NULL;
- AVCodecContext* aCodecCtx = NULL;
- AVCodec* aCodec = NULL;
- AVPacket* pkt = NULL;
- AVFrame* pfe = NULL;
- uint8_t* buf = NULL;
- struct SwrContext* audio_ctx = NULL;
- SDL_AudioSpec want = { 0 };
- SDL_AudioSpec recv = { 0 };
- av_register_all();
- if (SDL_Init(SDL_INIT_AUDIO) != 0)
- return ERROR_INIT;
- pFmtCtx = avformat_alloc_context();
- if ((iRes = avformat_open_input(&pFmtCtx, szFileName, NULL, NULL)) != 0)
- return ERROR_OPEN;
- if (avformat_find_stream_info(pFmtCtx, NULL) streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
- aindex = i;
- }
- if (aindex == -1)
- return ERROR_FIND;
- aCodecCtx = avcodec_alloc_context3(NULL);
- if (avcodec_parameters_to_context(aCodecCtx, pFmtCtx->streams[aindex]->codecpar) codec_id);
- if (!aCodec)
- return ERROR_FIND;
- if (avcodec_open2(aCodecCtx, aCodec, NULL) != 0)
- return ERROR_OPEN;
- want.callback = aCallback;
- //want.channels = 1;//设为单声道就不用装换pannel了
- want.channels = aCodecCtx->channels;
- want.format = AUDIO_S16SYS;//ffmpeg的fmt与SDL的不一样,但是可以自己计算转换
- want.freq = aCodecCtx->sample_rate;
- want.samples = aCodecCtx->frame_size;
- want.silence = 0;
- want.userdata = aCodecCtx;
- SDL_OpenAudio(&want, &recv);
- //audio_ctx = swr_alloc();
- audio_ctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(recv.channels), AV_SAMPLE_FMT_S16, recv.freq,
- av_get_default_channel_layout(aCodecCtx->channels), aCodecCtx->sample_fmt, aCodecCtx->sample_rate, 0, NULL);
- swr_init(audio_ctx);//必须要
- pkt = av_packet_alloc();
- pfe = av_frame_alloc();
- g_buf = (uint8_t*)av_malloc(av_samples_get_buffer_size(NULL, recv.channels, recv.samples, AV_SAMPLE_FMT_S16, 1));
- while (av_read_frame(pFmtCtx, pkt) >= 0)
- {
- if (pkt->stream_index == aindex)
- {
- if ((iRes = avcodec_send_packet(aCodecCtx, pkt)) != 0)
- av_strerror(iRes, errbuf, 256);//return -5;
- if ((iRes = avcodec_receive_frame(aCodecCtx, pfe)) != 0)
- av_strerror(iRes, errbuf, 256); //return -6;
- //单声道
- //memset(g_buf, 0, 10240);
- //memcpy(g_buf, pfe->data[0], pfe->linesize[0]);
- //g_CurPos = 0;
- //g_MaxLen = pfe->linesize[0];
- swr_convert(audio_ctx, &g_buf, av_samples_get_buffer_size(NULL, recv.channels, recv.samples, AV_SAMPLE_FMT_S16, 1),
- (const uint8_t **)pfe->data, pfe->nb_samples);
- g_CurPos = 0;
- g_MaxLen = av_samples_get_buffer_size(NULL, recv.channels, recv.samples, AV_SAMPLE_FMT_S16, 1);
- SDL_PauseAudio(0);
- while (g_MaxLen > 0)
- SDL_Delay(1);
- }
- }
- av_free(buf);
- av_frame_free(&pfe);
- av_packet_free(&pkt);
- swr_free(&audio_ctx);
- SDL_Quit();
- avcodec_free_context(&aCodecCtx);
- avformat_close_input(&pFmtCtx);
- avformat_free_context(pFmtCtx);
- return 0;
- }
视频的重要处理: sws_getContext,获得转换上下文
av_image_get_buffer_size,获得(转换后)图片大小
av_image_fill_arrays,将自定义内存块绑定到输出的AVFrame中
sws_scale,转换
音频的重要处理:
av_get_default_channel_layout,根据声道数获取默认的声道布局
swr_alloc_set_opts,获取转换上下文
swr_init,获取到上下文后必须初始化
av_samples_get_buffer_size,计算(参数格式的)音频数据的大小
swr_convert,转换
对于音频的相关参数,FFmpeg和SDL中的channels,sample_rate...等等这些"数值"都是可以直接互相赋值的。但是format,FFmpeg和SDL就各自有自己的定义。
下面是我自己做的由AVSampleFormat转SDL_AudioFormat的函数
[cpp] view plain copy
- /*{
- AV_SAMPLE_FMT_NONE = -1,
- AV_SAMPLE_FMT_U8, ///
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?