音频播放器—显示封面

------------------------------------全系列文章目录------------------------------------

大致操作流程如下

在这里插入图片描述

检测歌曲文件是否存在封面
  • AVStream结构体中的disposition参数,但该参数为AV_DISPOSITION_ATTACHED_PIC标志位时,表明存在封面图片。

  • ffmpeg中对disposition参数的部分解释:

    demuxing: set by libavformat when creating the stream or in avformat_find_stream_info().

  • ffmpeg中对AV_DISPOSITION_ATTACHED_PIC标志位解释如下

    The stream is stored in the file as an attached picture/“cover art” (e.g.APIC frame in ID3v2).The first (usually only) packet associated with it will be returned among the first few packets read from the file unless seeking takes place. It can also be accessed at any time in AVStream.attached_pic.

  • 因此当我们通过video stream的disposition参数判断是否有封面图片,然后从AVStream.attached_pic中去获取该封面图片。

封面图片解码操作
  • 从上文可知我们需要对AVStream.attached_pic数据包进行解码操作,需要注意的是若封面文件格式为png,则因为png数据格式原因,需要进行多次解码操作。

在这里插入图片描述

图片格式转换
  • 在创建纹理时需要指定输入数据的像素格式,同时该像素格式应为渲染器所支持。

  • 当封面图片的像素格式不符合预期时,需要将其转换为创建纹理时指定的像素格式,转换操作依赖于SwsContext结构体。该结构体用于对图像数据进行处理,如裁切、放大以及格式转换等。

  • 对于封面图片的像素格式可以从对应编码器结构体AVCodecContext的pix_fmt获取。

    /*创建纹理*/
    SDL_CreateTexture(pRender, SDL_PIXELFORMAT_IYUV, 
                      			SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);
    /*创建SwsContext*/
    sws_getContext(src_w, src_h, codec_ctx->pix_fmt,
    							src_w, src_h, out_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
    /*对原数据进行格式转换和裁切处理*/
    sws_scale(img_convert_ctx, pf->data, pf->linesize, 0, src_h, pf_YUV->data, pf_YUV->linesize);
    
调整封面图片大小
  • 封面图片大小的调整依赖于SDL事件,通过捕获SDL_WINDOWEVENT事件(当窗口变化时触发);在该事件中提取SDL_WINDOWEVENT_SIZE_CHANGED事件类型(窗口大小发生变化时触发),获取当前的窗口大小,更新渲染输出窗口的大小;最后用原图像数据再次进行一次渲染操作。

        SDL_PumpEvents();
    	while (1) {
    		while (!SDL_PeepEvents(&_event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
    			SDL_PumpEvents();
    		}
    		switch (_event.type) {
    		case SDL_WINDOWEVENT:
    			switch (_event.window.event) {
    			case SDL_WINDOWEVENT_SIZE_CHANGED:
    				SDL_LockMutex(vc->dis.mutex);
    				vc->dis.set_screen_wh(_event.window.data1, _event.window.data2);
    				vc->dis.set_out_ret_wh();
    				SDL_UnlockMutex(vc->dis.mutex);
    				vc->dis.display_frame(vc->deal.pf_YUV);
    				break;
    			default:
    				break;
    			}
    			break;
    		default:
    			break;
    		}
    	}
    
    /*显示一帧图像*/
    void display::display_frame(AVFrame  *pF)
    {
    	SDL_LockMutex(mutex);
    
    	SDL_UpdateTexture(pTexture, NULL, pF->data[0], pF->linesize[0]);		//更新整个纹理图像
    	SDL_RenderClear(pRender);												//清除渲染目标,接收下一帧
    	SDL_RenderCopy(pRender, pTexture, NULL, &out_ret);						//复制纹理图像至渲染器,选择整个纹理作为输入,选择渲染目标某块区域作为输出
    	SDL_RenderPresent(pRender);												//使用渲染结果更新屏幕
    
    	SDL_UnlockMutex(mutex);
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值