Hello,

I am working on video steganography in collaboration with northumbria university. I am working with the H.264 standard. I made a program to read and store the information about the macroblock partition and the motion vector values, and to change the motion vectors in an AVFrame structure. I am now trying to encode the video (with "avcodec_encode_video2") with the macroblock partition and the motion vectors stored in the AVFrame (instead of re-estimate these parameters). I tryed to fix the "me_method" to ME_X1 (6) but it is not sufficient. How to generate the bitstream (AVPacket) without estimate the MB partition and the MV values?

Please find attached my program.

Nb : the function which write the video, "MV_ReadWrite", begin line 626, the codec information are set line 687, and the encoding loop begin line 767.

Best regards,

Yves MICHELS.
// to compile
// gcc -std=c99 -o MV_ReadWrite -I/usr/include MV_ReadWrite.c -lavformat -lavcodec -lavutil -lz -lm



#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <malloc.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))))

#define FF_I_TYPE AV_PICTURE_TYPE_I ///< Intra
#define FF_P_TYPE AV_PICTURE_TYPE_P ///< Predicted
#define FF_B_TYPE AV_PICTURE_TYPE_B ///< Bi-dir predicted
#define CODEC_TYPE_VIDEO AVMEDIA_TYPE_VIDEO


int count = 0;
double sum = 0;
double h;
double w;
int ***new_3D_int(int idim, int jdim, int kdim)
{
  int ***matrice ;
  int i ;
  int j ;
  matrice = (int***)malloc(idim*sizeof(int**));
  for(i=0;i<idim;i++)
    {
       matrice[i] = (int**)malloc(jdim*sizeof(int*));
      for(j=0;j<jdim;j++)
	{
	   matrice[i][j] = (int*)malloc(kdim*sizeof(int));
	}
    }

  return matrice;
}

void del_3D_int(int ***matrice, int idim, int jdim)
{
  int i ;
  int j ;
for(i=0;i<idim;i++)
    {
      for(j=0;j<jdim;j++)
	{
	  free(matrice[i][j]);
	}
      free(matrice[i]);
    }
 free(matrice);
}

int ****new_4D_int(int idim, int jdim, int kdim, int ldim)
{
  int ****matrice ;
  int i ;
  int j ;
  int k ;
  matrice = (int****)malloc(idim*sizeof(int***));
  for(i=0;i<idim;i++)
    {
       matrice[i] = (int***)malloc(jdim*sizeof(int**));
      for(j=0;j<jdim;j++)
	{
	   matrice[i][j] = (int**)malloc(kdim*sizeof(int*));
	  for(k=0;k<kdim;k++)
	    {
	       matrice[i][j][k] = (int*)malloc(ldim*sizeof(int));
	    }
	}
    }

  return matrice;
}

void del_4D_int(int ****matrice, int idim, int jdim, int kdim)
{
  int i ;
  int j ;
  int k ;
for(i=0;i<idim;i++)
    {
      for(j=0;j<jdim;j++)
	{
	  for(k=0;k<kdim;k++)
	    {
	      free(matrice[i][j][k]);
	    }
	  free(matrice[i][j]);
	}
      free(matrice[i]);
    }
 free(matrice);
}

void print_vector(int x, int y, int dx, int dy)
{
	if (dx != 10000 && dy != 10000){
		sum = sum + sqrt((double)dx*(double)dx/w/w + (double)dy*(double)dy/h/h);
		count++;
	}
    //printf("%d %d ; %d %d\n", x, y, dx, dy);
    //printf(" %d", dy);
}

/* Print motion vector for each macroblock in this frame.  If there is
 * no motion vector in some macroblock, it prints a magic number NO_MV. */
