Especificação



Baixar 2,81 Mb.
Página12/24
Encontro01.07.2018
Tamanho2,81 Mb.
1   ...   8   9   10   11   12   13   14   15   ...   24

A3 Classes para escrita no arquivo H.264




      1. A3.1 Classe H264Mux



package br.ufsc.inf.guiga.media.multiplexer.video;
import java.io.IOException;

import java.util.List;
import javax.media.Buffer;

import javax.media.Format;

import javax.media.Multiplexer;

import javax.media.PlugIn;

import javax.media.protocol.ContentDescriptor;
import br.ufsc.inf.guiga.media.Global;

import br.ufsc.inf.guiga.media.codec.video.h264.nal.NALU;

import br.ufsc.inf.guiga.media.codec.video.h264.nal.NALUByteStream;

import br.ufsc.inf.guiga.media.codec.video.h264.nal.datavalue.NalRefIdc;

import br.ufsc.inf.guiga.media.codec.video.h264.nal.datavalue.NaluType;

import br.ufsc.inf.guiga.media.codec.video.h264.parset.PictureParameterSet;

import br.ufsc.inf.guiga.media.codec.video.h264.parset.SequenceParameterSet;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.Picture;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.Slice;

import br.ufsc.inf.guiga.media.control.H264Control;

import br.ufsc.inf.guiga.media.format.H264Format;

import br.ufsc.inf.guiga.media.parser.video.YUVFormatHandler;

import br.ufsc.inf.guiga.media.util.io.BitOutputStream;

import br.ufsc.inf.guiga.media.util.io.BitOutputStreamImpl;

import br.ufsc.inf.guiga.media.util.io.H264EntropyOutputStream;

import br.ufsc.inf.guiga.media.util.io.H264EntropyOutputStreamImpl;
import com.sun.media.multiplexer.BasicMux;
/**

* Multiplexes the H.264 Video Track into a Raw Bit Stream as specified by Annex B from

* H.264 International Standard.

*

* @author Guilherme Ferreira



*/

public class H264Mux extends BasicMux {
private static final String PLUGIN_NAME = "H.264/AVC Annex B Byte Stream Multiplexer";

private static final String MIME_TYPE = "video.264";
private SequenceParameterSet sps;

private PictureParameterSet pps;
/**

* Creates a H.264 Byte Stream Multiplexer.

*/

public H264Mux() {

super.supportedOutputs = new ContentDescriptor[] { new ContentDescriptor(

MIME_TYPE) };

super.supportedInputs = new Format[] {

new H264Format(YUVFormatHandler.SQCIF, 18432, 15),

new H264Format(YUVFormatHandler.QCIF, 38016, 15),

new H264Format(YUVFormatHandler.CIF, 152064, 15),

new H264Format(YUVFormatHandler._4CIF, 608256, 15) };

}
/**

* Gets the name of this plug-in as a human-readable string.

*

* @return A String that contains the descriptive name of the plug-in.



*/

public String getName() {

return PLUGIN_NAME;

}
/**

* Sets the input {@link Format} for the specified track.

*

* @param input The input {@link Format} of the specified track.



* @param trackID The index number of the track for which the {@link Format} is being

* set.


* @return The {@link Format} preferred by the {@link Multiplexer}. This might the

* same as the specified {@link Format}, a more well-defined {@link Format}

* than was specified, or null if the specified {@link Format} is not

* supported by the {@link Multiplexer} at all.

*/

public Format setInputFormat(Format input, int trackID) {

H264Control control = null;


if (input instanceof H264Format) {

H264Format h264Format = (H264Format) input;



int maxFrameNumber = Global.getInstance().getTotalFrameNumber();
sps = new SequenceParameterSet(h264Format, control, maxFrameNumber);

pps = new PictureParameterSet(sps);


return super.setInputFormat(input, trackID);

} else {



return null;

}

}


/**

* Processes the input {@link Buffer} and multiplexes it with data from other tracks.

* The multiplexed output is sent to an output DataSource.

*


* This multiplexer simply write the raw H.264 video stream into the file.

*

* @param buffer The Buffer of data to process.



* @param trackID The index number of the track to which the input Buffer belongs.

* @return BUFFER_PROCESSED_OK If the processing is successful. Other

* possible return codes are defined in {@link PlugIn}.

*/

protected int doProcess(Buffer buffer, int trackID) {



try {

BitOutputStream bitstream = new BitOutputStreamImpl();

H264EntropyOutputStream stream = new H264EntropyOutputStreamImpl(bitstream,

sps, pps);


// retrieve the coded frame/picture

Picture picture = (Picture) buffer.getData();


// get the nal_unit_type and nal_ref_idc based on picture type

NaluType naluType = picture.isIDR() ? NaluType.NALU_TYPE_IDR

: NaluType.NALU_TYPE_SLICE;

NalRefIdc nalRefIdc = picture.isIDR() ? NalRefIdc.NALU_PRIORITY_HIGHEST

: NalRefIdc.NALU_PRIORITY_HIGH;
// retrieve all slices from the picture

List slices = picture.getSlices();



for (Slice slice : slices) {

// write the slice

NALU nalu = new NALUByteStream(slice, naluType, nalRefIdc);

nalu.write(stream);

}
// write it all to the output

writeStream(bitstream);


} catch (IOException e) {

e.printStackTrace();

}

return BUFFER_PROCESSED_OK;

}
/**

* This method generates the appropriate sequence header.

*/

protected void writeHeader() {



try {

BitOutputStream bitstream = new BitOutputStreamImpl();

H264EntropyOutputStream stream = new H264EntropyOutputStreamImpl(bitstream,

sps, pps);


// write Sequence Parameter Set

NALU nalu = new NALUByteStream(sps, NaluType.NALU_TYPE_SPS,

NalRefIdc.NALU_PRIORITY_HIGHEST);

nalu.write(stream);


// write now the Picture Parameter Set (only one for now).

nalu = new NALUByteStream(pps, NaluType.NALU_TYPE_PPS,

NalRefIdc.NALU_PRIORITY_HIGHEST);

nalu.write(stream);


// write it all to the output

writeStream(bitstream);


} catch (IOException e) {

e.printStackTrace();

}

}
protected void writeStream(BitOutputStream stream) {



byte[] streamArray = stream.toByteArray();

write(streamArray, 0, streamArray.length);

}
}

      1. A3.2 Classe NALUByteStream



