Update h264 encoder/decoder. Decoder is not fed with non consistent data. Synchronized not to free memory while decoding/encoding. Tuned some of the quality settings.

cusax-fix
Damian Minkov 18 years ago
parent 7418ac79df
commit ee72136cae

@ -45,8 +45,7 @@ public boolean pushRTPInput(Buffer inputBuffer)
// if the timestamp changes we are starting receiving a new frame
if(!(currentStamp == lastTimestamp))
{
encodedFrame = new byte[MAX_FRAME_SIZE];
encodedFrameLen = 0;
reset();
}
// the new frame timestamp
lastTimestamp = currentStamp;
@ -83,7 +82,8 @@ else if (type == 28)
catch(Exception ex)
{
logger.warn("Cannot parse incoming " + ex.getMessage());
return true;
reset();
return false;
}
if(hasMarker)
@ -162,4 +162,10 @@ public int getEncodedFrameLen()
{
return encodedFrameLen;
}
void reset()
{
encodedFrame = new byte[MAX_FRAME_SIZE];
encodedFrameLen = 0;
}
}

@ -157,7 +157,7 @@ public Format setInputFormat(Format format)
else
return null;
}
@Override
public Format setOutputFormat(Format format)
{
@ -203,15 +203,20 @@ public void close()
if (opened)
{
opened = false;
super.close();
synchronized (AVCODEC)
{
super.close();
AVCODEC.avcodec_close(avcontext);
AVCODEC.avcodec_close(avcontext);
AVUTIL.av_free(avpicture.getPointer());
AVUTIL.av_free(avcontext.getPointer());
AVUTIL.av_free(avpicture.getPointer());
AVUTIL.av_free(avcontext.getPointer());
}
}
}
long lastReceivedSeq = -1;
public int process(Buffer inputBuffer, Buffer outputBuffer)
{
if (!checkInputBuffer(inputBuffer))
@ -225,65 +230,88 @@ public int process(Buffer inputBuffer, Buffer outputBuffer)
return BUFFER_PROCESSED_OK;
}
if(!parser.pushRTPInput(inputBuffer))
if (inputBuffer.isDiscard())
{
inputBuffer.setDiscard(true);
reset();
return BUFFER_PROCESSED_OK;
}
if(lastReceivedSeq != -1 && inputBuffer.getSequenceNumber() - lastReceivedSeq > 1)
{
lastReceivedSeq = inputBuffer.getSequenceNumber();
parser.reset();
inputBuffer.setDiscard(true);
outputBuffer.setDiscard(true);
reset();
return BUFFER_PROCESSED_OK;
}
else if(!parser.pushRTPInput(inputBuffer))
{
lastReceivedSeq = inputBuffer.getSequenceNumber();
return OUTPUT_BUFFER_NOT_FILLED;
}
lastReceivedSeq = inputBuffer.getSequenceNumber();
// fills the incoming data
IntByReference got_picture = new IntByReference();
Pointer encBuf = AVUTIL.av_malloc(parser.getEncodedFrameLen());
arraycopy(parser.getEncodedFrame(), 0, encBuf, 0, parser.getEncodedFrameLen());
// decodes the data
AVCODEC.avcodec_decode_video(
avcontext, avpicture, got_picture, encBuf, parser.getEncodedFrameLen());
if(currentVideoWidth != avcontext.width)
synchronized (AVCODEC)
{
currentVideoWidth = avcontext.width;
VideoFormat format = getVideoFormat(currentVideoWidth);
if(format != null)
// decodes the data
AVCODEC.avcodec_decode_video(
avcontext, avpicture, got_picture, encBuf, parser.getEncodedFrameLen());
if(currentVideoWidth != avcontext.width)
{
outputBuffer.setFormat(format);
outputFormat = format;
currentVideoWidth = avcontext.width;
VideoFormat format = getVideoFormat(currentVideoWidth);
if(format != null)
{
outputBuffer.setFormat(format);
outputFormat = format;
}
}
}
if(got_picture.getValue() == 0)
{
outputBuffer.setDiscard(true);
AVUTIL.av_free(encBuf);
if(got_picture.getValue() == 0)
{
outputBuffer.setDiscard(true);
AVUTIL.av_free(encBuf);
return BUFFER_PROCESSED_OK;
}
// convert the picture in RGB Format
int numBytes = AVCODEC.avpicture_get_size(
AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height);
Pointer buffer = AVUTIL.av_malloc(numBytes);
return BUFFER_PROCESSED_OK;
}
AVCODEC.avpicture_fill(
frameRGB, buffer, AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height);
// convert the picture in RGB Format
int numBytes = AVCODEC.avpicture_get_size(
AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height);
Pointer buffer = AVUTIL.av_malloc(numBytes);
// Convert the image from its native format to RGB
AVCODEC.img_convert(frameRGB, AVCodecLibrary.PIX_FMT_RGB32,
avpicture, avcontext.pix_fmt, avcontext.width,
avcontext.height);
AVCODEC.avpicture_fill(
frameRGB, buffer, AVCodecLibrary.PIX_FMT_RGB32, avcontext.width, avcontext.height);
int[] data =
frameRGB.data0.getIntArray(0, avcontext.height * avcontext.width);
int[] outData = validateIntArraySize(outputBuffer, data.length);
System.arraycopy(data, 0, outData, 0, data.length);
// Convert the image from its native format to RGB
AVCODEC.img_convert(frameRGB, AVCodecLibrary.PIX_FMT_RGB32,
avpicture, avcontext.pix_fmt, avcontext.width,
avcontext.height);
outputBuffer.setOffset(0);
outputBuffer.setLength(outData.length);
outputBuffer.setData(outData);
int[] data =
frameRGB.data0.getIntArray(0, avcontext.height * avcontext.width);
int[] outData = validateIntArraySize(outputBuffer, data.length);
System.arraycopy(data, 0, outData, 0, data.length);
AVUTIL.av_free(encBuf);
AVUTIL.av_free(buffer);
outputBuffer.setOffset(0);
outputBuffer.setLength(outData.length);
outputBuffer.setData(outData);
return BUFFER_PROCESSED_OK;
AVUTIL.av_free(encBuf);
AVUTIL.av_free(buffer);
return BUFFER_PROCESSED_OK;
}
}
/**

@ -218,33 +218,36 @@ public int process(Buffer inBuffer, Buffer outBuffer)
return BUFFER_PROCESSED_OK;
}
// copy data to avpicture
rawFrameBuffer.write(0,
(byte[])inBuffer.getData(), inBuffer.getOffset(), encFrameLen);
if(framesSinceLastIFrame >= IFRAME_INTERVAL )
{
avpicture.key_frame = 1;
framesSinceLastIFrame = 0;
}
else
synchronized (AVCODEC)
{
framesSinceLastIFrame++;
avpicture.key_frame = 0;
// copy data to avpicture
rawFrameBuffer.write(0,
(byte[])inBuffer.getData(), inBuffer.getOffset(), encFrameLen);
if(framesSinceLastIFrame >= IFRAME_INTERVAL )
{
avpicture.key_frame = 1;
framesSinceLastIFrame = 0;
}
else
{
framesSinceLastIFrame++;
avpicture.key_frame = 0;
}
// encode data
int encLen =
AVCODEC.avcodec_encode_video(
avcontext, encFrameBuffer, encFrameLen, avpicture);
byte[] r = encFrameBuffer.getByteArray(0, encLen);
outBuffer.setData(r);
outBuffer.setLength(r.length);
outBuffer.setOffset(0);
return BUFFER_PROCESSED_OK;
}
// encode data
int encLen =
AVCODEC.avcodec_encode_video(
avcontext, encFrameBuffer, encFrameLen, avpicture);
byte[] r = encFrameBuffer.getByteArray(0, encLen);
outBuffer.setData(r);
outBuffer.setLength(r.length);
outBuffer.setOffset(0);
return BUFFER_PROCESSED_OK;
}
public synchronized void open() throws ResourceUnavailableException
@ -281,7 +284,7 @@ public synchronized void open() throws ResourceUnavailableException
avcontext.qcompress = 1;
int _bitRate = 48000;
int _bitRate = 9600;
avcontext.bit_rate = _bitRate; // average bit rate
avcontext.bit_rate_tolerance = _bitRate;// so to be 1 in x264
avcontext.rc_max_rate = _bitRate;
@ -291,7 +294,7 @@ public synchronized void open() throws ResourceUnavailableException
avcontext.time_base.den = 15;//25500; //???
avcontext.time_base.num = 1000;
avcontext.qmin = 10;
avcontext.qmax = 22;
avcontext.qmax = 18;
avcontext.max_qdiff = 4;
avcontext.partitions |= 0x111;
@ -346,15 +349,18 @@ public synchronized void close()
if (opened)
{
opened = false;
super.close();
synchronized (AVCODEC)
{
super.close();
AVCODEC.avcodec_close(avcontext);
AVCODEC.avcodec_close(avcontext);
AVUTIL.av_free(avpicture.getPointer());
AVUTIL.av_free(avcontext.getPointer());
AVUTIL.av_free(avpicture.getPointer());
AVUTIL.av_free(avcontext.getPointer());
AVUTIL.av_free(rawFrameBuffer);
AVUTIL.av_free(encFrameBuffer);
AVUTIL.av_free(rawFrameBuffer);
AVUTIL.av_free(encFrameBuffer);
}
}
}

Loading…
Cancel
Save