| @@ -28,8 +28,11 @@ extern "C" { · 27 unmodified lines |
| 28 | #include "config.h" | 28 | #include "config.h" |
| 29 | #include "libavformat/avformat.h" | 29 | #include "libavformat/avformat.h" |
| 30 | #include "libavformat/internal.h" | 30 | #include "libavformat/internal.h" |
| | 31 | #include "libavutil/avutil.h" |
| 31 | #include "libavutil/common.h" | 32 | #include "libavutil/common.h" |
| 32 | #include "libavutil/imgutils.h" | 33 | #include "libavutil/imgutils.h" |
| | 34 | #include "libavutil/time.h" |
| | 35 | #include "libavutil/mathematics.h" |
| 33 | #if CONFIG_LIBZVBI | 36 | #if CONFIG_LIBZVBI |
| 34 | #include <libzvbi.h> | 37 | #include <libzvbi.h> |
| 35 | #endif | 38 | #endif |
| @@ -237,6 +240,44 @@ ULONG decklink_input_callback::Release(void) · 201 unmodified lines |
| 237 | return (ULONG)m_refCount; | 240 | return (ULONG)m_refCount; |
| 238 | } | 241 | } |
| 239 | | 242 | |
| | 243 | static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame, |
| | 244 | IDeckLinkAudioInputPacket *audioFrame, |
| | 245 | int64_t wallclock, |
| | 246 | DecklinkPtsSource pts_src, |
| | 247 | AVRational time_base, int64_t *initial_pts) |
| | 248 | { |
| | 249 | int64_t pts = AV_NOPTS_VALUE; |
| | 250 | BMDTimeValue bmd_pts; |
| | 251 | BMDTimeValue bmd_duration; |
| | 252 | HRESULT res = E_INVALIDARG; |
| | 253 | switch (pts_src) { |
| | 254 | case PTS_SRC_AUDIO: |
| | 255 | if (audioFrame) |
| | 256 | res = audioFrame->GetPacketTime(&bmd_pts, time_base.den); |
| | 257 | break; |
| | 258 | case PTS_SRC_VIDEO: |
| | 259 | if (videoFrame) |
| | 260 | res = videoFrame->GetStreamTime(&bmd_pts, &bmd_duration, time_base.den); |
| | 261 | break; |
| | 262 | case PTS_SRC_REFERENCE: |
| | 263 | if (videoFrame) |
| | 264 | res = videoFrame->GetHardwareReferenceTimestamp(time_base.den, &bmd_pts, &bmd_duration); |
| | 265 | break; |
| | 266 | case PTS_SRC_WALLCLOCK: |
| | 267 | pts = av_rescale_q(wallclock, AV_TIME_BASE_Q, time_base); |
| | 268 | break; |
| | 269 | } |
| | 270 | if (res == S_OK) |
| | 271 | pts = bmd_pts / time_base.num; |
| | 272 | |
| | 273 | if (pts != AV_NOPTS_VALUE && *initial_pts == AV_NOPTS_VALUE) |
| | 274 | *initial_pts = pts; |
| | 275 | if (*initial_pts != AV_NOPTS_VALUE) |
| | 276 | pts -= *initial_pts; |
| | 277 | |
| | 278 | return pts; |
| | 279 | } |
| | 280 | |
| 240 | HRESULT decklink_input_callback::VideoInputFrameArrived( | 281 | HRESULT decklink_input_callback::VideoInputFrameArrived( |
| 241 | IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame) | 282 | IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame) |
| 242 | { | 283 | { |
| @@ -244,8 +285,11 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( · 1 unmodified line |
| 244 | void *audioFrameBytes; | 285 | void *audioFrameBytes; |
| 245 | BMDTimeValue frameTime; | 286 | BMDTimeValue frameTime; |
| 246 | BMDTimeValue frameDuration; | 287 | BMDTimeValue frameDuration; |
| | 288 | int64_t wallclock = 0; |
| 247 | | 289 | |
| 248 | ctx->frameCount++; | 290 | ctx->frameCount++; |
| | 291 | if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) |
| | 292 | wallclock = av_gettime_relative(); |
| 249 | | 293 | |
| 250 | // Handle Video Frame | 294 | // Handle Video Frame |
| 251 | if (videoFrame) { | 295 | if (videoFrame) { |
| @@ -292,13 +336,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( · 40 unmodified lines |
| 292 | no_video = 0; | 336 | no_video = 0; |
| 293 | } | 337 | } |
| 294 | | 338 | |
| 295 | pkt.pts = frameTime / ctx->video_st->time_base.num; | 339 | pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts); |
| 296 | | | |
| 297 | if (initial_video_pts == AV_NOPTS_VALUE) { | | |
| 298 | initial_video_pts = pkt.pts; | | |
| 299 | } | | |
| 300 | | | |
| 301 | pkt.pts -= initial_video_pts; | | |
| 302 | pkt.dts = pkt.pts; | 340 | pkt.dts = pkt.pts; |
| 303 | | 341 | |
| 304 | pkt.duration = frameDuration; | 342 | pkt.duration = frameDuration; |
| @@ -368,13 +406,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( · 63 unmodified lines |
| 368 | pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (16 / 8); | 406 | pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (16 / 8); |
| 369 | audioFrame->GetBytes(&audioFrameBytes); | 407 | audioFrame->GetBytes(&audioFrameBytes); |
| 370 | audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den); | 408 | audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den); |
| 371 | pkt.pts = audio_pts / ctx->audio_st->time_base.num; | 409 | pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts); |
| 372 | | | |
| 373 | if (initial_audio_pts == AV_NOPTS_VALUE) { | | |
| 374 | initial_audio_pts = pkt.pts; | | |
| 375 | } | | |
| 376 | | | |
| 377 | pkt.pts -= initial_audio_pts; | | |
| 378 | pkt.dts = pkt.pts; | 410 | pkt.dts = pkt.pts; |
| 379 | | 411 | |
| 380 | //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts); | 412 | //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts); |
| @@ -451,6 +483,8 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 70 unmodified lines |
| 451 | ctx->video_input = decklink_video_connection_map[cctx->video_input]; | 483 | ctx->video_input = decklink_video_connection_map[cctx->video_input]; |
| 452 | if (cctx->audio_input > 0 && (unsigned int)cctx->audio_input < FF_ARRAY_ELEMS(decklink_audio_connection_map)) | 484 | if (cctx->audio_input > 0 && (unsigned int)cctx->audio_input < FF_ARRAY_ELEMS(decklink_audio_connection_map)) |
| 453 | ctx->audio_input = decklink_audio_connection_map[cctx->audio_input]; | 485 | ctx->audio_input = decklink_audio_connection_map[cctx->audio_input]; |
| | 486 | ctx->audio_pts_source = cctx->audio_pts_source; |
| | 487 | ctx->video_pts_source = cctx->video_pts_source; |
| 454 | cctx->ctx = ctx; | 488 | cctx->ctx = ctx; |
| 455 | | 489 | |
| 456 | #if !CONFIG_LIBZVBI | 490 | #if !CONFIG_LIBZVBI |