2个YUV文件的PSNR计算器使用c++分割错误

PSNR calclator of 2 YUV files using c++ segmentation fault

本文关键字:c++ 分割 错误 计算器 YUV 文件 PSNR 2个      更新时间:2023-10-16

Iam试图用c++编写一个代码来计算两个yuv视频文件的PSNR,但一切都应该正常,但我遇到了分段错误。。非常感谢您的帮助这是我的代码

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "base.h"

void makeAFrame( YuvFrame* f, int width, int height )
{
 f->lum.width = width;    f->lum.height  = height;     
 f->cb .width = width/2;  f->cb .height  = height/2;    
 f->cr .width = width/2;  f->cr .height  = height/2;   
}
void readColorComponent( ColorComponent* cc, FILE* file )
{
 unsigned int size   = cc->width*cc->height;
 unsigned int rsize;
 rsize = fread( cc->data, sizeof(unsigned char), size, file );

}
double psnr( ColorComponent& rec, ColorComponent& org)
{
 unsigned char*  pOrg  = org.data;
 unsigned char*  pRec  = rec.data;
 double          ssd   = 0;
 int             diff;
 for  ( int r = 0; r < rec.height; r++ )
 {
   for( int c = 0; c < rec.width;  c++ )
   {
     diff  = pRec[c] - pOrg[c];
     ssd  += (double)( diff * diff );
   }
   pRec   += rec.width;
   pOrg   += org.width;
 }
 if( ssd == 0.0 )
 {
   return 99.99;
 }
 return ( 10.0 * log10( (double)rec.width * (double)rec.height * 65025.0 / ssd ) );
}
void getPSNR( double& psnrY, double& psnrU, double& psnrV, YuvFrame& rcFrameOrg, YuvFrame& rcFrameRec )
{
 psnrY = psnr( rcFrameRec.lum, rcFrameOrg.lum );
 psnrU = psnr( rcFrameRec.cb,  rcFrameOrg.cb  );
 psnrV = psnr( rcFrameRec.cr,  rcFrameOrg.cr  );
}
void readFrame( YuvFrame* f, FILE* file )
{
 readColorComponent( &f->lum, file );
 readColorComponent( &f->cb,  file );
 readColorComponent( &f->cr,  file );
}

int main(int argc, char *argv[])
{
 int     acc = 10000;
 #define   OUT "%d,%04d"
 int           stream          = 0;
 unsigned int  width           = 0;
 unsigned int  height          = 0;
 unsigned int  temporal_stages = 0;
 unsigned int  skip_at_start   = 0;
 double        fps             = 0.0;
 FILE*         org_file        = 0;
 FILE*         rec_file        = 0;
 FILE*         str_file        = 0;
 char*         prefix_string   = 0;
 unsigned int  index, skip, skip_between, sequence_length;
 int           py, pu, pv, br;
 double        bitrate = 0.0;
 double        psnrY, psnrU, psnrV;
 YuvFrame      cOrgFrame, cRecFrame;
 double        AveragePSNR_Y = 0.0;
 double        AveragePSNR_U = 0.0;
 double        AveragePSNR_V = 0.0;
 int                  currarg = 5;
 int                  rpsnr   = 0;
 width             = 300; 
 height            = 240;
 org_file          = fopen("foreman_qcif.yuv","rb"); 
 rec_file          = fopen("foreman_qcif2.yuv","rb"); 
 temporal_stages=2;
 fseek(    rec_file, 0, SEEK_END );
 fseek(    org_file, 0, SEEK_END );
 size_t rsize = ftell( rec_file );
 size_t osize = ftell( org_file );
 fseek(    rec_file, 0, SEEK_SET );
 fseek(    org_file, 0, SEEK_SET );
 if (rsize < osize)
 {
   sequence_length = (unsigned int)((double)rsize/(double)((width*height*3)/2));
 }
  else
  {
   sequence_length = (unsigned int)((double)osize/(double)((width*height*3)/2));
  skip_between    = ( 1 << temporal_stages ) - 1;
}
 //here we try to make frames out of images
 makeAFrame( &cOrgFrame, width, height );
 makeAFrame( &cRecFrame, width, height );
 //looping over all frames
 for( skip = skip_at_start, index = 0; index < sequence_length; index++, skip = skip_between )
 {
   fseek( org_file, skip*width*height*3/2, SEEK_CUR);
   readFrame       ( &cOrgFrame, org_file );
   readFrame       ( &cRecFrame, rec_file );
   getPSNR         ( psnrY, psnrU, psnrV, cOrgFrame, cRecFrame);
   AveragePSNR_Y +=  psnrY;
   AveragePSNR_U +=  psnrU;
   AveragePSNR_V +=  psnrV;
   py = (int)floor( acc * psnrY + 0.5 );
   pu = (int)floor( acc * psnrU + 0.5 );
   pv = (int)floor( acc * psnrV + 0.5 );
   fprintf(stdout,"%dt"OUT"t"OUT"t"OUT"n",index,py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
 }
 fprintf(stdout,"n");
 py = (int)floor( acc * AveragePSNR_Y / (double)sequence_length + 0.5 );
 pu = (int)floor( acc * AveragePSNR_U / (double)sequence_length + 0.5 );
 pv = (int)floor( acc * AveragePSNR_V / (double)sequence_length + 0.5 );
 br = (int)floor( acc * bitrate                                 + 0.5 );
 if( stream )
 {
   if( prefix_string )
   {
     fprintf(stderr,"%st"OUT"t"OUT"t"OUT"t"OUT"n",prefix_string,br/acc,br%acc,py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
     fprintf(stdout,"%st"OUT"t"OUT"t"OUT"t"OUT"n",prefix_string,br/acc,br%acc,py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
   }
   else
   {
     fprintf(stderr,OUT"t"OUT"t"OUT"t"OUT"n",br/acc,br%acc,py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
     fprintf(stdout,OUT"t"OUT"t"OUT"t"OUT"n",br/acc,br%acc,py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
   }
 }
 else
 {
   fprintf(stderr,"totalt"OUT"t"OUT"t"OUT"n",py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
   fprintf(stdout,"totalt"OUT"t"OUT"t"OUT"n",py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
 }
 fprintf(stdout, "n");
 fclose     ( org_file   );
 fclose     ( rec_file   );
 if( stream )
 {
   fclose   ( str_file   );
 }
 return (rpsnr*py);
}

和碱.h包含结构

typedef struct
{
 int             width;
 int             height;
 unsigned char*  data;
} ColorComponent;
typedef struct
{
 ColorComponent lum;
 ColorComponent cb;
 ColorComponent cr;
} YuvFrame;

好吧,分段错误是由于您试图访问未分配给您的内存地址。。。as w热修复以避免错误将此功能添加到您的代码

void foo( ColorComponent* cc )
{
 if( ! ( cc->data = new unsigned char[cc->width * cc->height]))
 {
   fprintf(stderr, "nERROR: memory allocation failed!nn");
   exit(-1);
 }
}

并更改这些线路

void makeAFrame( YuvFrame* f, int width, int height )
{
 f->lum.width = width;    f->lum.height  = height;     
 f->cb .width = width/2;  f->cb .height  = height/2;    
 f->cr .width = width/2;  f->cr .height  = height/2;   
}

void makeAFrame( YuvFrame* f, int width, int height )
{
 f->lum.width = width;    f->lum.height  = height;    
 foo( &f->lum );
 f->cb .width = width/2;  f->cb .height  = height/2;
 foo( &f->cb  );
 f->cr .width = width/2;  f->cr .height  = height/2;   
 foo( &f->cr  );
}

现在应该可以工作了