Tôi cần thực hiện quy trình chỉ đọc trên CPU trên dữ liệu máy ảnh trực tiếp (chỉ từ mặt phẳng Y) sau đó hiển thị trên GPU. Khung không được hiển thị cho đến khi quá trình xử lý hoàn tất (vì vậy tôi không phải lúc nào cũng muốn hiển thị khung hình mới nhất từ máy ảnh, chỉ khung mới nhất mà bên CPU đã xử lý xong). Rendering được tách rời khỏi quá trình xử lý máy ảnh và nhắm tới 60 FPS ngay cả khi các khung máy ảnh đến với tốc độ thấp hơn.Đường ống xử lý và hiển thị máy ảnh không sao chép trên Android
Có một câu hỏi liên quan nhưng cao cấp hơn tại địa chỉ: Lowest overhead camera to CPU to GPU approach on android
Để mô tả các thiết lập hiện tại trong một chi tiết hơn chút: chúng ta có một vùng đệm dữ liệu ứng dụng-side cho dữ liệu máy ảnh nơi vùng đệm là một trong hai "tự do", "đang hiển thị" hoặc "đang chờ hiển thị". Khi một khung mới từ máy ảnh đến, chúng tôi lấy một bộ đệm miễn phí, lưu trữ khung (hoặc tham chiếu đến nó nếu dữ liệu thực tế nằm trong một số vùng đệm do hệ thống cung cấp), xử lý và lưu trữ kết quả trong bộ đệm, sau đó đặt bộ đệm "đang chờ hiển thị". Trong chuỗi trình kết xuất nếu có bất kỳ bộ đệm nào "đang chờ hiển thị" ở đầu vòng lặp kết xuất, chúng tôi sẽ chốt nó là "hiển thị" thay thế, hiển thị máy ảnh và hiển thị nội dung khác bằng thông tin được xử lý được tính toán từ cùng một khung máy ảnh.
Nhờ phản hồi của @ fadden về câu hỏi được liên kết ở trên, giờ đây tôi hiểu tính năng "đầu ra song song" của android camera2 chia sẻ bộ đệm giữa các hàng đợi đầu ra khác nhau, vì vậy không nên liên quan đến bất kỳ bản sao nào trên dữ liệu trên Android hiện đại.
Trong một nhận xét có một gợi ý rằng tôi có thể chốt các đầu ra SurfaceTexture và ImageReader cùng một lúc và chỉ "ngồi trên bộ đệm" cho đến khi quá trình xử lý hoàn tất. Thật không may, tôi không nghĩ rằng điều đó có thể áp dụng trong trường hợp của tôi do kết xuất được tách rời mà chúng tôi vẫn muốn lái xe ở tốc độ 60 FPS và vẫn cần truy cập vào khung hình trước đó trong khi khung mới đang được xử lý để đảm bảo mọi thứ không Không đồng bộ.
Một giải pháp mà bạn nghĩ đến là có nhiều SurfaceTextures - một trong mỗi bộ đệm bên ứng dụng của chúng tôi (chúng tôi hiện đang sử dụng 3). Với lược đồ đó khi chúng tôi nhận được một khung máy ảnh mới, chúng tôi sẽ có được bộ đệm miễn phí từ hồ bơi ứng dụng của chúng tôi. Sau đó, chúng tôi sẽ gọi acquireLatestImage()
trên ImageReader để lấy dữ liệu để xử lý và gọi updateTexImage()
trên SurfaceTexture trong bộ đệm miễn phí. Tại thời điểm hiển thị, chúng tôi chỉ cần đảm bảo rằng SufaceTexture từ bộ đệm "trong hiển thị" là bộ đệm được gắn với GL và mọi thứ phải đồng bộ phần lớn thời gian (như @fadden đã nhận xét có một cuộc gọi giữa số updateTexImage()
và acquireLatestImage()
nhưng cửa sổ thời gian đó phải đủ nhỏ để làm cho nó trở nên hiếm hoi, và có lẽ là dễ đọc và có thể sửa được bằng cách sử dụng dấu thời gian trong bộ đệm).
Tôi lưu ý trong tài liệu updateTexImage()
chỉ có thể được gọi khi SurfaceTexture bị ràng buộc với ngữ cảnh GL, điều này cho thấy tôi sẽ cần ngữ cảnh GL trong chuỗi xử lý máy ảnh để chủ đề camera có thể thực hiện updateTexImage()
trên SurfaceTexture trong bộ đệm "tự do" trong khi chuỗi hiển thị vẫn có thể hiển thị từ SurfaceTexture từ bộ đệm "trong hiển thị".
Vì vậy, để những câu hỏi:
- Điều này có vẻ giống như một cách tiếp cận hợp lý?
- SurfaceTextures cơ bản là một trình bao bọc ánh sáng xung quanh vùng đệm được chia sẻ, hay chúng tiêu thụ một số tài nguyên phần cứng hạn chế và nên được sử dụng một cách tiết kiệm?
- Các cuộc gọi SurfaceTexture có đủ rẻ để sử dụng nhiều tính năng vẫn sẽ là một chiến thắng lớn so với việc sao chép dữ liệu không?
- Kế hoạch có hai chủ đề với các ngữ cảnh GL riêng biệt với một SurfaceTexture khác nhau bị ràng buộc trong mỗi khả năng làm việc hay tôi đang yêu cầu một thế giới của các trình điều khiển đau và lỗi?
Có vẻ đủ hứa hẹn rằng tôi sẽ bỏ nó; nhưng nghĩ rằng nó có giá trị yêu cầu ở đây trong trường hợp bất cứ ai (về cơ bản @ fadden!) biết về bất kỳ chi tiết nội bộ mà tôi đã bỏ qua mà sẽ làm cho một ý tưởng tồi.
Cảm ơn lời giải thích tuyệt vời và nó có vẻ giống như một cách tiếp cận khả thi. Tôi có lẽ sẽ thử nó vào cuối tuần. Có lẽ sẽ đặt nó trên github – tangobravo
Bởi "các bước thông thường để đảm bảo đồng bộ hóa", bạn chỉ có nghĩa là thread gọi 'updateTexImage()' phải được gọi là 'detachFromGLContext()' trước khi render thread cố gắng đính kèm nó để render? Không có yêu cầu 'glFinish()' nào cần thiết nếu các ngữ cảnh được thiết lập để chia sẻ các kết cấu như đã đề cập trong lỗi grafika mà bạn đã liên kết? – tangobravo
Có ['getTimestamp()'] (https://developer.android.com/reference/android/media/Image.html#getTimestamp()) trên Hình ảnh từ API 19. Tôi hy vọng rằng sẽ trả về cùng dấu thời gian là SurfaceTexture nhưng sẽ kiểm tra khi tôi kiểm tra phương pháp tiếp cận. – tangobravo