// 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 }
static void I420_RGBA (filter_t *filter, picture_t *src, picture_t *dst) { struct yuv_pack out = { dst->p->p_pixels, dst->p->i_pitch }; struct yuv_planes in = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS, src->Y_PITCH }; i420_rgb_neon (&out, &in, filter->fmt_in.video.i_width, filter->fmt_in.video.i_height); }