![](/img/trans.png)
[英]DJI mavic pro : Receiving corrupted video when using remote controller
[英]DJI mobile SDK Mavic 2 Pro - Live Stream 4k
我是stackoverflow的新手,希望你们中的某个人能帮助我。
我用 DJI 移动 SDK 开发了一个应用程序,并实现了一个实时 stream。 问题是直播stream的分辨率不是4k,我需要4k。 我认为无人机为实时预览提供了辅助 stream。 是否可以将辅助 stream 更改为具有 4k 分辨率的主 stream? 如果有可能,我该怎么做? 或者是否可以简单地提高实时 stream / 二级 stream 的分辨率?
这是我当前的实现:
直播 stream 预览的表面纹理元素的初始化:
SurfaceTextureListener surfaceTextureListener = new SurfaceTextureListener(getApplicationContext());
this.videoStreamPreviewTtView.setSurfaceTextureListener(surfaceTextureListener);
这是我的听众:
public class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
private final Context context;
public SurfaceTextureListener(Context context) {
this.context = context;
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if (DroneControl.getCodecManager() == null) {
DroneControl.setCodecManager(new DJICodecManager(this.context, surface, width, height));
DroneControl.getCodecManager().resetKeyFrame();
DroneControl.getCodecManager().enabledYuvData(true);
DroneControl.getCodecManager().setYuvDataCallback(new LiveStreamDataCallback(this.context));
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if (DroneControl.getCodecManager() != null) {
DroneControl.getCodecManager().cleanSurface();
DroneControl.setCodecManager(null);
}
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}
这是我的回调 function:
public class LiveStreamDataCallback implements Base, DJICodecManager.YuvDataCallback {
private final Context context;
private final long lastUpdate;
public LiveStreamDataCallback(Context context) {
this.context = context;
this.lastUpdate = System.currentTimeMillis();
}
@Override
public void onYuvDataReceived(MediaFormat format, final ByteBuffer yuvFrame, int dataSize, final int width, final int height) {
long differenceInMillis = System.currentTimeMillis() - this.lastUpdate;
if (differenceInMillis > SCREEN_SHOT_PERIOD && yuvFrame != null) {
final byte[] bytes = new byte[dataSize];
yuvFrame.get(bytes);
newSaveYuvDataToJPEG(bytes, width, height);
}
}
private void newSaveYuvDataToJPEG(byte[] yuvFrame, int width, int height) {
if (yuvFrame.length < width * height) {
return;
}
int length = width * height;
byte[] u = new byte[width * height / 4];
byte[] v = new byte[width * height / 4];
for (int i = 0; i < u.length; i++) {
u[i] = yuvFrame[length + i];
v[i] = yuvFrame[length + u.length + i];
}
for (int i = 0; i < u.length; i++) {
yuvFrame[length + 2 * i] = v[i];
yuvFrame[length + 2 * i + 1] = u[i];
}
screenShot(yuvFrame, width, height);
}
private void screenShot(byte[] buf, int width, int height) {
ByteArrayOutputStream bOutput = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(buf,
ImageFormat.NV21,
width,
height,
null);
yuvImage.compressToJpeg(new Rect(0,
0,
width,
height), 100, bOutput);
insertIntoDB(Base64.getEncoder().encodeToString(bOutput.toByteArray()));
}
private void insertIntoDB(String base64EncodedContent) {
//only a limit of images will be saved inside the DB to avoid using too much space!
DatabaseUtil.reduceTableContentToMaxContentIfNecessary(this.context, ScreenShotModel.ScreenShotEntry.TABLE_NAME, MAX_KEEP_COUNT_FOR_LIVE_STREAM_SCREEN_SHOTS);
Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_FOR_LOGGING, Locale.GERMANY);
SQLiteDatabase db = DroneControl.getDbWriteAccess(this.context);
//create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(ScreenShotModel.ScreenShotEntry.COLUMN_NAME_DATA, base64EncodedContent);
values.put(ScreenShotModel.ScreenShotEntry.COLUMN_NAME_CREATED, dateFormat.format(now));
db.insert(ScreenShotModel.ScreenShotEntry.TABLE_NAME, null, values);
}
}
希望有人能解决我的问题。
非常感谢!
此致
做不到。 1080p 是最大的,ocusync 不能做得比这更高。 带宽不够高,无人机硬件不支持。
我不知道怎么做你要求的。 您唯一可以做的就是拍摄静止图像并下载它,但它当然会很慢,但可以用于图像识别等。 您没有说您将使用它来做什么,但由于您似乎正在查看框架,这可能是一个(缓慢的)解决方案。
来自 DJI web:OcuSync 作为 Lightbridge 系列的一部分,DJI 新开发的 OcuSync 传输系统在所有传输速度下的性能都远优于 Wi-Fi 传输。 OcuSync 还使用更有效的数字压缩和通道传输技术,即使在无线电干扰强烈的环境中也能可靠地传输高清视频。 与传统的模拟传输相比, OcuSync 可以传输 720p 和 1080p 的视频- 相当于提高 4-10 倍的质量,没有色偏、static 干扰、闪烁或其他与模拟传输相关的问题。 即使使用相同数量的无线电传输功率,OcuSync 在 4.1 英里(7 公里)处比模拟传输更远
非常感谢您的回答和帮助!
实际上,我尝试先捕获 4k 图像并进行传输。 正如你已经说过的,我尝试使用框架进行 object 检测,我需要我能获得的最佳性能。 捕获图像并传输它非常耗时。 我需要大约 1.5 秒来捕获和保存图像,再需要 3 秒来传输它,对我来说最大的惊喜是读取 SD 卡以找到最新图像需要将近 11 秒(我尝试了最大 class 10 的不同 SD 卡)。 总之,一张图像的整个过程需要 15.5 秒,这对我的目的来说太长了……
然后我想我可以用现场 stream 做到这一点。 实时 stream 的整个过程需要 500 毫秒,这对于我的项目来说是可以接受的值。 很是发人深省,这似乎是不可能的……
也许还有另一个机会可以非常快速地从无人机传输图像?
我从现场 stream 中得到了剧照,但以另一种方式。 我使用 fpv-widget(现场 stream 显示在设备上),并直接从小部件中读取 bmp。 这样就不用在java中处理这么多数据了。
我什至从 python 开始执行此操作,并且由于一些怪癖,我将其放入 opencv2 中而无需任何编组。 可以在 python 中读取 100 帧/秒,因此 java 应该至少那么快。 你可能会重新考虑你的做法。 尽量避免重新打包图像数据。 它仍然只有1080,但我必须说它的质量非常好。
<dji.ux.widget.FPVWidget
android:id="@+id/fpv_widget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
custom:sourceCameraNameVisibility="true" />
public Bitmap getFrameBitmap() {
fpvWidget = findViewById(R.id.fpv_widget);
return fpvWidget.getBitmap();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.