MUZLATAN / ffmpeg_rtsp_mpp

ffmpeg 拉取rtsp h264流, 使用mpp解码, 目前在firefly 板子上跑通了
179 stars 53 forks source link

解码本地H264(YUV420P)的视频Frame为空 #2

Closed nulijiabei closed 4 years ago

nulijiabei commented 4 years ago

在 orange pi 4 (rk3399) 主板上面使用您的 ffmpeg_rtsp_mpp 解码本地视频文件 frame 为空

使用 mpi_dec_test -i /root/test.h264 测试是可以解码的

root@orangepi4:~/ffmpeg_rtsp_mpp-master/build# mpi_dec_test -i /root/test.h264 
mpp[13317]: mpi_dec_test: cmd parse result:
mpp[13317]: mpi_dec_test: input  file name: /root/test.h264
mpp[13317]: mpi_dec_test: output file name: 
mpp[13317]: mpi_dec_test: config file name: 
mpp[13317]: mpi_dec_test: width      :    0
mpp[13317]: mpi_dec_test: height     :    0
mpp[13317]: mpi_dec_test: type       : 7
mpp[13317]: mpi_dec_test: debug flag : 0
mpp[13317]: mpi_dec_test: max frames : 0
mpp[13317]: mpi_dec_test: mpi_dec_test start
mpp[13317]: mpi_dec_test: input file size 31008729
mpp[13317]: mpi_dec_test: mpi_dec_test decoder test start w 0 h 0 type 7
mpp[13317]: mpp_info: mpp version: unknown mpp version for missing VCS info
mpp[13317]: mpp_rt: NOT found ion allocator
mpp[13317]: mpp_rt: found drm allocator
mpp[13317]: mpi_dec_test: decode_get_frame get info changed found
mpp[13317]: mpi_dec_test: decoder require buffer w:h [1920:1080] stride [1920:1088] buf_size 4177920
mpp[13317]: mpi_dec_test: decode_get_frame get frame 1
mpp[13317]: mpi_dec_test: decode_get_frame get frame 2
mpp[13317]: mpi_dec_test: decode_get_frame get frame 3
mpp[13317]: mpi_dec_test: decode_get_frame get frame 4
mpp[13317]: mpi_dec_test: decode_get_frame get frame 5
mpp[13317]: mpi_dec_test: decode_get_frame get frame 6
mpp[13317]: mpi_dec_test: decode_get_frame get frame 7
mpp[13317]: mpi_dec_test: decode_get_frame get frame 8
mpp[13317]: mpi_dec_test: decode_get_frame get frame 9
mpp[13317]: mpi_dec_test: decode_get_frame get frame 10
mpp[13317]: mpi_dec_test: decode_get_frame get frame 11
mpp[13317]: mpi_dec_test: decode_get_frame get frame 12
mpp[13317]: mpi_dec_test: decode_get_frame get frame 13
mpp[13317]: mpi_dec_test: decode_get_frame get frame 14
mpp[13317]: mpi_dec_test: decode_get_frame get frame 15
mpp[13317]: mpi_dec_test: decode_get_frame get frame 16

修改您代码 main.c 中如下 ...

    //打开网络流或文件流
    if (avformat_open_input(&pFormatCtx, "/root/yiyezi.mp4", NULL, &options) != 0)
    {
        printf("Couldn't open input stream.\n");
        return 0;
    }

...

    // paramter for resource malloc
    RK_U32 width        = 1280;
    RK_U32 height       = 720;
    MppCodingType type  = MPP_VIDEO_CodingAVC;

视频格式

root@orangepi4:~# ffmpeg -i yiyezi.mp4 
ffmpeg version 4.0 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 7 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)
  configuration: --enable-version3 --enable-libdrm --enable-rkmpp --enable-libx264 --enable-nonfree --enable-gpl --disable-static --enable-shared
  libavutil      56. 14.100 / 56. 14.100
  libavcodec     58. 18.100 / 58. 18.100
  libavformat    58. 12.100 / 58. 12.100
  libavdevice    58.  3.100 / 58.  3.100
  libavfilter     7. 16.100 /  7. 16.100
  libswscale      5.  1.100 /  5.  1.100
  libswresample   3.  1.100 /  3.  1.100
  libpostproc    55.  1.100 / 55.  1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'yiyezi.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : www.aliyun.com - Media Transcoding
  Duration: 00:00:30.11, start: 0.000000, bitrate: 1160 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(yuv420p) (tv, bt709), 1280x720, 1027 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

结果 frame 输出均为 NULL,然后 ret 确是 MPP_OK

            ret = mpi->decode_get_frame(ctx, &frame);
            if (MPP_ERR_TIMEOUT == ret) {
                if (times > 0) {
                    times--;
                    msleep(2);
                    goto try_again;
                }
                mpp_err("decode_get_frame failed too much time\n");
            }
            if (MPP_OK != ret) {
                mpp_err("decode_get_frame failed ret %d\n", ret);
                break;
            }
            if (frame == NULL)
            mpp_log("!!!!!!!!! FRAME IS NULL !!!!!!");
            if (frame) {
                if (mpp_frame_get_info_change(frame)) {
                    RK_U32 width = mpp_frame_get_width(frame);
                    RK_U32 height = mpp_frame_get_height(frame);
                    RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
                    RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
                    RK_U32 buf_size = mpp_frame_get_buf_size(frame);
root@orangepi4:~/ffmpeg_rtsp_mpp-master/build# ./mpp_test 
mpp[13601]: mpi_dec_test: mpi_dec_test start
mpp[13601]: mpi_dec_test: mpi_dec_test decoder test start w 1280 h 720 type 7
mpp[13601]: mpp_info: mpp version: unknown mpp version for missing VCS info
mpp[13601]: mpp: deprecated block control, use timeout control instead
mpp[13601]: mpp_rt: NOT found ion allocator
mpp[13601]: mpp_rt: found drm allocator
mpp[13601]: mpi_dec_test: --------------
data size is: 33505
-------------
mpp[13601]: mpi_dec_test: !!!!!!!!! FRAME IS NULL !!!!!!
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: --------------
data size is: 2553
-------------
mpp[13601]: mpi_dec_test: !!!!!!!!! FRAME IS NULL !!!!!!
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: --------------
data size is: 494
-------------
mpp[13601]: mpi_dec_test: !!!!!!!!! FRAME IS NULL !!!!!!
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: 0
mpp[13601]: mpi_dec_test: --------------
data size is: 2871
MUZLATAN commented 4 years ago

你有没有试过直接使用rtsp流解码, ffmpeg 直接解码h264文件没试过这种用法

MUZLATAN commented 4 years ago

按理说, ffmpeg 从rtsp拉码流, avpacket 给到mpp mpp 解码 264packet 到yuv数据帧

nulijiabei commented 4 years ago

感谢,找到一个解决办法就是把 AVC1 转 H264 ...

            //is video stream
            const char start_code[4] = { 0, 0, 0, 1 };
            if(memcmp(start_code, avpkt->data, 4) != 0)
            {//is avc1 code, have no start code of H264
                int len = 0;
                uint8_t *p = avpkt->data;
                do
                { //add start_code for each NAL, one frame may have multi NALs.
                    len = ntohl(*((long*)p));
                    memcpy(p, start_code, 4);
                    p += 4;
                    p += len;
                    if(p >= avpkt->data + avpkt->size)
                    {
                        break;
                    }
                } while (1);
            }