实时h264封装flv格式后黑屏

将实时h264封装flv后播放有时间但是一直黑屏,有哪位大佬能指导一二!

/*
 * FLV muxer
 * Copyright (c) 2003 The FFmpeg Project
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <typeinfo>
#include <unistd.h>
#include <boost/asio.hpp>

#include "client_ws.hpp"

#include "flv.h"

#undef NDEBUG
#include <assert.h>
using namespace std;
using WsClient = SimpleWeb::SocketClient<SimpleWeb::WS>;

double m_DTS=0.0;

/************************************************************/
TagHeader    m_tagHeader;     //tag头信息
NAL          m_nal;           //存储NAL单元

void saveH264File(unsigned char* pBuffer, int dwBufSize)
{
    FILE * fpVideo;
    fpVideo = fopen("444.flv", "ab+");   //以只读二进制方式打开文件
    if (!fpVideo)
    {
        printf("ERROR:open file failed!");
    }
    int pos = 0;

    fwrite(pBuffer, 1, dwBufSize, fpVideo);
    fclose(fpVideo);
}

void PrintBuffer(void* pBuff, unsigned int nLen)
{
    if (NULL == pBuff || 0 == nLen)
    {
        return;
    }
 
    const int nBytePerLine = 16;
    unsigned char* p = (unsigned char*)pBuff;
    char szHex[3*nBytePerLine+1] = {0};
    unsigned int i;
    
    printf("-----------------begin-------------------\n");
    for (i=0; i<nLen; ++i)
    {
        int idx = 3 * (i % nBytePerLine);
        if (0 == idx)
        {
            memset(szHex, 0, sizeof(szHex));
        }
#ifdef WIN32
        sprintf_s(&szHex[idx], 4, "%02x ", p[i]);// buff长度要多传入1个字节
#else
        snprintf(&szHex[idx], 4, "%02x ", p[i]); // buff长度要多传入1个字节
#endif
        
        // 以16个字节为一行,进行打印
        if (0 == ((i+1) % nBytePerLine))
        {
            printf("%s\n", szHex);
        }
    }
 
    // 打印最后一行未满16个字节的内容
    if (0 != (nLen % nBytePerLine))
    {
        printf("%s\n", szHex);
    }
 
    printf("------------------end-------------------\n");
}





void setFlvHeader()
{
    FlvHeader m_flvHeader;     //flv头信息
    m_flvHeader.signature[0] = 'F';
    m_flvHeader.signature[1] = 'L';
    m_flvHeader.signature[2] = 'V';
    m_flvHeader.version = 0x01;
    m_flvHeader.present = 0;
    m_flvHeader.present |= 0x01;
    m_flvHeader.size[0] = 0x00;
    m_flvHeader.size[1] = 0x00;
    m_flvHeader.size[2] = 0x00;
    m_flvHeader.size[3] = 0x09;
    saveH264File(m_flvHeader.data, 9);
    //printf("1: ");
    //PrintBuffer(m_flvHeader.data, 9);
    
}

/* 写第一个Tag Size */
void writeFirstTagSize()
{
    unsigned char data[4] = {0x00,0x00,0x00,0x00};
    saveH264File(data, 4);
    //printf("写第一个Tag Size2: ");
    //PrintBuffer(data, 4);
}

/* 写前一个Tag Size */
void writePreTagSize()
{
    FILE * fpVideo;
    fpVideo = fopen("444.flv", "ab+");   //以只读二进制方式打开文件
    unsigned char data[4] = {0x00,0x00,0x00,0x00};
    unsigned int  length  = m_tagHeader.getSize();
    data[3] = (unsigned char)(length&0xFF); length = length>>8;
    data[2] = (unsigned char)(length&0xFF); length = length>>8;
    data[1] = (unsigned char)(length&0xFF); length = length>>8;
    data[0] = (unsigned char)(length&0xFF); length = length>>8;
    PrintBuffer(data, 4);
    saveH264File(data, 4);
    //printf("前一个Tag Size3: ");
    //cout << "前一个Tag: " << length << endl;
    //PrintBuffer(data, 4);
    //fwrite(data,4,1,fpVideo);
    //fclose(fpVideo);
}