package br.ufsc.inf.guiga.media.codec.video.h264.nal;
import java.io.IOException;
import br.ufsc.inf.guiga.media.codec.video.h264.nal.datavalue.NalRefIdc;

import br.ufsc.inf.guiga.media.codec.video.h264.nal.datavalue.NaluType;

import br.ufsc.inf.guiga.media.util.io.H264EntropyOutputStream;
/**

* This class implements the NAL Unit from Annex B of ITU-T Recommendation

* H.264.

*

* @author Guilherme Ferreira



*/

public class NALUByteStream extends NALU {
/**

* @see br.ufsc.inf.guiga.media.codec.video.h264.nal.NALU#NALU(RBSP,

* NaluType, NalRefIdc)

*/

public NALUByteStream(

RBSP rbsp,

NaluType nalUnitType,

NalRefIdc nalReferenceIdc)

{

super(rbsp, nalUnitType, nalReferenceIdc);

}
/**

* Writes an Annex B Byte Stream NAL Unit.

*

* @param output



* the output video stream, where this NAL Unit will be write.

* @return number of bits written

*/

protected int doWrite(H264EntropyOutputStream output) throws IOException {

int bitsWritten = 0;
assert (forbidden_zero_bit == 0);

assert (startcodeprefix_len == 3 || startcodeprefix_len == 4);
// write the NALU Start Code Prefix

if (startcodeprefix_len > 3) {

output.write_u_v(8, 0);

}

output.write_u_v(8, 0);



output.write_u_v(8, 0);

output.write_u_v(8, 1);


// set the forbidden_zero_bit, nal_ref_idc and the nal_unit_type

output.write_u_v(8, (forbidden_zero_bit << 7)

| (nal_ref_idc.value() << 5) | nal_unit_type.value());
// write the Raw Byte Sequence Payload

writeRBSP(rbsp, output);


bitsWritten = output.size();
return bitsWritten;

}
}


      1. A3.3 Classe NALU



package br.ufsc.inf.guiga.media.codec.video.h264.nal;
import java.io.IOException;

import java.io.OutputStream;
import br.ufsc.inf.guiga.media.codec.video.h264.nal.datavalue.NalRefIdc;

import br.ufsc.inf.guiga.media.codec.video.h264.nal.datavalue.NaluType;

