grabbing native MPPBuffer from CamSource...
I want to grab the MPPBuffer that comes right from a CamSource and dump it to a file. Unfortunately I can't get around an error related to the memory mapping, but I don't understand why... The code was essentially taken from the encoder test example.
The critical call is this one: mpp_buffer_get_ptr
#include <iostream>
#define MODULE_TAG "mpi_video_cap"
#include <camera_source.h>
#include <mpp_debug.h>
#include "rk_mpi.h"
#include "mpp_env.h"
#include "mpp_mem.h"
#include "mpp_time.h"
#include "mpp_debug.h"
#include "mpp_common.h"
#include "utils.h"
#include "mpi_enc_utils.h"
#include "mpp_enc_roi_utils.h"
#include "mpp_rc_api.h"
extern RK_U32 mpp_debug;
int main(int argc, char* argv[])
{
mpp_debug = 1;
CamSource *cam_ctx = NULL;
MppFrameFormat fmt = MPP_FMT_YUV420SP;
//MppFrameFormat fmt = MPP_FMT_YUV422_YUYV;
std::cout << "Opening..." << std::endl;
cam_ctx = camera_source_init("/dev/video22", 4, 1920, 1080, fmt);
std::cout << "Test..." << std::endl;
if(cam_ctx == NULL)
{
std::cout << "Error!" << std::endl;
return -1;
}
std::cout << "Done..." << std::endl;
// need to wait for the stop event here...
RK_S32 cam_frm_idx = -1;
RK_U32 cap_num = 0;
MppBuffer cam_buf = NULL;
std::cout << "start loop..." << std::endl;
while(true)
{
cam_frm_idx = camera_source_get_frame(cam_ctx);
mpp_assert(cam_frm_idx >= 0);
// skip unstable frames
if (cap_num++ < 50) {
camera_source_put_frame(cam_ctx, cam_frm_idx);
continue;
}
cam_buf = camera_frame_to_buf(cam_ctx, cam_frm_idx);
mpp_assert(cam_buf);
// make copy
RK_U32 bufsz = mpp_buffer_get_size(cam_buf);
std::cout << "Size of buffer: " << bufsz << std::endl;
// THIS ONE FAILS CONSTANTLY
const uint8_t* buf = static_cast<const uint8_t*>(mpp_buffer_get_ptr(cam_buf));
std::cout << ((buf != NULL) ? "OK!" : "NULL") << std::endl;
mpp_assert(buf != NULL);
FILE* f = fopen("frame.raw", "wb");
fwrite(buf,bufsz,sizeof(uint8_t),f);
fclose(f);
camera_source_put_frame(cam_ctx, cam_frm_idx);
std::cout << "." << std::flush;
break;
}
camera_source_deinit(cam_ctx);
return 0;
}
The output basically looks like this:
mpp[9]: camera_source: input devices:Camera
mpp[9]: camera_source: fmt name: [UYVY 4:2:2]
mpp[9]: camera_source: fmt pixelformat: 'UYVY', description = 'UYVY 4:2:2'
mpp[9]: camera_source: fmt name: [Y/CbCr 4:2:2]
mpp[9]: camera_source: fmt pixelformat: 'NV16', description = 'Y/CbCr 4:2:2'
mpp[9]: camera_source: fmt name: [Y/CrCb 4:2:2]
mpp[9]: camera_source: fmt pixelformat: 'NV61', description = 'Y/CrCb 4:2:2'
mpp[9]: camera_source: fmt name: [Y/CrCb 4:2:0]
mpp[9]: camera_source: fmt pixelformat: 'NV21', description = 'Y/CrCb 4:2:0'
mpp[9]: camera_source: fmt name: [Y/CbCr 4:2:0]
mpp[9]: camera_source: fmt pixelformat: 'NV12', description = 'Y/CbCr 4:2:0'
mpp[9]: camera_source: fmt name: [Y/CrCb 4:2:0 (N-C)]
mpp[9]: camera_source: fmt pixelformat: 'NM21', description = 'Y/CrCb 4:2:0 (N-C)'
mpp[9]: camera_source: fmt name: [Y/CbCr 4:2:0 (N-C)]
mpp[9]: camera_source: fmt pixelformat: 'NM12', description = 'Y/CbCr 4:2:0 (N-C)'
mpp[9]: camera_source: get width 1920 height 1080
mpp[9]: camera_source: get dma buf(0)-fd: 33
mpp[9]: camera_source: get dma buf(1)-fd: 34
mpp[9]: camera_source: get dma buf(2)-fd: 35
mpp[9]: camera_source: get dma buf(3)-fd: 36
mpp[9]: mpp_buffer: mpp_buffer_mmap buffer 2 group 1 fd 35 map failed caller main
mpp[9]: mpp_buffer: Assertion p->info.ptr != __null failed at mpp_buffer_get_ptr_with_caller:178
mpp[9]: mpp_buffer: mpp_buffer_get_ptr buffer 0x1c86a868 ret NULL from main
mpp[9]: mpp_buffer: mpp_buffer_mmap buffer 3 group 1 fd 36 map failed caller main
mpp[9]: mpp_buffer: Assertion p->info.ptr != __null failed at mpp_buffer_get_ptr_with_caller:178
mpp[9]: mpp_buffer: mpp_buffer_get_ptr buffer 0x1c86a9e8 ret NULL from main
mpp[9]: mpp_buffer: mpp_buffer_mmap buffer 0 group 1 fd 33 map failed caller main
mpp[9]: mpp_buffer: Assertion p->info.ptr != __null failed at mpp_buffer_get_ptr_with_caller:178
mpp[9]: mpp_buffer: mpp_buffer_get_ptr buffer 0x1c86a568 ret NULL from main
mpp[9]: mpp_buffer: mpp_buffer_mmap buffer 1 group 1 fd 34 map failed caller main
mpp[9]: mpp_buffer: Assertion p->info.ptr != __null failed at mpp_buffer_get_ptr_with_caller:178
mpp[9]: mpp_buffer: mpp_buffer_get_ptr buffer 0x1c86a6e8 ret NULL from main
Any hint highly appreciated...
PS: Any of https://github.com/rockchip-linux/mpp/issues/418#issuecomment-1734916224 did not work...
Ok, so I found that there might be something missing.
The actual pointer from the data is stored here: https://github.com/rockchip-linux/mpp/blob/ee946af015c350c926a0fca2f02da8e429f8b079/utils/camera_source.c#L37
However, the MPPBuffer does not have the respective info->ptr set - it is NULL. The function returns the buf, but as soon as you try to get the ptr or do read or access, there is this error from the previous post.
Not sure if it is ok to put it here, but it does the trick: https://github.com/rockchip-linux/mpp/blob/ee946af015c350c926a0fca2f02da8e429f8b079/utils/camera_source.c#L429
This one should read somewhat like:
#include "mpp_buffer_impl.h"
...
MppBuffer camera_frame_to_buf(CamSource *ctx, RK_S32 idx)
{
MppBuffer buf = NULL;
if (idx < 0)
return buf;
buf = ctx->fbuf[idx].buffer;
MppBufferImpl *p = (MppBufferImpl*)buf;
p->info.ptr = ctx->fbuf[idx].start;
if (buf)
mpp_buffer_sync_end(buf);
return buf;
}
and then the buffer can be used as normal.
I did not find that it has any further implications and worked with my UVC camera. @HermanChen please comment if it is a bug and should get a fix...
0001-fix-ext_dma-Refine-mmap-permission-configuration.patch Thank you for your feedback and providing suggestions for modification. In mpp_buffer_get_ptr(), the pointer is obtained through mmap with the file descriptor (fd). The buffer_type of the camera adopts the ext_dma mode, which has some deficiencies in the mmap process. Therefore, modifications have been made. Please apply the patch to verify if the issue is resolved.
Thx a lot for the patch. It works flawlessly now!
are you going to integrate it in the repo? then the issue can be closed...
Yes, sure.