Hello
The omx encode example runs fine.Now i want to pass the QP parameter to the encode function along with the input,output,width,height, codec and numframes .Would my writing QP as one of the IL_ARGS STRUCTURE tell the encoder to code the first I frame of each GOP(group of pictures) with the quantization parameter that I provide.
Are any other settings required to change in the encode program so that the rate control parameters accepted by the application are user defined.
Below is the rough C program of the rate control algorithm we want to implement:
//************************************************************
// This program is written for a video of 2 minutes.
// Total time=2*60=120 seconds
// framerate=60
// total no of frames=30*120=3600
// total no of gop=total no of frames/frames in one GOP
// 3600/16=225
//**************************************************************
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <ti/xdais/xdas.h>
#include <ti/xdais/dm/xdm.h>
#include <ti/xdais/dm/ividenc2.h>
#include <ti/xdais/dm/ih264enc.h>
#include <ti/xdais/app_cfg.h>
#include <ti/xdais/ilclient.h>
#include <ti/xdais/ilclient_utils.h>
#include "init_seq.h"
#ifndef max
#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
#endif
#ifndef min
#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
#endif
int framenumber=0;
int Gopnumber;
void init_sequ()
{
extern XDAS_Int32 bitrate,framerate,width,height,complexity,dWp,w,PQP;
//XDAS_Int32 no_framesGOP;
extern XDAS_Int8 enableanalyticinfo;
IH264ENC_Params f;
f.enableAnalyticinfo=1;
enableanalyticinfo=f.enableAnalyticinfo;
extern struct IVIDENC2_DynamicParams a;
a.targetFrameRate=60000;
a.targetBitRate=2000000;
height=a.inputHeight;
width=a.inputWidth;
bitrate=a.targetBitRate;
framerate=a.targetFrameRate;
extern int remainbits, currentbufferfullness,PMADPicture_a1,PMADPicture_a2;
extern int No_ofcodedPframes,Ppreheader,PX1,PX2,No_OfPframes;
No_ofcodedPframes=0;
No_OfPframes=15;
currentbufferfullness = 0;
remainbits=0;
Ppreheader=0;
extern IVIDEO_DataMode datamode;
datamode=IVIDEO_ENTIREFRAME; //set datamode to frame
PX1=(bitrate)*1.0;
PX2 = 0.0;
// linear prediction model for P picture
PMADPicture_a1 = 1.0;
PMADPicture_a2 = 0.0;
extern int NoOfGop;
NoOfGop=226;
IH264ENC_Params c;//to access the intraframe interval
c.maxIntraFrameInterval=16;
const int no_framesGOP=c.maxIntraFrameInterval;//to access no of frames in one GOP
extern int overbits,lowerbound,upperbound,allocatedbits,overduantqp,NoGranularField;
overbits=lowerbound=upperbound=allocatedbits=overduantqp=0;
extern int targetbits,targetbufferlevel;
targetbits=0;
targetbufferlevel=0;
extern int weightedavgcompl;
weightedavgcompl=0;
extern int lowerbound1,upperbound1;
lowerbound1=upperbound1=0;
dWp=0;
PQP=0;
w=0;
int k;
for(k=0;k<17;k++)
{
qp[k]=0;
}
}
int genbits(int *nbits_element)
{
struct IVIDENC2_OutArgs b;
*nbits_element=b.bytesGenerated;
*nbits_element=(*nbits_element)*1024;
return(*nbits_element);
}
void init_GOP(int q[],int no_framesGOP)
{
//extern char layer[],frame[],interlace[];
//extern no_framesGOP;
extern bitrate,framerate,remainbits;
extern int lowbnd[17],upperbnd[17];
extern int QP[226],QPGOP;
extern int B[17];
int l;
extern int w;
w=0;
B[0]=0;
extern overbits,lowerbound,upperbound,allocatedbits,overduantqp,NoGranularField;
extern int nbits[17];
genbits(&nbits[framenumber]);
struct IH264ENC_StereoInfoParams f;
IH264ENC_RateControlParams g;
f.stereoInfoPreset=IH264_STEREOINFO_DISABLE;
IH264ENC_NumTemporalLayer layer;
if(layer==IH264_TEMPORAL_LAYERS_1)
{
overbits=-(remainbits);
}
if(layer==IH264_TEMPORAL_LAYERS_1)
{
if(Gopnumber==1 && framenumber==1)
{
lowbnd[1]=floor(bitrate/framerate);
//upperbnd[1]=
}
else if(framenumber==1)
{
lowbnd[1]=B[16]+(bitrate/framerate);
upperbnd[1]=B[16]+0.9;
}
}
else
{
if(Gopnumber==1 && framenumber==1)
{
lowbnd[1]=(bitrate/framerate);
//upperbnd[1]=
}
else if(framenumber==1)
{
lowbnd[1]=B[16]+(bitrate/framerate);
upperbnd[1]=B[16]+0.9;
}
lowerbound=(lowbnd[framenumber]);
upperbound=(upperbnd[framenumber]);
}
IVIDEO_FrameType frame;
if( layer==IH264_TEMPORAL_LAYERS_1)
{
if(frame==IVIDEO_I_FRAME && Gopnumber==1)
{
B[1]=(floor(bitrate/framerate))*no_framesGOP+B[0];
}
else if(frame==IVIDEO_I_FRAME)
{
B[1]=(bitrate/framerate)*no_framesGOP+B[16];
}
else
{
B[framenumber]=B[framenumber-1]-nbits[framenumber-1];
}
}
else
{
if(frame==IVIDEO_I_FRAME && Gopnumber==1)
{
B[1]=(bitrate/framerate)*no_framesGOP+B[0];
}
else if(frame==IVIDEO_I_FRAME)
{
B[1]=(bitrate/framerate)*no_framesGOP+B[16];
}
else
{
B[framenumber]=B[framenumber-1]-nbits[framenumber-1];
}
}
allocatedbits=(B[framenumber]);
overduantqp=floor((8*overbits)/allocatedbits); //decide order of * and /
IH264ENC_InterlaceCodingType interlace;
IVIDEO_DataMode datamode;
if(interlace!=IH264_INTERLACE_PICAFF && interlace!=IH264_INTERLACE_MBAFF && datamode==IVIDEO_ENTIREFRAME)
NoGranularField=0;
else
NoGranularField=1;
//QP for each GOP
for (l=1;l<17;l++)
{
w=w+qp[l];
}
if(Gopnumber==1)
{
g.qpI=40;
QP[1]=g.qpI;
}
else
{
QP[Gopnumber]=max(min((w/15)-1,QP[Gopnumber-1]+2),QP[Gopnumber-1]-2);
qp[1]=QP[Gopnumber];
}
if(QP[Gopnumber]>qp[14]-2)
QP[Gopnumber]=QP[Gopnumber]-1;
QPGOP=(QP[Gopnumber]);
}
void update_Pparams(int weightedavgcompl)
{
//extern char layer[],frame[];
extern No_OfPframes,No_ofcodedPframes,dWp;
IH264ENC_NumTemporalLayer layer;
if(layer==IH264_TEMPORAL_LAYERS_1)
{
IVIDEO_FrameType frame;
if(frame==IVIDEO_P_FRAME)
{
No_ofcodedPframes=No_ofcodedPframes+1;
No_OfPframes=No_OfPframes-1;
//No_ofcodedPframes=get(No_ofcodedPframes);
//No_ofPframes=get(No_ofPframes);
}
}
else
{
IVIDEO_FrameType frame;
if(frame==IVIDEO_P_FRAME)
{
No_ofcodedPframes=No_ofcodedPframes+1;
No_OfPframes=No_OfPframes-1;
//No_ofcodedPframes=get(No_ofcodedPframes);
//No_ofPframes=get(No_ofPframes);
}
}
dWp=weightedavgcompl;
}
void init_pict(int a)
{
extern int bitrate,framerate,currentbufferfullness,targetbufferlevel,remainbits,targetbits,lowerbound1,upperbound1,weightedavgcompl,weightcompl,No_ofcodedPframes,no_framesGOP;
extern nbits[17],w;
static int targetbufflev[17],weightedavgcomplexity[16],tarbits[17],remainingbits[17];
targetbufflev[1]=weightedavgcomplexity[0]=tarbits[1]=tarbits[2]=0;
struct IH264ENC_OutArgs d;
extern struct XDM1_AlgBufInfo e;
IH264ENC_NumTemporalLayer layer;
weightcompl=nbits[framenumber]*(w/16);
/*if(layer==IH264_TEMPORAL_LAYERS_1)
{
bitrate=get(bitrate);
currentbufferfullness=get(currentbufferfullness);
targetbufferlevel=get(targetbufferlevel);
remainbits=get(remainbits);
targetbits=get(targetbits);
lowerbound1=get(lowerbound1);
upperbound1=get(upperbound1);
No_ofcodedPframes=get(No_ofcodedPframes);
}
else
{
bitrate=get(bitrate);
currentbufferfullness=get(currentbufferfullness);
targetbufferlevel=get(targetbufferlevel);
remainbits=get(remainbits);
targetbits=get(targetbits);
lowerbound1=get(lowerbound1);
upperbound1=get(upperbound1);
No_ofcodedPframes=get(No_ofcodedPframes);
}*/
IVIDEO_DataMode datamode;
IVIDEO_FrameType frame;
if(datamode==IVIDEO_ENTIREFRAME && frame==IVIDEO_P_FRAME)
{
if(No_ofcodedPframes==0)
{
targetbufflev[2]=d.vbvBufferLevel;
}
else
{
targetbufflev[framenumber]=targetbufflev[framenumber-1]-(targetbufflev[2]-(int)e.minInBufSize[XDM_MAX_IO_BUFFERS].bytes/(no_framesGOP-1));
}
}
targetbufferlevel=(targetbufflev[framenumber]);
if(frame==IVIDEO_P_FRAME)
{
if(No_ofcodedPframes==0)
{
weightedavgcomplexity[1]=weightcompl;
}
else
{
weightedavgcomplexity[framenumber]=(weightcompl+(7*weightedavgcomplexity[framenumber-1]))/8;
}
}
weightedavgcompl=(weightedavgcomplexity[framenumber]);
if(frame==IVIDEO_P_FRAME)
{
if(datamode==IVIDEO_ENTIREFRAME)
{
if(No_ofcodedPframes>0)
{
tarbits[framenumber]=(bitrate/framerate)+0.125*targetbufferlevel-currentbufferfullness;
tarbits[framenumber]=0.875*remainingbits[framenumber]+(1-0.875)*tarbits[framenumber];
}
}
update_Pparams(weightedavgcompl);
}
targetbits=(tarbits[framenumber]);
}
void update_picture(int a[],int b[],int c[],int chan_nav_dya[]) //pass allocated,generated,upperbnd,lwbnd
//arrays to the functions
{
//char layer,frame;
//extern no_framesGOP;
extern int bitrate,framerate,No_OfPframes,No_ofcodedPframes,no_framesGOP;
int currentbufferfullness,lowerbound1,upperbound1;
extern IH264ENC_OutArgs d;
extern XDM1_AlgBufInfo e;
static int weightcomplexity[16],remainingbits[17];
extern int lowbnd[17],upperbnd[17];
XDM2_BufSize curbuflev[no_framesGOP];
extern w,remainbits;
XDAS_Int32 Deltabits=(nbits[framenumber]-(floor(bitrate/framerate)));
//setting the remaining bits;
if(No_ofcodedPframes<16)
{
weightcomplexity[No_ofcodedPframes]=nbits[framenumber]*w;
}
IH264ENC_NumTemporalLayer layer;
if(layer==IH264_TEMPORAL_LAYERS_1)
{
if(Gopnumber==1 && framenumber==1)
{
remainingbits[framenumber]=B[1];
}
else if (framenumber==1)
{
remainingbits[framenumber]=B[16];
}
else
remainingbits[framenumber]=floor((weightcomplexity[No_ofcodedPframes]*B[framenumber-1])/weightcomplexity[No_ofcodedPframes]*No_OfPframes);
}
remainbits=(remainingbits[framenumber]);
// setting currentbuffer fullness,upper and lower bounds
if(layer==IH264_TEMPORAL_LAYERS_1)
{
if(Gopnumber==1 && framenumber==1)
{
curbuflev[1]=e.minInBufSize[XDM_MAX_IO_BUFFERS];
}
else if(framenumber==1)
{
curbuflev[1]=curbuflev[16];
}
else
{
curbuflev[framenumber].bytes=floor(max(curbuflev[framenumber-1].bytes+nbits[framenumber]-(bitrate/framerate),0));
lowbnd[framenumber]=floor(lowbnd[framenumber-1]+(bitrate/framerate)-nbits[framenumber-1]);
upperbnd[framenumber]=upperbnd[framenumber-1]+((bitrate/framerate)-nbits[framenumber-1])*0.9;
}
}
else
{
if(Gopnumber==1 && framenumber==1)
{
curbuflev[1]=e.minInBufSize[XDM_MAX_IO_BUFFERS];
}
else if(framenumber==1)
{
curbuflev[1]=curbuflev[16];
}
else
{
curbuflev[framenumber].bytes=max(curbuflev[framenumber-1].bytes+nbits[framenumber]-(bitrate/framerate),0);
lowbnd[framenumber]=lowbnd[framenumber-1]+(bitrate/framerate)-nbits[framenumber-1];
upperbnd[framenumber]=upperbnd[framenumber-1]+((bitrate/framerate)-nbits[framenumber-1])*0.9;
}
}
currentbufferfullness=(int)curbuflev[framenumber].bytes;
lowerbound1=(lowbnd[framenumber]);
upperbound1=(upperbnd[framenumber]);
}
int updateQPRC(IH264ENC_RateControlParams i)
{
extern bitrate, framerate, Ppreheader, PMADPicture_a1, PMADPicture_a2,curbuflev[17],targetbits,No_ofPframes;
extern int PQP;
int QP,qp1,prevframeMAD,PMADPicture[16],currentFrameMAD,Vs;
extern int qp[17],QPGOP1[226];
//IH264ENC_RateControlParams g;
IVIDEO_FrameType frame;
IH264ENC_NumTemporalLayer layer;
/*if(layer==IH264_TEMPORAL_LAYERS_1)
{
bitrate=get(bitrate);
tarbits=get(tarbits);
Ppreheader=get(Ppreheader);
numberofPpict=get(No_ofPframes);
PQp=getPQp();
}
else
{
bitrate=get(bitrate);
targetbits=get(tarbits);
Ppreheader=get(Ppreheader);
numberofPpict=get(No_ofPframes);
PQp=get(PQp);
}*/
if(Gopnumber==1)
{
if(frame==IVIDEO_I_FRAME && framenumber==1)
{
qp[1]=i.qpI;
qp1=qp[1];
return qp1;
}
else
{
PQP=setPQP(framenumber, qp[framenumber-1]);
qp[framenumber]=PQP; //set qp of p frame to average of previous (framenumber-1) frames
if(framenumber==16)
{
QPGOP1[1]=qp[framenumber];
}
qp1=qp[framenumber];
return qp1;
}
}
else
{
if(frame==IVIDEO_I_FRAME)
{
qp[1]=setQPI(Gopnumber); //set qp of I frame to average qp of previous Gop
return qp[framenumber];
}
else
{
PQP=setPQP(framenumber, qp[framenumber-1]);
qp[framenumber]=PQP;
if(No_ofcodedPframes==15)
{
QPGOP1[Gopnumber]=qp[framenumber];
}
return qp[framenumber];
}
}
prevframeMAD=PMADPicture[framenumber-1];
//predict current frame MAD
currentFrameMAD=PMADPicture_a1*prevframeMAD+PMADPicture_a2;
}
int setQPI(int gopnum)
{
int j,N=16/15,QPI;
extern qp[17],QPGOP1[226],w;
QPI=max(min(w-min(2,N),(qp[1]+2)),(qp[1]-2));
if(QPI>(QPGOP1[gopnum-1]-2))
{
QPI=QPI-1;
}
return QPI;
}
int setPQP(int j, int QP)
{
int QP1;
QP1=QP+2;
QP=min(QP+2,max(QP-2,QP1));
QP=min(max(QP,0),51);
return QP;
}
int main(int argc,char *argv)
{
//int framenumber,Gopnumber;
extern int B[17],nbits[17];
extern int lowbnd[17],upperbnd[17];
IH264ENC_RateControlParams g;
init_sequ();
algAlloc();
printf("Framenumber\tQP\tBits Generated\n");
do
{ algInit();
algActivate();
control();
if(framenumber%16==0)
{
framenumber=1;
Gopnumber++;
}
else
framenumber++;
//init_GOP(qp[]);
init_pict(w);
update_picture(B,nbits,lowbnd,upperbnd);
updateQPRC(g);
);
algDeactivate();
algFree();
}while(Gopnumber<226);
return 0;
}
should we insert the main() directly in the main() of encode omx example?And include the functions abovre it in another file or insert them in il_client_utils.c or il_client.c?
Thank you