void printMVMatrix(int index, AVFrame *pict, AVCodecContext *ctx, int ***MBpart, int ****VectMV, int numFrame)
{
    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;


    //printf("frame %d, %d x %d\n", index, mb_height, mb_width);

    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 != FF_P_TYPE)
			      {
				continue;
			      }
			    direction = 0;
			    break;
			case 1:
			    if (pict->pict_type != FF_B_TYPE)
			      {
			       	continue;
			      }
			    direction = 0;
			    break;
			case 2:
			    if (pict->pict_type != FF_B_TYPE)
			      {
				continue;
			      }
			    direction = 1;
			    break;
		    }
		    if (!USES_LIST(pict->mb_type[mb_index], direction)) {
#define NO_MV 10000

			if (IS_8X8(pict->mb_type[mb_index])) {
			    MBpart[mb_y][mb_x][numFrame] = 3;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x][1][numFrame] = NO_MV;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x+1][1][numFrame] = NO_MV;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y+1][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x][1][numFrame] = NO_MV;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y+1][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][1][numFrame] = NO_MV;
			} else if (IS_16X8(pict->mb_type[mb_index])) {
			    MBpart[mb_y][mb_x][numFrame] = 2;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x][1][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x][1][numFrame] = NO_MV;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x+1][1][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][1][numFrame] = NO_MV;
			} else if (IS_8X16(pict->mb_type[mb_index])) {
			    MBpart[mb_y][mb_x][numFrame] = 1;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x][1][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x+1][1][numFrame] = NO_MV;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y+1][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x][1][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][1][numFrame] = NO_MV;
			} else {
			    MBpart[mb_y][mb_x][numFrame] = 0;
			    print_vector(mb_x, mb_y, NO_MV, NO_MV);
			    VectMV[2*mb_y][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x][1][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y][2*mb_x+1][1][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x][1][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][0][numFrame] = NO_MV;
			    VectMV[2*mb_y+1][2*mb_x+1][1][numFrame] = NO_MV;
			}
