这几天重新看了一下播放器的源码,对里边的一些知识又有了一些重新的认识。由于都是一些琐碎的知识点,不好放在其它的文章里,所以只能写这样一篇文章将它们记录下来。
平常的时候我们很少使用图像缩放。但对于播放器来说,在窗口指定的情况下,很可能与最终要显示的YUV的宽高不一致。为了达到更好的效果,一般都需要对视频进行缩放操作。下面就是使用 ffmpeg进行缩放的方法。
注:ffmpeg的 swscale 模块的效率不高,建议尽量使用libyuv进行图像的缩放。
sws_getCachedContext(*img_convert_ctx,
frame->width, frame->height, frame->format, frame->width, frame->height,
AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
或
sws_getContext(*img_convert_ctx,
frame->width, frame->height, frame->format, frame->width, frame->height,
AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
sws_flags 可以选用下面的参数:
uint8_t *pixels[4];
int pitch[4];
sws_scale(*sws_convert_ctx, (const uint8_t * const *)frame->data,
frame->linesize, 0, frame->height, pixels, pitch);
下面几个 SDL 的API之前没有用过,但今天看代码时发现这几个API非常有用,所以在这里记录一下,以便后面使用时便于查阅。
his function to update a rectangle within a planar YV12 or IYUV texture with new pixel data.
int SDL_UpdateYUVTexture(SDL_Texture* texture,
const SDL_Rect* rect,
const Uint8* Yplane, //Y分量
int Ypitch, //Y分量每行宽度
const Uint8* Uplane, //U分量
int Upitch, //U分量每行宽度
const Uint8* Vplane, //V分量
int Vpitch //V分量每行宽度
)
例子:
ret = SDL_UpdateYUVTexture(tex, NULL,
frame->data[0], frame->linesize[0],
frame->data[1], frame->linesize[1],
frame->data[2], frame->linesize[2]);
this function to lock a portion of the texture for write-only pixel access.
int SDL_LockTexture(SDL_Texture* texture,
const SDL_Rect* rect,
void** pixels,
int* pitch)
例子
uint8_t *pixels[4];
int pitch[4];
SDL_LockTexture(tex, NULL, (void **)pixels, pitch);
this function to unlock a texture, uploading the changes to video memory
在一些媒体文件中使用的音频数据格式是 FLTP格式,也就是 float格式。之前没有仔细研究过,以为都是用16位大小,这两天才搞明白原来是32位大小。
而使用SDL将音频在送往硬件设备时,一般都使用的是 16位大小的数据。这样数据不一致就导致音频在播放时出现了问题。所以最好的解决办法是将 FLTP 格式转换成 S16格式。这就要用到音频的数据转换了。
struct SwrContext swr_alloc_set_opts(struct SwrContext *s,
int64_t out_ch_layout,
enum AVSampleFormat out_sample_fmt,
int out_sample_rate,
int64_t in_ch_layout,
enum AVSampleFormat in_sample_fmt,
int in_sample_rate,
int log_offset,
void *log_ctx) ;
例子
swr_alloc_set_opts(NULL,
is->audio_tgt.channel_layout,
is->audio_tgt.fmt, is->audio_tgt.freq,
dec_channel_layout,
af->frame->format,
af->frame->sample_rate,
0, NULL);
int swr_init (struct SwrContext *s)
int swr_convert (struct SwrContext *s,
uint8_t *out_arg[SWR_CH_MAX],
int out_count,
const uint8_t *in_arg[SWR_CH_MAX],
int in_count) ;
例子
int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
知识是不断积累的。在工作和学习的过程中,不断的完善自己的识识图谱,并分享给大家既可以使自己记得更牢固,又可以与大家交流,想来也是一件很美的事儿。