我遵循了这个示例http://nezarobot.blogspot.com/2016/03/android-surfacetexture-camera2-opencv.html,以便在将帧发送到预览之前对其进行处理。
这是通过将Image
和Surface
发送到完成处理的本机函数来完成的。
我还成功使用openCV
和VideoWriter
将图像流写入了视频。
很不幸,唯一的格式是.avi
,我想拥有.mp4
。而且,我还希望在创建的视频中有音频。
我有用于处理和写入视频的以下代码:
extern "C"
JNIEXPORT void JNICALL
Java_com_erikbylow_mycamera3_JNIUtils_drawCircle(
JNIEnv *env, jobject type, jint srcWidth, jint srcHeight, jobject srcBuf, jobject dstSurface,
jstring path_, jint saveFile) {
uint8_t *srcLumaPtr = reinterpret_cast<uint8_t *>(env->GetDirectBufferAddress(srcBuf));
if (srcLumaPtr == nullptr){
LOGE("blit NULL pointer Error");
}
int dstWidth;
int dstHeight;
cv::Mat mYuv(srcHeight + srcHeight / 2, srcWidth, CV_8UC1, srcLumaPtr);
uint8_t*srcChromaUVInterleavedptr = nullptr;
bool swapDstUV;
ANativeWindow *win = ANativeWindow_fromSurface(env, dstSurface);
ANativeWindow_Buffer buf;
dstWidth = srcHeight;
dstHeight = srcWidth;
ANativeWindow_setBuffersGeometry(win, dstWidth, dstHeight, 0);
if (int32_t err = ANativeWindow_lock(win, &buf, NULL)){
LOGE("ANativeWindow_lock failed with error code %d\n", err);
ANativeWindow_release(win);
}
uint8_t *dstLumaPtr = reinterpret_cast<uint8_t*>(buf.bits);
cv::Mat dstRgba(dstHeight, buf.stride, CV_8UC4, dstLumaPtr);
cv::Mat srcRgba(srcHeight, srcWidth, CV_8UC4);
cv::Mat flipRgba(dstHeight, dstWidth, CV_8UC4);
// Convert YUV to RGBA
cv::cvtColor(mYuv, srcRgba, CV_YUV2RGBA_NV21);
// Rotate 90 degree
// cv::transpose(srcRgba, flipRgba);
cv::flip(srcRgba, flipRgba, 1);
cv::flip(flipRgba, flipRgba, 0);
// flipRgba = srcRgba;
// LaneDetect(flipRgba, str, savefile, outStr);
// Copy to TextureView surface
uchar *dbuf;
uchar *sbuf;
dbuf = dstRgba.data;
sbuf = flipRgba.data;
LOGE("buf.height: %d", buf.height);
LOGE("buf.width: %d", buf.width);
LOGE("buf.stride: %d", buf.stride);
LOGE("flipRgba.cols %d", flipRgba.cols);
for (int i = 0; i < flipRgba.rows; i++){
dbuf = dstRgba.data + i * buf.stride*4;
memcpy(dbuf, sbuf, buf.stride*4); // Is this one row at a time?
sbuf += flipRgba.cols * 4;
}
cv::Point p1(100,100);
int radius = 10;
cv::circle(flipRgba, p1, radius, cv::Scalar(255,255,255), CV_FILLED);
cv::circle(dstRgba, p1, radius, cv::Scalar(255,255,255), CV_FILLED);
mWriter.write(flipRgba);
ANativeWindow_unlockAndPost(win);
ANativeWindow_release(win);
}
最好的方法是什么?要ffmpeg
还是Android拥有MediaCodec
?我已经将这些帧作为Mat
文件使用,因此如果可以继续进行下去,那就太好了。包括音频。