#undef NO_MV
			continue;
		    }

		    if (IS_8X8(pict->mb_type[mb_index])) {
			MBpart[mb_y][mb_x][numFrame] = 3;
			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(mb_x, mb_y, dx, dy);
			if(i==0){
			    VectMV[2*mb_y][2*mb_x][0][numFrame] = dx;
			    VectMV[2*mb_y][2*mb_x][1][numFrame] = dy;}
			if(i==1){
			    VectMV[2*mb_y][2*mb_x+1][0][numFrame] = dx;
			    VectMV[2*mb_y][2*mb_x+1][1][numFrame] = dy;}
			if(i==2){
			    VectMV[2*mb_y+1][2*mb_x][0][numFrame] = dx;
			    VectMV[2*mb_y+1][2*mb_x][1][numFrame] = dy;}
			if(i==3){
			    VectMV[2*mb_y+1][2*mb_x+1][0][numFrame] = dx;
			    VectMV[2*mb_y+1][2*mb_x+1][1][numFrame] = dy;}
			}
		    } else if (IS_16X8(pict->mb_type[mb_index])) {
			MBpart[mb_y][mb_x][numFrame] = 2;
			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(mb_x, mb_y, dx, dy);
			    VectMV[2*mb_y][2*mb_x+i][0][numFrame] = dx;
			    VectMV[2*mb_y][2*mb_x+i][1][numFrame] = dy;
			    VectMV[2*mb_y+1][2*mb_x+i][0][numFrame] = dx;
			    VectMV[2*mb_y+1][2*mb_x+i][1][numFrame] = dy;
			}
		    } else if (IS_8X16(pict->mb_type[mb_index])) {
			MBpart[mb_y][mb_x][numFrame] = 1;
			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(mb_x, mb_y, dx, dy);
			    VectMV[2*mb_y+i][2*mb_x][0][numFrame] = dx;
			    VectMV[2*mb_y+i][2*mb_x][1][numFrame] = dy;
			    VectMV[2*mb_y+i][2*mb_x+1][0][numFrame] = dx;
			    VectMV[2*mb_y+i][2*mb_x+1][1][numFrame] = dy;
			}
		    } else {
			MBpart[mb_y][mb_x][numFrame] = 0;
			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(mb_x, mb_y, dx, dy);
			VectMV[2*mb_y][2*mb_x][0][numFrame] = dx;
			VectMV[2*mb_y][2*mb_x][1][numFrame] = dy;
			VectMV[2*mb_y+1][2*mb_x+1][0][numFrame] = dx;
			VectMV[2*mb_y+1][2*mb_x+1][1][numFrame] = dy;
			VectMV[2*mb_y+1][2*mb_x][0][numFrame] = dx;
			VectMV[2*mb_y+1][2*mb_x][1][numFrame] = dy;
			VectMV[2*mb_y][2*mb_x+1][0][numFrame] = dx;
			VectMV[2*mb_y][2*mb_x+1][1][numFrame] = dy;
		    }
		}
	    }
	    //printf("--\n");
	}
	//printf("====\n");
    }
}
// ====================== Write MV ======================
/* write the MV saved in VectMV in pict*/
void WriteMVMatrix(int index, AVFrame *pict, AVCodecContext *ctx, int ***MBpart, int ****VectMV, int numFrame)
{
    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;


    //printf("frame %d, %d x %d\n", index, mb_height, mb_width);

    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 != FF_P_TYPE)
			      {
				continue;
			      }
			    direction = 0;
			    break;
			case 1:
			    if (pict->pict_type != FF_B_TYPE)
			      {
			       	continue;
			      }
			    direction = 0;
			    break;
			case 2:
			    if (pict->pict_type != FF_B_TYPE)
			      {
				continue;
			      }
			    direction = 1;
			    break;
		    }
		    if (!USES_LIST(pict->mb_type[mb_index], direction)) {
#define NO_MV 10000

			if (IS_8X8(pict->mb_type[mb_index])) {

			} else if (IS_16X8(pict->mb_type[mb_index])) {

			} else if (IS_8X16(pict->mb_type[mb_index])) {

			} else {

			}
#undef NO_MV
			continue;
		    }

		    if (IS_8X8(pict->mb_type[mb_index])) {
			MBpart[mb_y][mb_x][numFrame] = 3;
			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(mb_x, mb_y, dx, dy);
			if(i==0){
			    pict->motion_val[direction][xy][0] = VectMV[2*mb_y][2*mb_x][0][numFrame];
			    pict->motion_val[direction][xy][1] = VectMV[2*mb_y][2*mb_x][1][numFrame];}
			if(i==1){
			    pict->motion_val[direction][xy][0] = VectMV[2*mb_y][2*mb_x+1][0][numFrame];
			    pict->motion_val[direction][xy][1] = VectMV[2*mb_y][2*mb_x+1][1][numFrame];}
			if(i==2){
			    pict->motion_val[direction][xy][0] = VectMV[2*mb_y+1][2*mb_x][0][numFrame];
			    pict->motion_val[direction][xy][1] = VectMV[2*mb_y+1][2*mb_x][1][numFrame];}
			if(i==3){
			    pict->motion_val[direction][xy][0] = VectMV[2*mb_y+1][2*mb_x+1][0][numFrame];
			    pict->motion_val[direction][xy][1] = VectMV[2*mb_y+1][2*mb_x+1][1][numFrame];}
			}
		    } else if (IS_16X8(pict->mb_type[mb_index])) {
			MBpart[mb_y][mb_x][numFrame] = 2;
			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(mb_x, mb_y, dx, dy);
			    pict->motion_val[direction][xy][0] = VectMV[2*mb_y][2*mb_x+i][0][numFrame];
			    pict->motion_val[direction][xy][1] = VectMV[2*mb_y][2*mb_x+i][1][numFrame];
			}
		    } else if (IS_8X16(pict->mb_type[mb_index])) {
			MBpart[mb_y][mb_x][numFrame] = 1;
			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(mb_x, mb_y, dx, dy);
			    pict->motion_val[direction][xy][0] = VectMV[2*mb_y+i][2*mb_x][0][numFrame];
			    pict->motion_val[direction][xy][1] = VectMV[2*mb_y+i][2*mb_x][1][numFrame];
			}
		    } else {
			MBpart[mb_y][mb_x][numFrame] = 0;
			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(mb_x, mb_y, dx, dy);
			pict->motion_val[direction][xy][0] = VectMV[2*mb_y][2*mb_x][0][numFrame];
			pict->motion_val[direction][xy][1] = VectMV[2*mb_y][2*mb_x][1][numFrame];

		    }
		}
	    }
	    //printf("--\n");
	}
	//printf("====\n");
    }
}

