1/********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 AVFormatContextWrapperImpl.inl 6 7 Dmitry Vedenko 8 9**********************************************************************/ 10 11//! Some checks for correct overlaying. 12// There is no AVDictionaryWrapper.inl, so put it here 13static_assert( 14 sizeof(AudacityAVDictionaryEntry) == sizeof(AVDictionaryEntry) && 15 offsetof(AudacityAVDictionaryEntry, key) == offsetof(AVDictionaryEntry, key) 16 && 17 offsetof(AudacityAVDictionaryEntry, value) == offsetof(AVDictionaryEntry, value), 18 "AudacityAVDictionaryEntry does not safely overlay AVDictionaryEntry" 19); 20 21//! More sanity checks of macro constants 22static_assert( 23 AV_DICT_MATCH_CASE == DICT_MATCH_CASE 24 && AV_DICT_IGNORE_SUFFIX == DICT_IGNORE_SUFFIX 25 && AV_NOPTS_VALUE == AUDACITY_AV_NOPTS_VALUE 26 && AV_TIME_BASE == AUDACITY_AV_TIME_BASE 27 && FF_QP2LAMBDA == AUDACITY_FF_QP2LAMBDA 28 && FF_PROFILE_AAC_LOW == AUDACITY_FF_PROFILE_AAC_LOW 29 && AVFMT_NOFILE == AUDACITY_AVFMT_NOFILE 30 && AVFMT_GLOBALHEADER == AUDACITY_AVFMT_GLOBALHEADER 31 && FF_COMPLIANCE_EXPERIMENTAL == AUDACITY_FF_COMPLIANCE_EXPERIMENTAL 32 && AV_SAMPLE_FMT_U8 == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_U8) 33 && AV_SAMPLE_FMT_U8P == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_U8P) 34 && AV_SAMPLE_FMT_U8P == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_U8P) 35 && AV_SAMPLE_FMT_S16P == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_S16P) 36 && AV_SAMPLE_FMT_S32 == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_S32) 37 && AV_SAMPLE_FMT_S32P == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_S32P) 38 && AV_SAMPLE_FMT_FLT == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_FLT) 39 && AV_SAMPLE_FMT_FLTP == static_cast<int>(AUDACITY_AV_SAMPLE_FMT_FLTP) 40, 41 "FFmpeg constants don't match" 42); 43 44class AVFormatContextWrapperImpl : public AVFormatContextWrapper 45{ 46public: 47 AVFormatContextWrapperImpl(const FFmpegFunctions& ffmpeg) 48 : AVFormatContextWrapper(ffmpeg) 49 { 50 mAVFormatContext = mFFmpeg.avformat_alloc_context(); 51 } 52 53 AVInputFormat* GetIFormat() const noexcept override 54 { 55 if (mAVFormatContext != nullptr) 56 return mAVFormatContext->iformat; 57 58 return {}; 59 } 60 61 AVOutputFormat* GetOFormat() const noexcept override 62 { 63 if (mAVFormatContext != nullptr) 64 return mAVFormatContext->oformat; 65 66 return {}; 67 } 68 69 void SetOutputFormat(std::unique_ptr<AVOutputFormatWrapper> oformat) noexcept override 70 { 71 if (mAVFormatContext != nullptr) 72 { 73 mAVFormatContext->oformat = oformat->GetWrappedValue(); 74 mOutputFormat = std::move(oformat); 75 } 76 } 77 78 AVIOContextWrapper* GetAVIOContext() const noexcept override 79 { 80 return mAVIOContext.get(); 81 } 82 83 void SetAVIOContext(std::unique_ptr<AVIOContextWrapper> pb) noexcept override 84 { 85 if (mAVFormatContext != nullptr) 86 { 87 mAVIOContext = std::move(pb); 88 mAVFormatContext->pb = mAVIOContext->GetWrappedValue(); 89 } 90 } 91 92 int GetCtxFlags() const noexcept override 93 { 94 if (mAVFormatContext != nullptr) 95 return mAVFormatContext->ctx_flags; 96 97 return {}; 98 } 99 100 unsigned int GetStreamsCount() const noexcept override 101 { 102 if (mAVFormatContext != nullptr) 103 return mAVFormatContext->nb_streams; 104 105 return {}; 106 } 107 108 const AVFormatContextWrapper::StreamsList& GetStreams() const noexcept override 109 { 110 return mStreams; 111 } 112 113 const char* GetFilename() const noexcept override 114 { 115 if (mAVFormatContext != nullptr) 116 return mAVFormatContext->filename; 117 118 return {}; 119 } 120 121 void SetFilename(const char* filename) noexcept override 122 { 123 if (mAVFormatContext == nullptr) 124 return; 125 126 const size_t len = 127 std::min(sizeof(mAVFormatContext->filename) - 1, std::strlen(filename)); 128 129 std::copy(filename, filename + len, mAVFormatContext->filename); 130 131 mAVFormatContext->filename[len] = '\0'; 132 } 133 134 int64_t GetStartTime() const noexcept override 135 { 136 if (mAVFormatContext != nullptr) 137 return mAVFormatContext->start_time; 138 139 return {}; 140 } 141 142 int64_t GetDuration() const noexcept override 143 { 144 if (mAVFormatContext != nullptr) 145 return mAVFormatContext->duration; 146 147 return {}; 148 } 149 150 int GetBitRate() const noexcept override 151 { 152 if (mAVFormatContext != nullptr) 153 // May truncate int64_t to int. But who uses such high rates, really? 154 return mAVFormatContext->bit_rate; 155 156 return {}; 157 } 158 159 void SetBitRate(int bit_rate) noexcept override 160 { 161 if (mAVFormatContext != nullptr) 162 mAVFormatContext->bit_rate = bit_rate; 163 } 164 165 unsigned int GetPacketSize() const noexcept override 166 { 167 if (mAVFormatContext != nullptr) 168 return mAVFormatContext->packet_size; 169 170 return {}; 171 } 172 173 void SetPacketSize(unsigned int packet_size) noexcept override 174 { 175 if (mAVFormatContext != nullptr) 176 mAVFormatContext->packet_size = packet_size; 177 } 178 179 int GetMaxDelay() const noexcept override 180 { 181 if (mAVFormatContext != nullptr) 182 return mAVFormatContext->max_delay; 183 184 return {}; 185 } 186 187 void SetMaxDelay(int max_delay) noexcept override 188 { 189 if (mAVFormatContext != nullptr) 190 mAVFormatContext->max_delay = max_delay; 191 } 192 193 int GetFlags() const noexcept override 194 { 195 if (mAVFormatContext != nullptr) 196 return mAVFormatContext->flags; 197 198 return {}; 199 } 200 201 void SetFlags(int flags) noexcept override 202 { 203 if (mAVFormatContext != nullptr) 204 mAVFormatContext->flags = flags; 205 } 206 207 unsigned int GetProbeSize() const noexcept override 208 { 209 if (mAVFormatContext != nullptr) 210 return mAVFormatContext->probesize; 211 212 return {}; 213 } 214 215 void SetProbeSize(unsigned int probesize) noexcept override 216 { 217 if (mAVFormatContext != nullptr) 218 mAVFormatContext->probesize = probesize; 219 } 220 221 int GetMaxAnalyzeDuration() const noexcept override 222 { 223 if (mAVFormatContext != nullptr) 224 return mAVFormatContext->max_analyze_duration; 225 226 return {}; 227 } 228 229 void SetMaxAnalyzeDuration(int max_analyze_duration) noexcept override 230 { 231 if (mAVFormatContext != nullptr) 232 mAVFormatContext->max_analyze_duration = max_analyze_duration; 233 } 234 235 AVCodecIDFwd GetAudioCodecId() const noexcept override 236 { 237 if (mAVFormatContext != nullptr) 238 return mAVFormatContext->audio_codec_id; 239 240 return {}; 241 } 242 243 void SetAudioCodecId(AVCodecIDFwd audio_codec_id) noexcept override 244 { 245 if (mAVFormatContext != nullptr) 246 mAVFormatContext->audio_codec_id = static_cast<AVCodecID>(audio_codec_id); 247 } 248 249 unsigned int GetMaxIndexSize() const noexcept override 250 { 251 if (mAVFormatContext != nullptr) 252 return mAVFormatContext->max_index_size; 253 254 return {}; 255 } 256 257 void SetMaxIndexSize(unsigned int max_index_size) noexcept override 258 { 259 if (mAVFormatContext != nullptr) 260 mAVFormatContext->max_index_size = max_index_size; 261 } 262 263 AVDictionaryWrapper GetMetadata() const noexcept override 264 { 265 if (mAVFormatContext != nullptr) 266 return AVDictionaryWrapper(mFFmpeg, mAVFormatContext->metadata); 267 268 return AVDictionaryWrapper(mFFmpeg); 269 } 270 271 void SetMetadata(AVDictionaryWrapper metadata) noexcept override 272 { 273 if (mAVFormatContext == nullptr) 274 return; 275 276 if (mAVFormatContext->metadata != nullptr) 277 mFFmpeg.av_dict_free(&mAVFormatContext->metadata); 278 279 // This Release() doesn't leak: 280 /* */https://ffmpeg.org/doxygen/2.8/structAVFormatContext.html#a3019a56080ed2e3297ff25bc2ff88adf */ 281 mAVFormatContext->metadata = metadata.Release(); 282 } 283 284 int64_t GetStartTimeRealtime() const noexcept override 285 { 286 if (mAVFormatContext != nullptr) 287 return mAVFormatContext->start_time_realtime; 288 289 return {}; 290 } 291 292 void SetStartTimeRealtime(int64_t start_time_realtime) noexcept override 293 { 294 if (mAVFormatContext != nullptr) 295 mAVFormatContext->start_time_realtime = start_time_realtime; 296 } 297 298 int GetFpsProbeSize() const noexcept override 299 { 300 if (mAVFormatContext != nullptr) 301 return mAVFormatContext->fps_probe_size; 302 303 return {}; 304 } 305 306 void SetFpsProbeSize(int fps_probe_size) noexcept override 307 { 308 if (mAVFormatContext != nullptr) 309 mAVFormatContext->fps_probe_size = fps_probe_size; 310 } 311 312 int GetErrorRecognition() const noexcept override 313 { 314 if (mAVFormatContext != nullptr) 315 return mAVFormatContext->error_recognition; 316 317 return {}; 318 } 319 320 void SetErrorRecognition(int error_recognition) noexcept override 321 { 322 if (mAVFormatContext != nullptr) 323 mAVFormatContext->error_recognition = error_recognition; 324 } 325 326 int64_t GetMaxInterleaveDelta() const noexcept override 327 { 328 if (mAVFormatContext != nullptr) 329 return mAVFormatContext->max_interleave_delta; 330 331 return {}; 332 } 333 334 void SetMaxInterleaveDelta(int64_t max_interleave_delta) noexcept override 335 { 336 if (mAVFormatContext != nullptr) 337 mAVFormatContext->max_interleave_delta = max_interleave_delta; 338 } 339 340 int GetStrictStdCompliance() const noexcept override 341 { 342 if (mAVFormatContext != nullptr) 343 return mAVFormatContext->strict_std_compliance; 344 345 return {}; 346 } 347 348 void SetStrictStdCompliance(int strict_std_compliance) noexcept override 349 { 350 if (mAVFormatContext != nullptr) 351 mAVFormatContext->strict_std_compliance = strict_std_compliance; 352 } 353 354 int GetAudioPreload() const noexcept override 355 { 356 if (mAVFormatContext != nullptr) 357 return mAVFormatContext->audio_preload; 358 359 return {}; 360 } 361 362 void SetAudioPreload(int audio_preload) noexcept override 363 { 364 if (mAVFormatContext != nullptr) 365 mAVFormatContext->audio_preload = audio_preload; 366 } 367 368 int GetMaxChunkDuration() const noexcept override 369 { 370 if (mAVFormatContext != nullptr) 371 return mAVFormatContext->max_chunk_duration; 372 373 return {}; 374 } 375 376 void SetMaxChunkDuration(int max_chunk_duration) noexcept override 377 { 378 if (mAVFormatContext != nullptr) 379 mAVFormatContext->max_chunk_duration = max_chunk_duration; 380 } 381 382 int GetMaxChunkSize() const noexcept override 383 { 384 if (mAVFormatContext != nullptr) 385 return mAVFormatContext->max_chunk_size; 386 387 return {}; 388 } 389 390 void SetMaxChunkSize(int max_chunk_size) noexcept override 391 { 392 if (mAVFormatContext != nullptr) 393 mAVFormatContext->max_chunk_size = max_chunk_size; 394 } 395 396 int GetUseWallclockAsTimestamps() const noexcept override 397 { 398 if (mAVFormatContext != nullptr) 399 return mAVFormatContext->use_wallclock_as_timestamps; 400 401 return {}; 402 } 403 404 void SetUseWallclockAsTimestamps( 405 int use_wallclock_as_timestamps) noexcept override 406 { 407 if (mAVFormatContext != nullptr) 408 mAVFormatContext->use_wallclock_as_timestamps = use_wallclock_as_timestamps; 409 } 410 411 int GetAvoidNegativeTs() const noexcept override 412 { 413 if (mAVFormatContext != nullptr) 414 return mAVFormatContext->avoid_negative_ts; 415 416 return {}; 417 } 418 419 void SetAvoidNegativeTs(int avoid_negative_ts) noexcept override 420 { 421 if (mAVFormatContext != nullptr) 422 mAVFormatContext->avoid_negative_ts = avoid_negative_ts; 423 } 424 425 int GetAvioFlags() const noexcept override 426 { 427 if (mAVFormatContext != nullptr) 428 return mAVFormatContext->avio_flags; 429 430 return {}; 431 } 432 433 void SetAvioFlags(int avio_flags) noexcept override 434 { 435 if (mAVFormatContext != nullptr) 436 mAVFormatContext->avio_flags = avio_flags; 437 } 438 439 int64_t GetSkipInitialBytes() const noexcept override 440 { 441 if (mAVFormatContext != nullptr) 442 return mAVFormatContext->skip_initial_bytes; 443 444 return {}; 445 } 446 447 void SetSkipInitialBytes(int64_t skip_initial_bytes) noexcept override 448 { 449 if (mAVFormatContext != nullptr) 450 mAVFormatContext->skip_initial_bytes = skip_initial_bytes; 451 } 452 453 unsigned int GetCorrectTsOverflow() const noexcept override 454 { 455 if (mAVFormatContext != nullptr) 456 return mAVFormatContext->correct_ts_overflow; 457 458 return {}; 459 } 460 461 void SetCorrectTsOverflow(unsigned int correct_ts_overflow) noexcept override 462 { 463 if (mAVFormatContext != nullptr) 464 mAVFormatContext->correct_ts_overflow = correct_ts_overflow; 465 } 466 467 int GetSeek2any() const noexcept override 468 { 469 if (mAVFormatContext != nullptr) 470 return mAVFormatContext->seek2any; 471 472 return {}; 473 } 474 475 void SetSeek2any(int seek2any) noexcept override 476 { 477 if (mAVFormatContext != nullptr) 478 mAVFormatContext->seek2any = seek2any; 479 } 480 481 int GetFlushPackets() const noexcept override 482 { 483 if (mAVFormatContext != nullptr) 484 return mAVFormatContext->flush_packets; 485 486 return {}; 487 } 488 489 void SetFlushPackets(int flush_packets) noexcept override 490 { 491 if (mAVFormatContext != nullptr) 492 mAVFormatContext->flush_packets = flush_packets; 493 } 494 495 int GetProbeScore() const noexcept override 496 { 497 if (mAVFormatContext != nullptr) 498 return mAVFormatContext->probe_score; 499 500 return {}; 501 } 502 503 int GetFormatProbeSize() const noexcept override 504 { 505 if (mAVFormatContext != nullptr) 506 return mAVFormatContext->format_probesize; 507 508 return {}; 509 } 510 511 void SetFormatProbeSize(int format_probesize) noexcept override 512 { 513 if (mAVFormatContext != nullptr) 514 mAVFormatContext->format_probesize = format_probesize; 515 } 516 517 AVCodecWrapper* GetAudioCodec() const noexcept override 518 { 519 return mForcedAudioCodec.get(); 520 } 521 522 void SetAudioCodec(std::unique_ptr<AVCodecWrapper> audio_codec) noexcept override 523 { 524 if (mAVFormatContext == nullptr) 525 return; 526 527 mAVFormatContext->audio_codec = audio_codec->GetWrappedValue(); 528 mForcedAudioCodec = move(audio_codec); 529 } 530 531 void* GetOpaque() const noexcept override 532 { 533 if (mAVFormatContext != nullptr) 534 return mAVFormatContext->opaque; 535 536 return {}; 537 } 538 539 void SetOpaque(void* opaque) noexcept override 540 { 541 if (mAVFormatContext != nullptr) 542 mAVFormatContext->opaque = opaque; 543 } 544 545 int64_t GetOutputTsOffset() const noexcept override 546 { 547 if (mAVFormatContext != nullptr) 548 return mAVFormatContext->output_ts_offset; 549 550 return {}; 551 } 552 553 void SetOutputTsOffset(int64_t output_ts_offset) noexcept override 554 { 555 if (mAVFormatContext != nullptr) 556 mAVFormatContext->output_ts_offset = output_ts_offset; 557 } 558 559 void UpdateStreamList() noexcept override 560 { 561 mStreams.clear(); 562 563 for (int i = 0; i < mAVFormatContext->nb_streams; ++i) 564 mStreams.emplace_back(mFFmpeg.CreateAVStreamWrapper(mAVFormatContext->streams[i])); 565 } 566}; 567 568std::unique_ptr<AVFormatContextWrapper> CreateAVFormatContextWrapper (const FFmpegFunctions& ffmpeg) 569{ 570 return std::make_unique<AVFormatContextWrapperImpl>(ffmpeg); 571} 572