c++ - 使用 C++ 段错误的 2 个 YUV 文件的 PSNR 计算器

标签 c++

我正在尝试用 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,"%d\t"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,"%s\t"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,"%s\t"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,"total\t"OUT"\t"OUT"\t"OUT"\n",py/acc,py%acc,pu/acc,pu%acc,pv/acc,pv%acc);
   fprintf(stdout,"total\t"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);
}

和base.h包含结构

typedef struct
{
 int             width;
 int             height;
 unsigned char*  data;
} ColorComponent;

typedef struct
{
 ColorComponent lum;
 ColorComponent cb;
 ColorComponent cr;
} YuvFrame;

最佳答案

好吧,段错误是由于您试图访问未分配给您的内存地址而引起的...作为 w hot-fix 以避免错误,将此函数添加到您的代码中

void foo( ColorComponent* cc )
{
 if( ! ( cc->data = new unsigned char[cc->width * cc->height]))
 {
   fprintf(stderr, "\nERROR: memory allocation failed!\n\n");
   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  );
}

现在一切正常

关于c++ - 使用 C++ 段错误的 2 个 YUV 文件的 PSNR 计算器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26425892/

相关文章:

c++ - 如何从另一个类访问已经声明的类?

c++ - STL vector 元素去除效率

c++ - 读/写 unicode c++

c++ - 书中的一个测验 "C++ Strategies and Tactics"

c++ - atoi() 转换错误

c++ - 使用逗号运算符和可变模板参数包折叠表达式

c++释放数组指针的内存

c++ - 关联容器的 lower_bound 复杂度 : member function vs non-member function

c++ - 为什么编译器将类函数作为非静态函数处理?

c++ - 如何在不同类中交叉引用 typedef?