ffmpeg取流然后rtmp推流

第一步:使用ffmpeg取流,不解码

// TEST_RTMP.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "TranserStream.h"


#ifdef _WIN32
    #include <windows.h>
    #include <sys/timeb.h>
    #pragma warning(disable:4996)
#else

#endif

extern "C"
{
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libswscale/swscale.h"
    #include "libavdevice/avdevice.h"
    #include "libavutil/mathematics.h"
    #include "libavutil/time.h"
    #include "SDL2/include/SDL.h"
};

uint64_t TimeMilliSecond()
{
    timeb now;
    ftime(&now);
    return now.time * 1000 + now.millitm;
}


int _tmain(int argc, _TCHAR* argv[])
{
    TranserStream m_Transfer;
    m_Transfer.EnableWrite264(true);
    m_Transfer.EnableWriteFlv(true);
    m_Transfer.Init("rtmp://120.78.76.179:1935/hls/test");
    


    av_register_all();
    avformat_network_init();
    AVFormatContext* pFormatContext = avformat_alloc_context();
    if (avformat_open_input(&pFormatContext, "rtsp://192.168.0.105/live/main_stream", NULL, NULL) != 0) {
        return 0;
    }

    if (avformat_find_stream_info(pFormatContext, NULL) < 0) {
        return 0;
    }
    int dwVideoType = -1;
    for (int i = 0; i < pFormatContext->nb_streams; i++) {
        if (pFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            dwVideoType = i;
            break;
        }
    }
    AVCodecContext* pCodecContext = pFormatContext->streams[dwVideoType]->codec;
    AVCodec* pCodec = avcodec_find_decoder(pCodecContext->codec_id);
    if (avcodec_open2(pCodecContext, pCodec, NULL) != 0) {
        avformat_close_input(&pFormatContext);
        return 0;
    }

    int nGot = 0;
    AVFrame* pFrame = av_frame_alloc();
    AVFrame* pRGB = av_frame_alloc();
    AVPacket* pPacket = (AVPacket*)av_malloc(sizeof(AVPacket));

    int nPicSize = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecContext->width, pCodecContext->height);
    uint8_t* buf = (uint8_t*)av_malloc(nPicSize);

    if (buf == NULL) {
        printf("av malloc failed!\n");
        exit(1);
    }
    avpicture_fill((AVPicture*)pRGB, buf, AV_PIX_FMT_YUV420P, pCodecContext->width, pCodecContext->height);

    //SwsContext* pSws = sws_getContext(pCodecContext->width, pCodecContext->height, pCodecContext->pix_fmt, pCodecContext->width, pCodecContext->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
    while (true) {
        if (av_read_frame(pFormatContext, pPacket) >= 0) {
            if (pPacket->stream_index == dwVideoType) {
                if (avcodec_decode_video2(pCodecContext, pFrame, &nGot, pPacket) < 0) {
                    break;
                }
                if (nGot) {
                    //int nRet = sws_scale(pSws, pFrame->data, pFrame->linesize, 0, pCodecContext->height, pRGB->data, pRGB->linesize);

                    m_Transfer.PushData(pPacket->data, pPacket->size);
                }
            }
            av_free_packet(pPacket);
        }
        else {
            break;
        }
    }

    

    //sws_freeContext(pSws);
    av_free(pFrame);
    av_free(pRGB);
    av_free(buf);
    avcodec_close(pCodecContext);
    avformat_close_input(&pFormatContext);

    m_Transfer.UnInit();
    return 0;
}




第二步:推流

#include "stdafx.h"
#include "TranserStream.h"

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>


#pragma comment(lib, "ws2_32")


int GetLen(int nPos, int nTotalSize, BYTE* btData)
{
    int nStart = nPos;
    while (nStart < nTotalSize) {
        if (btData[nStart] == 0x00 && btData[nStart + 1] == 0x00 && btData[nStart + 2] == 0x01) {
            return nStart - nPos;
        }
        else if (btData[nStart] == 0x00 && btData[nStart + 1] == 0x00 && btData[nStart + 2] == 0x00 && btData[nStart + 3] == 0x01) {
            return nStart - nPos;
        }
        else {
            nStart++;
        }
    }
    return nTotalSize - nPos;//最后一帧。
}

unsigned char Convert(unsigned char btData)
{
    char cData[2048] = {0};
    sprintf(cData, "%02x", btData);

    return strtoull(cData, NULL, 16);
}

