/* ***** BEGIN LICENSE BLOCK ***** * * $Id: encmain.cpp,v 1.53 2007/04/11 08:08:48 tjdwave Exp $ $Name: Dirac_0_7_0 $ * * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is BBC Research and Development code. * * The Initial Developer of the Original Code is the British Broadcasting * Corporation. * Portions created by the Initial Developer are Copyright (C) 2004. * All Rights Reserved. * * Contributor(s): Thomas Davies (Original Author), * Scott R Ladd, * Anuradha Suraparaju * Andrew Kennedy * David Flynn * Johannes Reinhardt * Myo Tun (Brunel University) * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser * Public License Version 2.1 (the "LGPL"), in which case the provisions of * the GPL or the LGPL are applicable instead of those above. If you wish to * allow use of your version of this file only under the terms of the either * the GPL or LGPL and not to allow others to use your version of this file * under the MPL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by the GPL * or LGPL. If you do not delete the provisions above, a recipient may use * your version of this file under the terms of any one of the MPL, the GPL * or the LGPL. * ***** END LICENSE BLOCK ***** */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const int VIDEO_BUFFER_SIZE = 1024*1024; unsigned char video_buf[VIDEO_BUFFER_SIZE]; static void display_help() { cout << "\nDIRAC wavelet video coder."; cout << "\n"; cout << "\nUsage: progname - [] ... "; cout << "\nIn case of multiple assignment to the same parameter, the last holds."; cout << "\n"; cout << "\nName Type Default Value Description"; cout << "\n==== ==== ============= =========== "; cout << "\nQSIF bool false Use QSIF compression presets"; cout << "\nQCIF bool false Use QCIF compression presets"; cout << "\nSIF bool false Use SIF compression presets"; cout << "\nCIF bool false Use CIF compression presets"; cout << "\n4CIF bool false Use 4CIF compression presets"; cout << "\n4SIF bool false Use 4SIF compression presets"; cout << "\nSD480 bool false Use SD-480 compression presets"; cout << "\nSD576 bool false Use SD-576 compression presets"; cout << "\nHD720 bool false Use HD-720 compression presets"; cout << "\nHD1080 bool false Use HD-1080 compression presets"; cout << "\nwidth ulong Preset Width of frame"; cout << "\nheight ulong Preset Length of frame"; cout << "\nheight ulong Preset Length of frame"; cout << "\ncformat ulong 444 Chroma format 0=444 1=422 2=420"; cout << "\nfr ulong Preset Frame rate(s) (e.n or e/n format)"; cout << "\nstart ulong 0UL Frame number to start encoding from"; cout << "\nstop ulong EOF Frame number after which encoding finishes"; cout << "\nL1_sep ulong 0UL Separation of L1 frames"; cout << "\nnum_L1 ulong 0UL Number of L1 frames"; cout << "\nxblen ulong 0UL Overlapping block horizontal length"; cout << "\nyblen ulong 0UL Overlapping block vertical length"; cout << "\nxbsep ulong 0UL Overlapping block horizontal separation"; cout << "\nybsep ulong 0UL Overlapping block vertical separation"; cout << "\ncpd ulong 0UL Perceptual weighting - vertical cycles per deg."; cout << "\nqf float 0.0F Overall quality factor (>0, typically: 7=medium, 9=high)"; cout << "\ntargetrate ulong 0UL Target Bit Rate in Kbps"; cout << "\nlossless bool false Lossless coding (overrides qf)"; cout << "\niwlt_filter string DD9_3 Intra frame Transform Filter (DD9_3 LEGALL5_3 DD13_5 HAAR0 HAAR1 HAAR2 FIDELITY DAUB9_7)"; cout << "\nrwlt_filter string LEGALL5_3 Inter frame Transform Filter (DD9_3 LEGALL5_3 DD13_5 HAAR0 HAAR1 HAAR2 FIDELITY DAUB9_7)"; cout << "\nwlt_depth ulong 4 Transform Depth"; cout << "\nmulti_quants bool false Use multiple quantisers"; cout << "\nmv_prec string false MV Pixel Precision (1, 1/2, 1/4, 1/8)"; cout << "\nno_spartition bool false Do not use spatial partitioning while coding transform data"; cout << "\ndenoise bool false Denoise input before coding (NB: PSNR stats will relate to denoised video)"; cout << "\nverbose bool false verbose mode"; cout << "\nlocal bool false Write diagnostics & locally decoded video"; cout << "\ninput string [ required ] Input file name"; cout << "\noutput string [ required ] Output file name [May not be '-']"; cout << endl; } bool WritePicData (std::ofstream &fdata, dirac_encoder_t *encoder) { dirac_seqparams_t &sparams = encoder->enc_ctx.seq_params; dirac_framebuf_t &fbuf = encoder->dec_buf; bool ret_stat = true; if (encoder->decoded_frame_avail) { ios::iostate oldExceptions = fdata.exceptions(); fdata.exceptions (ios::failbit | ios::badbit); try { assert (fbuf.buf[0] != 0); fdata.write ((char *)fbuf.buf[0], sparams.width*sparams.height); assert (fbuf.buf[1] != 0); assert (fbuf.buf[2] != 0); fdata.write ((char *)fbuf.buf[1], sparams.chroma_width*sparams.chroma_height); fdata.write ((char *)fbuf.buf[2], sparams.chroma_width*sparams.chroma_height); } catch (...) { std::cout << "Incomplete frame " << std::endl; ret_stat = false; } fdata.exceptions (oldExceptions); } return ret_stat; } bool WriteSequenceHeader (std::ofstream &fdata, dirac_encoder_t *encoder) { bool ret_stat = true; dirac_seqparams_t &sparams = encoder->enc_ctx.seq_params; dirac_sourceparams_t &srcparams = encoder->enc_ctx.src_params; ios::iostate oldExceptions = fdata.exceptions(); fdata.exceptions (ios::failbit | ios::badbit); try { fdata << sparams.chroma << std::endl; fdata << sparams.width << std::endl; fdata << sparams.height << std::endl; fdata << sparams.video_depth << std::endl; fdata << srcparams.interlace << std::endl; fdata << srcparams.topfieldfirst << std::endl; fdata << srcparams.frame_rate.numerator << std::endl; fdata << srcparams.frame_rate.denominator << std::endl; fdata << srcparams.pix_asr.numerator << std::endl; fdata << srcparams.pix_asr.denominator << std::endl; } catch (...) { std::cerr << "Error writing sequence info in diagnostics file." << std::endl; ret_stat = false; } fdata.exceptions (oldExceptions); return ret_stat; } bool WriteDiagnosticsData (std::ofstream &fdata, dirac_encoder_t *encoder) { //dirac_seqparams_t &sparams = encoder->enc_ctx.seq_params; dirac_instr_t &instr = encoder->instr; bool ret_stat = true; if (encoder->instr_data_avail) { ios::iostate oldExceptions = fdata.exceptions(); fdata.exceptions (ios::failbit | ios::badbit); try { fdata << std::endl << "[frame:" << instr.fnum << "]"; if (instr.ftype == INTRA_FRAME) { fdata << ">intra" << std::endl; return true; } fdata << ">mo_comp"; fdata << std::endl << std::endl << instr.num_refs << " "; for (int i=0; i 1) { for (int j=0; j 5) cerr << "Exceeds maximum transform depth "; else parsed[i] = true; } else if ( strcmp(argv[i], "-iwlt_filter") == 0 ) { parsed[i] = true; i++; WltFilter wf = StringToTransformFilter(string(argv[i])); if (wf == filterNK) cerr << "Unrecognised Intra Wavelet Filter " << argv[i]; else parsed[i] = true; enc_ctx.enc_params.intra_wlt_filter = wf; } else if ( strcmp(argv[i], "-rwlt_filter") == 0 ) { parsed[i] = true; i++; WltFilter wf = StringToTransformFilter(argv[i]); if (wf == filterNK) cerr << "Unrecognised Intra Wavelet Filter " << argv[i]; else parsed[i] = true; enc_ctx.enc_params.inter_wlt_filter = wf; } else if ( strcmp(argv[i], "-mv_prec") == 0 ) { parsed[i]=true; ++i; if(strcmp(argv[i], "1/2")==0) { parsed[i] = true; enc_ctx.enc_params.mv_precision = MV_PRECISION_HALF_PIXEL; } else if(strcmp(argv[i], "1/4")==0) { parsed[i] = true; enc_ctx.enc_params.mv_precision = MV_PRECISION_QUARTER_PIXEL; } else if(strcmp(argv[i], "1/8")==0) { parsed[i] = true; enc_ctx.enc_params.mv_precision = MV_PRECISION_EIGHTH_PIXEL; } else if(strncmp(argv[i], "1", 3)==0) { parsed[i] = true; enc_ctx.enc_params.mv_precision = MV_PRECISION_PIXEL; } } i++; }//opt /* check that we have been suplied with input and output files */ if(parsed[argc-2] || parsed[argc-1]) { std::cerr<enc_buf.buffer = video_buf; encoder->enc_buf.size = VIDEO_BUFFER_SIZE; state = dirac_encoder_output ( encoder ); switch (state) { case ENC_STATE_AVAIL: assert (encoder->enc_buf.size > 0); outfile.write((char *)encoder->enc_buf.buffer, encoder->enc_buf.size); frames_written++; break; case ENC_STATE_BUFFER: break; case ENC_STATE_INVALID: std::cerr << "Invalid state. Unrecoverable Encoder Error. Quitting..." << std::endl; return EXIT_FAILURE; default: std::cerr << "Unknown Encoder state" << endl; break; } WritePicData (*outyuv, encoder); WriteDiagnosticsData (*outimt, encoder); } while (state == ENC_STATE_AVAIL); } while (frames_written <= (end_pos - start_pos)); stop_t = clock(); encoder->enc_buf.buffer = video_buf; encoder->enc_buf.size = VIDEO_BUFFER_SIZE; if (dirac_encoder_end_sequence( encoder ) > 0) { outfile.write((char *)encoder->enc_buf.buffer, encoder->enc_buf.size); if ( verbose ) std::cout << "The resulting bit-rate at " << (double)encoder->enc_ctx.src_params.frame_rate.numerator/ encoder->enc_ctx.src_params.frame_rate.denominator << "Hz is " << encoder->enc_seqstats.bit_rate << " bits/sec." << std::endl; if ( verbose ) std::cout<<"Time per frame: "<< (double)(stop_t-start_t)/(double)(CLOCKS_PER_SEC*frames_written); std::cout<close(); delete outyuv; } // close the decoded output header file if (outimt) { outimt->close(); delete outimt; } // close the pic data file ip_pic_ptr.close(); // delete frame buffer delete [] frame_buf; delete[] parsed; return EXIT_SUCCESS; }