/* Extract info */
int MV_info(const char *name, int *idim, int *jdim, int *Nb, int *GOP)
{

  av_register_all();
  AVFormatContext *pFormatCtx = NULL;

  // Open video file
  if(avformat_open_input(&pFormatCtx, name, NULL, NULL)!=0)
    return -1; // couldn't open the file

  // Retrieve stream information
  if (avformat_find_stream_info(pFormatCtx, NULL)<0)
    return -1; // couldn't find stream info

  // Dump information about file onto standard error
  //av_dump_format(pFormatCtx, 0, name, 0);

  /* Now pFormatCtx->streams is an array of poiner, of size pFormatCtx->nb_stream, the next lines walks through it until it find a video stream. */

  int i;
  AVCodecContext *pCodecCtxOrig = NULL;
  AVCodecContext *pCodecCtx = NULL;

  // Find the first video stream
  int videoStream = -1;

  for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
      {
	videoStream = i;
 	break;
      }
  if(videoStream==-1)
    return -1; // didn't find a video stream

  // Get a pointer to the codec context for the video stream
  pCodecCtx = pFormatCtx->streams[videoStream]->codec;

  *idim = (int) (pCodecCtx->height)/16;
  *jdim = (int) (pCodecCtx->width)/16;
  int N = pCodecCtx->gop_size;
  int M = pCodecCtx->max_b_frames;
  *GOP = N + N*M/(M+1) - 1; // number of MV map (number of frames + number of B frames (there are 2MVmap) - number of I frames (1))
 AVCodec *pCodec = NULL;

  // Find the decoder for the video stream
  pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  if(pCodec==NULL)
    {
      fprintf(stderr, "Unsupported codec !\n");
      return -1; // codec not found
    }

  // Copy context
  /*pCodecCtxOrig = avcodec_alloc_context3(pCodec);
  if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig)!=0)
    {
      fprintf(stderr, "Couldn't copy codex context");
      return -1; // Err copying codec context
    }*/

  // Open codec
  if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
    return -1; // couldn't open codec

  AVFrame *pFrame = NULL;

  // Allocate video frame
  pFrame = avcodec_alloc_frame();
  
  // read through the entire video stream
  int frameFinished;
  AVPacket packet;
  i = 0;
  int f=1;
  int NB=0;
  while(av_read_frame(pFormatCtx, &packet)>=0)
    {
      // Is this packet from video stream ?
      if(packet.stream_index==videoStream)
   	{
	  // Decode video frame
     	  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
   	  // Did we get a video frame ?
   	  if(frameFinished)
	    {
  	      // Ignore I-Frame
	      if (pFrame->pict_type != FF_I_TYPE)
 		{NB = NB +1;}

              ++f;

	    }
	}
      i = i+1;
    }

  *Nb = NB;

return 1;
}

/* Extract the MB partition and the MV values */
int MV_extract(const char *name, int ****VectMV, int ***MBpart)
{

  av_register_all();
  AVFormatContext *pFormatCtx = NULL;

  // Open video file
  if(avformat_open_input(&pFormatCtx, name, NULL, NULL)!=0)
    return -1; // couldn't open the file

  // Retrieve stream information
  if (avformat_find_stream_info(pFormatCtx, NULL)<0)
    return -1; // couldn't find stream info

  // Dump information about file onto standard error
  //av_dump_format(pFormatCtx, 0, name, 0);

  /* Now pFormatCtx->streams is an array of poiner, of size pFormatCtx->nb_stream, the next lines walks through it until it find a video stream. */

  int i;
  AVCodecContext *pCodecCtxOrig = NULL;
  AVCodecContext *pCodecCtx = NULL;

  // Find the first video stream
  int videoStream = -1;

  for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
      {
	videoStream = i;
 	break;
      }
  if(videoStream==-1)
    return -1; // didn't find a video stream

  // Get a pointer to the codec context for the video stream
  pCodecCtx = pFormatCtx->streams[videoStream]->codec;



  /* The stream info about the codec is what we call the "codec context". This contain all the information about the codec that the stream is un=sing, and now we have this pointer to it. We now need to find the actual codec and open it. */
  // show some info (size and type of GOP)
  printf("\n");
  printf("width = %d\n", pCodecCtx->width);
  printf("height = %d\n", pCodecCtx->height);
  printf("GOP: N%d", pCodecCtx->gop_size);
  printf("M%d\n\n", pCodecCtx->max_b_frames);

  AVCodec *pCodec = NULL;

  // Find the decoder for the video stream
  pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  if(pCodec==NULL)
    {
      fprintf(stderr, "Unsupported codec !\n");
      return -1; // codec not found
    }

  // Open codec
  if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
    return -1; // couldn't open codec

  AVFrame *pFrame = NULL;

  // Allocate video frame
  pFrame = avcodec_alloc_frame();
  
  // read through the entire video stream
  int frameFinished;
  AVPacket packet;
  i = 0;
  int f=1;
  int numFrame;
  while(av_read_frame(pFormatCtx, &packet)>=0)
    {
      // Is this packet from video stream ?
      if(packet.stream_index==videoStream)
   	{
	  // Decode video frame
     	  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
   	  // Did we get a video frame ?
   	  if(frameFinished)
	    {
  	      // Ignore I-Frame
	      if (pFrame->pict_type != FF_I_TYPE)
	        {
	          printMVMatrix(f, pFrame, pCodecCtx, MBpart, VectMV, numFrame);
		  numFrame = numFrame + 1;
		}
	          ++f;

	    }
	}
      i = i+1;
    }


return f-1;
}


 // ======================= write =======================