string TranserStream::GetFilePath(bool bValue)
{
#ifdef _WIN32
    SYSTEMTIME stInfo;
    GetLocalTime(&stInfo);

    char cName[2048] = { 0 };
    GetCurrentDirectoryA(2048, cName);

    if (!bValue) {
        sprintf(cName + strlen(cName), "\\%04d_%02d_%02d_%02d_%02d_%02d_%03d.264", stInfo.wYear, stInfo.wMonth, stInfo.wDay, stInfo.wHour, stInfo.wMinute, stInfo.wSecond, stInfo.wMilliseconds);
    }
    else {
        sprintf(cName + strlen(cName), "\\%04d_%02d_%02d_%02d_%02d_%02d_%03d.flv", stInfo.wYear, stInfo.wMonth, stInfo.wDay, stInfo.wHour, stInfo.wMinute, stInfo.wSecond, stInfo.wMilliseconds);
    }
    return cName;
#else

#endif
}

void TranserStream::InitFile264()
{
    string qstrFile = GetFilePath(false);
    m_pFile264 = fopen(qstrFile.c_str(), "ab+");
}
void TranserStream::InitFileFlv()
{
    string qstrFile = GetFilePath(true);
    m_pFileFlv = fopen(qstrFile.c_str(), "ab+");

    //
    Save_flv_header();
}

TranserStream::TranserStream()
{
#ifdef _WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

    //
    m_bWriteFile264 = false;
    m_bWriteFileFlv = false;

    //
    m_nspsLen = 0;
    m_nppsLen = 0;
    memset(m_spsData, 0, 2048);
    memset(m_ppsData, 0, 2048);

    //
    m_nIndex = 0;
    m_nPreTagSize = 0;

    //
    m_pData = NULL;
    while (!m_pData) {
        try {
            m_pData = new unsigned char[20 * 2048 * 2048];
        }
        catch (...) {}
    }

    //
    m_pTransferData = NULL;
    while (!m_pTransferData) {
        try{
            m_pTransferData = new unsigned char[40 * 1024 * 1024];
        }
        catch (...) {}
    }

    //
    m_hCLOSE_ALL_THREAD = CreateEvent(NULL, true, false, L"");//关闭事件
    m_threadOfParseData = (HANDLE)_beginthreadex(NULL, 0, ParseDataThread, this, 0, NULL);
    m_threadOfTransferData = (HANDLE)_beginthreadex(NULL, 0, TransferDataThread, this, 0, NULL);

    //
    InitFile264();
    InitFileFlv();
}
TranserStream::~TranserStream()
{
    if (m_pFile264) {
        fclose(m_pFile264);
    }
    if (m_pFileFlv) {
        fclose(m_pFileFlv);
    }

    SetEvent(m_hCLOSE_ALL_THREAD);

    WaitForSingleObject(m_threadOfParseData, INFINITE);
    CloseHandle(m_threadOfParseData);

    WaitForSingleObject(m_threadOfTransferData, INFINITE);
    CloseHandle(m_threadOfTransferData);

    CloseHandle(m_hCLOSE_ALL_THREAD);

#ifdef _WIN32
    WSACleanup();
#endif

    if (m_pData) {
        delete[]m_pData;
        m_pData = NULL;
    }

    if (m_pTransferData) {
        delete[] m_pTransferData;
        m_pTransferData = NULL;
    }
}

bool TranserStream::Init(char* pUrl)
{
    m_pRTMP = RTMP_Alloc();
    RTMP_Init(m_pRTMP);

    // 设置推流地址
    m_pRTMP->Link.timeout = 10;
    m_pRTMP->Link.lFlags |= RTMP_LF_LIVE;
    RTMP_SetupURL(m_pRTMP, pUrl);

    // 开启推流标志
    RTMP_EnableWrite(m_pRTMP);

    // 连接服务器
    int b = RTMP_Connect(m_pRTMP, NULL);
    if (!b)
    {
        return false;
    }

    // 连接流地址
    b = RTMP_ConnectStream(m_pRTMP, 0);
    if (!b)
    {
        return false;
    }
    return true;
}
void TranserStream::UnInit()
{
    RTMP_Close(m_pRTMP);
    RTMP_Free(m_pRTMP);
}



