jc-kynesim / rpi-ffmpeg

FFmpeg work for RPI
Other
111 stars 27 forks source link

Does initalizing DRM depend on an active incoming stream? #12

Closed Fredrum closed 3 years ago

Fredrum commented 3 years ago

Hello! I got my basic example program working well, seemingly, to read hevc files off disk and decoding with hw accelleration and piping straight to openGL. That's awesome! Now I'm trying to translate what I did (what you did :)) to a different program that is taking a raw h264 stream from network. I know the original code worked fine.

But I'm struggling to get the avcodec part initialized correctly in this new program. I never manage to get a positive result from

decoder->codec_context->get_format = AV_PIX_FMT_DRM_PRIME;
if(decoder->codec_context->pix_fmt != AV_PIX_FMT_DRM_PRIME)
    printf("Couldn't negoitiate AV_PIX_FMT_DRM_PRIME\n");

The stage in the programs startup where avcodec is initialized in is before the video stream is available. Is this a problem? Like I said the program works fine as is, using a different hw accellerator on my Ubuntu PC.

Iv'e hackily added the init to after the stream is available and it gets further, but still does not report a good pixel format.

Is there anything particular to the Raspberry "drm" decoder that I need to do differently here with avcodec?

Cheers Fred

jc-kynesim commented 3 years ago

The important bits of init are that you must have picked the right decoder (for h264 that is h264_v4l2m2m) and your get_format call must return DRM_PRIME to ffmpeg. I can't offhand remember how you turn on debug from the API but turn that up to DEBUG and look at the trace for clues - there normally are some. Otherwise I haven't had to do much to make it work in other code.

Fredrum commented 3 years ago

I think maybe I have the right init now (I'm starting testing with a h264 stream.) I'm using this to get debug ffmpeg printouts, av_log_set_level(AV_LOG_DEBUG);

Right now I get this,

[h264_mp4toannexb @ 0x1192a30] The input looks like it is Annex B already
[h264_v4l2m2m @ 0x1191fc0] level=-99
[h264_v4l2m2m @ 0x1191fc0] Format yuv420p chosen by get_format().
[h264_v4l2m2m @ 0x1191fc0] avctx requested=-1 ((null)); get_format requested=0 (yuv420p)
[h264_v4l2m2m @ 0x1191fc0] probing device /dev/video12
[h264_v4l2m2m @ 0x1191fc0] driver 'bcm2835-codec' on card 'bcm2835-codec-isp' in mplane mode
[h264_v4l2m2m @ 0x1191fc0] v4l2 output format not supported
[h264_v4l2m2m @ 0x1191fc0] probing device /dev/video11
[h264_v4l2m2m @ 0x1191fc0] driver 'bcm2835-codec' on card 'bcm2835-codec-encode' in mplane mode
[h264_v4l2m2m @ 0x1191fc0] v4l2 output format not supported
[h264_v4l2m2m @ 0x1191fc0] probing device /dev/video10
[h264_v4l2m2m @ 0x1191fc0] driver 'bcm2835-codec' on card 'bcm2835-codec-decode' in mplane mode
[h264_v4l2m2m @ 0x1191fc0] Using device /dev/video10
[h264_v4l2m2m @ 0x1191fc0] driver 'bcm2835-codec' on card 'bcm2835-codec-decode' in mplane mode
[h264_v4l2m2m @ 0x1191fc0] requesting formats: output=H264 capture=YU12
[h264_v4l2m2m @ 0x1191fc0] output: H264 16 buffers initialized: 0000x0000, sizeimage 00524288, bytesperline 0000000
...
...
[h264_v4l2m2m @ 0x1191fc0] output set status 1074026002 (ON) OK
[h264_v4l2m2m @ 0x1191fc0] --- output pre VIDIOC_QBUF: index 0, ts=0.000001 count=0
[h264_v4l2m2m @ 0x1191fc0] --- output VIDIOC_QBUF: index 0, ts=0.000001 count=1
[h264_v4l2m2m @ 0x1191fc0] Post G selection ret=0, err=0 32x32
[h264_v4l2m2m @ 0x1191fc0] capture: YU12 20 buffers initialized: 0032x0032, sizeimage 00001536, bytesperline 00000032
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 0, ts=0.000000 count=1
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 1, ts=0.000000 count=2
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 2, ts=0.000000 count=3
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 3, ts=0.000000 count=4
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 4, ts=0.000000 count=5
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 5, ts=0.000000 count=6
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 6, ts=0.000000 count=7
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 7, ts=0.000000 count=8
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 8, ts=0.000000 count=9
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 9, ts=0.000000 count=10
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 10, ts=0.000000 count=11
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 11, ts=0.000000 count=12
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 12, ts=0.000000 count=13
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 13, ts=0.000000 count=14
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 14, ts=0.000000 count=15
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 15, ts=0.000000 count=16
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 16, ts=0.000000 count=17
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 17, ts=0.000000 count=18
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 18, ts=0.000000 count=19
[h264_v4l2m2m @ 0x1191fc0] --- capture VIDIOC_QBUF: index 19, ts=0.000000 count=20
[h264_v4l2m2m @ 0x1191fc0] capture set status 1074026002 (ON) OK

Right at the end of init my readouts indicate that I have a "drm" hw decoder and DRM_PRIME as pixel format in the decoder. That pixel format seems to get lost at some point in the code. (Someone else set up the avcodec code and I'm not used to it yet).

Hopefully the above debug messages mean I'm good and its just something I'm not doing right yet in the rest of the code.

UPDATE: I'm doing the Init in a different way now and I think it's getting me further. I'm now using avio_alloc_context(). I think I'm just breaking it when I'm passing AVFrames around and trying to pick them up elsewhere.

jc-kynesim commented 3 years ago

The line you care about is: [h264_v4l2m2m @ 0x1191fc0] Format yuv420p chosen by get_format(). You need to have a AVCodecContext->get_format function that returns DRM_PRIME

Fredrum commented 3 years ago

I got it working now! :) I had to shuffle the order of some of the init lines then I got good get_format() returns.

There were some other gotchas that confused my like other parts if the code that picked a different version of the pixel formats .h so AV_PIX_FMT_DRM_PRIME wouldn't get accepted. I had to fix that in the cmake file.

Cheers!

sava41 commented 3 years ago

Sorry if this is reopening an old thread but I'm trying to work through the same issue. I have the test/4.3.2/rpi_main branch compiled and installed on my system. when get_format() gets called, drm_prime is not one of the available options in the list. I only get rpi, vaapi_vld, vdpau, and yuv420p. This happens when trying to play hevc videos (https://s3.amazonaws.com/x265.org/video/BigBuckBunny_2000hevc.mp4). Playing h264 does give drm_prime as an option.

jc-kynesim commented 3 years ago

1st question - do you have /dev/video19 on your system? It not then "sudo dtoverlay rpivid-v4l2" and try again (you can add the dtoverlay to config.txt but probably worth trying from the command line 1st).

sava41 commented 3 years ago

I had dtoverlay=rpivid-v4l2 in the config and running ls -la /dev/video* returns /dev/video19 as an option.

We ended up starting from a fresh image of raspbian lite and re-installing/recompiling everything and it worked. We had one error message DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory that was fixed by removing memory split in the config.txt