Commit f9d3841a authored by Kieran Kunhya's avatar Kieran Kunhya

mpeg4video: Add support for MPEG-4 Simple Studio Profile.

This is a profile supporting > 8-bit video and has a higher quality DCT
parent 699fa8f3
...@@ -814,7 +814,8 @@ static int er_supported(ERContext *s) ...@@ -814,7 +814,8 @@ static int er_supported(ERContext *s)
{ {
if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice || if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice ||
!s->cur_pic.f || !s->cur_pic.f ||
s->cur_pic.field_picture s->cur_pic.field_picture ||
s->avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO
) )
return 0; return 0;
return 1; return 1;
......
...@@ -47,6 +47,12 @@ ...@@ -47,6 +47,12 @@
static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) static enum AVPixelFormat h263_get_format(AVCodecContext *avctx)
{ {
/* MPEG-4 Studio Profile only, not supported by hardware */
if (avctx->bits_per_raw_sample > 8) {
av_assert1(avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO);
return avctx->pix_fmt;
}
if (avctx->codec->id == AV_CODEC_ID_MSS2) if (avctx->codec->id == AV_CODEC_ID_MSS2)
return AV_PIX_FMT_YUV420P; return AV_PIX_FMT_YUV420P;
...@@ -197,6 +203,11 @@ static int decode_slice(MpegEncContext *s) ...@@ -197,6 +203,11 @@ static int decode_slice(MpegEncContext *s)
ff_set_qscale(s, s->qscale); ff_set_qscale(s, s->qscale);
if (s->studio_profile) {
if ((ret = ff_mpeg4_decode_studio_slice_header(s->avctx->priv_data)) < 0)
return ret;
}
if (s->avctx->hwaccel) { if (s->avctx->hwaccel) {
const uint8_t *start = s->gb.buffer + get_bits_count(&s->gb) / 8; const uint8_t *start = s->gb.buffer + get_bits_count(&s->gb) / 8;
ret = s->avctx->hwaccel->decode_slice(s->avctx, start, s->gb.buffer_end - start); ret = s->avctx->hwaccel->decode_slice(s->avctx, start, s->gb.buffer_end - start);
......
...@@ -256,9 +256,15 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) ...@@ -256,9 +256,15 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx)
c->perm_type = FF_IDCT_PERM_NONE; c->perm_type = FF_IDCT_PERM_NONE;
} else { } else {
if (avctx->bits_per_raw_sample == 10 || avctx->bits_per_raw_sample == 9) { if (avctx->bits_per_raw_sample == 10 || avctx->bits_per_raw_sample == 9) {
/* 10-bit MPEG-4 Simple Studio Profile requires a higher precision IDCT
However, it only uses idct_put */
if (avctx->codec_id == AV_CODEC_ID_MPEG4 && avctx->profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO)
c->idct_put = ff_simple_idct_put_int32_10bit;
else {
c->idct_put = ff_simple_idct_put_int16_10bit; c->idct_put = ff_simple_idct_put_int16_10bit;
c->idct_add = ff_simple_idct_add_int16_10bit; c->idct_add = ff_simple_idct_add_int16_10bit;
c->idct = ff_simple_idct_int16_10bit; c->idct = ff_simple_idct_int16_10bit;
}
c->perm_type = FF_IDCT_PERM_NONE; c->perm_type = FF_IDCT_PERM_NONE;
} else if (avctx->bits_per_raw_sample == 12) { } else if (avctx->bits_per_raw_sample == 12) {
c->idct_put = ff_simple_idct_put_int16_12bit; c->idct_put = ff_simple_idct_put_int16_12bit;
......
...@@ -207,12 +207,27 @@ static int h263_decode_gob_header(MpegEncContext *s) ...@@ -207,12 +207,27 @@ static int h263_decode_gob_header(MpegEncContext *s)
} }
/** /**
* Decode the group of blocks / video packet header. * Decode the group of blocks / video packet header / slice header (MPEG-4 Studio).
* @return bit position of the resync_marker, or <0 if none was found * @return bit position of the resync_marker, or <0 if none was found
*/ */
int ff_h263_resync(MpegEncContext *s){ int ff_h263_resync(MpegEncContext *s){
int left, pos, ret; int left, pos, ret;
/* In MPEG-4 studio mode look for a new slice startcode
* and decode slice header */
if(s->codec_id==AV_CODEC_ID_MPEG4 && s->studio_profile) {
align_get_bits(&s->gb);
while (get_bits_left(&s->gb) >= 32 && show_bits_long(&s->gb, 32) != SLICE_START_CODE) {
get_bits(&s->gb, 8);
}
if (show_bits_long(&s->gb, 32) == SLICE_START_CODE)
return get_bits_count(&s->gb);
else
return -1;
}
if(s->codec_id==AV_CODEC_ID_MPEG4){ if(s->codec_id==AV_CODEC_ID_MPEG4){
skip_bits1(&s->gb); skip_bits1(&s->gb);
align_get_bits(&s->gb); align_get_bits(&s->gb);
......
...@@ -649,16 +649,6 @@ static inline int get_dmv(MpegEncContext *s) ...@@ -649,16 +649,6 @@ static inline int get_dmv(MpegEncContext *s)
return 0; return 0;
} }
static inline int get_qscale(MpegEncContext *s)
{
int qscale = get_bits(&s->gb, 5);
if (s->q_scale_type)
return ff_mpeg2_non_linear_qscale[qscale];
else
return qscale << 1;
}
/* motion type (for MPEG-2) */ /* motion type (for MPEG-2) */
#define MT_FIELD 1 #define MT_FIELD 1
#define MT_FRAME 2 #define MT_FRAME 2
...@@ -751,7 +741,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) ...@@ -751,7 +741,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
s->interlaced_dct = get_bits1(&s->gb); s->interlaced_dct = get_bits1(&s->gb);
if (IS_QUANT(mb_type)) if (IS_QUANT(mb_type))
s->qscale = get_qscale(s); s->qscale = mpeg_get_qscale(s);
if (s->concealment_motion_vectors) { if (s->concealment_motion_vectors) {
/* just parse them */ /* just parse them */
...@@ -819,7 +809,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) ...@@ -819,7 +809,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
} }
if (IS_QUANT(mb_type)) if (IS_QUANT(mb_type))
s->qscale = get_qscale(s); s->qscale = mpeg_get_qscale(s);
s->last_mv[0][0][0] = 0; s->last_mv[0][0][0] = 0;
s->last_mv[0][0][1] = 0; s->last_mv[0][0][1] = 0;
...@@ -840,7 +830,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) ...@@ -840,7 +830,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
} }
if (IS_QUANT(mb_type)) if (IS_QUANT(mb_type))
s->qscale = get_qscale(s); s->qscale = mpeg_get_qscale(s);
/* motion vectors */ /* motion vectors */
s->mv_dir = (mb_type >> 13) & 3; s->mv_dir = (mb_type >> 13) & 3;
...@@ -1728,7 +1718,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, ...@@ -1728,7 +1718,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
ff_mpeg1_clean_buffers(s); ff_mpeg1_clean_buffers(s);
s->interlaced_dct = 0; s->interlaced_dct = 0;
s->qscale = get_qscale(s); s->qscale = mpeg_get_qscale(s);
if (s->qscale == 0) { if (s->qscale == 0) {
av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n"); av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n");
......
...@@ -373,4 +373,120 @@ const uint8_t ff_mpeg4_dc_threshold[8]={ ...@@ -373,4 +373,120 @@ const uint8_t ff_mpeg4_dc_threshold[8]={
99, 13, 15, 17, 19, 21, 23, 0 99, 13, 15, 17, 19, 21, 23, 0
}; };
/* Note these are different in studio mode */
const uint16_t ff_mpeg4_studio_dc_luma[19][2]={
{0x0e, 6}, {0x06, 5}, {0x00, 4}, {0x02, 4},
{0x07, 3}, {0x05, 3}, {0x03, 3}, {0x02, 3},
{0x04, 3}, {0x06, 3}, {0x01, 4}, {0x1e, 7},
{0x3e, 8}, {0x7e, 9}, {0xfe, 10}, {0x1fe, 11},
{0x3fe, 12}, {0x7fe, 13}, {0x7ff, 13}
};
const uint16_t ff_mpeg4_studio_dc_chroma[19][2]={
{0x00, 4}, {0x02, 4}, {0x07, 3}, {0x05, 3},
{0x03, 3}, {0x02, 3}, {0x04, 3}, {0x06, 3},
{0x01, 4}, {0x06, 5}, {0x0e, 6}, {0x1e, 7},
{0x3e, 8}, {0x7e, 9}, {0xfe, 10}, {0x1fe, 11},
{0x3fe, 12}, {0x7fe, 13}, {0x7ff, 13}
};
const uint16_t ff_mpeg4_studio_intra[12][22][2]={
{
{0x05, 4}, {0x04, 4}, {0x05, 7}, {0x09, 9},
{0x21, 11}, {0x41, 12}, {0x81, 13}, {0x03, 4},
{0x03, 5}, {0x05, 6}, {0x04, 7}, {0x03, 7},
{0x05, 8}, {0x03, 2}, {0x05, 3}, {0x04, 3},
{0x03, 3}, {0x02, 4}, {0x04, 6}, {0x03, 6},
{0x11, 10}, {0x80, 13}
},
{
{0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
{0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
{0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0},
{0x00, 0}, {0x00, 0}, {0x01, 1}, {0x01, 2},
{0x01, 3}, {0x01, 4}, {0x01, 5}, {0x03, 7},
{0x05, 8}, {0x04, 8}
},
{
{0x05, 3}, {0x03, 5}, {0x02, 5}, {0x03, 7},
{0x09, 9}, {0x103, 14}, {0x102, 14}, {0x04, 3},
{0x03, 3}, {0x03, 4}, {0x02, 4}, {0x03, 6},
{0x11, 10}, {0x03, 2}, {0x02, 3}, {0x02, 6},
{0x05, 8}, {0x21, 11}, {0x83, 13}, {0x101, 14},
{0x201, 15}, {0x82, 13}
},
{
{0x05, 5}, {0x05, 4}, {0x04, 5}, {0x03, 6},
{0x09, 9}, {0x83, 13}, {0x82, 13}, {0x03, 3},
{0x04, 4}, {0x03, 4}, {0x03, 5}, {0x05, 8},
{0x81, 13}, {0x03, 2}, {0x02, 2}, {0x02, 5},
{0x02, 6}, {0x03, 7}, {0x11, 10}, {0x43, 12},
{0x80, 13}, {0x42, 12}
},
{
{0x05, 7}, {0x03, 4}, {0x03, 5}, {0x04, 7},
{0x09, 9}, {0x83, 13}, {0x101, 14}, {0x03, 3},
{0x02, 4}, {0x05, 6}, {0x03, 7}, {0x11, 10},
{0x201, 15}, {0x03, 2}, {0x02, 2}, {0x02, 3},
{0x04, 6}, {0x03, 6}, {0x05, 8}, {0x21, 11},
{0x82, 13}, {0x81, 13}
},
{
{0x13, 10}, {0x03, 5}, {0x05, 7}, {0x12, 10},
{0x43, 12}, {0x83, 13}, {0x82, 13}, {0x02, 5},
{0x04, 7}, {0x05, 8}, {0x23, 11}, {0x81, 13},
{0x101, 14}, {0x03, 2}, {0x02, 2}, {0x01, 2},
{0x01, 3}, {0x03, 6}, {0x03, 7}, {0x22, 11},
{0x201, 15}, {0x42, 12}
},
{
{0x23, 11}, {0x01, 4}, {0x07, 8}, {0x13, 10},
{0x22, 11}, {0x103, 14}, {0x102, 14}, {0x03, 6},
{0x06, 8}, {0x12, 10}, {0x43, 12}, {0x101, 14},
{0x201, 15}, {0x03, 3}, {0x02, 3}, {0x03, 2},
{0x02, 2}, {0x01, 3}, {0x02, 6}, {0x05, 8},
{0x42, 12}, {0x41, 12}
},
{
{0x0b, 9}, {0x03, 5}, {0x07, 8}, {0x07, 7},
{0x06, 7}, {0x23, 11}, {0x41, 12}, {0x05, 7},
{0x06, 8}, {0x0a, 9}, {0x13, 10}, {0x22, 11},
{0x40, 12}, {0x03, 4}, {0x02, 4}, {0x03, 2},
{0x02, 2}, {0x01, 2}, {0x02, 5}, {0x04, 7},
{0x12, 10}, {0x21, 11}
},
{
{0x15, 10}, {0x03, 6}, {0x14, 10}, {0x23, 11},
{0x07, 8}, {0x43, 12}, {0x81, 13}, {0x06, 8},
{0x0b, 9}, {0x13, 10}, {0x12, 10}, {0x42, 12},
{0x80, 13}, {0x01, 4}, {0x03, 3}, {0x02, 3},
{0x03, 2}, {0x02, 2}, {0x01, 3}, {0x02, 6},
{0x22, 11}, {0x41, 12}
},
{
{0x43, 12}, {0x05, 6}, {0x07, 8}, {0x04, 6},
{0x03, 6}, {0x13, 10}, {0x42, 12}, {0x05, 7},
{0x04, 7}, {0x06, 8}, {0x12, 10}, {0x41, 12},
{0x40, 12}, {0x03, 5}, {0x03, 4}, {0x03, 3},
{0x02, 3}, {0x03, 2}, {0x02, 2}, {0x02, 4},
{0x05, 8}, {0x11, 10}
},
{
{0x83, 13}, {0x05, 7}, {0x07, 8}, {0x03, 4},
{0x21, 11}, {0x82, 13}, {0x81, 13}, {0x04, 7},
{0x06, 8}, {0x0b, 9}, {0x0a, 9}, {0x11, 10},
{0x80, 13}, {0x03, 5}, {0x02, 5}, {0x02, 4},
{0x03, 3}, {0x02, 3}, {0x03, 2}, {0x02, 2},
{0x03, 6}, {0x09, 9}
},
{
{0x13, 10}, {0x03, 5}, {0x03, 6}, {0x0d, 9},
{0x0c, 9}, {0x21, 11}, {0x20, 11}, {0x02, 5},
{0x02, 6}, {0x07, 8}, {0x0b, 9}, {0x12, 10},
{0x11, 10}, {0x05, 3}, {0x04, 3}, {0x05, 4},
{0x04, 4}, {0x03, 4}, {0x02, 4}, {0x03, 3},
{0x03, 2}, {0x0a, 9}
}
};
#endif /* AVCODEC_MPEG4DATA_H */ #endif /* AVCODEC_MPEG4DATA_H */
...@@ -61,6 +61,10 @@ ...@@ -61,6 +61,10 @@
#define GOP_STARTCODE 0x1B3 #define GOP_STARTCODE 0x1B3
#define VISUAL_OBJ_STARTCODE 0x1B5 #define VISUAL_OBJ_STARTCODE 0x1B5
#define VOP_STARTCODE 0x1B6 #define VOP_STARTCODE 0x1B6
#define SLICE_STARTCODE 0x1B7
#define EXT_STARTCODE 0x1B8
#define QUANT_MATRIX_EXT_ID 0x3
/* smaller packets likely don't contain a real frame */ /* smaller packets likely don't contain a real frame */
#define MAX_NVOP_SIZE 19 #define MAX_NVOP_SIZE 19
...@@ -108,8 +112,16 @@ typedef struct Mpeg4DecContext { ...@@ -108,8 +112,16 @@ typedef struct Mpeg4DecContext {
int cplx_estimation_trash_i; int cplx_estimation_trash_i;
int cplx_estimation_trash_p; int cplx_estimation_trash_p;
int cplx_estimation_trash_b; int cplx_estimation_trash_b;
VLC studio_intra_tab[12];
VLC studio_luma_dc;
VLC studio_chroma_dc;
int rgb;
} Mpeg4DecContext; } Mpeg4DecContext;
static const uint8_t mpeg4_block_count[4] = {0, 6, 8, 12};
/* dc encoding for MPEG-4 */ /* dc encoding for MPEG-4 */
extern const uint8_t ff_mpeg4_DCtab_lum[13][2]; extern const uint8_t ff_mpeg4_DCtab_lum[13][2];
extern const uint8_t ff_mpeg4_DCtab_chrom[13][2]; extern const uint8_t ff_mpeg4_DCtab_chrom[13][2];
...@@ -137,6 +149,10 @@ extern const uint16_t ff_mpeg4_resync_prefix[8]; ...@@ -137,6 +149,10 @@ extern const uint16_t ff_mpeg4_resync_prefix[8];
extern const uint8_t ff_mpeg4_dc_threshold[8]; extern const uint8_t ff_mpeg4_dc_threshold[8];
extern const uint16_t ff_mpeg4_studio_dc_luma[19][2];
extern const uint16_t ff_mpeg4_studio_dc_chroma[19][2];
extern const uint16_t ff_mpeg4_studio_intra[12][22][2];
void ff_mpeg4_encode_mb(MpegEncContext *s, void ff_mpeg4_encode_mb(MpegEncContext *s,
int16_t block[6][64], int16_t block[6][64],
int motion_x, int motion_y); int motion_x, int motion_y);
...@@ -155,6 +171,7 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s); ...@@ -155,6 +171,7 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s);
int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx); int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx);
int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s); int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx); int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx);
int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
void ff_mpeg4_init_direct_mv(MpegEncContext *s); void ff_mpeg4_init_direct_mv(MpegEncContext *s);
void ff_mpeg4videodec_static_init(void); void ff_mpeg4videodec_static_init(void);
int ff_mpeg4_workaround_bugs(AVCodecContext *avctx); int ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
......
This diff is collapsed.
...@@ -386,6 +386,9 @@ static int init_duplicate_context(MpegEncContext *s) ...@@ -386,6 +386,9 @@ static int init_duplicate_context(MpegEncContext *s)
for (i = 0; i < 12; i++) { for (i = 0; i < 12; i++) {
s->pblocks[i] = &s->block[i]; s->pblocks[i] = &s->block[i];
} }
FF_ALLOCZ_OR_GOTO(s->avctx, s->block32, sizeof(*s->block32), fail)
if (s->avctx->codec_tag == AV_RL32("VCR2")) { if (s->avctx->codec_tag == AV_RL32("VCR2")) {
// exchange uv // exchange uv
FFSWAP(void *, s->pblocks[4], s->pblocks[5]); FFSWAP(void *, s->pblocks[4], s->pblocks[5]);
...@@ -421,6 +424,7 @@ static void free_duplicate_context(MpegEncContext *s) ...@@ -421,6 +424,7 @@ static void free_duplicate_context(MpegEncContext *s)
av_freep(&s->me.map); av_freep(&s->me.map);
av_freep(&s->me.score_map); av_freep(&s->me.score_map);
av_freep(&s->blocks); av_freep(&s->blocks);
av_freep(&s->block32);
av_freep(&s->ac_val_base); av_freep(&s->ac_val_base);
s->block = NULL; s->block = NULL;
} }
...@@ -438,6 +442,7 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) ...@@ -438,6 +442,7 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src)
COPY(me.score_map); COPY(me.score_map);
COPY(blocks); COPY(blocks);
COPY(block); COPY(block);
COPY(block32);
COPY(start_mb_y); COPY(start_mb_y);
COPY(end_mb_y); COPY(end_mb_y);
COPY(me.map_generation); COPY(me.map_generation);
...@@ -811,6 +816,7 @@ static void clear_context(MpegEncContext *s) ...@@ -811,6 +816,7 @@ static void clear_context(MpegEncContext *s)
s->dct_error_sum = NULL; s->dct_error_sum = NULL;
s->block = NULL; s->block = NULL;
s->blocks = NULL; s->blocks = NULL;
s->block32 = NULL;
memset(s->pblocks, 0, sizeof(s->pblocks)); memset(s->pblocks, 0, sizeof(s->pblocks));
s->ac_val_base = NULL; s->ac_val_base = NULL;
s->ac_val[0] = s->ac_val[0] =
...@@ -2120,8 +2126,31 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], ...@@ -2120,8 +2126,31 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64],
ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr); ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr);
} }
} else { } else {
/* Only MPEG-4 Simple Studio Profile is supported in > 8-bit mode.
TODO: Integrate 10-bit properly into mpegvideo.c so that ER works properly */
if (s->avctx->bits_per_raw_sample > 8){
const int act_block_size = block_size * 2;
s->idsp.idct_put(dest_y, dct_linesize, (int16_t*)(*s->block32)[0]);
s->idsp.idct_put(dest_y + act_block_size, dct_linesize, (int16_t*)(*s->block32)[1]);
s->idsp.idct_put(dest_y + dct_offset, dct_linesize, (int16_t*)(*s->block32)[2]);
s->idsp.idct_put(dest_y + dct_offset + act_block_size, dct_linesize, (int16_t*)(*s->block32)[3]);
dct_linesize = uvlinesize << s->interlaced_dct;
dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize*block_size;
s->idsp.idct_put(dest_cb, dct_linesize, (int16_t*)(*s->block32)[4]);
s->idsp.idct_put(dest_cr, dct_linesize, (int16_t*)(*s->block32)[5]);
s->idsp.idct_put(dest_cb + dct_offset, dct_linesize, (int16_t*)(*s->block32)[6]);
s->idsp.idct_put(dest_cr + dct_offset, dct_linesize, (int16_t*)(*s->block32)[7]);
if(!s->chroma_x_shift){//Chroma444
s->idsp.idct_put(dest_cb + act_block_size, dct_linesize, (int16_t*)(*s->block32)[8]);
s->idsp.idct_put(dest_cr + act_block_size, dct_linesize, (int16_t*)(*s->block32)[9]);
s->idsp.idct_put(dest_cb + act_block_size + dct_offset, dct_linesize, (int16_t*)(*s->block32)[10]);
s->idsp.idct_put(dest_cr + act_block_size + dct_offset, dct_linesize, (int16_t*)(*s->block32)[11]);
}
}
/* dct only in intra block */ /* dct only in intra block */
if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ else if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){
put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale);
put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale);
put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale);
...@@ -2202,7 +2231,8 @@ void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) ...@@ -2202,7 +2231,8 @@ void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h)
void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename
const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics const int linesize = s->current_picture.f->linesize[0]; //not s->linesize as this would be wrong for field pics
const int uvlinesize = s->current_picture.f->linesize[1]; const int uvlinesize = s->current_picture.f->linesize[1];
const int mb_size= 4 - s->avctx->lowres; const int width_of_mb = (4 + (s->avctx->bits_per_raw_sample > 8)) - s->avctx->lowres;
const int height_of_mb = 4 - s->avctx->lowres;
s->block_index[0]= s->b8_stride*(s->mb_y*2 ) - 2 + s->mb_x*2; s->block_index[0]= s->b8_stride*(s->mb_y*2 ) - 2 + s->mb_x*2;
s->block_index[1]= s->b8_stride*(s->mb_y*2 ) - 1 + s->mb_x*2; s->block_index[1]= s->b8_stride*(s->mb_y*2 ) - 1 + s->mb_x*2;
...@@ -2212,20 +2242,20 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename ...@@ -2212,20 +2242,20 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename
s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x - 1; s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x - 1;
//block_index is not used by mpeg2, so it is not affected by chroma_format //block_index is not used by mpeg2, so it is not affected by chroma_format
s->dest[0] = s->current_picture.f->data[0] + (int)((s->mb_x - 1U) << mb_size); s->dest[0] = s->current_picture.f->data[0] + (int)((s->mb_x - 1U) << width_of_mb);
s->dest[1] = s->current_picture.f->data[1] + (int)((s->mb_x - 1U) << (mb_size - s->chroma_x_shift)); s->dest[1] = s->current_picture.f->data[1] + (int)((s->mb_x - 1U) << (width_of_mb - s->chroma_x_shift));
s->dest[2] = s->current_picture.f->data[2] + (int)((s->mb_x - 1U) << (mb_size - s->chroma_x_shift)); s->dest[2] = s->current_picture.f->data[2] + (int)((s->mb_x - 1U) << (width_of_mb - s->chroma_x_shift));
if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME)) if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME))
{ {
if(s->picture_structure==PICT_FRAME){ if(s->picture_structure==PICT_FRAME){
s->dest[0] += s->mb_y * linesize << mb_size; s->dest[0] += s->mb_y * linesize << height_of_mb;
s->dest[1] += s->mb_y * uvlinesize << (mb_size - s->chroma_y_shift); s->dest[1] += s->mb_y * uvlinesize << (height_of_mb - s->chroma_y_shift);
s->dest[2] += s->mb_y * uvlinesize << (mb_size - s->chroma_y_shift); s->dest[2] += s->mb_y * uvlinesize << (height_of_mb - s->chroma_y_shift);
}else{ }else{
s->dest[0] += (s->mb_y>>1) * linesize << mb_size; s->dest[0] += (s->mb_y>>1) * linesize << height_of_mb;
s->dest[1] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); s->dest[1] += (s->mb_y>>1) * uvlinesize << (height_of_mb - s->chroma_y_shift);
s->dest[2] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); s->dest[2] += (s->mb_y>>1) * uvlinesize << (height_of_mb - s->chroma_y_shift);
av_assert1((s->mb_y&1) == (s->picture_structure == PICT_BOTTOM_FIELD)); av_assert1((s->mb_y&1) == (s->picture_structure == PICT_BOTTOM_FIELD));
} }
} }
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "mpegpicture.h" #include "mpegpicture.h"
#include "mpegvideodsp.h" #include "mpegvideodsp.h"
#include "mpegvideoencdsp.h" #include "mpegvideoencdsp.h"
#include "mpegvideodata.h"
#include "pixblockdsp.h" #include "pixblockdsp.h"
#include "put_bits.h" #include "put_bits.h"
#include "ratecontrol.h" #include "ratecontrol.h"
...@@ -71,6 +72,8 @@ ...@@ -71,6 +72,8 @@
#define SLICE_MAX_START_CODE 0x000001af #define SLICE_MAX_START_CODE 0x000001af
#define EXT_START_CODE 0x000001b5 #define EXT_START_CODE 0x000001b5
#define USER_START_CODE 0x000001b2 #define USER_START_CODE 0x000001b2
#define SLICE_START_CODE 0x000001b7
/** /**
* MpegEncContext. * MpegEncContext.
...@@ -378,6 +381,8 @@ typedef struct MpegEncContext { ...@@ -378,6 +381,8 @@ typedef struct MpegEncContext {
int custom_pcf; int custom_pcf;
/* MPEG-4 specific */ /* MPEG-4 specific */
int studio_profile;
int dct_precision;
///< number of bits to represent the fractional part of time (encoder only) ///< number of bits to represent the fractional part of time (encoder only)
int time_increment_bits; int time_increment_bits;
int last_time_base; int last_time_base;
...@@ -501,7 +506,10 @@ typedef struct MpegEncContext { ...@@ -501,7 +506,10 @@ typedef struct MpegEncContext {
int16_t (*block)[64]; ///< points to one of the following blocks int16_t (*block)[64]; ///< points to one of the following blocks
int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block
int (*decode_mb)(struct MpegEncContext *s, int16_t block[6][64]); // used by some codecs to avoid a switch() int (*decode_mb)(struct MpegEncContext *s, int16_t block[12][64]); // used by some codecs to avoid a switch()
int32_t (*block32)[12][64];
#define SLICE_OK 0 #define SLICE_OK 0
#define SLICE_ERROR -1 #define SLICE_ERROR -1
#define SLICE_END -2 ///<end marker found #define SLICE_END -2 ///<end marker found
...@@ -729,7 +737,8 @@ void ff_mpv_motion(MpegEncContext *s, ...@@ -729,7 +737,8 @@ void ff_mpv_motion(MpegEncContext *s,
qpel_mc_func (*qpix_op)[16]); qpel_mc_func (*qpix_op)[16]);
static inline void ff_update_block_index(MpegEncContext *s){ static inline void ff_update_block_index(MpegEncContext *s){
const int block_size= 8 >> s->avctx->lowres; const int bytes_per_pixel = 1 + (s->avctx->bits_per_raw_sample > 8);
const int block_size= (8*bytes_per_pixel) >> s->avctx->lowres;
s->block_index[0]+=2; s->block_index[0]+=2;
s->block_index[1]+=2; s->block_index[1]+=2;
...@@ -738,8 +747,8 @@ static inline void ff_update_block_index(MpegEncContext *s){ ...@@ -738,8 +747,8 @@ static inline void ff_update_block_index(MpegEncContext *s){
s->block_index[4]++; s->block_index[4]++;
s->block_index[5]++; s->block_index[5]++;
s->dest[0]+= 2*block_size; s->dest[0]+= 2*block_size;
s->dest[1]+= block_size; s->dest[1]+= (2 >> s->chroma_x_shift) * block_size;
s->dest[2]+= block_size; s->dest[2]+= (2 >> s->chroma_x_shift) * block_size;
} }
static inline int get_bits_diff(MpegEncContext *s){ static inline int get_bits_diff(MpegEncContext *s){
...@@ -751,4 +760,13 @@ static inline int get_bits_diff(MpegEncContext *s){ ...@@ -751,4 +760,13 @@ static inline int get_bits_diff(MpegEncContext *s){
return bits - last; return bits - last;
} }
static inline int mpeg_get_qscale(MpegEncContext *s)
{
int qscale = get_bits(&s->gb, 5);
if (s->q_scale_type)
return ff_mpeg2_non_linear_qscale[qscale];
else
return qscale << 1;
}
#endif /* AVCODEC_MPEGVIDEO_H */ #endif /* AVCODEC_MPEGVIDEO_H */
...@@ -123,6 +123,7 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, ...@@ -123,6 +123,7 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
} }
if (avctx->bits_per_raw_sample == 10 && if (avctx->bits_per_raw_sample == 10 &&
avctx->codec_id != AV_CODEC_ID_MPEG4 &&
(avctx->idct_algo == FF_IDCT_AUTO || (avctx->idct_algo == FF_IDCT_AUTO ||
avctx->idct_algo == FF_IDCT_SIMPLEAUTO || avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
avctx->idct_algo == FF_IDCT_SIMPLE)) { avctx->idct_algo == FF_IDCT_SIMPLE)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment