編輯:關於Android編程
之前項目裡面需要解碼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數據
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
5、使用方法:
[cpp] v
if(first == 0){
int numBytes = avpicture_get_size(PIX_FMT_RGB565, codec_ctx->width, codec_ctx->height);
uint8_t *fill_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill(&frame_rgb, fill_buffer, PIX_FMT_RGB565, codec_ctx->width, codec_ctx->height);
first = 1;
}
yuv420_2_rgb565(frame_rgb.data[0], frame->data[0], frame->data[1],frame->data[2], codec_ctx->width, codec_ctx->height, frame->linesize[0],
frame->linesize[1], codec_ctx->width << 1, yuv2rgb565_table,3);
if(first == 0){
int numBytes = avpicture_get_size(PIX_FMT_RGB565, codec_ctx->width, codec_ctx->height);
uint8_t *fill_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill(&frame_rgb, fill_buffer, PIX_FMT_RGB565, codec_ctx->width, codec_ctx->height);
first = 1;
}
yuv420_2_rgb565(frame_rgb.data[0], frame->data[0], frame->data[1],frame->data[2], codec_ctx->width, codec_ctx->height, frame->linesize[0],
frame->linesize[1], codec_ctx->width << 1, yuv2rgb565_table,3);
6、如果從java傳進數組指針,然後從c傳出方法(jbyteArray output):
[cpp]
uint8_t *buffer = (uint8_t *)(*env)->GetByteArrayElements(env, output, JNI_FALSE);
memcpy(buffer, frame_rgb.data[0], codec_ctx->width * codec_ctx->height * 2);
(*env)->ReleaseByteArrayElements(env, output, (jbyte *)buffer, 0);
uint8_t *buffer = (uint8_t *)(*env)->GetByteArrayElements(env, output, JNI_FALSE);
memcpy(buffer, frame_rgb.data[0], codec_ctx->width * codec_ctx->height * 2);
(*env)->ReleaseByteArrayElements(env, output, (jbyte *)buffer, 0);
7、如上步驟就可以將yuv420數據轉換為rgb565數據,並且從c傳遞給java層。
專業的Android app開發人員會關注一些成熟的項目管理技術,以成功構建Android app,並讓這個app在Google Play Store嶄露頭角。考慮高端客
前言在一些APP中我們可以看到一些存放標簽的容器控件,和我們平時使用的一些布局方式有些不同,它們一般都可以自動適應屏幕的寬度進行布局,根據對自定義控件的一些理解,今天寫一
首先,很榮幸此專欄能被CSDN推薦到主頁。榮幸的同時,也激勵自己會把這個專欄一直更新下去。進入今天的主題:我們在qq登錄的時候,會有一個下拉的按鈕,來查看歷史登錄賬號。這
有時候,我們的微信會收到一些不認識的人發的廣告,甚至是一些微商的詐騙信息,特別一些微信群上,時不時就會遇到一些做垃圾廣告或者不法分子詐騙的,或者不小心就被加