无法始终从 Camera2Raw 示例程序获取原始文件的问题
Problem with not always getting the raw file from the Camera2Raw sample program
我在使用 AndroidStudio 附带的示例程序时遇到问题。我只在 S8 上试过这个,所以我不确定这是这个特定设备的问题还是通用的。
如果我尝试一次拍摄多张照片,通过将 mPendingUserCaptures 设置为 4 这样的数字,特别是如果我手动将曝光时间设置为较低的值(通常低于 30 毫秒左右),我总是得到 4 JPG 图像,但有时我只得到 3 个原始文件(最后一个丢失)。
问题出在 ImageSaver class,它并不总是为 RAW 文件调用,但总是为 JPG 文件调用。
我想知道,有没有人遇到过这样的情况,RAW 图像有时无法到达?
好的,在断断续续地寻找这个错误数周之后,我终于发现了发生了什么。
我在这里发布了解决方案,以防其他人偶然发现这个问题。
有时函数 public void onImageAvailable(ImageReader reader) { dequeueAndSaveImage(mRawResultQueue, mRawImageReader); } 会连续调用两次。
密码是:
Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry = pendingQueue.firstEntry();
ImageSaver.ImageSaverBuilder builder = entry.getValue();
这会产生一个大问题,因为有时两个图像会被添加到同一个 TreeMap 条目中,所以如果我们有 4 个条目,最后一个条目将永远不会得到它的图像:/
The fixed code (I left my extra logs there) looks like this:
private void dequeueAndSaveImage(TreeMap<Integer, ImageSaver.ImageSaverBuilder> pendingQueue, RefCountedAutoCloseable<ImageReader> reader) {
synchronized (mCameraStateLock) {
ImageSaver.ImageSaverBuilder builder=null;
Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry;
int key=4;//shut up, stupid java shit
for (Map.Entry<Integer, ImageSaver.ImageSaverBuilder> ent : pendingQueue.entrySet()) {
builder = ent.getValue();
if(builder.mImage==null) {
key = ent.getKey();
break;
}
}
//Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry = pendingQueue.firstEntry();
//ImageSaver.ImageSaverBuilder builder = entry.getValue();
Log.w(TAG, "StartingdequeueAndSaveImage, builder: " + builder);
if(builder.mImage!=null)
{
Log.w(TAG, "!!!!!!!!!!!!!!!!!!!!Builder: " + builder + " already has an image!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
// Increment reference count to prevent ImageReader from being closed while we
// are saving its Images in a background thread (otherwise their resources may
// be freed while we are writing to a file).
if (reader == null || reader.getAndRetain() == null) {
Log.e(TAG, "Paused the activity before we could save the image," + " ImageReader already closed.");
pendingQueue.remove(key);
return;
}
Image image;
try {
image = reader.get().acquireNextImage();
} catch (IllegalStateException e) {
Log.e(TAG, "Too many images queued for saving, dropping image for request: " + key);
pendingQueue.remove(key);
return;
}
builder.setRefCountedReader(reader).setImage(image);
if(image==null)Log.e(TAG, "Cacatul de imagine e null...... Sa ma fut in mortii lor.");
handleCompletionLocked(key, builder, pendingQueue);
Log.e(TAG, "Call handled completed in deque" + pendingQueue);
}
}
我在使用 AndroidStudio 附带的示例程序时遇到问题。我只在 S8 上试过这个,所以我不确定这是这个特定设备的问题还是通用的。
如果我尝试一次拍摄多张照片,通过将 mPendingUserCaptures 设置为 4 这样的数字,特别是如果我手动将曝光时间设置为较低的值(通常低于 30 毫秒左右),我总是得到 4 JPG 图像,但有时我只得到 3 个原始文件(最后一个丢失)。 问题出在 ImageSaver class,它并不总是为 RAW 文件调用,但总是为 JPG 文件调用。
我想知道,有没有人遇到过这样的情况,RAW 图像有时无法到达?
好的,在断断续续地寻找这个错误数周之后,我终于发现了发生了什么。 我在这里发布了解决方案,以防其他人偶然发现这个问题。
有时函数 public void onImageAvailable(ImageReader reader) { dequeueAndSaveImage(mRawResultQueue, mRawImageReader); } 会连续调用两次。
密码是:
Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry = pendingQueue.firstEntry();
ImageSaver.ImageSaverBuilder builder = entry.getValue();
这会产生一个大问题,因为有时两个图像会被添加到同一个 TreeMap 条目中,所以如果我们有 4 个条目,最后一个条目将永远不会得到它的图像:/
The fixed code (I left my extra logs there) looks like this:
private void dequeueAndSaveImage(TreeMap<Integer, ImageSaver.ImageSaverBuilder> pendingQueue, RefCountedAutoCloseable<ImageReader> reader) {
synchronized (mCameraStateLock) {
ImageSaver.ImageSaverBuilder builder=null;
Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry;
int key=4;//shut up, stupid java shit
for (Map.Entry<Integer, ImageSaver.ImageSaverBuilder> ent : pendingQueue.entrySet()) {
builder = ent.getValue();
if(builder.mImage==null) {
key = ent.getKey();
break;
}
}
//Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry = pendingQueue.firstEntry();
//ImageSaver.ImageSaverBuilder builder = entry.getValue();
Log.w(TAG, "StartingdequeueAndSaveImage, builder: " + builder);
if(builder.mImage!=null)
{
Log.w(TAG, "!!!!!!!!!!!!!!!!!!!!Builder: " + builder + " already has an image!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
// Increment reference count to prevent ImageReader from being closed while we
// are saving its Images in a background thread (otherwise their resources may
// be freed while we are writing to a file).
if (reader == null || reader.getAndRetain() == null) {
Log.e(TAG, "Paused the activity before we could save the image," + " ImageReader already closed.");
pendingQueue.remove(key);
return;
}
Image image;
try {
image = reader.get().acquireNextImage();
} catch (IllegalStateException e) {
Log.e(TAG, "Too many images queued for saving, dropping image for request: " + key);
pendingQueue.remove(key);
return;
}
builder.setRefCountedReader(reader).setImage(image);
if(image==null)Log.e(TAG, "Cacatul de imagine e null...... Sa ma fut in mortii lor.");
handleCompletionLocked(key, builder, pendingQueue);
Log.e(TAG, "Call handled completed in deque" + pendingQueue);
}
}