/* Write a video with the modified MV stored in VectMV */
int MV_ReadWrite(const char *name, const char *filename, int ****VectMV, int ***MBpart)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, ret, x, y, got_output;
    int codec_id = AV_CODEC_ID_H264;
    FILE *file;
    AVFrame *frame;
    AVPacket pkt;
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };
    printf("Encode video file %s\n", filename);
    /* find the mpeg video encoder */
    codec = avcodec_find_encoder(codec_id);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }
    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }

  av_register_all();
  AVFormatContext *pFormatCtx = NULL;

  // Open video file
  if(avformat_open_input(&pFormatCtx, name, NULL, NULL)!=0)
    return -1; // couldn't open the file

  // Retrieve stream information
  if (avformat_find_stream_info(pFormatCtx, NULL)<0)
    return -1; // couldn't find stream info

  // Dump information about file onto standard error
  //av_dump_format(pFormatCtx, 0, name, 0);

  /* Now pFormatCtx->streams is an array of poiner, of size pFormatCtx->nb_stream, the next lines walks through it until it find a video stream. */

  AVCodecContext *pCodecCtxOrig = NULL;
  AVCodecContext *pCodecCtx = NULL;

  // Find the first video stream
  int videoStream = -1;

  for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
      {
	videoStream = i;
 	break;
      }
  if(videoStream==-1)
    return -1; // didn't find a video stream

  // Get a pointer to the codec context for the video stream
  pCodecCtx = pFormatCtx->streams[videoStream]->codec;



  /* The stream info about the codec is what we call the "codec context". This contain all the information about the codec that the stream is using, and now we have this pointer to it. We now need to find the actual codec and open it. */

    /* put sample parameters */
    c->bit_rate = pCodecCtx->bit_rate;
    /* resolution must be a multiple of two */
    c->width = pCodecCtx->width;
    c->height = pCodecCtx->height;
    /* frames per second */
    c->time_base = pCodecCtx->time_base;
    c->time_base.den = 25;
    /* emit one intra frame every ten frames
     * check frame pict_type before passing frame
     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
     * then gop_size is ignored and the output of encoder
     * will always be I frame irrespective to gop_size
     */
    //c->gop_size = pCodecCtx->gop_size;
    //c->max_b_frames = pCodecCtx->max_b_frames;
    c->pix_fmt = pCodecCtx->pix_fmt;
    c->me_method = ME_ZERO;    // ME_X1 to use the saved MV
    //c->ildct_cmp = 7;
    pCodecCtx->me_method = ME_ZERO;    // ME_X1 to use the saved MV
printf("%d, %d, %d, %d, %d\n",c->bit_rate,c->gop_size,c->height,c->time_base.num,c->time_base.den);
  AVCodec *pCodec = NULL;

  // Find the decoder for the video stream
  pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  if(pCodec==NULL)
    {
      fprintf(stderr, "Unsupported codec !\n");
      return -1; // codec not found
    }

  // Open codec
  if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
    return -1; // couldn't open codec

  AVFrame *pFrame = NULL;

  // Allocate video frame
  pFrame = avcodec_alloc_frame();
  
  int frameFinished;
  AVPacket packet;
  i = 0;
  int f=1;
  int numFrame;

  // === prepare the new video ===
    
    if (codec_id == AV_CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);
    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }
    file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Could not open %s\n", filename);
        exit(1);
    }
    frame = avcodec_alloc_frame();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;
    
    /* the image can be allocated by any means and av_image_alloc() is
     * just the most convenient way if av_malloc() is to be used */
    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height,
                         c->pix_fmt, 32);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw picture buffer\n");
        exit(1);
    }
    /* ============ encode video ========== */