FrameData* TranserStream::MallocFrame(int nLen)
{
    FrameData* pstData = NULL;
    while (!pstData) {
        try {
            pstData = new FrameData;
        }
        catch (...) {}
    }

    pstData->pData = NULL;
    pstData->nLen = nLen;
    while (!pstData->pData) {
        try {
            pstData->pData = new unsigned char[nLen];
        }
        catch (...) {}
    }
    return pstData;
}

void TranserStream::SaveFile264(unsigned char* pData, uint32_t nLen)
{
    if (m_bWriteFile264) {
        if (m_pFile264) {
            fwrite(pData, 1, nLen, m_pFile264);

            long nSize = ftell(m_pFile264);
            if (nSize >= 100 * 1024 * 1024) {
                fclose(m_pFile264);
                m_pFile264 = NULL;
            }
        }
    }
}
void TranserStream::SaveFileFlv(unsigned char* pData, uint32_t nLen, bool bFlvHeader)
{
    if (m_bWriteFileFlv || bFlvHeader) {
        if (m_pFileFlv) {
            fwrite(pData, 1, nLen, m_pFileFlv);

            long nSize = ftell(m_pFileFlv);
            if (nSize >= 100 * 1024 * 1024) {
                fclose(m_pFileFlv);
                m_pFileFlv = NULL;
            }
        }
    }
}