/*设置Tag头信息*/
void setTagHeader(unsigned char tagType, unsigned int timestamp)
{
    memset(m_tagHeader.data,0,11);
    m_tagHeader.tagType = tagType;
    m_tagHeader.timestamp[2] = (unsigned char)(timestamp&0xFF); timestamp = timestamp>>8;
    m_tagHeader.timestamp[1] = (unsigned char)(timestamp&0xFF); timestamp = timestamp>>8;
    m_tagHeader.timestamp[0] = (unsigned char)(timestamp&0xFF); timestamp = timestamp>>8;
    m_tagHeader.timestamp[3] = (unsigned char)(timestamp&0xFF); timestamp = timestamp>>8;
    //printf("设置Tag头信息4: ");
    //PrintBuffer(m_tagHeader.data, 11);
}

/*设置Tag数据长度*/
void setTagHeaderDataSize(unsigned int datasize)
{
    m_tagHeader.datasize[2] = (unsigned char)(datasize&0xFF); datasize = datasize>>8;
    m_tagHeader.datasize[1] = (unsigned char)(datasize&0xFF); datasize = datasize>>8;
    m_tagHeader.datasize[0] = (unsigned char)(datasize&0xFF); datasize = datasize>>8;
}


void writeTagHeader()
{
    saveH264File(m_tagHeader.data, 11);
    //printf("写入Tag Header5: ");
    //PrintBuffer(m_tagHeader.data, 11);
}

//写MetaData信息
void writeMetaData()
{
    setTagHeader(TAGTYPE_META,0);
    /*unsigned char data[135] = {
        0x02,0x00,0x0a,0x6f,0x6e,0x4d,0x65,0x74,0x61,0x44,
        0x61,0x74,0x61,0x08,0x00,0x00,0x00,0x07,0x00,0x08,
        0x64,0x75,0x72,0x61,0x74,0x69,0x6f,0x6e,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x77,
        0x69,0x64,0x74,0x68,0x00,0x40,0x9e,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x06,0x68,0x65,0x69,0x67,0x68,
        0x74,0x00,0x40,0x90,0xe0,0x00,0x00,0x00,0x00,0x00,
        0x00,0x09,0x66,0x72,0x61,0x6d,0x65,0x72,0x61,0x74,
        0x65,0x00,0x40,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x0c,0x76,0x69,0x64,0x65,0x6f,0x63,0x6f,0x64,
        0x65,0x63,0x69,0x64,0x00,0x40,0x1c,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x08,0x66,0x69,0x6c,0x65,0x73,
        0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x09
    };*/
    unsigned char data[8] = {0x02,0x00,0x05,0x58,0x49,0x41,0x4F,0x43};
    setTagHeaderDataSize(8);
    writeTagHeader();
    //printf("6: ");
    //PrintBuffer(data, 135);
    saveH264File(data, 8);
    /* 写前一个Tag Size */
    writePreTagSize();
}


//检查NAL起始符 并返回起始符长度
int checkStartecode(unsigned char data[4],unsigned char pos)
{
    if(data[pos]!=0x01) return 0;
    for(int i = 0; i<2; i++)
    {
        unsigned char pos2 = (pos + 4 - 1)%4;
        if(data[pos2]!=0x00) return 0;
        pos--;
    }
    unsigned char pos3 = (pos + 4 - 1)%4;
    if(data[pos3] == 0x00)
    {
        return 4;
    }
    else
    {
        return 3;
    }
}