i=0;

  while(av_read_frame(pFormatCtx, &packet)>=0)
    {
      // Is this packet from video stream ?
      if(packet.stream_index==videoStream)
   	{
	  // Decode video frame
     	  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
   	  // Did we get a video frame ?
        av_init_packet(&pkt);
        pkt.data = NULL;    // packet data will be allocated by the encoder
        pkt.size = 0;
        fflush(stdout);
        /* prepare a dummy image */
 	  if(frameFinished)
	    {
  	      // Ignore I-Frame
	      if (pFrame->pict_type != FF_I_TYPE)
	        {
	          WriteMVMatrix(f, pFrame, pCodecCtx, MBpart, VectMV, numFrame);
		  numFrame = numFrame + 1;
		}
	          ++f;
        pFrame->pts = i;

        /* encode the image */
printf("mb_cmp =  %d, me_method = %d\n",c->mb_cmp, c->me_method); // test
        ret = avcodec_encode_video2(c, &pkt, pFrame, &got_output); // <= avcodec_encode_video2 estimate the MB partition and the MV value instead of using the ones stored in pFrame   /!\

        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }
        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
            fwrite(pkt.data, 1, pkt.size, file);
            av_free_packet(&pkt);
        }
i = i+1;
	    }

	}
       
    }

    /* get the delayed frames */
    for (got_output = 1; got_output; i++) {
        fflush(stdout);
        ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }
        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
            fwrite(pkt.data, 1, pkt.size, file);
            av_free_packet(&pkt);
        }
    }
    /* add sequence end code to have a real mpeg file */
    fwrite(endcode, 1, sizeof(endcode), file);
    fclose(file);
    avcodec_close(c);
    av_free(c);
    av_freep(&frame->data[0]);
    //av_frame_free(&frame);
    printf("\n");


return f-1;
}

void main()
{
  int i,j,k,l;
  int ****VectMV;
  int ****TestVectMV;
  int ***MBpart;
  int ***TestMB;
  int Nbi,Nbj,Nb,GOP;
  const char *name = "001.mp4";
  const char *nameOut = "MVtest.mp4";

// Extract info for the allocations
  MV_info(name, &Nbi, &Nbj, &Nb, &GOP);
// Allocations  
  VectMV = new_4D_int(2*Nbi, 2*Nbj, 2, Nb);
  TestVectMV = new_4D_int(2*Nbi, 2*Nbj, 2, Nb);
  TestMB = new_3D_int(Nbi, Nbj, Nb);
  MBpart = new_3D_int(Nbi, Nbj, Nb);
  printf("%s\n%d, %d, %d, %d\n", name, Nbi, Nbj, Nb, GOP);
  GOP = 1; // useless here
// Extract the MV from the video name
  MV_extract(name, VectMV, MBpart);

// To modify the MV
for(i=0;i<Nbi;i++)
{for(j=0;j<Nbj;j++)
{for(k=0;k<2;k++)
{for(l=0;l<Nb;l++)
{//TestVectMV[i][j][k][l] = VectMV[i][j][k][l];
VectMV[i][j][k][l] = VectMV[i][j][k][l] ;
}}}}

// Write the the new video (nameOut) with the new MV (VectMV)
  MV_ReadWrite(name, nameOut, VectMV, MBpart);
// Extract the MV from nameOut to verify if MV_ReadWrite worked
  MV_extract(nameOut, TestVectMV, TestMB);

// Print Test
for(i=0;i<Nbi;i++)
{for(j=0;j<Nbj;j++)
{for(k=0;k<2;k++)
{for(l=0;l<Nb;l++)
{//printf("%d   %d    %d\n",TestVectMV[i][j][k][l]-VectMV[i][j][k][l],VectMV[i][j][k][l],TestVectMV[i][j][k][l]);
if(TestMB[i][j][l]!=MBpart[i][j][l]){printf("%d   %d    %d\n",TestMB[i][j][l]-MBpart[i][j][l],MBpart[i][j][l],TestMB[i][j][l]);} // print when the MB are different
}}}}

  del_4D_int(VectMV, 2*Nbi, 2*Nbj, 2);
  del_4D_int(TestVectMV, 2*Nbi, 2*Nbj, 2);
  del_3D_int(TestMB, Nbi, Nbj);
  del_3D_int(MBpart, Nbi, Nbj);

}
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to