Signed-off-by: Paul B Mahol <one...@gmail.com> --- libavcodec/mpegvideo.c | 10 +++++ libavfilter/vf_codecview.c | 105 +++++++++++++++++++++++++++++++++++++++++++++ libavutil/frame.h | 4 ++ 3 files changed, 119 insertions(+)
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 2f5793b9a4..ce6108d094 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1603,6 +1603,16 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_ } } + if (mb_height && mb_width) { + AVFrameSideData *sd; + + av_log(avctx, AV_LOG_DEBUG, "Adding %d MB types info to frame %d\n", mb_width * mb_height, avctx->frame_number); + sd = av_frame_new_side_data(pict, AV_FRAME_DATA_MACROBLOCK_TYPES, mb_width * mb_height * sizeof(uint32_t)); + if (!sd) + return; + memcpy(sd->data, mbtype_table, mb_width * mb_height * sizeof(uint32_t)); + } + #if FF_API_DEBUG_MV if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || (avctx->debug_mv)) { diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c index 331bfba777..40fb8dfb7a 100644 --- a/libavfilter/vf_codecview.c +++ b/libavfilter/vf_codecview.c @@ -29,6 +29,7 @@ * TODO: segmentation */ +#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/motion_vector.h" #include "libavutil/opt.h" @@ -44,9 +45,23 @@ #define FRAME_TYPE_P (1<<1) #define FRAME_TYPE_B (1<<2) +#define IS_PCM(a) ((a) & (1 << 2)) +#define IS_INTRA(a) ((a) & 7) +#define IS_ACPRED(a) ((a) & (1 << 9)) +#define IS_INTRA16x16(a) ((a) & (1 << 1)) +#define IS_INTRA4x4(a) ((a) & (1 << 0)) +#define IS_DIRECT(a) ((a) & (1 << 8)) +#define IS_SKIP(a) ((a) & (1 << 11)) +#define IS_GMC(a) ((a) & (1 << 10)) +#define USES_LIST(a, list) ((a) & (((1 << 12) | (1 << 13)) << (2 * (list)))) +#define IS_8X8(a) ((a) & ((1 << 6))) +#define IS_16X8(a) ((a) & ((1 << 4))) +#define IS_8X16(a) ((a) & ((1 << 5))) + typedef struct CodecViewContext { const AVClass *class; unsigned mv; + unsigned mbtypes; unsigned frame_type; unsigned mv_type; int hsub, vsub; @@ -72,6 +87,7 @@ static const AVOption codecview_options[] = { CONST("if", "I-frames", FRAME_TYPE_I, "frame_type"), CONST("pf", "P-frames", FRAME_TYPE_P, "frame_type"), CONST("bf", "B-frames", FRAME_TYPE_B, "frame_type"), + { "mb", "visualize macroblock types", OFFSET(mbtypes), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, }, { NULL } }; @@ -277,6 +293,95 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } } + if (s->mbtypes) { + AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MACROBLOCK_TYPES); + if (sd) { + int mb_height = (frame->height + 31) / 32 * 2; + int mb_width = (frame->width + 15) / 16; + int block_height = 16 >> 1; + int mb_stride = mb_width + 1; + int mb_y, mb_x; + uint32_t *mbtype_table = (uint32_t *)sd->data; + + for (mb_y = 0; mb_y < mb_height; mb_y++) { + for (mb_x = 0; mb_x < mb_width; mb_x++) { + const int mb_index = mb_x + mb_y * mb_stride; + /*{ + uint64_t c = (qscale_table[mb_index] * 128 / 31) * + 0x0101010101010101ULL; + int y; + for (y = 0; y < block_height; y++) { + *(uint64_t *)(frame->data[1] + 8 * mb_x + + (block_height * mb_y + y) * + frame->linesize[1]) = c; + *(uint64_t *)(frame->data[2] + 8 * mb_x + + (block_height * mb_y + y) * + frame->linesize[2]) = c; + } + } */ + { + int mb_type = mbtype_table[mb_index]; + uint64_t u,v; + int y; + +#define COLOR(theta, r) \ + u = (int)(128 + r * cos(theta * M_PI / 180)); \ + v = (int)(128 + r * sin(theta * M_PI / 180)); + + u = v = 128; + if (IS_PCM(mb_type)) { + COLOR(120, 48) + } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || + IS_INTRA16x16(mb_type)) { + COLOR(30, 48) + } else if (IS_INTRA4x4(mb_type)) { + COLOR(90, 48) + } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) { + COLOR(120, 48) + } else if (IS_DIRECT(mb_type)) { + COLOR(150, 48) + } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) { + COLOR(170, 48) + } else if (IS_GMC(mb_type)) { + COLOR(190, 48) + } else if (IS_SKIP(mb_type)) { + COLOR(180, 48) + } else if (!USES_LIST(mb_type, 1)) { + COLOR(240, 48) + } else if (!USES_LIST(mb_type, 0)) { + COLOR(0, 48) + } else { + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + COLOR(300,48) + } + + u *= 0x0101010101010101ULL; + v *= 0x0101010101010101ULL; + for (y = 0; y < block_height; y++) { + *(uint64_t *)(frame->data[1] + 8 * mb_x + + (block_height * mb_y + y) * frame->linesize[1]) = u; + *(uint64_t *)(frame->data[2] + 8 * mb_x + + (block_height * mb_y + y) * frame->linesize[2]) = v; + } + + // segmentation + if (IS_8X8(mb_type) || IS_16X8(mb_type)) { + *(uint64_t *)(frame->data[0] + 16 * mb_x + 0 + + (16 * mb_y + 8) * frame->linesize[0]) ^= 0x8080808080808080ULL; + *(uint64_t *)(frame->data[0] + 16 * mb_x + 8 + + (16 * mb_y + 8) * frame->linesize[0]) ^= 0x8080808080808080ULL; + } + if (IS_8X8(mb_type) || IS_8X16(mb_type)) { + for (y = 0; y < 16; y++) + frame->data[0][16 * mb_x + 8 + (16 * mb_y + y) * + frame->linesize[0]] ^= 0x80; + } + } + } + } + } + } + return ff_filter_frame(outlink, frame); } diff --git a/libavutil/frame.h b/libavutil/frame.h index fef558ea2f..8481dc080b 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -141,6 +141,10 @@ enum AVFrameSideDataType { * metadata key entry "name". */ AV_FRAME_DATA_ICC_PROFILE, + /** + * Macroblock types exported by some codecs. + */ + AV_FRAME_DATA_MACROBLOCK_TYPES, }; enum AVActiveFormatDescription { -- 2.11.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel