h263enc: Add an option for outputting info about MBs as side data
Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
442c1320e7
commit
bdc1220eeb
@ -743,6 +743,7 @@ enum AVPacketSideDataType {
|
||||
AV_PKT_DATA_PALETTE,
|
||||
AV_PKT_DATA_NEW_EXTRADATA,
|
||||
AV_PKT_DATA_PARAM_CHANGE,
|
||||
AV_PKT_DATA_H263_MB_INFO,
|
||||
};
|
||||
|
||||
typedef struct AVPacket {
|
||||
@ -825,6 +826,24 @@ typedef struct AVPacket {
|
||||
* s32le height
|
||||
*/
|
||||
|
||||
/**
|
||||
* An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of
|
||||
* structures with info about macroblocks relevant to splitting the
|
||||
* packet into smaller packets on macroblock edges (e.g. as for RFC 2190).
|
||||
* That is, it does not necessarily contain info about all macroblocks,
|
||||
* as long as the distance between macroblocks in the info is smaller
|
||||
* than the target payload size.
|
||||
* Each MB info structure is 12 bytes, and is laid out as follows:
|
||||
* u32le bit offset from the start of the packet
|
||||
* u8 current quantizer at the start of the macroblock
|
||||
* u8 GOB number
|
||||
* u16le macroblock address within the GOB
|
||||
* u8 horizontal MV predictor
|
||||
* u8 vertical MV predictor
|
||||
* u8 horizontal MV predictor for block number 3
|
||||
* u8 vertical MV predictor for block number 3
|
||||
*/
|
||||
|
||||
enum AVSideDataParamChangeFlags {
|
||||
AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001,
|
||||
AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002,
|
||||
|
@ -506,6 +506,10 @@ typedef struct MpegEncContext {
|
||||
int gob_index;
|
||||
int obmc; ///< overlapped block motion compensation
|
||||
int showed_packed_warning; ///< flag for having shown the warning about divxs invalid b frames
|
||||
int mb_info; ///< interval for outputting info about mb offsets as side data
|
||||
int prev_mb_info, last_mb_info;
|
||||
uint8_t *mb_info_ptr;
|
||||
int mb_info_size;
|
||||
|
||||
/* H.263+ specific */
|
||||
int umvplus; ///< == H263+ && unrestricted_mv
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "flv.h"
|
||||
#include "mpeg4video.h"
|
||||
#include "internal.h"
|
||||
#include "bytestream.h"
|
||||
#include <limits.h>
|
||||
|
||||
//#undef NDEBUG
|
||||
@ -1426,6 +1427,12 @@ int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
|
||||
if (!pkt->data &&
|
||||
(ret = ff_alloc_packet(pkt, s->mb_width*s->mb_height*MAX_MB_BYTES)) < 0)
|
||||
return ret;
|
||||
if (s->mb_info) {
|
||||
s->mb_info_ptr = av_packet_new_side_data(pkt,
|
||||
AV_PKT_DATA_H263_MB_INFO,
|
||||
s->mb_width*s->mb_height*12);
|
||||
s->prev_mb_info = s->last_mb_info = s->mb_info_size = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < context_count; i++) {
|
||||
int start_y = s->thread_context[i]->start_mb_y;
|
||||
@ -1593,6 +1600,8 @@ vbv_retry:
|
||||
pkt->dts = pkt->pts;
|
||||
if (s->current_picture.f.key_frame)
|
||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||
if (s->mb_info)
|
||||
av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size);
|
||||
} else {
|
||||
assert((put_bits_ptr(&s->pb) == s->pb.buf));
|
||||
s->frame_bits = 0;
|
||||
@ -2336,6 +2345,49 @@ static void write_slice_end(MpegEncContext *s){
|
||||
s->misc_bits+= get_bits_diff(s);
|
||||
}
|
||||
|
||||
static void write_mb_info(MpegEncContext *s)
|
||||
{
|
||||
uint8_t *ptr = s->mb_info_ptr + s->mb_info_size - 12;
|
||||
int offset = put_bits_count(&s->pb);
|
||||
int mba = s->mb_x + s->mb_width * (s->mb_y % s->gob_index);
|
||||
int gobn = s->mb_y / s->gob_index;
|
||||
int pred_x, pred_y;
|
||||
if (CONFIG_H263_ENCODER)
|
||||
ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
|
||||
bytestream_put_le32(&ptr, offset);
|
||||
bytestream_put_byte(&ptr, s->qscale);
|
||||
bytestream_put_byte(&ptr, gobn);
|
||||
bytestream_put_le16(&ptr, mba);
|
||||
bytestream_put_byte(&ptr, pred_x); /* hmv1 */
|
||||
bytestream_put_byte(&ptr, pred_y); /* vmv1 */
|
||||
/* 4MV not implemented */
|
||||
bytestream_put_byte(&ptr, 0); /* hmv2 */
|
||||
bytestream_put_byte(&ptr, 0); /* vmv2 */
|
||||
}
|
||||
|
||||
static void update_mb_info(MpegEncContext *s, int startcode)
|
||||
{
|
||||
if (!s->mb_info)
|
||||
return;
|
||||
if (put_bits_count(&s->pb) - s->prev_mb_info*8 >= s->mb_info*8) {
|
||||
s->mb_info_size += 12;
|
||||
s->prev_mb_info = s->last_mb_info;
|
||||
}
|
||||
if (startcode) {
|
||||
s->prev_mb_info = put_bits_count(&s->pb)/8;
|
||||
/* This might have incremented mb_info_size above, and we return without
|
||||
* actually writing any info into that slot yet. But in that case,
|
||||
* this will be called again at the start of the after writing the
|
||||
* start code, actually writing the mb info. */
|
||||
return;
|
||||
}
|
||||
|
||||
s->last_mb_info = put_bits_count(&s->pb)/8;
|
||||
if (!s->mb_info_size)
|
||||
s->mb_info_size += 12;
|
||||
write_mb_info(s);
|
||||
}
|
||||
|
||||
static int encode_thread(AVCodecContext *c, void *arg){
|
||||
MpegEncContext *s= *(void**)arg;
|
||||
int mb_x, mb_y, pdif = 0;
|
||||
@ -2481,6 +2533,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
|
||||
int number_mb = (mb_y - s->resync_mb_y)*s->mb_width + mb_x - s->resync_mb_x;
|
||||
s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, current_packet_size, number_mb);
|
||||
}
|
||||
update_mb_info(s, 1);
|
||||
|
||||
switch(s->codec_id){
|
||||
case CODEC_ID_MPEG4:
|
||||
@ -2524,6 +2577,8 @@ static int encode_thread(AVCodecContext *c, void *arg){
|
||||
s->mb_skipped=0;
|
||||
s->dquant=0; //only for QP_RD
|
||||
|
||||
update_mb_info(s, 0);
|
||||
|
||||
if (mb_type & (mb_type-1) || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) { // more than 1 MB type possible or FF_MPV_FLAG_QP_RD
|
||||
int next_block=0;
|
||||
int pb_bits_count, pb2_bits_count, tex_pb_bits_count;
|
||||
@ -4074,6 +4129,7 @@ int ff_dct_quantize_c(MpegEncContext *s,
|
||||
static const AVOption h263_options[] = {
|
||||
{ "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
|
||||
{ "structured_slices","Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE},
|
||||
{ "mb_info", "emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size", OFFSET(mb_info), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VE },
|
||||
FF_MPV_COMMON_OPTS
|
||||
{ NULL },
|
||||
};
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define AVCODEC_VERSION_H
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 54
|
||||
#define LIBAVCODEC_VERSION_MINOR 3
|
||||
#define LIBAVCODEC_VERSION_MINOR 4
|
||||
#define LIBAVCODEC_VERSION_MICRO 0
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user