| 301 | } |
| 302 | |
| 303 | int FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) { |
| 304 | AVPacket *Packet = av_packet_alloc(); |
| 305 | if (!Packet) |
| 306 | throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_ALLOCATION_FAILED, |
| 307 | "Could not allocate packet."); |
| 308 | if (!ReadPacket(Packet)) { |
| 309 | av_packet_free(&Packet); |
| 310 | throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN, |
| 311 | "ReadPacket unexpectedly failed to read a packet"); |
| 312 | } |
| 313 | |
| 314 | CurrentFrame = &Frames[PacketNumber]; |
| 315 | CurrentSample = CurrentFrame->SampleStart; |
| 316 | |
| 317 | // Value code intentionally ignored, combined with the checks when indexing this mostly gives the expected behavior |
| 318 | avcodec_send_packet(CodecContext, Packet); |
| 319 | |
| 320 | int NumberOfSamples = 0; |
| 321 | AudioBlock *CachedBlock = nullptr; |
| 322 | |
| 323 | while (true) { |
| 324 | av_frame_unref(DecodeFrame); |
| 325 | int Ret = avcodec_receive_frame(CodecContext, DecodeFrame); |
| 326 | if (Ret == 0) { |
| 327 | NumberOfSamples += DecodeFrame->nb_samples; |
| 328 | if (DecodeFrame->nb_samples > 0) { |
| 329 | if (pos) |
| 330 | CachedBlock = CacheBlock(*pos); |
| 331 | } |
| 332 | break; |
| 333 | } else if (Ret == AVERROR(EAGAIN)) { |
| 334 | if (!ReadPacket(Packet)) { |
| 335 | av_packet_free(&Packet); |
| 336 | throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN, |
| 337 | "ReadPacket unexpectedly failed to read a packet"); |
| 338 | } |
| 339 | avcodec_send_packet(CodecContext, Packet); |
| 340 | } else if (Ret == AVERROR_EOF) { |
| 341 | break; |
| 342 | } else { |
| 343 | throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, "Audio decoding error"); |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | av_packet_free(&Packet); |
| 348 | |
| 349 | // Zero sample packets aren't included in the index |
| 350 | if (!NumberOfSamples) |
| 351 | return NumberOfSamples; |
| 352 | ++PacketNumber; |
| 353 | |
| 354 | // Add padding after the packet, if needed |
| 355 | if (!CachedBlock || CachedBlock->Samples == CurrentFrame->SampleCount) |
| 356 | return NumberOfSamples; |
| 357 | |
| 358 | const int64_t MissingSamples = static_cast<int64_t>(CurrentFrame->SampleCount - CachedBlock->Samples); |
| 359 | // This can apparently happen in some rare circumstances, caused by inaccurate seeking? |
| 360 | if (MissingSamples <= 0) |
nothing calls this directly
no test coverage detected