From: Limin Wang <lance.lmw...@gmail.com> Signed-off-by: Limin Wang <lance.lmw...@gmail.com> --- libavcodec/internal.h | 15 ++++++++++++ libavcodec/utils.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+)
diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 0a72a0e..09eb102 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -374,6 +374,21 @@ int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, void **data, size_t *sei_size); /** + * Check AVFrame for S12M timecode side data and allocate and fill TC SEI message with timecode info + * + * @param frame Raw frame to get S12M timecode side data from + * @param prefix_len Number of bytes to allocate before SEI message + * @param data Pointer to a variable to store allocated memory + * Upon return the variable will hold NULL on error or if frame has no S12M timecode info. + * Otherwise it will point to prefix_len uninitialized bytes followed by + * *sei_size SEI message + * @param sei_size Pointer to a variable to store generated SEI message length + * @return Zero on success, negative error code on failure + */ +int ff_alloc_timecode_sei(const AVFrame *frame, size_t prefix_len, + void **data, size_t *sei_size); + +/** * Get an estimated video bitrate based on frame size, frame rate and coded * bits per pixel. */ diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a9c69e3..d4216b4 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -50,6 +50,7 @@ #include "thread.h" #include "frame_thread_encoder.h" #include "internal.h" +#include "put_bits.h" #include "raw.h" #include "bytestream.h" #include "version.h" @@ -2236,6 +2237,68 @@ int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, return 0; } +static unsigned bcd2uint(uint8_t bcd) +{ + unsigned low = bcd & 0xf; + unsigned high = bcd >> 4; + if (low > 9 || high > 9) + return 0; + return low + 10*high; +} + +int ff_alloc_timecode_sei(const AVFrame *frame, size_t prefix_len, + void **data, size_t *sei_size) +{ + AVFrameSideData *sd = NULL; + uint8_t *sei_data; + PutBitContext pb; + uint32_t *tc; + int m; + + if (frame) + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE); + + if (!sd) { + *data = NULL; + return 0; + } + tc = (uint32_t*)sd->data; + m = tc[0] & 3; + + *sei_size = sizeof(uint32_t) * 4; + *data = av_mallocz(*sei_size + prefix_len); + if (!*data) + return AVERROR(ENOMEM); + sei_data = (uint8_t*)*data + prefix_len; + + init_put_bits(&pb, sei_data, *sei_size); + put_bits(&pb, 2, m); // num_clock_ts + + for (int j = 1; j <= m; j++) { + uint32_t tcsmpte = tc[j]; + unsigned hh = bcd2uint(tcsmpte & 0x3f); // 6-bit hours + unsigned mm = bcd2uint(tcsmpte>>8 & 0x7f); // 7-bit minutes + unsigned ss = bcd2uint(tcsmpte>>16 & 0x7f); // 7-bit seconds + unsigned ff = bcd2uint(tcsmpte>>24 & 0x3f); // 6-bit frames + unsigned drop = tcsmpte & 1<<30 && !0; // 1-bit drop if not arbitrary bit + + put_bits(&pb, 1, 1); // clock_timestamp_flag + put_bits(&pb, 1, 1); // units_field_based_flag + put_bits(&pb, 5, 0); // counting_type + put_bits(&pb, 1, 1); // full_timestamp_flag + put_bits(&pb, 1, 0); // discontinuity_flag + put_bits(&pb, 1, drop); + put_bits(&pb, 9, ff); + put_bits(&pb, 6, ss); + put_bits(&pb, 6, mm); + put_bits(&pb, 5, hh); + put_bits(&pb, 5, 0); + } + flush_put_bits(&pb); + + return 0; +} + int64_t ff_guess_coded_bitrate(AVCodecContext *avctx) { AVRational framerate = avctx->framerate; -- 1.8.3.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".