else
h->param.b_sliced_threads = 0;
h->i_thread_frames = h->param.b_sliced_threads ? 1 : h->param.i_threads;
+ if( h->i_thread_frames > 1 )
+ h->param.nalu_process = NULL;
if( h->param.b_interlaced )
{
{
x264_nal_t *nal = &h->out.nal[h->out.i_nal];
- nal->i_ref_idc = i_ref_idc;
- nal->i_type = i_type;
+ nal->i_ref_idc = i_ref_idc;
+ nal->i_type = i_type;
+ nal->b_long_startcode = 1;
nal->i_payload= 0;
nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8];
{
x264_nal_t *nal = &h->out.nal[h->out.i_nal];
nal->i_payload = &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8] - nal->p_payload;
+ if( h->param.nalu_process )
+ h->param.nalu_process( h, nal );
h->out.i_nal++;
return x264_nal_check_buffer( h );
{
int nal_size = 0, previous_nal_size = 0;
+ if( h->param.nalu_process )
+ {
+ for( int i = start; i < h->out.i_nal; i++ )
+ nal_size += h->out.nal[i].i_payload;
+ return nal_size;
+ }
+
for( int i = 0; i < start; i++ )
previous_nal_size += h->out.nal[i].i_payload;
for( int i = start; i < h->out.i_nal; i++ )
{
- int long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
- int size = x264_nal_encode( h, nal_buffer, &h->out.nal[i], long_startcode );
- h->out.nal[i].i_payload = size;
- h->out.nal[i].p_payload = nal_buffer;
- nal_buffer += size;
+ h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
+ x264_nal_encode( h, nal_buffer, &h->out.nal[i] );
+ nal_buffer += h->out.nal[i].i_payload;
}
x264_emms();
/* Slice */
x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );
+ h->out.nal[h->out.i_nal].i_first_mb = h->sh.i_first_mb;
/* Slice header */
x264_macroblock_thread_init( h );
i_mb_x = 0;
}
}
+ h->out.nal[h->out.i_nal].i_last_mb = h->sh.i_last_mb;
if( h->param.b_cabac )
{
#include <stdarg.h>
-#define X264_BUILD 100
+#define X264_BUILD 101
/* x264_t:
* opaque handler for encoder */
typedef struct x264_t x264_t;
+/****************************************************************************
+ * NAL structure and functions
+ ****************************************************************************/
+
+enum nal_unit_type_e
+{
+ NAL_UNKNOWN = 0,
+ NAL_SLICE = 1,
+ NAL_SLICE_DPA = 2,
+ NAL_SLICE_DPB = 3,
+ NAL_SLICE_DPC = 4,
+ NAL_SLICE_IDR = 5, /* ref_idc != 0 */
+ NAL_SEI = 6, /* ref_idc == 0 */
+ NAL_SPS = 7,
+ NAL_PPS = 8,
+ NAL_AUD = 9,
+ NAL_FILLER = 12,
+ /* ref_idc == 0 for 6,9,10,11,12 */
+};
+enum nal_priority_e
+{
+ NAL_PRIORITY_DISPOSABLE = 0,
+ NAL_PRIORITY_LOW = 1,
+ NAL_PRIORITY_HIGH = 2,
+ NAL_PRIORITY_HIGHEST = 3,
+};
+
+/* The data within the payload is already NAL-encapsulated; the ref_idc and type
+ * are merely in the struct for easy access by the calling application.
+ * All data returned in an x264_nal_t, including the data in p_payload, is no longer
+ * valid after the next call to x264_encoder_encode. Thus it must be used or copied
+ * before calling x264_encoder_encode or x264_encoder_headers again. */
+typedef struct
+{
+ int i_ref_idc; /* nal_priority_e */
+ int i_type; /* nal_unit_type_e */
+ int b_long_startcode;
+ int i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */
+ int i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */
+
+ /* Size of payload in bytes. */
+ int i_payload;
+ /* If param->b_annexb is set, Annex-B bytestream with startcode.
+ * Otherwise, startcode is replaced with a 4-byte size.
+ * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
+ uint8_t *p_payload;
+} x264_nal_t;
+
/****************************************************************************
* Encoder parameters
****************************************************************************/
* i.e. when an x264_param_t is passed to x264_t in an x264_picture_t or in zones.
* Not used when x264_encoder_reconfig is called directly. */
void (*param_free)( void* );
+
+ /* Optional low-level callback for low-latency encoding. Called for each output NAL unit
+ * immediately after the NAL unit is finished encoding. This allows the calling application
+ * to begin processing video data (e.g. by sending packets over a network) before the frame
+ * is done encoding.
+ *
+ * This callback MUST do the following in order to work correctly:
+ * 1) Have available an output buffer of at least size nal->i_payload*3/2 + 5 + 16.
+ * 2) Call x264_nal_encode( h, dst, nal ), where dst is the output buffer.
+ * After these steps, the content of nal is valid and can be used in the same way as if
+ * the NAL unit were output by x264_encoder_encode.
+ *
+ * This does not need to be synchronous with the encoding process: the data pointed to
+ * by nal (both before and after x264_nal_encode) will remain valid until the next
+ * x264_encoder_encode call. The callback must be re-entrant.
+ *
+ * This callback does not work with frame-based threads; threads must be disabled
+ * or sliced-threads enabled. This callback also does not work as one would expect
+ * with HRD -- since the buffering period SEI cannot be calculated until the frame
+ * is finished encoding, it will not be sent via this callback.
+ *
+ * Note also that the NALs are not necessarily returned in order when sliced threads is
+ * enabled. Accordingly, the variable i_first_mb and i_last_mb are available in
+ * x264_nal_t to help the calling application reorder the slices if necessary.
+ *
+ * When this callback is enabled, x264_encoder_encode does not return valid NALs;
+ * the calling application is expected to acquire all output NALs through the callback.
+ *
+ * It is generally sensible to combine this callback with a use of slice-max-mbs or
+ * slice-max-size. */
+ void (*nalu_process) ( x264_t *h, x264_nal_t *nal );
} x264_param_t;
+void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal );
+
/****************************************************************************
* H.264 level restriction information
****************************************************************************/
* x264_picture_alloc ONLY */
void x264_picture_clean( x264_picture_t *pic );
-/****************************************************************************
- * NAL structure and functions
- ****************************************************************************/
-
-enum nal_unit_type_e
-{
- NAL_UNKNOWN = 0,
- NAL_SLICE = 1,
- NAL_SLICE_DPA = 2,
- NAL_SLICE_DPB = 3,
- NAL_SLICE_DPC = 4,
- NAL_SLICE_IDR = 5, /* ref_idc != 0 */
- NAL_SEI = 6, /* ref_idc == 0 */
- NAL_SPS = 7,
- NAL_PPS = 8,
- NAL_AUD = 9,
- NAL_FILLER = 12,
- /* ref_idc == 0 for 6,9,10,11,12 */
-};
-enum nal_priority_e
-{
- NAL_PRIORITY_DISPOSABLE = 0,
- NAL_PRIORITY_LOW = 1,
- NAL_PRIORITY_HIGH = 2,
- NAL_PRIORITY_HIGHEST = 3,
-};
-
-/* The data within the payload is already NAL-encapsulated; the ref_idc and type
- * are merely in the struct for easy access by the calling application.
- * All data returned in an x264_nal_t, including the data in p_payload, is no longer
- * valid after the next call to x264_encoder_encode. Thus it must be used or copied
- * before calling x264_encoder_encode or x264_encoder_headers again. */
-typedef struct
-{
- int i_ref_idc; /* nal_priority_e */
- int i_type; /* nal_unit_type_e */
-
- /* Size of payload in bytes. */
- int i_payload;
- /* If param->b_annexb is set, Annex-B bytestream with 4-byte startcode.
- * Otherwise, startcode is replaced with a 4-byte size.
- * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
- uint8_t *p_payload;
-} x264_nal_t;
-
/****************************************************************************
* Encoder functions
****************************************************************************/