* Decode an #AVPacket and send the resulting PCM data to the decoder * API. * * @param min_frame skip all data before this PCM frame number; this * is used after seeking to skip data in an AVPacket until the exact * desired time stamp has been reached */
| 273 | * desired time stamp has been reached |
| 274 | */ |
| 275 | static DecoderCommand |
| 276 | ffmpeg_send_packet(DecoderClient &client, InputStream *is, |
| 277 | const AVPacket &packet, |
| 278 | AVCodecContext &codec_context, |
| 279 | const AVStream &stream, |
| 280 | AVFrame &frame, |
| 281 | uint64_t min_frame, size_t pcm_frame_size, |
| 282 | FfmpegBuffer &buffer) |
| 283 | { |
| 284 | size_t skip_bytes = 0; |
| 285 | |
| 286 | const auto pts = StreamRelativePts(packet, stream); |
| 287 | if (pts >= 0) { |
| 288 | if (min_frame > 0) { |
| 289 | auto cur_frame = PtsToPcmFrame(pts, stream, |
| 290 | codec_context); |
| 291 | if (cur_frame < min_frame) |
| 292 | skip_bytes = pcm_frame_size * (min_frame - cur_frame); |
| 293 | } else |
| 294 | client.SubmitTimestamp(FfmpegTimeToDouble(pts, |
| 295 | stream.time_base)); |
| 296 | } |
| 297 | |
| 298 | bool eof = false; |
| 299 | |
| 300 | int err = avcodec_send_packet(&codec_context, &packet); |
| 301 | switch (err) { |
| 302 | case 0: |
| 303 | break; |
| 304 | |
| 305 | case AVERROR_EOF: |
| 306 | eof = true; |
| 307 | break; |
| 308 | |
| 309 | default: |
| 310 | { |
| 311 | char msg[256]; |
| 312 | av_strerror(err, msg, sizeof(msg)); |
| 313 | FmtWarning(ffmpeg_domain, |
| 314 | "avcodec_send_packet() failed: {}", msg); |
| 315 | } |
| 316 | |
| 317 | return DecoderCommand::NONE; |
| 318 | } |
| 319 | |
| 320 | auto cmd = FfmpegReceiveFrames(client, is, codec_context, |
| 321 | frame, |
| 322 | skip_bytes, buffer, eof); |
| 323 | |
| 324 | if (eof) |
| 325 | cmd = DecoderCommand::STOP; |
| 326 | |
| 327 | return cmd; |
| 328 | } |
| 329 | |
| 330 | [[gnu::const]] |
| 331 | static SampleFormat |
no test coverage detected