好的,我终于有时间花在这上面并让它工作了!我敢肯定还有其他人会乞求知道如何做到这一点,所以就在这里。
您将需要自己的 FramedSource 来获取每一帧、编码并为流式传输做好准备,我将很快提供一些源代码。
基本上将您的 FramedSource 放入 H264VideoStreamDiscreteFramer,然后将其放入 H264RTPSink。像这样的东西
scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);   
framedSource = H264FramedSource::createNew(*env, 0,0);
h264VideoStreamDiscreteFramer 
= H264VideoStreamDiscreteFramer::createNew(*env, framedSource);
// initialise the RTP Sink stuff here, look at 
// testH264VideoStreamer.cpp to find out how
videoSink->startPlaying(*h264VideoStreamDiscreteFramer, NULL, videoSink);
env->taskScheduler().doEventLoop();
现在在您的主渲染循环中,将您保存到系统内存的后备缓冲区扔到您的 FramedSource 中,以便对其进行编码等。有关如何设置编码内容的更多信息,请查看此答案How do do one encode a series of使用 x264 C API 将图像转换为 H264?
我的实现非常处于 hacky 状态,并且根本没有优化,由于编码,我的 d3d 应用程序以大约 15fps 的速度运行,哎呀,所以我必须研究一下。但是出于所有意图和目的,这个 StackOverflow 问题得到了回答,因为我主要是在关注如何流式传输它。我希望这对其他人有所帮助。
至于我的 FramedSource,它看起来有点像这样
concurrent_queue<x264_nal_t> m_queue;
SwsContext* convertCtx;
x264_param_t param;
x264_t* encoder;
x264_picture_t pic_in, pic_out;
EventTriggerId H264FramedSource::eventTriggerId = 0;
unsigned H264FramedSource::FrameSize = 0;
unsigned H264FramedSource::referenceCount = 0;
int W = 720;
int H = 960;
H264FramedSource* H264FramedSource::createNew(UsageEnvironment& env,
                                              unsigned preferredFrameSize, 
                                              unsigned playTimePerFrame) 
{
        return new H264FramedSource(env, preferredFrameSize, playTimePerFrame);
}
H264FramedSource::H264FramedSource(UsageEnvironment& env,
                                   unsigned preferredFrameSize, 
                                   unsigned playTimePerFrame)
    : FramedSource(env),
    fPreferredFrameSize(fMaxSize),
    fPlayTimePerFrame(playTimePerFrame),
    fLastPlayTime(0),
    fCurIndex(0)
{
        if (referenceCount == 0) 
        {
        }
        ++referenceCount;
        x264_param_default_preset(¶m, "veryfast", "zerolatency");
        param.i_threads = 1;
        param.i_width = 720;
        param.i_height = 960;
        param.i_fps_num = 60;
        param.i_fps_den = 1;
        // Intra refres:
        param.i_keyint_max = 60;
        param.b_intra_refresh = 1;
        //Rate control:
        param.rc.i_rc_method = X264_RC_CRF;
        param.rc.f_rf_constant = 25;
        param.rc.f_rf_constant_max = 35;
        param.i_sps_id = 7;
        //For streaming:
        param.b_repeat_headers = 1;
        param.b_annexb = 1;
        x264_param_apply_profile(¶m, "baseline");
        encoder = x264_encoder_open(¶m);
        pic_in.i_type            = X264_TYPE_AUTO;   
        pic_in.i_qpplus1         = 0;
        pic_in.img.i_csp         = X264_CSP_I420;   
        pic_in.img.i_plane       = 3;
        x264_picture_alloc(&pic_in, X264_CSP_I420, 720, 920);
        convertCtx = sws_getContext(720, 960, PIX_FMT_RGB24, 720, 760, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
        if (eventTriggerId == 0) 
        {
            eventTriggerId = envir().taskScheduler().createEventTrigger(deliverFrame0);
        }
}
H264FramedSource::~H264FramedSource() 
{
    --referenceCount;
    if (referenceCount == 0) 
    {
        // Reclaim our 'event trigger'
        envir().taskScheduler().deleteEventTrigger(eventTriggerId);
        eventTriggerId = 0;
    }
}
void H264FramedSource::AddToBuffer(uint8_t* buf, int surfaceSizeInBytes)
{
    uint8_t* surfaceData = (new uint8_t[surfaceSizeInBytes]);
    memcpy(surfaceData, buf, surfaceSizeInBytes);
    int srcstride = W*3;
    sws_scale(convertCtx, &surfaceData, &srcstride,0, H, pic_in.img.plane, pic_in.img.i_stride);
    x264_nal_t* nals = NULL;
    int i_nals = 0;
    int frame_size = -1;
    frame_size = x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);
    static bool finished = false;
    if (frame_size >= 0)
    {
        static bool alreadydone = false;
        if(!alreadydone)
        {
            x264_encoder_headers(encoder, &nals, &i_nals);
            alreadydone = true;
        }
        for(int i = 0; i < i_nals; ++i)
        {
            m_queue.push(nals[i]);
        }   
    }
    delete [] surfaceData;
    surfaceData = NULL;
    envir().taskScheduler().triggerEvent(eventTriggerId, this);
}
void H264FramedSource::doGetNextFrame() 
{
    deliverFrame();
}
void H264FramedSource::deliverFrame0(void* clientData) 
{
    ((H264FramedSource*)clientData)->deliverFrame();
}
void H264FramedSource::deliverFrame() 
{
    x264_nal_t nalToDeliver;
    if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {
        if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
            // This is the first frame, so use the current time:
            gettimeofday(&fPresentationTime, NULL);
        } else {
            // Increment by the play time of the previous data:
            unsigned uSeconds   = fPresentationTime.tv_usec + fLastPlayTime;
            fPresentationTime.tv_sec += uSeconds/1000000;
            fPresentationTime.tv_usec = uSeconds%1000000;
        }
        // Remember the play time of this data:
        fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;
        fDurationInMicroseconds = fLastPlayTime;
    } else {
        // We don't know a specific play time duration for this data,
        // so just record the current time as being the 'presentation time':
        gettimeofday(&fPresentationTime, NULL);
    }
    if(!m_queue.empty())
    {
        m_queue.wait_and_pop(nalToDeliver);
        uint8_t* newFrameDataStart = (uint8_t*)0xD15EA5E;
        newFrameDataStart = (uint8_t*)(nalToDeliver.p_payload);
        unsigned newFrameSize = nalToDeliver.i_payload;
        // Deliver the data here:
        if (newFrameSize > fMaxSize) {
            fFrameSize = fMaxSize;
            fNumTruncatedBytes = newFrameSize - fMaxSize;
        }
        else {
            fFrameSize = newFrameSize;
        }
        memcpy(fTo, nalToDeliver.p_payload, nalToDeliver.i_payload);
        FramedSource::afterGetting(this);
    }
}
哦,对于那些想知道我的并发队列是什么的人,就在这里,它工作得很好http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-变量.html
享受和好运!