VirtualBox

Changeset 65330 in vbox


Ignore:
Timestamp:
Jan 16, 2017 1:38:36 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
112908
Message:

VideoRec: Update.

Location:
trunk/src/VBox/Main/src-client
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp

    r65281 r65330  
    9696    AVRECCODEC           Codec;
    9797    /** (Audio) frame buffer. */
     98    PRTCIRCBUF           pCircBuf;
    9899    uint8_t             *pvFrameBuf;
    99100    size_t               cbFrameBufSize;
     
    121122     *  See the AVRECMODE enumeration for more information. */
    122123    WebMWriter          *pEBML;
     124    /** Track number for audio data. */
     125    uint8_t              uTrack;
    123126} DRVAUDIOVIDEOREC, *PDRVAUDIOVIDEOREC;
    124127
     
    141144
    142145#ifdef VBOX_WITH_LIBOPUS
     146    RTCircBufCreate(&pStreamOut->pCircBuf, _4K);
     147
    143148    rc = DrvAudioHlpStreamCfgToProps(pCfgReq, &pStreamOut->Props);
    144149    if (RT_SUCCESS(rc))
    145150    {
    146         size_t cbFrameBuf = sizeof(uint8_t) * _8K; /** @todo Make this configurable */
     151        size_t cbFrameBuf = sizeof(uint8_t) * _4K; /** @todo Make this configurable */
    147152
    148153        pStreamOut->pvFrameBuf = (uint8_t *)RTMemAlloc(cbFrameBuf);
     
    235240                                          WebMWriter::AudioCodec_Opus, WebMWriter::VideoCodec_None);
    236241                if (RT_SUCCESS(rc))
    237                     rc = pThis->pEBML->AddAudioTrack(44100, 2, 16);
     242                    rc = pThis->pEBML->AddAudioTrack(44100, 2, 16, &pThis->uTrack);
    238243                break;
    239244            }
     
    285290 */
    286291static DECLCALLBACK(int) drvAudioVideoRecStreamPlay(PPDMIHOSTAUDIO pInterface,
    287                                                     PPDMAUDIOSTREAM pStream, const void *pvBuf, uint32_t cbBuf,
     292                                                    PPDMAUDIOSTREAM pStream, const void *pvBuf2, uint32_t cbBuf2,
    288293                                                    uint32_t *pcbWritten)
    289294{
    290     RT_NOREF2(pvBuf, cbBuf);
     295    RT_NOREF2(pvBuf2, cbBuf2);
    291296
    292297    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    319324                 pStreamOut->Props.cBits, pStreamOut->Props.fSigned, cSamplesToSend));
    320325
    321     uint32_t csRead = 0;
     326    uint32_t csReadTotal = 0;
    322327
    323328    int rc;
     
    329334
    330335    /** @todo For now we ASSUME 25 FPS. */
    331     uint16_t csFrameSize = /*pStreamOut->Props.uHz*/ 48000 / 25;
    332     size_t   cbFrameSize = AUDIOMIXBUF_S2B(&pStream->MixBuf, csFrameSize);
    333 
    334     rc = AudioMixBufReadCirc(&pStream->MixBuf, (uint8_t *)&pStreamOut->pvFrameBuf[pStreamOut->offFrameBufWrite],
    335                              pStreamOut->cbFrameBufSize - pStreamOut->offFrameBufWrite, &csRead);
    336     if (RT_SUCCESS(rc))
    337     {
    338         const uint32_t cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, csRead);
    339 
    340         pStreamOut->offFrameBufWrite =
    341             (pStreamOut->offFrameBufWrite + cbRead) % pStreamOut->cbFrameBufSize;
    342         Assert(pStreamOut->offFrameBufWrite <= pStreamOut->cbFrameBufSize);
    343         pStreamOut->cbFrameBufUsed  += cbRead;
    344         Assert(pStreamOut->cbFrameBufUsed  <= pStreamOut->cbFrameBufSize);
    345 
    346         if (pStreamOut->cbFrameBufUsed >= cbFrameSize)
     336    uint16_t cbFrameSize = (/*pStreamOut->Props.uHz*/ 48000 / 25 /* FPS */);
     337
     338    PRTCIRCBUF pCircBuf = pStreamOut->pCircBuf;
     339
     340    while (pStreamOut->cbFrameBufUsed < cbFrameSize)
     341    {
     342        void  *pvBuf;
     343        size_t cbBuf;
     344        RTCircBufAcquireWriteBlock(pCircBuf, RTCircBufFree(pCircBuf), &pvBuf, &cbBuf);
     345
     346        uint32_t cbRead = 0;
     347
     348        if (cbBuf)
    347349        {
    348             /* Opus always encodes PER FRAME, that is, 2.5, 5, 10, 20, 40 or 60 ms of audio data. */
     350            uint32_t csRead = 0;
     351            rc = AudioMixBufReadCirc(&pStream->MixBuf, pvBuf, cbBuf, &csRead);
     352            if (RT_SUCCESS(rc))
     353            {
     354                AudioMixBufFinish(&pStream->MixBuf, csRead);
     355
     356                cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, csRead);
     357                csReadTotal += csRead;
     358            }
     359        }
     360
     361        RTCircBufReleaseWriteBlock(pCircBuf, cbRead);
     362
     363        if (   RT_FAILURE(rc)
     364            || !cbRead)
     365        {
     366            break;
     367        }
     368
     369        if (RTCircBufUsed(pCircBuf) >= cbFrameSize)
     370        {
     371            uint8_t abSrc[_4K];
     372            size_t  cbSrc = 0;
     373
     374            while (cbSrc < cbFrameSize)
     375            {
     376                RTCircBufAcquireReadBlock(pCircBuf, cbFrameSize - cbSrc, &pvBuf, &cbBuf);
     377
     378                if (cbBuf)
     379                {
     380                    memcpy(&abSrc[cbSrc], pvBuf, cbBuf);
     381
     382                    cbSrc += cbBuf;
     383                    Assert(cbSrc <= sizeof(abSrc));
     384                }
     385
     386                RTCircBufReleaseReadBlock(pCircBuf, cbBuf);
     387
     388                if (!cbBuf)
     389                    break;
     390            }
     391
     392            /*
     393             * Opus always encodes PER FRAME, that is, 2.5, 5, 10, 20, 40 or 60 ms of audio data.
     394             *
     395             * A packet can have up to 120ms worth of audio data.
     396             * Anything > 120ms of data will result in a "corrupted package" error message by
     397             * by decoding application.
     398             */
    349399            uint8_t abDst[_4K];
    350400            size_t  cbDst = sizeof(abDst);
    351401
    352402            /* Call the encoder to encode our input samples. */
     403            opus_encoder_ctl(pStreamOut->Codec.Opus.pEnc, OPUS_SET_BITRATE(196000)); /** @todo */
    353404            opus_int32 cbWritten = opus_encode(pStreamOut->Codec.Opus.pEnc,
    354                                                (opus_int16 *)&pStreamOut->pvFrameBuf[pStreamOut->offFrameBufRead],
    355                                                csFrameSize, abDst, cbDst);
     405                                               (opus_int16 *)abSrc, cbSrc, abDst, cbDst);
    356406            if (cbWritten > 0)
    357407            {
    358                 pStreamOut->offFrameBufRead = (pStreamOut->offFrameBufRead + cbWritten) % pStreamOut->cbFrameBufSize;
    359                 Assert(pStreamOut->cbFrameBufUsed >= cbFrameSize);
    360                 pStreamOut->cbFrameBufUsed -= cbFrameSize;
    361 
    362408                /* Call the WebM writer to actually write the encoded audio data. */
    363409                WebMWriter::BlockData_Opus blockData = { abDst, cbDst };
    364                 rc = pThis->pEBML->WriteBlock(WebMWriter::BlockType_Audio, &blockData, sizeof(blockData));
     410                rc = pThis->pEBML->WriteBlock(pThis->uTrack, &blockData, sizeof(blockData));
    365411                AssertRC(rc);
    366412            }
    367413            else if (cbWritten < 0)
     414            {
    368415                AssertMsgFailed(("Encoding failed: %s\n", opus_strerror(cbWritten)));
     416                rc = VERR_INVALID_PARAMETER;
     417            }
     418
     419            if (RT_FAILURE(rc))
     420                break;
    369421        }
    370422    }
     
    372424    rc = VERR_NOT_SUPPORTED;
    373425#endif /* VBOX_WITH_LIBOPUS */
    374 
    375     if (csRead)
    376         AudioMixBufFinish(&pStream->MixBuf, csRead);
    377426
    378427    /*
     
    381430     */
    382431    if (pcbWritten)
    383         *pcbWritten = csRead;
    384 
    385     LogFlowFunc(("csRead=%RU32, rc=%Rrc\n", csRead, rc));
     432        *pcbWritten = csReadTotal;
     433
     434    LogFlowFunc(("csReadTotal=%RU32, rc=%Rrc\n", csReadTotal, rc));
    386435    return rc;
    387436}
     
    393442    RT_NOREF(pThis);
    394443    PAVRECSTREAMOUT   pStreamOut = (PAVRECSTREAMOUT)pStream;
     444
     445    if (pStreamOut->pCircBuf)
     446    {
     447        RTCircBufDestroy(pStreamOut->pCircBuf);
     448        pStreamOut->pCircBuf = NULL;
     449    }
    395450
    396451    if (pStreamOut->pvFrameBuf)
  • trunk/src/VBox/Main/src-client/EbmlWriter.cpp

    r65308 r65330  
    1818
    1919#include <list>
     20#include <map>
    2021#include <stack>
    2122#include <iprt/asm.h>
     
    295296    struct WebMTrack
    296297    {
    297         WebMTrack(WebMTrackType a_enmType, uint64_t a_offID)
     298        WebMTrack(WebMTrackType a_enmType, uint8_t a_uTrack, uint64_t a_offID)
    298299            : enmType(a_enmType)
     300            , uTrack(a_uTrack)
    299301            , offID(a_offID)
    300302        {
    301             uID = RTRandU32();
     303            uUUID = RTRandU32();
    302304        }
    303305
    304306        /** The type of this track. */
    305307        WebMTrackType enmType;
    306         /** The track's UUID. */
    307         uint32_t      uID;
     308        /** Track parameters. */
     309        union
     310        {
     311            struct
     312            {
     313                /** Sample rate of input data. */
     314                uint16_t uHzIn;
     315                /** Sample rate the codec is using. */
     316                uint16_t uHzCodec;
     317                /** Frame size (in bytes), based on the codec sample rate. */
     318                size_t   cbFrameSize;
     319            } Audio;
     320        };
     321        /** This track's track number. Also used as key in track map. */
     322        uint8_t       uTrack;
     323        /** The track's "UUID".
     324         *  Needed in case this track gets mux'ed with tracks from other files. Not really unique though. */
     325        uint32_t      uUUID;
    308326        /** Absolute offset in file of track ID.
    309327         *  Needed to write the hash sum within the footer. */
     
    367385    std::list<WebMCueEntry>     m_lstCue;
    368386
    369     /** List of tracks. */
    370     std::list<WebMTrack>        m_lstTracks;
     387    /** Map of tracks.
     388     *  The key marks the track number (*not* the UID!). */
     389    std::map <uint8_t, WebMTrack *> m_mapTracks;
     390    /** Whether we're currently in an opened tracks segment. */
    371391    bool                        m_fTracksOpen;
    372392
     
    380400
    381401    Ebml                        m_Ebml;
     402
     403public:
     404
     405    typedef std::map <uint8_t, WebMTrack *> WebMTracks;
    382406
    383407public:
     
    397421        , m_offSegClusterStart(0) {}
    398422
    399     int AddAudioTrack(uint16_t uHz, uint8_t cChannels, uint8_t cBits)
     423    virtual ~WebMWriter_Impl()
     424    {
     425        close();
     426    }
     427
     428    int AddAudioTrack(uint16_t uHz, uint8_t cChannels, uint8_t cBits, uint8_t *puTrack)
    400429    {
    401430#ifdef VBOX_WITH_LIBOPUS
    402431        m_Ebml.subStart(TrackEntry);
    403         m_Ebml.serializeUnsignedInteger(TrackNumber, (uint8_t)m_lstTracks.size());
     432        m_Ebml.serializeUnsignedInteger(TrackNumber, (uint8_t)m_mapTracks.size());
    404433        /** @todo Implement track's "Language" property? Currently this defaults to English ("eng"). */
    405434
    406         WebMTrack TrackAudio(WebMTrackType_Audio, RTFileTell(m_Ebml.getFile()));
    407         m_lstTracks.push_back(TrackAudio);
    408 
    409         if (uHz >= 44100)
    410             uHz = 48000;
     435        uint8_t uTrack = m_mapTracks.size();
     436
     437        WebMTrack *pTrack = new WebMTrack(WebMTrackType_Audio, uTrack, RTFileTell(m_Ebml.getFile()));
     438
     439        /* Clamp the codec rate value if it reaches a certain threshold. */
     440        if      (uHz > 24000) pTrack->Audio.uHzCodec = 48000;
     441        else if (uHz > 16000) pTrack->Audio.uHzCodec = 24000;
     442        else if (uHz > 12000) pTrack->Audio.uHzCodec = 16000;
     443        else if (uHz > 8000 ) pTrack->Audio.uHzCodec = 12000;
     444        else                  pTrack->Audio.uHzCodec = 8000;
     445
     446        pTrack->Audio.uHzIn = uHz;
     447
     448        /** @todo 1920 bytes is 40ms worth of audio data. Make this configurable. */
     449        pTrack->Audio.cbFrameSize =  1920 / (48000 / pTrack->Audio.uHzCodec);
    411450
    412451        /** @todo Resolve codec type. */
    413452        OpusPrivData opusPrivData(uHz, cChannels);
    414453
    415         m_Ebml.serializeUnsignedInteger(TrackUID, TrackAudio.uID, 4)
     454        m_Ebml.serializeUnsignedInteger(TrackUID, pTrack->uUUID, 4)
    416455              .serializeUnsignedInteger(TrackType, 2 /* Audio */)
    417456              .serializeString(CodecID, "A_OPUS")
     
    420459              .serializeUnsignedInteger(SeekPreRoll, 80000000)
    421460              .subStart(Audio)
    422                   .serializeFloat(SamplingFrequency,       (float)uHz)
    423                   .serializeUnsignedInteger(Channels,      cChannels)
    424                   .serializeUnsignedInteger(BitDepth,      cBits)
     461                  .serializeFloat(SamplingFrequency,  (float)pTrack->Audio.uHzCodec)
     462                  .serializeUnsignedInteger(Channels, cChannels)
     463                  .serializeUnsignedInteger(BitDepth, cBits)
    425464              .subEnd(Audio)
    426465              .subEnd(TrackEntry);
     466
     467        m_mapTracks[uTrack] = pTrack;
     468
     469        if (puTrack)
     470            *puTrack = uTrack;
    427471
    428472        return VINF_SUCCESS;
     
    433477    }
    434478
    435     int AddVideoTrack(uint16_t uWidth, uint16_t uHeight, double dbFPS)
     479    int AddVideoTrack(uint16_t uWidth, uint16_t uHeight, double dbFPS, uint8_t *puTrack)
    436480    {
    437481        m_Ebml.subStart(TrackEntry);
    438         m_Ebml.serializeUnsignedInteger(TrackNumber, (uint8_t)m_lstTracks.size());
    439 
    440         WebMTrack TrackVideo(WebMTrackType_Video, RTFileTell(m_Ebml.getFile()));
    441         m_lstTracks.push_back(TrackVideo);
     482        m_Ebml.serializeUnsignedInteger(TrackNumber, (uint8_t)m_mapTracks.size());
     483
     484        uint8_t uTrack = m_mapTracks.size();
     485
     486        WebMTrack *pTrack = new WebMTrack(WebMTrackType_Video, uTrack, RTFileTell(m_Ebml.getFile()));
    442487
    443488        /** @todo Resolve codec type. */
    444 
    445         m_Ebml.serializeUnsignedInteger(TrackUID, TrackVideo.uID /* UID */, 4)
     489        m_Ebml.serializeUnsignedInteger(TrackUID, pTrack->uUUID /* UID */, 4)
    446490              .serializeUnsignedInteger(TrackType, 1 /* Video */)
    447491              .serializeString(CodecID, "V_VP8")
     
    452496              .subEnd(Video)
    453497              .subEnd(TrackEntry);
     498
     499        m_mapTracks[uTrack] = pTrack;
     500
     501        if (puTrack)
     502            *puTrack = uTrack;
    454503
    455504        return VINF_SUCCESS;
     
    510559    }
    511560
    512     int writeBlockVP8(const vpx_codec_enc_cfg_t *a_pCfg, const vpx_codec_cx_pkt_t *a_pPkt)
    513     {
     561    int writeBlockVP8(const WebMTrack *a_pTrack, const vpx_codec_enc_cfg_t *a_pCfg, const vpx_codec_cx_pkt_t *a_pPkt)
     562    {
     563        RT_NOREF(a_pTrack);
     564
    514565        /* Calculate the PTS of this frame in milliseconds. */
    515566        int64_t tsPtsMs = a_pPkt->data.frame.pts * 1000
     
    570621            fFlags |= 0x08; /* Invisible frame. */
    571622
    572         return writeSimpleBlockInternal(0 /** @todo FIX! */, tsBlockMs, a_pPkt->data.frame.buf, a_pPkt->data.frame.sz, fFlags);
     623        return writeSimpleBlockInternal(a_pTrack->uTrack, tsBlockMs, a_pPkt->data.frame.buf, a_pPkt->data.frame.sz, fFlags);
    573624    }
    574625
    575626#ifdef VBOX_WITH_LIBOPUS
    576627    /* Audio blocks that have same absolute timecode as video blocks SHOULD be written before the video blocks. */
    577     int writeBlockOpus(const void *pvData, size_t cbData)
    578     {
     628    int writeBlockOpus(const WebMTrack *a_pTrack, const void *pvData, size_t cbData)
     629    {
     630        AssertPtrReturn(a_pTrack, VERR_INVALID_POINTER);
     631        AssertReturn(a_pTrack->Audio.cbFrameSize == cbData, VERR_INVALID_PARAMETER);
     632
    579633static uint16_t s_uTimecode = 0;
    580634
     
    586640        }
    587641
    588         return writeSimpleBlockInternal(0 /** @todo FIX! */, s_uTimecode++, pvData, cbData, 0 /* Flags */);
     642        uint64_t ts = (s_uTimecode * 1000 * 1000 * 1000) / 48000;
     643
     644        LogFunc(("ts=%RU64 (timecode %RU16)\n", ts, s_uTimecode));
     645
     646        s_uTimecode += a_pTrack->Audio.cbFrameSize;
     647
     648        return writeSimpleBlockInternal(a_pTrack->uTrack, ts, pvData, cbData, 0 /* Flags */);
    589649    }
    590650#endif
    591651
    592     int WriteBlock(WebMWriter::BlockType blockType, const void *pvData, size_t cbData)
     652    int WriteBlock(uint8_t uTrack, const void *pvData, size_t cbData)
    593653    {
    594654        RT_NOREF(cbData); /* Only needed for assertions for now. */
     655
     656        WebMTracks::const_iterator itTrack = m_mapTracks.find(uTrack);
     657        if (itTrack == m_mapTracks.end())
     658            return VERR_NOT_FOUND;
     659
     660        const WebMTrack *pTrack = itTrack->second;
     661        AssertPtr(pTrack);
    595662
    596663        int rc;
     
    602669        }
    603670
    604         switch (blockType)
    605         {
    606 
    607             case WebMWriter::BlockType_Audio:
     671        switch (pTrack->enmType)
     672        {
     673
     674            case WebMTrackType_Audio:
    608675            {
    609676#ifdef VBOX_WITH_LIBOPUS
     
    612679                    Assert(cbData == sizeof(WebMWriter::BlockData_Opus));
    613680                    WebMWriter::BlockData_Opus *pData = (WebMWriter::BlockData_Opus *)pvData;
    614                     rc = writeBlockOpus(pData->pvData, pData->cbData);
     681                    rc = writeBlockOpus(pTrack, pData->pvData, pData->cbData);
    615682                }
    616683                else
     
    620687            }
    621688
    622             case WebMWriter::BlockType_Video:
     689            case WebMTrackType_Video:
    623690            {
    624691                if (m_enmVideoCodec == WebMWriter::VideoCodec_VP8)
     
    626693                    Assert(cbData == sizeof(WebMWriter::BlockData_VP8));
    627694                    WebMWriter::BlockData_VP8 *pData = (WebMWriter::BlockData_VP8 *)pvData;
    628                     rc = writeBlockVP8(pData->pCfg, pData->pPkt);
     695                    rc = writeBlockVP8(pTrack, pData->pCfg, pData->pPkt);
    629696                }
    630697                else
     
    687754    }
    688755
     756    int close(void)
     757    {
     758        WebMTracks::iterator itTrack = m_mapTracks.begin();
     759        for (; itTrack != m_mapTracks.end(); ++itTrack)
     760        {
     761            delete itTrack->second;
     762            itTrack = m_mapTracks.erase(itTrack);
     763        }
     764
     765        Assert(m_mapTracks.size() == 0);
     766
     767        m_Ebml.close();
     768
     769        return VINF_SUCCESS;
     770    }
     771
    689772    friend class Ebml;
    690773    friend class WebMWriter;
     
    778861
    779862    int rc = m_pImpl->writeFooter();
    780 
    781     /* Close the file in any case. */
    782     m_pImpl->m_Ebml.close();
     863    if (RT_SUCCESS(rc))
     864        m_pImpl->close();
    783865
    784866    return rc;
    785867}
    786868
    787 int WebMWriter::AddAudioTrack(uint16_t uHz, uint8_t cChannels, uint8_t cBitDepth)
     869int WebMWriter::AddAudioTrack(uint16_t uHz, uint8_t cChannels, uint8_t cBitDepth, uint8_t *puTrack)
    788870{
    789     return m_pImpl->AddAudioTrack(uHz, cChannels, cBitDepth);
     871    return m_pImpl->AddAudioTrack(uHz, cChannels, cBitDepth, puTrack);
    790872}
    791873
    792 int WebMWriter::AddVideoTrack(uint16_t uWidth, uint16_t uHeight, double dbFPS)
     874int WebMWriter::AddVideoTrack(uint16_t uWidth, uint16_t uHeight, double dbFPS, uint8_t *puTrack)
    793875{
    794     return m_pImpl->AddVideoTrack(uWidth, uHeight, dbFPS);
     876    return m_pImpl->AddVideoTrack(uWidth, uHeight, dbFPS, puTrack);
    795877}
    796878
    797 int WebMWriter::WriteBlock(WebMWriter::BlockType blockType, const void *pvData, size_t cbData)
     879int WebMWriter::WriteBlock(uint8_t uTrack, const void *pvData, size_t cbData)
    798880{
    799881    int rc;
     
    801883    try
    802884    {
    803         rc = m_pImpl->WriteBlock(blockType, pvData, cbData);
     885        rc = m_pImpl->WriteBlock(uTrack, pvData, cbData);
    804886    }
    805887    catch(int rc2)
  • trunk/src/VBox/Main/src-client/EbmlWriter.h

    r65281 r65330  
    7979    };
    8080
    81     /**
    82      * Block type to write.
    83      */
    84     enum BlockType
    85     {
    86         BlockType_Invalid = 0,
    87         BlockType_Audio   = 1,
    88         BlockType_Video   = 2,
    89         BlockType_Raw     = 3
    90     };
    91 
    9281public:
    9382
     
    11099    int Close(void);
    111100
    112     int AddAudioTrack(uint16_t uHz, uint8_t cChannels, uint8_t cBits);
     101    int AddAudioTrack(uint16_t uHz, uint8_t cChannels, uint8_t cBits, uint8_t *puTrack);
    113102
    114     int AddVideoTrack(uint16_t uWidth, uint16_t uHeight, double dbFPS);
     103    int AddVideoTrack(uint16_t uWidth, uint16_t uHeight, double dbFPS, uint8_t *puTrack);
    115104
    116105    /**
    117106     * Writes a block of compressed data.
    118107     *
    119      * @param blockType         Block type to write.
     108     * @param uTrack            Track number to write data to.
    120109     * @param pvData            Pointer to block data to write.
    121110     * @param cbData            Size (in bytes) of block data to write.
     
    123112     * @returns VBox status code.
    124113     */
    125     int WriteBlock(WebMWriter::BlockType blockType, const void *pvData, size_t cbData);
     114    int WriteBlock(uint8_t uTrack, const void *pvData, size_t cbData);
    126115
    127116    /**
  • trunk/src/VBox/Main/src-client/VideoRec.cpp

    r65263 r65330  
    109109    /** Container context. */
    110110    WebMWriter         *pEBML;
     111    /** Track number of video stream. */
     112    uint8_t             uTrackVideo;
    111113    /** Codec data. */
    112114    VIDEORECCODEC       Codec;
     
    754756    if (fHasVideoTrack)
    755757    {
    756         rc = pStream->pEBML->AddVideoTrack(uWidth, uHeight, uFps);
     758        rc = pStream->pEBML->AddVideoTrack(uWidth, uHeight, uFps, &pStream->uTrackVideo);
    757759        if (RT_FAILURE(rc))
    758760        {
     
    914916            {
    915917                WebMWriter::BlockData_VP8 blockData = { &pStream->Codec.VPX.Config, pPacket };
    916                 rc = pStream->pEBML->WriteBlock(WebMWriter::BlockType_Video, &blockData, sizeof(blockData));
     918                rc = pStream->pEBML->WriteBlock(pStream->uTrackVideo, &blockData, sizeof(blockData));
    917919                break;
    918920            }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette