Changeset 68338 in vbox
- Timestamp:
- Aug 8, 2017 10:34:58 AM (7 years ago)
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
r68323 r68338 123 123 /** The encoding rate to use. */ 124 124 uint32_t uHz; 125 /** Duration of the frame in samples (per channel).126 *127 * For Opus, valid frame size are:128 * ms Frame size129 * 2.5 120130 * 5 240131 * 10 480132 * 20 (Default) 960133 * 40 1920134 * 60 2880135 */136 125 /** Number of audio channels to encode. 137 126 * Currently we only supported stereo (2) channels. */ 138 127 uint8_t cChannels; 128 /** Bits per sample. */ 129 uint8_t cBits; 139 130 /** The codec's bitrate. 0 if not used / cannot be specified. */ 140 131 uint32_t uBitrate; … … 156 147 /** Encoder we're going to use. */ 157 148 OpusEncoder *pEnc; 158 /** Number of samples per frame. */ 159 uint32_t csFrame; 160 /** The maximum frame size (in samples) we can handle. */ 161 uint32_t csFrameMax; 149 /** Time (in ms) an (encoded) frame takes. 150 * 151 * For Opus, valid frame size are: 152 * ms Frame size 153 * 2.5 120 154 * 5 240 155 * 10 480 156 * 20 (Default) 960 157 * 40 1920 158 * 60 2880 159 */ 160 uint32_t msFrame; 162 161 } Opus; 163 162 #endif /* VBOX_WITH_LIBOPUS */ … … 182 181 /** Container data to use for data processing. */ 183 182 AVRECCONTAINER Con; 184 /** Codec data this s treamuses for encoding. */183 /** Codec data this sink uses for encoding. */ 185 184 AVRECCODEC Codec; 186 185 } AVRECSINK, *PAVRECSINK; … … 233 232 static int avRecSinkInit(PDRVAUDIOVIDEOREC pThis, PAVRECSINK pSink, PAVRECCONTAINERPARMS pConParms, PAVRECCODECPARMS pCodecParms) 234 233 { 235 uint32_t uHz = pCodecParms->uHz; 234 uint32_t uHz = pCodecParms->uHz; 235 uint8_t cBits = 16; /** @ŧodo Make this configurable? */ 236 uint8_t cChannels = pCodecParms->cChannels; 237 uint32_t uBitrate = pCodecParms->uBitrate; 236 238 237 239 /* Opus only supports certain input sample rates in an efficient manner. … … 243 245 else uHz = 8000; 244 246 245 OpusEncoder *pEnc = NULL; 247 if (cChannels > 2) 248 { 249 LogRel(("VideoRec: More than 2 (stereo) channels are not supported at the moment\n")); 250 cChannels = 2; 251 } 252 253 LogRel2(("VideoRec: Recording audio in %RU16Hz, %RU8 channels, %RU32 bitrate\n", uHz, cChannels, uBitrate)); 246 254 247 255 int orc; 248 pEnc = opus_encoder_create(pCodecParms->uHz, pCodecParms->cChannels, OPUS_APPLICATION_AUDIO, &orc);256 OpusEncoder *pEnc = opus_encoder_create(uHz, cChannels, OPUS_APPLICATION_AUDIO, &orc); 249 257 if (orc != OPUS_OK) 250 258 { … … 255 263 AssertPtr(pEnc); 256 264 257 opus_encoder_ctl(pEnc, OPUS_SET_BITRATE( pCodecParms->uBitrate));265 opus_encoder_ctl(pEnc, OPUS_SET_BITRATE(uBitrate)); 258 266 if (orc != OPUS_OK) 259 267 { 260 LogRel(("VideoRec: Audio codec failed to set bitrate (%RU32): %s\n", pCodecParms->uBitrate, opus_strerror(orc))); 268 opus_encoder_destroy(pEnc); 269 pEnc = NULL; 270 271 LogRel(("VideoRec: Audio codec failed to set bitrate (%RU32): %s\n", uBitrate, opus_strerror(orc))); 261 272 return VERR_AUDIO_BACKEND_INIT_FAILED; 262 273 } 263 264 LogRel(("VideoRec: Recording audio in %RU16Hz, %RU8 channels, %RU32 bpS\n",265 pCodecParms->uHz, pCodecParms->cChannels, pCodecParms->uBitrate / 1000));266 274 267 275 int rc; … … 281 289 case AVRECCONTAINERTYPE_WEBM: 282 290 { 283 rc = VINF_SUCCESS; 291 /* If we only record audio, create our own WebM writer instance here. */ 292 if (!pSink->Con.WebM.pWebM) /* Do we already have our WebM writer instance? */ 293 { 294 char szFile[RTPATH_MAX]; 295 if (RTStrPrintf(szFile, sizeof(szFile), "%s%s", 296 VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH, "DrvAudioVideoRec.webm" /** @todo Make this configurable. */)) 297 { 298 /** @todo Add sink name / number to file name. */ 299 300 LogRel2(("VideoRec: Recording audio to file '%s'\n", szFile)); 301 302 pSink->Con.WebM.pWebM = new WebMWriter(); 303 rc = pSink->Con.WebM.pWebM->Create(szFile, 304 /** @ŧodo Add option to add some suffix if file exists instead of overwriting? */ 305 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE, 306 WebMWriter::AudioCodec_Opus, WebMWriter::VideoCodec_None); 307 if (RT_SUCCESS(rc)) 308 { 309 rc = pSink->Con.WebM.pWebM->AddAudioTrack(uHz, cChannels, cBits, 310 &pSink->Con.WebM.uTrack); 311 if (RT_FAILURE(rc)) 312 LogRel(("VideoRec: Error creating audio track for file '%s' (%Rrc)\n", szFile, rc)); 313 } 314 else 315 LogRel(("VideoRec: Error creating audio file '%s' (%Rrc)\n", szFile, rc)); 316 } 317 else 318 { 319 AssertFailed(); /* Should never happen. */ 320 LogRel(("VideoRec: Error creating audio file path\n")); 321 } 322 } 323 284 324 break; 285 325 } … … 300 340 301 341 pSink->Codec.Parms.uHz = uHz; 302 pSink->Codec.Parms.cChannels = pCodecParms->cChannels; 303 pSink->Codec.Parms.uBitrate = pCodecParms->uBitrate; 342 pSink->Codec.Parms.cChannels = cChannels; 343 pSink->Codec.Parms.cBits = cBits; 344 pSink->Codec.Parms.uBitrate = uBitrate; 304 345 305 346 pSink->Codec.Opus.pEnc = pEnc; 306 pSink->Codec.Opus. csFrame = uHz / 50;347 pSink->Codec.Opus.msFrame = 20; /** @todo 20 ms of audio data. Make this configurable? */ 307 348 308 349 #ifdef VBOX_WITH_STATISTICS … … 310 351 pSink->Codec.STAM.msEncTotal = 0; 311 352 #endif 312 313 /* Calculate the maximum frame size. */ 314 pSink->Codec.Opus.csFrameMax = AVREC_OPUS_HZ_MAX /* Maximum sample rate Opus can handle */ 315 * pCodecParms->cChannels; /* Number of channels */ 353 } 354 else 355 { 356 if (pEnc) 357 { 358 opus_encoder_destroy(pEnc); 359 pEnc = NULL; 360 } 361 362 LogRel(("VideoRec: Error creating sink (%Rrc)\n", rc)); 316 363 } 317 364 … … 343 390 if (pSink->Con.WebM.pWebM) 344 391 { 392 LogRel2(("VideoRec: Finished recording audio to file '%s' (%zu bytes)\n", 393 pSink->Con.WebM.pWebM->GetFileName().c_str(), pSink->Con.WebM.pWebM->GetFileSize())); 394 345 395 int rc2 = pSink->Con.WebM.pWebM->Close(); 346 396 AssertRC(rc2); … … 392 442 393 443 #ifdef VBOX_WITH_LIBOPUS 394 /* If we only record audio, create our own WebM writer instance here. */ 395 if (pSink->Con.Parms.enmType == AVRECCONTAINERTYPE_WEBM) 396 { 397 pSink->Con.WebM.pWebM = new WebMWriter(); 398 rc = pSink->Con.WebM.pWebM->Create(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "DrvAudioVideoRec.webm", /** @todo Make this configurable. */ 399 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE, 400 WebMWriter::AudioCodec_Opus, WebMWriter::VideoCodec_None); 401 if (RT_SUCCESS(rc)) 402 rc = pSink->Con.WebM.pWebM->AddAudioTrack(pSink->Codec.Parms.uHz, pCfgReq->Props.cChannels, pCfgReq->Props.cBits, 403 &pSink->Con.WebM.uTrack); 404 } 405 406 if (RT_FAILURE(rc)) 407 return rc; 408 409 rc = RTCircBufCreate(&pStreamAV->pCircBuf, (pSink->Codec.Opus.csFrame * pSink->Codec.Parms.cChannels) * sizeof(uint16_t)); 444 const unsigned cFrames = 2; /** @todo Use the PreRoll param for that? */ 445 446 const uint32_t csFrame = pSink->Codec.Parms.uHz / (1000 /* s in ms */ / pSink->Codec.Opus.msFrame); 447 const uint32_t cbFrame = csFrame * pSink->Codec.Parms.cChannels * (pSink->Codec.Parms.cBits / 8 /* Bytes */); 448 449 rc = RTCircBufCreate(&pStreamAV->pCircBuf, cbFrame * cFrames); 410 450 if (RT_SUCCESS(rc)) 411 451 { … … 494 534 495 535 AVRECCONTAINERPARMS ContainerParms; 496 ContainerParms.enmType = AVRECCONTAINERTYPE_ MAIN_CONSOLE; /** @todo Make this configurable. */536 ContainerParms.enmType = AVRECCONTAINERTYPE_WEBM; /** @todo Make this configurable. */ 497 537 498 538 AVRECCODECPARMS CodecParms; … … 594 634 size_t cbSrc; 595 635 596 const uint32_t csFrame = pSink->Codec. Opus.csFrame;597 const uint32_t cbFrame = PDMAUDIOSTREAMCFG_F2B(pStreamAV->pCfg, csFrame);636 const uint32_t csFrame = pSink->Codec.Parms.uHz / (1000 /* s in ms */ / pSink->Codec.Opus.msFrame); 637 const uint32_t cbFrame = csFrame * pSink->Codec.Parms.cChannels * (pSink->Codec.Parms.cBits / 8 /* Bytes */); 598 638 599 639 while (RTCircBufUsed(pCircBuf) >= cbFrame) -
trunk/src/VBox/Main/src-client/EbmlWriter.cpp
r68333 r68338 583 583 584 584 pTrack->Audio.uHz = uHz; 585 pTrack->Audio.csFrame = pTrack->Audio.uHz / 50; /** @todo 20 ms of audio data. Make this configurable? */585 pTrack->Audio.csFrame = pTrack->Audio.uHz / (1000 /* s in ms */ / 20); /** @todo 20 ms of audio data. Make this configurable? */ 586 586 587 587 OpusPrivData opusPrivData(uHz, cChannels); … … 594 594 .serializeData(MkvElem_CodecPrivate, &opusPrivData, sizeof(opusPrivData)) 595 595 .serializeUnsignedInteger(MkvElem_CodecDelay, 0) 596 .serializeUnsignedInteger(MkvElem_SeekPreRoll, 80 000000) /* 80ms in ns. */596 .serializeUnsignedInteger(MkvElem_SeekPreRoll, 80 * 1000000) /* 80ms in ns. */ 597 597 .subStart(MkvElem_Audio) 598 598 .serializeFloat(MkvElem_SamplingFrequency, (float)uHz)
Note:
See TracChangeset
for help on using the changeset viewer.