void TranserStream::Save_flv_header()
{
    unsigned char btData[FLV_HEADER] = { 0x46, 0x4c, 0x56, 0x01, 0x01, 0x00, 0x00, 0x00, 0x09 };
    SaveFileFlv(btData, FLV_HEADER, true);

    Save_flv_script(614.28, 1920.0, 1080.0, 25.0, 7.0, 77777.0);
}
void TranserStream::Save_flv_script(double dbDuration, double dbWidth, double dbHeight, double dbFrameRate, double dbCodeID, double dvFileSize)
{
    unsigned char btScriptData[196] = { 0 };

    //script previous Tag size
    btScriptData[0] = 0x00;
    btScriptData[1] = 0x00;
    btScriptData[2] = 0x00;
    btScriptData[3] = 0x00;

    //
    btScriptData[4] = 0x12;//18:脚本

    //DataSize
    btScriptData[5] = 0x00;//
    btScriptData[6] = 0x00;//
    btScriptData[7] = 0xB8;//

    //TimeStamp
    btScriptData[8] = 0x00;
    btScriptData[9] = 0x00;
    btScriptData[10] = 0x00;

    //TimeStamp Extended
    btScriptData[11] = 0x00;

    //stram ID
    btScriptData[12] = 0x00;
    btScriptData[13] = 0x00;
    btScriptData[14] = 0x00;

    //------------------------------------------------------------------------------------
    //第一个AMF包类型,总为0x02
    btScriptData[15] = 0x02;

    //第一个AMF包数据长度
    btScriptData[16] = 0x00;
    btScriptData[17] = 0x0A;

    //onMetaData
    btScriptData[18] = 0x6f;
    btScriptData[19] = 0x6e;
    btScriptData[20] = 0x4d;
    btScriptData[21] = 0x65;
    btScriptData[22] = 0x74;
    btScriptData[23] = 0x61;
    btScriptData[24] = 0x44;
    btScriptData[25] = 0x61;
    btScriptData[26] = 0x74;
    btScriptData[27] = 0x61;

    //------------------------------------------------------------------------------------
    //第2个AMF包类型,总为0x08
    btScriptData[28] = 0x08;

    //medtaData count
    btScriptData[29] = 0x00;
    btScriptData[30] = 0x00;
    btScriptData[31] = 0x00;
    btScriptData[32] = 0x08;//metaData的数量

    //------------------------------------------------------------------------------------
    //时长
    btScriptData[33] = 0x00;
    btScriptData[34] = 0x08;//duration长度

    //duration字符串
    btScriptData[35] = 0x64;
    btScriptData[36] = 0x75;
    btScriptData[37] = 0x72;
    btScriptData[38] = 0x61;
    btScriptData[39] = 0x74;
    btScriptData[40] = 0x69;
    btScriptData[41] = 0x6f;
    btScriptData[42] = 0x6e;

    //.
    btScriptData[43] = 0x00;

    //duration数值
    {
        unsigned char* p = (unsigned char*)&dbDuration;

        char cDuration[sizeof(double)] = { 0 };//double 占8个字节
        for (int i = 0; i < sizeof(double); i++)
        {
            sprintf(cDuration, "%02x", p[i]);
        }

        int j = 0;
        for (int i = sizeof(double) - 1; i >= 0; i--) {
            btScriptData[44 + j] = cDuration[i];
            j++;
        }
    }
    

    //------------------------------------------------------------------------------------
    //width
    btScriptData[52] = 0x00;
    btScriptData[53] = 0x05;//width这5个字符的长度

    //width字符串
    btScriptData[54] = 0x77;
    btScriptData[55] = 0x69;
    btScriptData[56] = 0x64;
    btScriptData[57] = 0x74;
    btScriptData[58] = 0x68;

    //
    btScriptData[59] = 0x00;

    //
    {
        unsigned char* p = (unsigned char*)&dbWidth;

        char cData[sizeof(double)] = { 0 };//double 占8个字节
        for (int i = 0; i < sizeof(double); i++)
        {
            sprintf(cData, "%02x", p[i]);
        }

        int j = 0;
        for (int i = sizeof(double) - 1; i >= 0; i--) {
            btScriptData[60 + j] = cData[i];
            j++;
        }
    }

    //------------------------------------------------------------------------------------
    //height
    btScriptData[68] = 0x00;
    btScriptData[69] = 0x06;//height这5个字符的长度

    //height字符串
    btScriptData[70] = 0x77;
    btScriptData[71] = 0x69;
    btScriptData[72] = 0x64;
    btScriptData[73] = 0x74;
    btScriptData[74] = 0x68;
    btScriptData[75] = 0x74;

    //
    btScriptData[76] = 0x00;

    //
    {
        unsigned char* p = (unsigned char*)&dbHeight;

        char cData[sizeof(double)] = { 0 };//double 占8个字节
        for (int i = 0; i < sizeof(double); i++)
        {
            sprintf(cData, "%02x", p[i]);
        }

        int j = 0;
        for (int i = sizeof(double) - 1; i >= 0; i--) {
            btScriptData[77 + j] = cData[i];
            j++;
        }
    }

    //------------------------------------------------------------------------------------
    //videodatarate
    btScriptData[85] = 0x00;
    btScriptData[86] = 0x0D;//videodatarate这几个字符的长度

    //videodatarate字符串
    btScriptData[87] = 0x76;
    btScriptData[88] = 0x69;//
    btScriptData[88] = 0x64;
    btScriptData[90] = 0x65;//
    btScriptData[91] = 0x6f;
    btScriptData[92] = 0x64;//
    btScriptData[93] = 0x61;
    btScriptData[94] = 0x74;//
    btScriptData[95] = 0x61;
    btScriptData[96] = 0x72;//
    btScriptData[97] = 0x61;
    btScriptData[98] = 0x74;//
    btScriptData[99] = 0x65;//

    //.
    btScriptData[100] = 0x00;

    //
    btScriptData[101] = 0x00;//
    btScriptData[102] = 0x00;//
    btScriptData[103] = 0x00;
    btScriptData[104] = 0x00;//
    btScriptData[105] = 0x00;//
    btScriptData[106] = 0x00;
    btScriptData[107] = 0x00;//
    btScriptData[108] = 0x00;//

    //------------------------------------------------------------------------------------
    //framerate
    btScriptData[109] = 0x00;
    btScriptData[110] = 0x09;//这几个字符的长度

    //framerate字符串
    btScriptData[111] = 0x66;
    btScriptData[112] = 0x72;//
    btScriptData[113] = 0x61;
    btScriptData[114] = 0x6d;//
    btScriptData[115] = 0x65;
    btScriptData[116] = 0x72;//
    btScriptData[117] = 0x61;
    btScriptData[118] = 0x74;//
    btScriptData[119] = 0x65;


    //.
    btScriptData[120] = 0x00;

    //
    {
        unsigned char* p = (unsigned char*)&dbFrameRate;

        char cData[sizeof(double)] = { 0 };//double 占8个字节
        for (int i = 0; i < sizeof(double); i++)
        {
            sprintf(cData, "%02x", p[i]);
        }

        int j = 0;
        for (int i = sizeof(double) - 1; i >= 0; i--) {
            btScriptData[121 + j] = cData[i];
            j++;
        }
    }

    //------------------------------------------------------------------------------------
    //videocodecid
    btScriptData[129] = 0x00;
    btScriptData[130] = 0x0c;//这几个字符的长度

    //videocodecid字符串
    btScriptData[131] = 0x76;
    btScriptData[132] = 0x69;//
    btScriptData[133] = 0x64;
    btScriptData[134] = 0x65;//
    btScriptData[135] = 0x6f;
    btScriptData[136] = 0x63;//
    btScriptData[137] = 0x6f;
    btScriptData[138] = 0x64;//
    btScriptData[139] = 0x65;
    btScriptData[140] = 0x63;
    btScriptData[141] = 0x69;//
    btScriptData[142] = 0x64;

    //
    btScriptData[143] = 0x00;

    //
    {
        unsigned char* p = (unsigned char*)&dbCodeID;

        char cData[sizeof(double)] = { 0 };//double 占8个字节
        for (int i = 0; i < sizeof(double); i++)
        {
            sprintf(cData, "%02x", p[i]);
        }

        int j = 0;
        for (int i = sizeof(double) - 1; i >= 0; i--) {
            btScriptData[144 + j] = cData[i];
            j++;
        }
    }

    //------------------------------------------------------------------------------------
    //encoder
    btScriptData[152] = 0x00;
    btScriptData[153] = 0x07;//这几个字符的长度

    btScriptData[154] = 0x65;
    btScriptData[155] = 0x6e;//
    btScriptData[156] = 0x63;
    btScriptData[157] = 0x6f;//
    btScriptData[158] = 0x64;
    btScriptData[159] = 0x65;//
    btScriptData[160] = 0x72;

    //.
    btScriptData[161] = 0x02;
    btScriptData[162] = 0x00;

    //
    btScriptData[163] = 0x0d;
    btScriptData[164] = 0x4c;
    btScriptData[165] = 0x61;
    btScriptData[166] = 0x76;
    btScriptData[167] = 0x66;
    btScriptData[168] = 0x35;
    btScriptData[169] = 0x37;
    btScriptData[170] = 0x2e;
    btScriptData[171] = 0x35;
    btScriptData[172] = 0x36;
    btScriptData[173] = 0x2e;
    btScriptData[174] = 0x31;
    btScriptData[175] = 0x30;
    btScriptData[176] = 0x31;

    //------------------------------------------------------------------------------------
    //encoder
    btScriptData[177] = 0x00;
    btScriptData[178] = 0x08;//这几个字符的长度

    btScriptData[179] = 0x66;
    btScriptData[180] = 0x69;
    btScriptData[181] = 0x6c;
    btScriptData[182] = 0x65;
    btScriptData[183] = 0x73;
    btScriptData[184] = 0x69;
    btScriptData[185] = 0x7a;
    btScriptData[186] = 0x65;

    //
    btScriptData[187] = 0x00;

    //
    {
        unsigned char* p = (unsigned char*)&dvFileSize;

        char cData[sizeof(double)] = { 0 };//double 占8个字节
        for (int i = 0; i < sizeof(double); i++)
        {
            sprintf(cData, "%02x", p[i]);
        }

        int j = 0;
        for (int i = sizeof(double) - 1; i >= 0; i--) {
            btScriptData[188 + j] = cData[i];
            j++;
        }
    }
    SaveFileFlv(btScriptData, 196, true);

    //List Terminator  解析见表SCRIPTDATAOBJECTEND  (数组结束位,占3个字节 一定为 0x 00 00 09)
    unsigned char btDataOfTerminator[3] = { 0x00, 0x00, 0x09 };
    SaveFileFlv(btDataOfTerminator, 3, true);

    //
    //unsigned char btData[PREVIOUS_TAG_SIZE] = {0x00, 0x00, 0x00, 0xc3};
    //SaveFileFlv(btData, PREVIOUS_TAG_SIZE, true);

    m_nPreTagSize = 0xc3;
}
void TranserStream::Save_flv_spsData(uint8_t nType)
{
    //1个字节的FrameType
    //1个字节的AVC Packet Type
    //3个字节的CompositionTime Offset
    //1个字节的ConfigurationVersion
    //1个字节的AVC Profile Indication
    //1个字节的profile compatibility
    //1个字节的AVC Level Indication
    //1个字节的LengthSizeMinusOne
    //1个字节的sps的个数
    //2个字节的sps的长度
    //1个字节的pps的个数
    //2个字节的pps的长度
    int nLen = m_nspsLen + m_nppsLen + 16;

    unsigned char btTagHeader[TAG_HEADER] = { 0x00 };

    //Tag类型:
            //8:音频   
            //9:视频    
            //18:脚本     
            //其他:保留
    btTagHeader[0] = nType;

    //数据长度
    btTagHeader[1] = (nLen >> 16) & 0xff;
    btTagHeader[2] = (nLen >> 8) & 0xff;
    btTagHeader[3] = nLen & 0xff;

    //时间戳
    btTagHeader[4] = 0;
    btTagHeader[5] = 0;
    btTagHeader[6] = 0;
    btTagHeader[7] = 0;

    //streamID
    btTagHeader[8] = 0;
    btTagHeader[9] = 0;
    btTagHeader[10] = 0;


    //------------------------------------------------------------------------------
    //Tag Data
    unsigned char btAVCData[2048] = { 0 };

    //Tag Data的第一个字节是视频信息或音频信息
        //帧类型(4 bit):
                //1: keyframe(for AVC, a seekable frame)
                //2 : inter frame(for AVC, a non - seekable frame)
                //3 : disposable inter frame(H.263 only)
                //4 : generated keyframe(reserved for server use only)
                //5 : video info / command frame
        //编码ID(4 bit):
                //1: JPEG(currently unused)
                //2 : Sorenson H.263
                //3 : Screen video
                //4 : On2 VP6
                //5 : On2 VP6 with alpha channel
                //6 : Screen video version 2
                //7 : AVC
    btAVCData[0] = 0x17;//看注释.关键帧且为AVC数据

    //AVC Packet Type
    //0: AVC sequence header
    //1: AVC NALU
    //2: AVC end of sequence
    btAVCData[1] = 0x00;

    //CompositionTime Offset
    btAVCData[2] = 0x00;//默认为0
    btAVCData[3] = 0x00;
    btAVCData[4] = 0x00;


    btAVCData[5] = 1;// 版本号
    btAVCData[6] = m_spsData[1];//将sps的从第2位开始的三个数据拷贝进来
    btAVCData[7] = m_spsData[2];
    btAVCData[8] = m_spsData[3];
    btAVCData[9] = 0xff;//需要查看其他情况下的值是多少

    //二进制 1110 0000 + sps个数
    btAVCData[10] = 0xe0 + 1;

    //sps 数据长度
    btAVCData[11] = (m_nspsLen >> 8) & 0xff;
    btAVCData[12] = m_nspsLen & 0xff;

    //sps 数据
    memcpy(btAVCData + 13, m_spsData, m_nspsLen);

    //pps个数
    btAVCData[m_nspsLen + 13] = 1;

    //pps 数据长度
    btAVCData[m_nspsLen + 14] = (m_nppsLen >> 8) & 0xff;
    btAVCData[m_nspsLen + 15] = m_nppsLen & 0xff;

    //pps 数据
    memcpy(btAVCData + m_nspsLen + 16, m_ppsData, m_nppsLen);

    //
    Transer(nType, btAVCData, nLen, 0);

    //------------------------------------------------------------------------------------------------------------------
    //preTag 长度
    unsigned char btPreTagData[4] = { 0 };
    btPreTagData[0] = (m_nPreTagSize >> 24) & 0xff;
    btPreTagData[1] = (m_nPreTagSize >> 16) & 0xff;
    btPreTagData[2] = (m_nPreTagSize >> 8) & 0xff;
    btPreTagData[3] = m_nPreTagSize & 0xff;
    SaveFileFlv( btPreTagData, 4);

    //
    SaveFileFlv( btTagHeader, TAG_HEADER);
    SaveFileFlv( btAVCData, m_nspsLen + m_nppsLen + 16);

    //------------------------------------------------------------------------------------------------------------------
    //
    m_nIndex++;
    m_nPreTagSize = TAG_HEADER + nLen;
}

