android yuv2rgb方案
之前项目里面需要解码h264视频,使用的是ffmpeg,解码出来的是yuv,最好的显示方法是通过opengl es 2.0来实现视频的显示,如果不会opengl es 2.0的话,那么就必须将yuv2rgb然后在绘制图像,而yuv2rgb我只知道两种方法1.通过ffmpeg里面的sws_scale来实现,不过这种方法比较慢,2.这是我之前使用的方法在http://wss.co.uk/pinknoise/yuv2rgb/ 官网上有yuv2rgb的优化代码,里面有c实现和汇编实现两种,实现汇编这种方法yuv2rgb消耗10ms。
下面的rgb格式是PIX_FMT_RGB565
前提:拿到解码以后的AVFrame *frame,frame里面存放解码后的yuv数据。下面是需要用到的变量:
[cpp]
AVCodecContext *codec_ctx; uint8_t *fill_buffer; struct SwsContext *img_convert_ctx;
VFrame *frame_rgb;AVFrame *frame;
AVCodecContext *codec_ctx; uint8_t *fill_buffer; struct SwsContext *img_convert_ctx;
AVFrame *frame_rgb;AVFrame *frame;
方法一:
[cpp]
if(frame){
int numBytes = avpicture_get_size(PIX_FMT_RGB565, codec_ctx->width,codec_ctx->height);
fill_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *)frame_rgb, fill_buffer, PIX_FMT_RGB565,codec_ctx->width, codec_ctx->height);
img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
codec_ctx->width, codec_ctx->height, PIX_FMT_RGB565, SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(img_convert_ctx, frame->data, frame->linesize, 0, codec_ctx->height, frame_rgb->data, frame_rgb->linesize);
}
if(frame){
int numBytes = avpicture_get_size(PIX_FMT_RGB565, codec_ctx->width,codec_ctx->height);
fill_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *)frame_rgb, fill_buffer, PIX_FMT_RGB565,codec_ctx->width, codec_ctx->height);
img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
codec_ctx->width, codec_ctx->height, PIX_FMT_RGB565, SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(img_convert_ctx, frame->data, frame->linesize, 0, codec_ctx->height, frame_rgb->data, frame_rgb->linesize);
}方法二:
1、到官网
下载源码,最新的版本yuv2rgb003
2、解压文件,能够看到里面有如下的文件,包含了不同的格式互相转换,由于我这边是需要yuv420转换为rgb565,所以就使用yuv420rgb565.s这个文件:
[cpp]
root@zhangjie:/home/yuv2rgb# ls
COPYING yuv2rgbX.s yuv422rgb565c.c yuv444rgb565.s
out.yuv yuv420rgb565c.c yuv422rgb565.s yuv444rgb8888c.c
README yuv420rgb565.s yuv422rgb8888c.c yuv444rgb8888.s
test.c yuv420rgb8888c.c yuv422rgb8888.s yuv444rgb888c.c
yuv2rgb16tab.c yuv420rgb8888.s yuv422rgb888c.c yuv444rgb888.s
yuv2rgb555.s yuv420rgb888c.c yuv422rgb888.s
yuv2rgb.h yuv420rgb888.s yuv444rgb565c.c
root@zhangjie:/home/yuv2rgb# ls
COPYING yuv2rgbX.s yuv422rgb565c.c yuv444rgb565.s
out.yuv yuv420rgb565c.c yuv422rgb565.s yuv444rgb8888c.c
README yuv420rgb565.s yuv422rgb8888c.c yuv444rgb8888.s
test.c yuv420rgb8888c.c yuv422rgb8888.s yuv444rgb888c.c
yuv2rgb16tab.c yuv420rgb8888.s yuv422rgb888c.c yuv444rgb888.s
yuv2rgb555.s yuv420rgb888c.c yuv422rgb888.s
yuv2rgb.h yuv420rgb888.s yuv444rgb565c.c3、首先将yuv422rgb565.s,yuv2rgb.h,yuv2rgb16tab.c这三个文件拷贝到你们项目里面去
4、在解码.c文件中,添加"yuv2rgb.h","#include "yuv2rgb16tab.c""然后在文件里添加
[cpp]
extern const uint32_t yuv2rgb565_table[];
extern void yuv420_2_rgb565(uint8_t *dst_ptr, //存放rgb的指针
const uint8_t *y_ptr, //y数据
const uint8_t *u_ptr, //u数据
const uint8_t *v_ptr, //v数据
int32_t width, //视频的宽度
int32_t height, //视频的高度
int32_t y_span, //frame->linesize[0]
int32_t uv_span,//frame->linesize[1]
int32_t dst_span, //codec_ctx->width << 1
const uint32_t *tables, //之前声明的yuv2rgb565_table
int32_t dither); //dither可以有四个选择 0,1,2,3
extern const uint32_t yuv2rgb565_table[];
extern void yuv420_2_rgb565(uint8_t *dst_ptr, //存放rgb的指针
const uint8_t *y_ptr, //y数据
&
补充:移动开发 , Android ,