00001
00002
00003
00004
00005
00006 #include "standard.h"
00007 #include <unistd.h>
00008 #include "video_codec.h"
00009 #include "input.h"
00010 #include "vid_wrapper.h"
00011
00012 #define LOW_WATER_MARK 250
00013 #define STRLEN 256
00014 #define CHUNKSIZE 500
00015
00016 video_codec *VidSt;
00017
00018 static int filelen(char *fn)
00019
00020
00021
00022 {
00023 int f, l;
00024 f = open(fn);
00025 if (f == -1)
00026 l = 0;
00027 else {
00028 lseek(f, 0, 2);
00029
00030 close(f);
00031 }
00032 return (l);
00033 }
00034
00035
00036
00037 static char *stripext(char *fn)
00038
00039
00040
00041
00042 {
00043 static char r[256];
00044 int i, ok;
00045
00046
00047 strcpy(r, fn);
00048 i = strlen(r) - 1;
00049
00050 while (i >= 0) {
00051 if ((r[i]=='.') && (i != 0)) {
00052 r[i]='\0';
00053 break;
00054 }
00055 else
00056 i--;
00057 }
00058 return (r);
00059 }
00060
00061
00062 static void config_vc(video_codec *v)
00063
00064
00065
00066 {
00067 char s[256], sx[256];
00068 int okf;
00069
00070 strcpy(v->input_file, DEF_VID_INPUT_FILE);
00071
00072 sprintf(sx, "%s.263.sent", v->label);
00073 strcpy(v->streamname, sx);
00074
00075 sprintf(sx, "%s.263.received", v->label);
00076 strcpy(v->output_file, sx);
00077
00078 v->start = 0;
00079
00080 v->targetrate = DEF_TARGET_BITRATE;
00081 }
00082
00083 void set_frames(video_codec *v)
00084
00085
00086
00087 {
00088 int numf;
00089
00090 numf = (filelen(v->input_file) / ((v->pels * v->lines) * 1.5)) - 1;
00091 v->end = numf;
00092 }
00093
00094 int FindFrameSkip(int last)
00095
00096
00097
00098 {
00099 float seconds_elapsed = (float) (get_clock()-(VidSt->start_time)) / 1000;
00100
00101 int ideal_frame = (int) (seconds_elapsed * (VidSt->ref_frame_rate));
00102 return (ideal_frame - last);
00103 }
00104
00105
00106 video_codec *new_video_codec(char *name)
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 {
00117 video_codec *v;
00118
00119 v = malloc(sizeof(video_codec));
00120 if (v != NULL) {
00121
00122 memset(v, 0, sizeof(video_codec));
00123
00124 VidSt = v;
00125
00126 strcpy(v->label, name);
00127 v->done = 0;
00128
00129
00130
00131
00132
00133
00134 v->prev_image = NULL;
00135 v->curr_image = NULL;
00136 v->curr_recon = NULL;
00137 v->prev_recon = NULL;
00138 v->B_recon = NULL;
00139 v->B_image = NULL;
00140 v->pic = (Pict *)malloc(sizeof(Pict));
00141 v->first_loop_finished=0;
00142 v->PPFlag = 0;
00143 v->pdist = 0;
00144 v->bdist = 0;
00145 v->bits = (Bits *)malloc(sizeof(Bits));
00146 v->total_bits = (Bits *)malloc(sizeof(Bits));
00147 v->intra_bits = (Bits *)malloc(sizeof(Bits));
00148 v->res = (Results *)malloc(sizeof(Results));
00149 v->total_res = (Results *)malloc(sizeof(Results));
00150 v->b_res = (Results *)malloc(sizeof(Results));
00151
00152 v->streamname = (char *)malloc(sizeof(char)*100);
00153 v->outputfile = (char *)malloc(sizeof(char)*100);
00154 v->diff_filename=DEF_DIFFILENAME;
00155 v->tracefile = (char *)malloc(sizeof(char)*100);
00156
00157
00158 fprintf(stdout, "\nTMN (H.263) coder version 2.0, ");
00159 fprintf(stdout, "Copyright (C) 1995, 1996 Telenor R&D, Norway\n");
00160 fprintf(stdout, "Heavy modification by Brendan Dowling based upon work by Feng Chen\n");
00161
00162 v->headerlength = DEF_HEADERLENGTH;
00163
00164 #ifndef FASTIDCT
00165 init_idctref();
00166 #endif
00167
00168
00169 v->advanced = DEF_ADV_MODE;
00170 v->syntax_arith_coding = DEF_SAC_MODE;
00171 v->pic->unrestricted_mv_mode = DEF_UMV_MODE;
00172 v->mv_outside_frame = DEF_UMV_MODE || DEF_ADV_MODE;
00173 v->long_vectors = DEF_UMV_MODE;
00174 v->pb_frames = DEF_PBF_MODE;
00175
00176 v->QP = DEF_INTER_QUANT;
00177 v->QPI = DEF_INTRA_QUANT;
00178 v->pic->BQUANT = DEF_BQUANT;
00179 v->pic->source_format = DEF_CODING_FORMAT;
00180
00181 v->ref_frame_rate = (float)DEF_REF_FRAME_RATE;
00182 v->chosen_frameskip = DEF_FRAMESKIP + 1;
00183 v->orig_frameskip = DEF_ORIG_SKIP + 1;
00184
00185 v->pic->target_frame_rate = (float)DEF_TARGET_FRAME_RATE;
00186
00187
00188 v->seqfilename = v->input_file;
00189
00190 strcpy(v->outputfile, DEF_OUTFILENAME);
00191
00192 v->writediff = DEF_WRITE_DIFF;
00193 v->trace = DEF_WRITE_TRACE;
00194 v->write_repeated = DEF_WRITE_REPEATED;
00195 v->pic->seek_dist = DEF_SEEK_DIST;
00196 v->pic->use_gobsync = DEF_INSERT_SYNC;
00197 v->start = DEF_START_FRAME;
00198 v->end = DEF_STOP_FRAME;
00199
00200 v->targetrate = 0;
00201
00202
00203 v->frames = 0;
00204 v->pframes = 0;
00205 v->bframes = 0;
00206 v->total_frames_passed = 0;
00207 v->pic->PB = 0;
00208 v->wcopies = v->icopies = 1;
00209
00210 v->pic->TR = 0;
00211 v->pic->QP_mean = (float)0.0;
00212
00213
00214 switch (v->pic->source_format) {
00215 case (SF_SQCIF):
00216 fprintf(stdout, "Encoding format: SQCIF (128x96)\n");
00217 v->pels = 128;
00218 v->lines = 96;
00219 break;
00220 case (SF_QCIF):
00221 fprintf(stdout, "Encoding format: QCIF (176x144)\n");
00222 v->pels = 176;
00223 v->lines = 144;
00224 break;
00225 case (SF_CIF):
00226 fprintf(stdout, "Encoding format: CIF (352x288)\n");
00227 v->pels = 352;
00228 v->lines = 288;
00229 break;
00230 case (SF_4CIF):
00231 fprintf(stdout, "Encoding format: 4CIF (704x576)\n");
00232 v->pels = 704;
00233 v->lines = 576;
00234 break;
00235 case (SF_16CIF):
00236 fprintf(stdout, "Encoding format: 16CIF (1408x1152)\n");
00237 v->pels = 1408;
00238 v->lines = 1152;
00239 break;
00240 default:
00241 fprintf(stderr,"Illegal coding format\n");
00242 exit(-1);
00243 }
00244 v->cpels = v->pels/2;
00245
00246
00247
00248
00249 config_vc(v);
00250
00251
00252
00253
00254 v->first = 1;
00255
00256 v->tmndecode = 0;
00257 v->no_coding = 0;
00258 }
00259 return (v);
00260 }
00261
00262
00263 void code_video(video_codec *v)
00264
00265
00266
00267
00268 {
00269 int i, ok;
00270 FILE *cleared;
00271 FILE *inputfile;
00272
00273 VidSt = v;
00274
00275
00276
00277
00278
00279 if (v->no_coding) {
00280 if (al_buffer_level(v->output) < LOW_WATER_MARK) {
00281
00282 if (v->input_file==NULL)
00283 error("code_video","Input video not available");
00284 inputfile = fopen (v->input_file, "r");
00285 if (inputfile == NULL) {
00286 error("code_video","Unable to open input file\n");
00287 }
00288 fseek(inputfile,v->bytecnt,0);
00289 for (i=0;i<CHUNKSIZE;i++) {
00290 al_send_byte(v->output,fgetc(inputfile));
00291 }
00292 v->bytecnt += CHUNKSIZE;
00293 fclose(inputfile);
00294 }
00295 }
00296
00297
00298
00299
00300
00301 else if (v->first) {
00302
00303
00304
00305
00306 if (v->seqfilename[0] == '\0') {
00307 fprintf(stderr,"Required input parameter missing\n");
00308 exit(-1);
00309 }
00310
00311
00312
00313
00314 v->pic->bit_rate = v->targetrate;
00315 v->pic->src_frame_rate = (int)(v->ref_frame_rate / v->orig_frameskip);
00316 v->DelayBetweenFramesInSeconds = (float) 1.0/(float)v->pic->src_frame_rate;
00317 InitializeRateControl();
00318
00319
00320 if (v->QP == 0 || v->QPI == 0) {
00321 fprintf(stderr,"Warning:");
00322 fprintf(stderr,
00323 "QP is zero. Bitstream will not be correctly decodable\n");
00324 }
00325
00326 if (v->ref_frame_rate != 25.0 && v->ref_frame_rate != 30.0) {
00327 fprintf(stderr,"Warning: Reference frame rate should be 25 or 30 fps\n");
00328 }
00329
00330 v->frame_rate = v->ref_frame_rate / (float)(v->orig_frameskip * v->chosen_frameskip);
00331
00332 if (v->pic->bit_rate == 0)
00333 fprintf(stdout,"Encoding frame rate : %.2f\n", v->frame_rate);
00334 else
00335 fprintf(stdout,"Encoding frame rate : variable\n");
00336
00337 fprintf(stdout,"Reference frame rate : %.2f\n", v->ref_frame_rate);
00338 fprintf(stdout,"Orig. seq. frame rate: %.2f\n\n",
00339 v->ref_frame_rate / (float)v->orig_frameskip);
00340
00341
00342 v->streamfile = fopen (v->streamname, "wb");
00343 if (v->streamfile == NULL) {
00344 fprintf(stderr, "Unable to open streamfile\n");
00345 exit(-1);
00346 }
00347
00348
00349
00350
00351 initbits (v);
00352
00353 if (v->trace) {
00354 strcpy(v->tracefile, "trace.intra");
00355
00356 if ((v->tf = fopen(v->tracefile,"w")) == NULL) {
00357 fprintf(stderr,"Unable to open tracefile (intra)\n");
00358 exit(-1);
00359 }
00360 }
00361
00362
00363
00364
00365 if ((cleared = fopen(v->outputfile,"wb")) == NULL) {
00366 fprintf(stderr,"Couldn't open outputfile: %s\n",v->outputfile);
00367 exit(-1);
00368 }
00369 else
00370 fclose(cleared);
00371 if (v->writediff) {
00372 if ((cleared = fopen(v->diff_filename,"wb")) == NULL) {
00373 fprintf(stderr,"Couldn't open diff-file: %s\n",v->diff_filename);
00374 exit(-1);
00375 }
00376 else
00377 fclose(cleared);
00378 }
00379
00380
00381
00382
00383 v->start_time = get_clock();
00384 v->last_frame = 0;
00385 v->simbuffer = 0;
00386
00387
00388
00389
00390
00391 v->image = ReadImage(v->seqfilename, v->start, v->headerlength);
00392 fprintf(stdout,"Coding...\n");
00393 v->curr_image = FillImage(v->image);
00394 v->pic->picture_coding_type = PCT_INTRA;
00395 v->pic->QUANT = v->QPI;
00396
00397 v->curr_recon = CodeOneIntra(v->curr_image, v->QPI, v->bits, v->pic);
00398
00399 if (v->arith_used) {
00400 v->bits->header += encoder_flush();
00401 v->arith_used = 0;
00402 }
00403 v->bits->header += alignbits ();
00404
00405 fprintf(stdout,"Finished INTRA\n");
00406
00407 ComputeSNR(v->curr_image, v->curr_recon, v->res, v->writediff);
00408 AddBitsPicture(v->bits);
00409 PrintSNR(v->res, 1);
00410 PrintResult(v->bits, 1, 1);
00411 memcpy(v->intra_bits,v->bits,sizeof(Bits));
00412 ZeroBits(v->total_bits);
00413 ZeroRes(v->total_res);
00414 ZeroRes(v->b_res);
00415
00416 if (v->trace) {
00417 strcpy(v->tracefile, "trace");
00418 fclose(v->tf);
00419
00420 if ((v->tf = fopen(v->tracefile,"w")) == NULL) {
00421 fprintf(stderr,"Unable to open tracefile (non-intra)\n");
00422 exit(-1);
00423 }
00424 }
00425
00426
00427
00428
00429
00430 v->pic->picture_coding_type = PCT_INTER;
00431 v->pic->QUANT = v->QP;
00432 v->bdist = v->chosen_frameskip;
00433
00434
00435
00436
00437
00438
00439 if (v->pb_frames) {
00440 v->pic->PB = 0;
00441 v->pdist = 2*v->chosen_frameskip - v->bdist;
00442 }
00443
00444 if (v->write_repeated)
00445 v->icopies = v->chosen_frameskip;
00446 for (i = 0; i < v->icopies; i++)
00447 WriteImage(v->curr_recon,v->outputfile);
00448
00449
00450
00451
00452
00453 v->first = 0;
00454 v->last_frame = v->start;
00455 v->frame_no = v->start;
00456 }
00457 else {
00458
00459
00460
00461
00462 ok = 0;
00463
00464 if (v->frame_no <= v->end) {
00465
00466 if (al_buffer_level(v->output) < LOW_WATER_MARK)
00467 ok = 1;
00468
00469 if (ok) {
00470 v->frameskip = FindFrameSkip(v->last_frame);
00471 v->frame_no += v->frameskip;
00472 }
00473 }
00474 if ((ok) && (v->frame_no <= v->end) &&(v->frameskip)) {
00475
00476
00477 v->prev_image = v->curr_image;
00478 v->prev_recon = v->curr_recon;
00479
00480
00481
00482 v->QP = v->pic->QUANT;
00483
00484 if (!v->PPFlag) {
00485 if (v->pic->PB) {
00486 v->bdist = v->frameskip;
00487 v->pdist = 2*v->frameskip - v->bdist;
00488 v->pic->TRB = v->bdist * v->orig_frameskip;
00489 if (v->pic->TRB > 8)
00490 fprintf(stdout,"distance too large for B-frame\n");
00491
00492 v->image = ReadImage(v->seqfilename,v->frame_no,v->headerlength);
00493 v->B_image = FillImage(v->image);
00494 v->first_loop_finished = 1;
00495 if (v->frame_no + v->pdist <= v->end) {
00496 v->image = ReadImage(v->seqfilename,v->frame_no + v->pdist,v->headerlength);
00497 }
00498 else {
00499 v->pic->PB = 0;
00500 v->image = ReadImage(v->seqfilename,v->frame_no,v->headerlength);
00501 }
00502 }
00503 else {
00504 v->image = ReadImage(v->seqfilename,v->frame_no,v->headerlength);
00505 }
00506 v->curr_image = FillImage(v->image);
00507
00508 if (v->pic->PB) {
00509 if (v->pic->TRB > 8 || !NextTwoPB(v->curr_image, v->B_image, v->prev_image,
00510 v->bdist, v->pdist, v->pic->seek_dist)) {
00511
00512
00513 v->pic->PB = 0;
00514
00515 FreeImage(v->curr_image);
00516
00517 v->frameskip = v->bdist;
00518
00519 v->curr_image = v->B_image;
00520 v->PPFlag = 1;
00521 }
00522 else {
00523 v->frame_no += v->pdist;
00524 }
00525 }
00526 }
00527 else {
00528
00529
00530
00531 v->image = ReadImage(v->seqfilename,v->frame_no,v->headerlength);
00532 v->curr_image = FillImage(v->image);
00533
00534 v->pic->PB = 0;
00535 v->PPFlag = 0;
00536 }
00537
00538
00539
00540 v->pic->TR += (( (v->frameskip+(v->pic->PB?v->pdist:0)) *v->orig_frameskip) % 256);
00541 if (v->frameskip+(v->pic->PB?v->pdist:0) > 256)
00542 fprintf(stdout,"Warning: frameskip > 256\n");
00543
00544
00545 v->frames += (v->pic->PB ? 2: 1);
00546 v->bframes += (v->pic->PB ? 1 : 0);
00547 v->pframes += 1;
00548
00549 if (v->pic->PB) {
00550 v->B_recon = InitImage(v->pels*v->lines);
00551 fprintf(stdout,"Coding PB frames %d and %d... ",
00552 v->frame_no - v->pdist, v->frame_no);
00553 fflush(stdout);
00554 }
00555 else {
00556 fprintf(stdout,"Coding P frame %d... ", v->frame_no);
00557 fflush(stdout);
00558 }
00559 v->curr_recon = InitImage(v->pels*v->lines);
00560
00561
00562 CodeOneOrTwo(v->curr_image, v->B_image, v->prev_image, v->prev_recon,
00563 v->QP, (v->bdist+v->pdist)*v->orig_frameskip, v->bits, v->pic,
00564 v->B_recon, v->curr_recon);
00565
00566
00567 fprintf(stdout,"done\n");
00568 if (v->targetrate != 0)
00569 fprintf(stdout,"Inter QP: %d\n", v->QP);
00570 fflush(stdout);
00571
00572 if (v->arith_used) {
00573 v->bits->header += encoder_flush();
00574 v->arith_used = 0;
00575 }
00576
00577 v->bits->header += alignbits ();
00578 AddBitsPicture(v->bits);
00579 AddBits(v->total_bits, v->bits);
00580
00581 if (v->pic->bit_rate != 0 && v->pic->PB)
00582 v->CommBacklog -= (int)
00583 ( v->DelayBetweenFramesInSeconds*v->pic->bit_rate ) * v->pdist;
00584
00585 if (v->pic->bit_rate != 0) {
00586 UpdateRateControl(v->bits->total);
00587
00588 v->CommBacklog += v->bits->total;
00589 v->frameskip = 1;
00590 v->CommBacklog -= (int)
00591 (v->frameskip * v->DelayBetweenFramesInSeconds *v->pic->bit_rate);
00592
00593 while ( (int)(v->DelayBetweenFramesInSeconds*v->pic->bit_rate) <= v->CommBacklog)
00594 {
00595 v->CommBacklog -= (int) ( v->DelayBetweenFramesInSeconds * v->pic->bit_rate );
00596 v->frameskip += 1;
00597 }
00598 }
00599
00600 if (v->pic->PB) {
00601 if (v->write_repeated)
00602 v->wcopies = v->pdist;
00603 #if(0)
00604 for (i = 0; i <v-> wcopies; i++)
00605 WriteImage(v->B_recon,v->outputfile);
00606 #endif
00607 ComputeSNR(v->B_image, v->B_recon, v->res, v->writediff);
00608 fprintf(stdout,"Results for B-frame:\n");
00609 AddRes(v->b_res,v->res,v->pic);
00610 PrintSNR(v->res, 1);
00611 FreeImage(v->B_image);
00612 FreeImage(v->B_recon);
00613 }
00614
00615 if (v->write_repeated)
00616 v->wcopies = (v->pb_frames) ? v->bdist : v->frameskip;
00617 #if(0)
00618 for (i = 0; i < v->wcopies; i++)
00619 WriteImage(v->curr_recon,v->outputfile);
00620 #endif
00621 if (v->pb_frames)
00622 v->pic->PB = 1;
00623
00624 ComputeSNR(v->curr_image, v->curr_recon, v->res, v->writediff);
00625 fprintf(stdout,"Results for P-frame:\n");
00626 AddRes(v->total_res,v->res,v->pic);
00627 PrintSNR(v->res, 1);
00628 PrintResult(v->bits, 1, 1);
00629 FreeImage(v->prev_image);
00630 FreeImage(v->prev_recon);
00631 fflush(stdout);
00632
00633
00634 v->last_frame = v->frame_no;
00635 }
00636
00637 }
00638 }
00639
00640
00641 void close_video_codec(video_codec *v)
00642 {
00643 char s[STRLEN];
00644 int junk;
00645
00646 VidSt = v;
00647
00648
00649
00650 fclose (v->streamfile);
00651 if (v->trace) {
00652 fclose(v->tf);
00653 }
00654
00655
00656 v->total_frames_passed = v->frame_no - v->start;
00657
00658 fprintf(stdout,"\n==== TOTAL ====\n");
00659 fprintf(stdout,"for %d images of %s\n", v->frames, v->seqfilename);
00660
00661 if (v->frames != 0) {
00662 if (v->write_repeated)
00663 fprintf(stdout,"Frames saved : %d predicted + %d intra\n",
00664 v->total_frames_passed,v->icopies);
00665
00666 fprintf(stdout,"--------------\n");
00667
00668 if (v->pb_frames && v->bframes != 0) {
00669 fprintf(stdout,"SNR for %d B-frames:\n",v->bframes);
00670 PrintSNR(v->b_res,v->bframes);
00671 }
00672
00673 fprintf(stdout,"SNR for %d P-frames:\n",v->pframes);
00674 PrintSNR(v->total_res,v->pframes);
00675
00676 PrintResult(v->total_bits, v->pframes, v->frames);
00677
00678 if (v->targetrate != 0 || v->pic->bit_rate != 0)
00679 fprintf(stdout,"Original seq time: %.2f sec\n",
00680 v->total_frames_passed / v->ref_frame_rate);
00681
00682 fprintf(stdout,"Mean quantizer : %.2f\n", v->total_res->QP_mean/v->pframes);
00683
00684 #if(0)
00685 fprintf(stdout,"Total frames : %3d\n",
00686 v->total_frames_passed);
00687 #endif
00688
00689 fprintf(stdout,"Encoded frames : %3d (%3d)\n",
00690 v->frames + 1,
00691 v->frames);
00692
00693 v->mean_frame_rate = v->frames / (float)v->total_frames_passed *
00694 v->ref_frame_rate / (float)v->orig_frameskip;
00695
00696 fprintf(stdout,"Mean frame rate : %.2f Hz\n", v->mean_frame_rate);
00697
00698 if (v->targetrate != 0)
00699 fprintf(stdout,"Target bit rate : %.2f kbit/sec\n",
00700 v->targetrate/1000.0);
00701
00702 fprintf(stdout,"Obtained bit rate: %.2f (%.2f) kbit/sec\n",
00703 (v->total_bits->total + v->intra_bits->total) /
00704 ((v->total_frames_passed) /
00705 v->ref_frame_rate * v->orig_frameskip)/1000.0,
00706 (v->total_bits->total / (float)v->frames) * v->mean_frame_rate/1000.0);
00707
00708 fprintf(stdout,"============================================\n");
00709
00710 }
00711 #if(0)
00712 fprintf(stdout,"Total number of bits: %d (%d)\n",
00713 v->total_bits->total + v->intra_bits->total,
00714 (v->total_bits->total + v->intra_bits->total) / 8);
00715 #endif
00716
00717
00718 if (v->tmndecode) {
00719 printf("[%s] ready to use tmndec to display output video..\n",v->label);
00720 printf("Press return key when ready. . .\n");
00721 junk = getchar();
00722 printf("displaying...\n");
00723 sprintf(s,"tmndecode -o4 -q %s &",v->output_file);
00724 system(s);
00725 printf("Press return key when ready to resume. . .\n");
00726 junk = getchar();
00727 }
00728
00729
00730 if (v->frames != 0) {
00731 FreeImage(v->curr_recon);
00732 FreeImage(v->curr_image);
00733 }
00734 free(v->streamname);
00735 free(v->outputfile);
00736 free(v->tracefile);
00737 free(v->bits);
00738 free(v->total_bits);
00739 free(v->intra_bits);
00740 free(v->res);
00741 free(v->total_res);
00742 free(v->b_res);
00743 free(v->pic);
00744 free(v);
00745 }
00746
00747
00748 void decode_video(video_codec *bob)
00749
00750
00751
00752 {
00753 FILE *outfile=NULL;
00754
00755 byte b;
00756
00757 if (al_indication(bob->input)) {
00758
00759 outfile = fopen(bob->output_file, "a");
00760
00761 if (outfile == NULL) {
00762 error("decode_video","can't open output file");
00763 }
00764 }
00765
00766 while (al_indication(bob->input)) {
00767
00768 b = al_receive(bob->input);
00769
00770 fputc(b, outfile);
00771 }
00772
00773 if (outfile) {
00774 fclose(outfile);
00775 }
00776 }
00777
00778