void TranserStream::Saveflv_toFile(unsigned char* pData, uint32_t nLen, uint8_t nType)
{
#define TAG_DATA_NALU_HEADER    9
    unsigned char btTagHeader[TAG_HEADER] = { 0x00 };

    //Tag类型:
            //8:音频
            //9:视频
            //18:脚本
            //其他:保留
    btTagHeader[0] = nType;

    //数据长度
    btTagHeader[1] = ((nLen + TAG_DATA_NALU_HEADER) >> 16) & 0xff;
    btTagHeader[2] = ((nLen + TAG_DATA_NALU_HEADER) >> 8) & 0xff;
    btTagHeader[3] = (nLen + TAG_DATA_NALU_HEADER) & 0xff;

    //时间戳
    unsigned long long nTime = m_nIndex * 40;
    btTagHeader[4] = Convert(((nTime) >> 16) & 0xff);
    btTagHeader[5] = Convert(((nTime) >> 8) & 0xff);
    btTagHeader[6] = Convert(nTime & 0xff);
    btTagHeader[7] = 0;

    //streamID
    btTagHeader[8] = 0;
    btTagHeader[9] = 0;
    btTagHeader[10] = 0;

    //
    m_nIndex++;


    //-------------------------------------------------------------------
    //
    unsigned char btAVCData[TAG_DATA_NALU_HEADER] = {0};
    if ((pData[0] & 0x1f) == 0x05) {//关键帧
        btAVCData[0] = 0x17;//看注释.关键帧且为AVC数据
    }
    else {
        btAVCData[0] = 0x27;//看注释.关键帧且为AVC数据
    }

    if ((pData[0] & 0x1f) == 7 || (pData[0] & 0x1f) == 8) {//sps帧和pps帧
        btAVCData[1] = 0x00;
    }
    else {
        btAVCData[1] = 0x01;
    }
    btAVCData[2] = Convert(((nTime) >> 16) & 0xff);
    btAVCData[3] = Convert(((nTime) >> 8) & 0xff);
    btAVCData[4] = Convert(nTime & 0xff);

    btAVCData[5] = (nLen >> 24) & 0xff;
    btAVCData[6] = (nLen >> 16) & 0xff;
    btAVCData[7] = (nLen >> 8) & 0xff;
    btAVCData[8] = nLen & 0xff;

    //
    memcpy(m_pTransferData, btAVCData, TAG_DATA_NALU_HEADER);
    memcpy(m_pTransferData + TAG_DATA_NALU_HEADER, pData, nLen);
    Transer(nType, m_pTransferData, nLen + TAG_DATA_NALU_HEADER, nTime);

    //preTag 长度
    unsigned char btPreTagData[4] = { 0 };
    btPreTagData[0] = (m_nPreTagSize >> 24) & 0xff;
    btPreTagData[1] = (m_nPreTagSize >> 16) & 0xff;
    btPreTagData[2] = (m_nPreTagSize >> 8) & 0xff;
    btPreTagData[3] = m_nPreTagSize & 0xff;
    SaveFileFlv( btPreTagData, 4);

    //
    SaveFileFlv( btTagHeader, TAG_HEADER);
    SaveFileFlv( btAVCData, TAG_DATA_NALU_HEADER);
    SaveFileFlv( pData, nLen);

    //
    m_nPreTagSize = TAG_HEADER + TAG_DATA_NALU_HEADER + nLen;
}

