ffmpeg获取运动矢量问题

来源:互联网 发布:subcrew淘宝专卖店 编辑:程序博客网 时间:2024/06/06 03:07
解码过程中得到的运动矢量,在avcodec_decode_video2()函数解码之后就可以从AVFrame中提取运动矢量信息了。运动矢量提取与编码方式有关,一些格式无法提取运动矢量,近几年较为流行的如H264等均可以。

运动矢量关注motion_val变量。注意画运动矢量图时,需要考虑视频块是8*8,16*8,8*16还是16*16的。针对雷霄骅的100行简易ffmpeg播放器代码
http://blog.csdn.net/leixiaohua1020?viewmode=list:
加上提取运动矢量部分。
#include "stdafx.h"#define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED)#define IS_16X16(a)      ((a)&MB_TYPE_16x16)#define IS_16X8(a)       ((a)&MB_TYPE_16x8)#define IS_8X16(a)       ((a)&MB_TYPE_8x16)#define IS_8X8(a)        ((a)&MB_TYPE_8x8)#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list))))void print_vector(FILE *fp1, int frame, int code, int x, int y, int dx, int dy){fprintf(fp1,"%d %d %d %d %d %d\n", frame, code, x, y, dx, dy);}void printMVMatrix(FILE *fp2, int index, AVFrame *pict, AVCodecContext *ctx){    const int mb_width  = (ctx->width + 15) / 16;    const int mb_height = (ctx->height + 15) / 16;    const int mb_stride = mb_width + 1;    const int mv_sample_log2 = 4 - pict->motion_subsample_log2;    const int mv_stride = (mb_width << mv_sample_log2) + (ctx->codec_id == CODEC_ID_H264 ? 0 : 1);    const int quarter_sample = (ctx->flags & CODEC_FLAG_QPEL) != 0;    const int shift = 1 + quarter_sample;    for (int mb_y = 0; mb_y < mb_height; mb_y++) {for (int mb_x = 0; mb_x < mb_width; mb_x++) {    const int mb_index = mb_x + mb_y * mb_stride;    if (pict->motion_val) {for (int type = 0; type < 3; type++) {    int direction = 0;    switch (type) {case 0:    if (pict->pict_type != AV_PICTURE_TYPE_P)continue;    direction = 0;    break;case 1:    if (pict->pict_type != AV_PICTURE_TYPE_B)       continue;    direction = 0;    break;case 2:    if (pict->pict_type != AV_PICTURE_TYPE_B)continue;    direction = 1;    break;    }    if (!USES_LIST(pict->mb_type[mb_index], direction)) {#define NO_MV 0if (IS_8X8(pict->mb_type[mb_index])) {    print_vector(fp2, index, 0, mb_x, mb_y, NO_MV, NO_MV);    print_vector(fp2, index, 1, mb_x, mb_y, NO_MV, NO_MV);    print_vector(fp2, index, 2, mb_x, mb_y, NO_MV, NO_MV);    print_vector(fp2, index, 3, mb_x, mb_y, NO_MV, NO_MV);} else if (IS_16X8(pict->mb_type[mb_index])) {    print_vector(fp2, index, 0, mb_x, mb_y, NO_MV, NO_MV);    print_vector(fp2, index, 1, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 2, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 3, mb_x, mb_y, NO_MV, NO_MV);} else if (IS_8X16(pict->mb_type[mb_index])) {    print_vector(fp2, index, 0, mb_x, mb_y, NO_MV, NO_MV);    print_vector(fp2, index, 1, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 2, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 3, mb_x, mb_y, NO_MV, NO_MV);} else {    print_vector(fp2, index, 0, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 1, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 2, mb_x, mb_y, NO_MV, NO_MV);print_vector(fp2, index, 3, mb_x, mb_y, NO_MV, NO_MV);}#undef NO_MVcontinue;    }    if (IS_8X8(pict->mb_type[mb_index])) {for (int i = 0; i < 4; i++) {    int xy = (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride) << (mv_sample_log2-1);    int dx = (pict->motion_val[direction][xy][0]>>shift);    int dy = (pict->motion_val[direction][xy][1]>>shift);    print_vector(fp2, index, i, mb_x, mb_y, dx, dy);}    } else if (IS_16X8(pict->mb_type[mb_index])) {for (int i = 0; i < 2; i++) {    int xy = (mb_x*2 + (mb_y*2 + i)*mv_stride) << (mv_sample_log2-1);    int dx = (pict->motion_val[direction][xy][0]>>shift);    int dy = (pict->motion_val[direction][xy][1]>>shift);    if (IS_INTERLACED(pict->mb_type[mb_index]))dy *= 2;    print_vector(fp2, index, i*2, mb_x, mb_y, dx, dy);print_vector(fp2, index, i*2+1, mb_x, mb_y, dx, dy);}    } else if (IS_8X16(pict->mb_type[mb_index])) {for (int i = 0; i < 2; i++) {    int xy =  (mb_x*2 + i + mb_y*2*mv_stride) << (mv_sample_log2-1);    int dx = (pict->motion_val[direction][xy][0]>>shift);    int dy = (pict->motion_val[direction][xy][1]>>shift);    if (IS_INTERLACED(pict->mb_type[mb_index]))dy *= 2;    print_vector(fp2, index, i, mb_x, mb_y, dx, dy);print_vector(fp2, index, i+2, mb_x, mb_y, dx, dy);}    } else {int xy = (mb_x + mb_y*mv_stride) << mv_sample_log2;int dx = (pict->motion_val[direction][xy][0]>>shift);int dy = (pict->motion_val[direction][xy][1]>>shift);print_vector(fp2, index, 0, mb_x, mb_y, dx, dy);print_vector(fp2, index, 1, mb_x, mb_y, dx, dy);print_vector(fp2, index, 2, mb_x, mb_y, dx, dy);print_vector(fp2, index, 3, mb_x, mb_y, dx, dy);    }}    }}    }}int _tmain(int argc, _TCHAR* argv[]){AVFormatContext*pFormatCtx;inti, videoindex;int             q_number;AVCodecContext*pCodecCtx;AVCodec*pCodec;FILE *fp;for (q_number = 1; q_number < 2; q_number++){int gindex=0;char filepath[]="";char querynumber[5];itoa(q_number, querynumber, 10);strcat(filepath, querynumber);strcat(filepath, ".avi");char motionname[] = "WZM";strcat(motionname, querynumber);strcat(motionname, ".txt");fp = fopen(motionname, "w");av_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){printf("无法打开文件\n");return -1;}if(av_find_stream_info(pFormatCtx)<0){printf("Couldn't find stream information.\n");return -1;}videoindex=-1;for(i=0; i<pFormatCtx->nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){videoindex=i;break;}if(videoindex==-1){printf("Didn't find a video stream.\n");return -1;}pCodecCtx=pFormatCtx->streams[videoindex]->codec;pCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL){printf("Codec not found.\n");return -1;}if(avcodec_open(pCodecCtx, pCodec)<0){printf("Could not open codec.\n");return -1;}AVFrame*pFrame,*pFrameYUV;pFrame=avcodec_alloc_frame();pFrameYUV=avcodec_alloc_frame();uint8_t *out_buffer;out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//------------SDL----------------/*if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  printf( "Could not initialize SDL - %s\n", SDL_GetError()); exit(1);} SDL_Surface *screen; screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);if(!screen) {  printf("SDL: could not set video mode - exiting\n");  exit(1);}SDL_Overlay *bmp; bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen); SDL_Rect rect;*///---------------int ret, got_picture;static struct SwsContext *img_convert_ctx;int y_size = pCodecCtx->width * pCodecCtx->height;AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));av_new_packet(packet, y_size);//输出一下信息-----------------------------printf("文件信息-----------------------------------------\n");av_dump_format(pFormatCtx,0,filepath,0);printf("-------------------------------------------------\n");//------------------------------while(av_read_frame(pFormatCtx, packet)>=0){if(packet->stream_index==videoindex){ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);gindex++;if(ret < 0){printf("解码错误\n");return -1;}if(got_picture){printMVMatrix(fp, gindex, pFrame, pCodecCtx);}}av_free_packet(packet);}fclose(fp);delete[] out_buffer;av_free(pFrameYUV);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);}return 0;}


0 1
原创粉丝点击