//读取NAL单元
bool readNal(unsigned char* packetData, int size)
{
    unsigned char start[4] = {0xFF,0xFF,0xFF,0xFF};
    unsigned char data[4]  = {0xFF,0xFF,0xFF,0xFF};
    unsigned char pos      = 0;
    unsigned char d;
    //读取起始符
    //fread(start,1,4,g_h264_file);
    
    if(packetData[0] == 0x00 && packetData[1] == 0x00)
    {
        if(packetData[2]== 0x01)
        {
            m_nal.startcodesize = 3;
        }
        else if(packetData[2] == 0x00)
        {
            if(packetData[3] == 0x01)
            {
                //cout << "关键帧" << endl;
                m_nal.startcodesize = 4;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
    
    memcpy(m_nal.payload,packetData,size);
    m_nal.size = size; //copy到nal单元中
    return true;
}

/* 封装 SPS PPS */
void encapsulateSPSPPS()
{
    cout << "11111" << endl;
    FILE * fpVideo;
    fpVideo = fopen("444.flv", "ab+");   //以只读二进制方式打开文件
    if (!fpVideo)
    {
        printf("ERROR:open file failed!");
    }    
    unsigned char *sps     = (unsigned char*)malloc(m_nal.size);
    unsigned int   spsSize =  29;
    memcpy(sps,m_nal.payload,29);
    /*if(!readNal())
    {
        free(sps);
        printf("SPS after must be PPS\n");
        return;
    }*/
    //cout << "next: " << endl;
    //PrintBuffer(sps, spsSize);
    //sleep(10);
    //PrintBuffer(m_nal.payload, m_nal.size);
    //m_nal.nalType = (m_nal.payload[m_nal.startcodesize]&0x1F);//获取NAL类型
    m_nal.nalType = (m_nal.payload[33]&0x1F);
    //printf("Tpey: %02x\n", m_nal.payload[33]&0x1F);
    //sleep(1);
    if(m_nal.nalType != NAL_PPS)
    {
        printf("SPS after must be PPS\n");
    }
    setTagHeaderDataSize(spsSize - m_nal.startcodesize + 8 - m_nal.startcodesize + 5 + 11);//注意11是AVconfiguration数据长度
    writeTagHeader(); 
    unsigned char data[6] = {0x17,0x00,0x00,0x00,0x00,0x01};//关键帧 H264 AVC sequence header  Composition time offset = 00 00 00 configurationVersion 0x01
    fwrite(data,6,1,fpVideo);
    fwrite(sps + m_nal.startcodesize + 1,3,1,fpVideo);//写从SPS拷贝的前三个字节
    unsigned char reserveBit0 = 0xFC;//111111
    unsigned char lengthSizeMinusOne = m_nal.startcodesize - 1;
    unsigned char d = reserveBit0 + lengthSizeMinusOne;
    fwrite(&d,1,1,fpVideo);//NAL起始码字节数目
    unsigned char numOfSequenceParameterSets = 0xE1; 
    fwrite(&numOfSequenceParameterSets,1,1,fpVideo);//SPS个数1个
    unsigned char sequenceParameterSetLength[2];
    unsigned int s = spsSize - m_nal.startcodesize;
    sequenceParameterSetLength[1] = (unsigned char)(s&0xFF); s = s>>8;
    sequenceParameterSetLength[0] = (unsigned char)(s&0xFF); s = s>>8;
    fwrite(sequenceParameterSetLength,2,1,fpVideo);//写SPS长度
    fwrite(sps+m_nal.startcodesize,spsSize-m_nal.startcodesize,1,fpVideo);//写SPS

    free(sps);//释放内存

    unsigned char numOfPictureParameterSets = 0x01; //PPS个数
    fwrite(&numOfPictureParameterSets,1,1,fpVideo);//写PPS个数
    unsigned char pictureParameterSetLength[2];
    s = 8 - m_nal.startcodesize;
    pictureParameterSetLength[1] = (unsigned char)(s&0xFF); s = s>>8;
    pictureParameterSetLength[0] = (unsigned char)(s&0xFF); s = s>>8;
    fwrite(pictureParameterSetLength,2,1,fpVideo);//写PPS长度
    fwrite(m_nal.payload + m_nal.startcodesize,8-m_nal.startcodesize,1,fpVideo);//写PPS
    fclose(fpVideo);
}

/* 封装 NAL*/
void encapsulateNAL()
{
    /*FILE * fpVideos;
    fpVideos = fopen("789.flv", "ab+");
    fwrite(m_nal.payload,m_nal.size,1,fpVideos);
    fclose(fpVideos);*/
    FILE * fpVideo;
    fpVideo = fopen("444.flv", "ab+");   //以只读二进制方式打开文件
    setTagHeaderDataSize(m_nal.size - 41 + 5 + 4);//5为video头 4为NAL长度
    writeTagHeader(); 
    unsigned char data[5] = {0x17,0x01,0x00,0x00,0x00};//关键帧 H264 AVC sequence header  Composition time offset = 00 00 00 
    fwrite(data,5,1,fpVideo);

    unsigned char length[4];
    unsigned int s = m_nal.size - 41;
    length[3] = (unsigned char)(s&0xFF); s = s>>8;
    length[2] = (unsigned char)(s&0xFF); s = s>>8;
    length[1] = (unsigned char)(s&0xFF); s = s>>8;
    length[0] = (unsigned char)(s&0xFF); s = s>>8;
    //PrintBuffer(length, 4);
    //sleep(10);
    fwrite(length,4,1,fpVideo);//写NAL长度
    unsigned char test[m_nal.size-41];
    //memcpy(test,m_nal.payload+41,m_nal.size-41);
    //PrintBuffer(test, m_nal.size-41);

    /*FILE * fpVideoss;
    fpVideoss = fopen("987.flv", "ab+");
    fwrite(m_nal.payload+41,m_nal.size-41,1,fpVideoss);
    fclose(fpVideoss);
    sleep(10);*/
    fwrite(m_nal.payload + 41, m_nal.size-41,1,fpVideo);//写NAL
    fclose(fpVideo);

}

/* 封装 SEI*/
void encapsulateSEI()
{
    FILE * fpVideo;
    fpVideo = fopen("444.flv", "ab+");   //以只读二进制方式打开文件
    unsigned char  *sei     = (unsigned char*)malloc(m_nal.size);
    unsigned int   seiSize =  m_nal.size;
    memcpy(sei,m_nal.payload,m_nal.size);
    m_nal.nalType = (m_nal.payload[m_nal.startcodesize]&0x1F);//获取NAL类型
    if(m_nal.nalType != NAL_SLICE_IDR)
    {
        printf("SEI after must be IDR\n");;
    }
    setTagHeaderDataSize(seiSize - m_nal.startcodesize + m_nal.size - m_nal.startcodesize + 8 + 5);//注意8是两个NAL的长度
    writeTagHeader(); 

    unsigned char data[5] = {0x17,0x01,0x00,0x00,0x00};//关键帧 H264 AVC sequence header  Composition time offset = 00 00 00 
    fwrite(data,5,1,fpVideo);

    unsigned char length[4];
    unsigned int s = seiSize - m_nal.startcodesize;

    length[3] = (unsigned char)(s&0xFF); s = s>>8;
    length[2] = (unsigned char)(s&0xFF); s = s>>8;
    length[1] = (unsigned char)(s&0xFF); s = s>>8;
    length[0] = (unsigned char)(s&0xFF); s = s>>8;
    fwrite(length,4,1,fpVideo);//写NAL长度
    fwrite(sei + m_nal.startcodesize,seiSize-m_nal.startcodesize,1,fpVideo);//写NAL

    free(sei);

    s = m_nal.size - m_nal.startcodesize;

    length[3] = (unsigned char)(s&0xFF); s = s>>8;
    length[2] = (unsigned char)(s&0xFF); s = s>>8;
    length[1] = (unsigned char)(s&0xFF); s = s>>8;
    length[0] = (unsigned char)(s&0xFF); s = s>>8;
    fwrite(length,4,1,fpVideo);//写NAL长度
    fwrite(m_nal.payload + m_nal.startcodesize,m_nal.size-m_nal.startcodesize,1,fpVideo);//写NAL
    fclose(fpVideo);
}






int flv_init( const char *filename, int fps,int width,int height)
{
    setFlvHeader();
    writeFirstTagSize();
    writeMetaData();
    //sleep(1);
    return 0;
}


int flv_write_video_packet(unsigned char* packetData,int size,unsigned int ts)
{

    //PrintBuffer(packetData, size);
    //sleep(2);
    cout << "原始长度: " << size << endl;
    readNal(packetData, size);
    //m_nal.nalType = (m_nal.payload[m_nal.startcodesize]&0x1F);//获取NAL类型
    setTagHeader(TAGTYPE_VIDEO,ts);
    //printf("Type: %02x\n", m_nal.payload[m_nal.startcodesize]);
    //sleep(5);
    //cout << "m_nal.startcodesize:" << m_nal.nalType << endl;
    //cout << "Size:" << size << endl;
    //cout << "NAL_SPS" << endl;
    if(ts > 33){
        encapsulateSPSPPS();
        /* 写前一个Tag Size */
        writePreTagSize();
        encapsulateNAL();
        /* 写前一个Tag Size */
        writePreTagSize();
        m_DTS += 1000.0/25;
    }

    return 0;
}
不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^