void TranserStream::PushData(unsigned char* pData, uint32_t nLen)
{
    SaveFile264(pData, nLen);

    //
    FrameData* pstData = MallocFrame(nLen);
    memcpy(pstData->pData, pData, nLen);

    //
    m_mutexOfPacket.lock();
    m_vPacketData.push_back(pstData);
    m_mutexOfPacket.unlock();
}
void TranserStream::ParseData(unsigned char* pData, uint32_t dwFileSize)
{
    int j = 0;//多少帧
    int i = 0;//偏移量
    while (i < dwFileSize - H264_HEADER2) {
        if (pData[i] == 0x00 && pData[i + 1] == 0x00 && pData[i + 2] == 0x01) {
            int nLen = GetLen(i + H264_HEADER1, dwFileSize, (unsigned char*)pData);

            FrameData* pstData = MallocFrame(nLen);

            memset(pstData->pData, 0, nLen);
            memcpy(pstData->pData, &pData[i + H264_HEADER1], nLen);

            //
            m_mutexOfFrame.lock();
            m_vFrameData.push_back(pstData);
            m_mutexOfFrame.unlock();

            j++;
            i += H264_HEADER1;
        }
        else if (pData[i] == 0x00 && pData[i + 1] == 0x00 && pData[i + 2] == 0x00 && pData[i + 3] == 0x01) {
            int nLen = GetLen(i + H264_HEADER2, dwFileSize, (unsigned char*)pData);
            FrameData* pstData = MallocFrame(nLen);

            memset(pstData->pData, 0, nLen);
            memcpy(pstData->pData, &pData[i + H264_HEADER2], nLen);

            //
            m_mutexOfFrame.lock();
            m_vFrameData.push_back(pstData);
            m_mutexOfFrame.unlock();

            //
            j++;
            i += H264_HEADER2;
        }
        else {
            i++;
        }
    }
}

