使用C ++

时间:2019-02-10 03:21:58

标签: c++ ffmpeg h.264 codec

我有一个工作代码,可以使用JRTPLIB通过RTP接收NAL单元。它将NAL单元保存到我可以通过VLC播放的文件中。

我愿意使用ffmpeg解码这些NAL单元。我已经看到了有关NAL单元和ffmpeg的stackoverflow的所有线程,但它们都没有确切地回答如何实现。

据我了解,RTP是一种可以将NAL单元分解为多个RTP数据包的协议。因此,我收到的NAL单元甚至还不完整。所以我想我不能直接将它们输入ffmpeg。我想我需要某种方式来累计它们,然后将它们以正确的格式发送给ffmpeg。

看看ffmpeg库中的avcodec_decode_video2函数:

attribute_deprecated int avcodec_decode_video2  (   
    AVCodecContext *    avctx,
    AVFrame *   picture,
    int *   got_picture_ptr,
    const AVPacket *    avpkt 
)   

这是关于avpkt的意思:

  

avpkt:包含输入缓冲区的输入AVPacket。您可以创建   带有av_init_packet()的数据包

我想有一种方法可以将NAL单位转换为AVPacket。我试图在文档中找到与此相关的内容,但找不到有用的东西。

我也阅读了本教程:http://dranger.com/ffmpeg/tutorial01.html,但它只讨论从文件读取,而ffmpeg在将帧转换为AVPacket时做了一些后台工作,所以我对此一无所知。

ps:我的代码在文件的开头写入一次VPS,SPS和PPS信息,然后仅按顺序保存NAL单元。

那么:如何用ffmpeg解码NAL单元?

更新:

这是接收NAL单元的代码。我尝试在每个NAL单元的开头添加0x00000001

const size_t BufSize = 98304;
uint8_t buf[4 + BufSize];//4 bytes for 0x00000001 at beggining
uint8_t* paddedBuf = buf + 4;
/* Adds the delimiters for a h264 bitstream*/
buf[0] = char(0x00);
buf[1] = char(0x00);
buf[2] = char(0x00);
buf[3] = char(0x01);
size_t size = 0;
size_t write_size = 0;

/* Get SPS, PPS, VPS manually start */
std::cout << "writing vps" << std::endl;

Client.SetObtainVpsSpsPpsPeriodly(false);
if(!Client.GetVPSNalu(paddedBuf, &size)) {
    if(write(fd, paddedBuf, size) < 0) {
        perror("write");
    }
} 
if(!Client.GetSPSNalu(paddedBuf, &size)) {
    if(write(fd, paddedBuf, size) < 0) {
        perror("write");
    }
} 
if(!Client.GetPPSNalu(paddedBuf, &size)) {
    if(write(fd, paddedBuf, size) < 0) {
        perror("write");
    }
} 
/* Get SPS, PPS, VPS manually end */


while(true) {
    if(!Client.GetMediaData("video", paddedBuf+write_size, &size, BufSize)) {
        if(ByeFromServerFlag) {
            printf("ByeFromServerFlag\n");
            break;
        }
        if(try_times > 5) {
            printf("try_times > 5\n");
            break;
        }
        try_times++;
        continue;
    }
    write_size += size;
    std::cout << "gonna decode frame" << std::endl;

    ffmpegDecoder->decodeFrame(paddedBuf,size);
    std::cout << "decoded frame" << std::endl;

现在,功能decodeFrame给了我分段错误。但是我什至不知道我在做什么是否可以。

void  FfmpegDecoder::decodeFrame(uint8_t* frameBuffer, int frameLength)
{
    if (frameLength <= 0) return;

    int frameFinished = 0;

    AVPacket framePacket;
    av_init_packet(&framePacket);

    framePacket.size = frameLength;
    framePacket.data = frameBuffer;

    std::cout << "gonna decode video2" << std::endl;

    int ret = avcodec_decode_video2(m_pAVCodecContext, m_pAVFrame, &frameFinished, &framePacket); //GIVES SEGMENTATION FAULT HERE

Here's a snapshot of this code and the entire project,如果您进入/dev并执行。/build来构建docker映像,然后./run来输入docker映像,则可以对其进行编译。只需执行cmake .make。但是,您应该使用~/orwell$ LD_LIBRARY_PATH=.:./jrtplib/src ./orwell_monitor在docker外部运行二进制文件,因为在docker内部存在错误。

0 个答案:

没有答案