import br.ufsc.inf.guiga.media.util.io.H264EntropyOutputStream;
/**

* NAL Unit.

*

* @author Guilherme Ferreira



*/

public abstract class NALU {
// private byte[] payloadBuffer; // used as temporary buffer to store data.
// 4 for parameter sets and first slice in picture

// 3 for everything else (suggested)



protected int startcodeprefix_len;

// Length of the NAL unit (Excluding the start code, which does not belong

// to the NALU)

protected NaluType nal_unit_type; // NALU_TYPE_xxxx (NaluType)

protected NalRefIdc nal_ref_idc; // NALU_PRIORITY_xxxx (NalRefIdc)

protected byte forbidden_zero_bit; // should be always zero

protected RBSP rbsp; // NAL Unit Payload
protected boolean useAnnexbLongStartcode;
/**

* Creates a NAL Unit containing the given {@link RBSP}.

*

* @param rbsp An object that implements the {@link RBSP} and whom the data will be



* wrap by this NAL Unit.

* @param nalUnitType The {@link NaluType} value that specify the type of payload

* within this NAL unit.

* @param nalReferenceIdc One of {@link NalRefIdc} values to specify the picture

* priority.

*/

public NALU(RBSP rbsp, NaluType nalUnitType, NalRefIdc nalReferenceIdc) {



this.rbsp = rbsp;

this.forbidden_zero_bit = 0;

this.nal_unit_type = nalUnitType;

this.nal_ref_idc = nalReferenceIdc;

this.useAnnexbLongStartcode = true;

this.startcodeprefix_len = useAnnexbLongStartcode ? 4 : 3;
// payloadBuffer = new byte[126720];

}
/**

* Writes a NALU to an {@link OutputStream}.

*

* @param output the output stream where this NAL Unit data will be write.



* @return number of bits written.

* @throws IOException Danger Will Robinson, Danger!

*/

public int write(H264EntropyOutputStream output) throws IOException {

output.setNalu(this);


return doWrite(output);

}
/**

* This method must be overwrite in subclasses in order to write the RBSP

*

* @param output the output stream where the NALU subclass data will be write.



* @return number of bits written.

* @throws IOException

*/

protected abstract int doWrite(H264EntropyOutputStream output) throws IOException;
/**

* Converts an RBSP to a NALU.

*

* @param rbsp byte buffer with the Raw Byte Sequence Payload (RBSP)



* @param output bit stream where the RBSP will be write.

* @return length of the NALU in bytes.

*/

protected int writeRBSP(RBSP rbsp, H264EntropyOutputStream output) {

// delegate the payload write to the RBSP object



int rbsp_size = rbsp.write(output);
// check if it isn't too big :-)

if (rbsp_size < RBSP.MAXRBSPSIZE) {

// TODO throw an exception. PayloadOverloadedException?

}
// check if there isn't any start code prefix within the RBSP

int length = 1 + preventEmulationOfStartCode(output, 0);
return length;

}
/**

* This function converts a RBSP payload to an EBSP (Encapsulated Byte Stream Payload)

* payload, preventing that no sequence of consecutive byte-aligned bytes in the NAL

* unit contains a start code prefix.

*


* This is done by placing an emulation prevention byte, a byte equal to 0x03 that may

* be present within a NAL unit.

*

* @param output data bits



* @param beginBytePos The byte position after start-code, after which stuffing to

* prevent start-code emulation begins.

* @return size of output after stuffing.

*/

protected int preventEmulationOfStartCode(

H264EntropyOutputStream output, int beginBytePos)

{

int endBytePos = output.size() / 8;


int i, j;
// System.arraycopy(

// output.toByteArray(), beginBytePos, payloadBuffer, beginBytePos,

// (endBytePos - beginBytePos));
j = beginBytePos;

for (i = beginBytePos; i < endBytePos; i++) {

// TODO must implement, but I didn't find any file that need this

// emulation byte

j++;


}
return j;

}
/**

* @return the {@link NaluType} of this NAL Unit.

*/

public NaluType getNalUnitType() {



return nal_unit_type;

}
/**

* @return the {@link NalRefIdc} of this NAL Unit.

*/

public NalRefIdc getNalRefIdc() {



return nal_ref_idc;

}
}





1   ...   8   9   10   11   12   13   14   15   ...   24


©livred.info 2017
enviar mensagem

    Página principal