unsigned int TranserStream::ParseDataThread(void* args)
{
    TranserStream* pThis = (TranserStream*)args;

    while (true) {
        if (WaitForSingleObject(pThis->m_hCLOSE_ALL_THREAD, 0) == WAIT_OBJECT_0) {
            break;
        }
        FrameData* pstData = NULL;
        pThis->m_mutexOfPacket.lock();
        if (pThis->m_vPacketData.size() > 0) {
            pstData = pThis->m_vPacketData[0];
            pThis->m_vPacketData.erase(pThis->m_vPacketData.begin());
        }
        pThis->m_mutexOfPacket.unlock();

        if (pstData) {
            pThis->ParseData(pstData->pData, pstData->nLen);
            delete pstData;
            pstData = NULL;
        }
    }

    return 0;
}
unsigned int TranserStream::TransferDataThread(void* args)
{
    bool b_sps_exists = false;
    bool b_pps_exists = false;
    TranserStream* pThis = (TranserStream*)args;
    while (true) {
        if (WaitForSingleObject(pThis->m_hCLOSE_ALL_THREAD, 0) == WAIT_OBJECT_0) {
            break;
        }

        FrameData* pstData = NULL;
        pThis->m_mutexOfFrame.lock();
        if (pThis->m_vFrameData.size() > 0) {
            pstData = pThis->m_vFrameData[0];
            pThis->m_vFrameData.erase(pThis->m_vFrameData.begin());
        }
        pThis->m_mutexOfFrame.unlock();

        if (pstData) {
            if ((pstData->pData[0] & 0x1f) == 7) {//sps
                pThis->m_nspsLen = pstData->nLen;
                b_sps_exists = true;
                memset(pThis->m_spsData, 0, 2048);
                memcpy(pThis->m_spsData, pstData->pData, pstData->nLen);
            }
            else if ((pstData->pData[0] & 0x1f) == 8) {//pps
                pThis->m_nppsLen = pstData->nLen;
                b_pps_exists = true;
                memset(pThis->m_ppsData, 0, 2048);
                memcpy(pThis->m_ppsData, pstData->pData, pstData->nLen);
            }
            else {//关键帧
                pThis->Saveflv_toFile(pstData->pData, pstData->nLen, TagType_Video);
            }
            delete pstData;
            pstData = NULL;
        }
        if (b_sps_exists && b_pps_exists) {
            b_sps_exists = false;
            b_pps_exists = false;
            pThis->Save_flv_spsData(TagType_Video);
        }
    }
    return 0;
}


