int cap_image_convert(int width, int height, enum AVPixelFormat dst_format, uint8_t **dst_data, int *dst_linesize, enum AVPixelFormat src_format, const uint8_t **src_data, const int *src_linesize) { #if defined(__ANDROID__) switch (src_format) { case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUVJ420P: // FIXME: 9 not equal to AV_PIX_FMT_YUV420P, but a workaround switch (dst_format) { case AV_PIX_FMT_RGB565: return I420ToRGB565( src_data[0], src_linesize[0], src_data[1], src_linesize[1], src_data[2], src_linesize[2], dst_data[0], dst_linesize[0], width, height); case AV_PIX_FMT_0BGR32: return I420ToABGR( src_data[0], src_linesize[0], src_data[1], src_linesize[1], src_data[2], src_linesize[2], dst_data[0], dst_linesize[0], width, height); default: break; } break; default: break; } #endif return -1; }
// for android neon accelerate status_t FFRender::render_neon(AVFrame* frame) { #if !defined(__ANDROID__) || defined(__i386__) || defined(__x86_64__) return ERROR; #else void* surfacePixels = NULL; if (Surface_getPixels(mNativeWindow, &mSurfaceWidth, &mSurfaceHeight, &mSurfaceStride, &surfacePixels) != OK) return ERROR; int64_t begin_scale = getNowMs(); //Convert format switch(mFrameFormat) { case AV_PIX_FMT_YUV420P: { if (mDoOnce) { LOGI("frame->data: %p, %p, %p", frame->data[0], frame->data[1], frame->data[2]); //((((int32_t)frame->data[0])+0x20)&0xffffffe0) LOGI("frame->linesize: %d,%d,%d", frame->linesize[0], frame->linesize[1], frame->linesize[2]); LOGI("frame->width: %d, frame->height: %d", frame->width, frame->height); LOGI("mSurface width %d, height %d, stride %d", mSurfaceWidth, mSurfaceHeight, mSurfaceStride); mDoOnce = false; } // 2015.4.24 guoliangma modify mSurfaceStride to mSurfaceWidth // fix crash when play some small res clip then play big res clip if ((int)mSurfaceWidth >= frame->width && (int)mSurfaceHeight >= frame->height) { #ifdef __arm__ #ifdef RENDER_RGB565 /*yuv420_2_rgb565((uint8_t *)surfacePixels, frame->data[0], frame->data[1], frame->data[2], frame->width, frame->height, // picture width and height frame->linesize[0], //Y span/pitch frame->linesize[1], //UV span/pitch //frame->linesize[1] mSurfaceStride<<1, //bitmap span/pitch yuv2rgb565_table, 0);*/ ConvertYCbCrToRGB565( frame->data[0], frame->data[1], frame->data[2], (uint8_t*)surfacePixels, frame->width, frame->height, // picture width and height frame->linesize[0], //Y span/pitch frame->linesize[1], //UV span/pitch //frame->linesize[1] mSurfaceStride<<1, //bitmap span/pitch 420); #else struct yuv_pack out = {surfacePixels, (int32_t)mSurfaceStride * 4}; struct yuv_planes in = {frame->data[0], frame->data[1], frame->data[2], frame->linesize[0]}; i420_rgb_neon(&out, &in, frame->width, frame->height); #endif // end of RENDER_RGB565 #else // __aarch64__ I420ToABGR(frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2], (uint8_t *)surfacePixels, mSurfaceStride * 4, frame->width, frame->height); #endif // end of __arm__ } else { LOGW("surface memory is too small: surf_w %d, surf_h %d, surf_stride %d, frame_w %d, frame_h %d", mSurfaceWidth, mSurfaceHeight, mSurfaceStride, frame->width, frame->height); } break; } #ifdef __arm__ // only supported in armeabi case AV_PIX_FMT_NV12: { struct yuv_pack out = {surfacePixels, (int32_t)mSurfaceStride * 4}; struct yuv_planes in = {frame->data[0], frame->data[1], frame->data[2], frame->linesize[0]}; nv12_rgb_neon (&out, &in, frame->width, frame->height); break; } case AV_PIX_FMT_NV21: { struct yuv_pack out = {surfacePixels, (int32_t)mSurfaceStride * 4}; struct yuv_planes in = {frame->data[0], frame->data[1], frame->data[2], frame->linesize[0]}; nv21_rgb_neon (&out, &in, frame->width, frame->height); break; } #endif default: LOGE("Video output format:%d does not support", mFrameFormat); return ERROR; } LOGD("before rendering frame"); if(Surface_updateSurface(mNativeWindow) != OK) { LOGE("Failed to render picture"); return ERROR; } LOGD("after rendering frame"); int64_t end_scale = getNowMs(); int64_t costTime = end_scale - begin_scale; if(mAveScaleTimeMs == 0) { mAveScaleTimeMs = costTime; } else { mAveScaleTimeMs = (mAveScaleTimeMs*4+costTime)/5; } LOGD("neon scale picture cost %lld[ms]", costTime); LOGV("mAveScaleTimeMs %lld[ms]", mAveScaleTimeMs); //For debug /* char path[1024] = {0}; static int num=0; num++; sprintf(path, "/mnt/sdcard/frame_rgb_%d", num); LOGD("mSurfaceFrame->linesize[0]:%d, mOptiSurfaceHeight:%d", mSurfaceFrame->linesize[0], mOptiSurfaceHeight); saveFrameRGB(mSurfaceFrame->data[0], mSurfaceFrame->linesize[0], mOptiSurfaceHeight, path); */ return OK; #endif }
void decodeRGBX(struct Theoraplayer_PixelTransform* t) { I420ToABGR(t->y, t->yStride, t->u, t->uStride, t->v, t->vStride, t->out, t->w * 4, t->w, t->h); }
void decodeRGBA(struct Theoraplayer_PixelTransform* t) { I420ToABGR(t->y, t->yStride, t->u, t->uStride, t->v, t->vStride, t->out, t->w * 4, t->w, t->h); _decodeAlpha(incOut(t, 3), t->w * 4); }