void TranserStream::EnableWrite264(bool bValue)
{
    m_bWriteFile264 = bValue;
}
void TranserStream::EnableWriteFlv(bool bValue)
{
    m_bWriteFileFlv = bValue;
}
bool TranserStream::Transer(uint8_t nType, unsigned char* pData, uint32_t nLen, uint32_t timestamp)
{
    // 初使化RTMP报文
    RTMPPacket* packet = (RTMPPacket*)malloc(RTMP_HEAD_SIZE + nLen);
    memset(packet, 0, RTMP_HEAD_SIZE);

    packet->m_body = (char*)packet + RTMP_HEAD_SIZE;
    packet->m_nBodySize = nLen;
    memcpy(packet->m_body, pData, nLen);
    packet->m_hasAbsTimestamp = 0;
    packet->m_packetType = nType;

    packet->m_nInfoField2 = m_pRTMP->m_stream_id;
    packet->m_nChannel = 6;
    

    // 组织报文并发送
    packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
    if (RTMP_PACKET_TYPE_AUDIO == nType && nLen != 4)
    {
        packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
    }

    packet->m_nTimeStamp = timestamp;
    

    if (!RTMP_SendPacket(m_pRTMP, packet, 0))
    {
        free(packet);
        return false;
    }


    free(packet);
    return true;
}

Demo:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值