You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
avcodec/mjpegenc: Bypass the 2 pass encoding when optimal tables are not requested
This limits the bugs, speedloss and extra memory allocation to the case when optimal tables are needed. Fixes regressions with slice multi-threading Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
@@ -79,7 +79,7 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
|
|||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
m = av_malloc(sizeof(MJpegContext));
|
m = av_mallocz(sizeof(MJpegContext));
|
||||||
if (!m)
|
if (!m)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
@@ -117,7 +117,10 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
|
|||||||
m->huff_ncode = 0;
|
m->huff_ncode = 0;
|
||||||
s->mjpeg_ctx = m;
|
s->mjpeg_ctx = m;
|
||||||
|
|
||||||
return alloc_huffman(s);
|
if(s->huffman == HUFFMAN_TABLE_OPTIMAL)
|
||||||
|
return alloc_huffman(s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_cold void ff_mjpeg_encode_close(MpegEncContext *s)
|
av_cold void ff_mjpeg_encode_close(MpegEncContext *s)
|
||||||
@@ -224,7 +227,7 @@ static void ff_mjpeg_encode_coef(MJpegContext *s, uint8_t table_id, int val, int
|
|||||||
* @param block The block.
|
* @param block The block.
|
||||||
* @param n The block's index or number.
|
* @param n The block's index or number.
|
||||||
*/
|
*/
|
||||||
static void encode_block(MpegEncContext *s, int16_t *block, int n)
|
static void record_block(MpegEncContext *s, int16_t *block, int n)
|
||||||
{
|
{
|
||||||
int i, j, table_id;
|
int i, j, table_id;
|
||||||
int component, dc, last_index, val, run;
|
int component, dc, last_index, val, run;
|
||||||
@@ -267,36 +270,127 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n)
|
|||||||
ff_mjpeg_encode_code(m, table_id, 0);
|
ff_mjpeg_encode_code(m, table_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void encode_block(MpegEncContext *s, int16_t *block, int n)
|
||||||
|
{
|
||||||
|
int mant, nbits, code, i, j;
|
||||||
|
int component, dc, run, last_index, val;
|
||||||
|
MJpegContext *m = s->mjpeg_ctx;
|
||||||
|
uint8_t *huff_size_ac;
|
||||||
|
uint16_t *huff_code_ac;
|
||||||
|
|
||||||
|
/* DC coef */
|
||||||
|
component = (n <= 3 ? 0 : (n&1) + 1);
|
||||||
|
dc = block[0]; /* overflow is impossible */
|
||||||
|
val = dc - s->last_dc[component];
|
||||||
|
if (n < 4) {
|
||||||
|
ff_mjpeg_encode_dc(&s->pb, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance);
|
||||||
|
huff_size_ac = m->huff_size_ac_luminance;
|
||||||
|
huff_code_ac = m->huff_code_ac_luminance;
|
||||||
|
} else {
|
||||||
|
ff_mjpeg_encode_dc(&s->pb, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
|
||||||
|
huff_size_ac = m->huff_size_ac_chrominance;
|
||||||
|
huff_code_ac = m->huff_code_ac_chrominance;
|
||||||
|
}
|
||||||
|
s->last_dc[component] = dc;
|
||||||
|
|
||||||
|
/* AC coefs */
|
||||||
|
|
||||||
|
run = 0;
|
||||||
|
last_index = s->block_last_index[n];
|
||||||
|
for(i=1;i<=last_index;i++) {
|
||||||
|
j = s->intra_scantable.permutated[i];
|
||||||
|
val = block[j];
|
||||||
|
if (val == 0) {
|
||||||
|
run++;
|
||||||
|
} else {
|
||||||
|
while (run >= 16) {
|
||||||
|
put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
|
||||||
|
run -= 16;
|
||||||
|
}
|
||||||
|
mant = val;
|
||||||
|
if (val < 0) {
|
||||||
|
val = -val;
|
||||||
|
mant--;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbits= av_log2_16bit(val) + 1;
|
||||||
|
code = (run << 4) | nbits;
|
||||||
|
|
||||||
|
put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
|
||||||
|
|
||||||
|
put_sbits(&s->pb, nbits, mant);
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* output EOB only if not already 64 values */
|
||||||
|
if (last_index < 63 || run != 0)
|
||||||
|
put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
|
||||||
|
}
|
||||||
|
|
||||||
void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64])
|
void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (s->chroma_format == CHROMA_444) {
|
if (s->huffman == HUFFMAN_TABLE_OPTIMAL) {
|
||||||
encode_block(s, block[0], 0);
|
if (s->chroma_format == CHROMA_444) {
|
||||||
encode_block(s, block[2], 2);
|
record_block(s, block[0], 0);
|
||||||
encode_block(s, block[4], 4);
|
record_block(s, block[2], 2);
|
||||||
encode_block(s, block[8], 8);
|
record_block(s, block[4], 4);
|
||||||
encode_block(s, block[5], 5);
|
record_block(s, block[8], 8);
|
||||||
encode_block(s, block[9], 9);
|
record_block(s, block[5], 5);
|
||||||
|
record_block(s, block[9], 9);
|
||||||
|
|
||||||
if (16*s->mb_x+8 < s->width) {
|
if (16*s->mb_x+8 < s->width) {
|
||||||
encode_block(s, block[1], 1);
|
record_block(s, block[1], 1);
|
||||||
encode_block(s, block[3], 3);
|
record_block(s, block[3], 3);
|
||||||
encode_block(s, block[6], 6);
|
record_block(s, block[6], 6);
|
||||||
encode_block(s, block[10], 10);
|
record_block(s, block[10], 10);
|
||||||
encode_block(s, block[7], 7);
|
record_block(s, block[7], 7);
|
||||||
encode_block(s, block[11], 11);
|
record_block(s, block[11], 11);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(i=0;i<5;i++) {
|
||||||
|
record_block(s, block[i], i);
|
||||||
|
}
|
||||||
|
if (s->chroma_format == CHROMA_420) {
|
||||||
|
record_block(s, block[5], 5);
|
||||||
|
} else {
|
||||||
|
record_block(s, block[6], 6);
|
||||||
|
record_block(s, block[5], 5);
|
||||||
|
record_block(s, block[7], 7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(i=0;i<5;i++) {
|
if (s->chroma_format == CHROMA_444) {
|
||||||
encode_block(s, block[i], i);
|
encode_block(s, block[0], 0);
|
||||||
}
|
encode_block(s, block[2], 2);
|
||||||
if (s->chroma_format == CHROMA_420) {
|
encode_block(s, block[4], 4);
|
||||||
|
encode_block(s, block[8], 8);
|
||||||
encode_block(s, block[5], 5);
|
encode_block(s, block[5], 5);
|
||||||
|
encode_block(s, block[9], 9);
|
||||||
|
|
||||||
|
if (16*s->mb_x+8 < s->width) {
|
||||||
|
encode_block(s, block[1], 1);
|
||||||
|
encode_block(s, block[3], 3);
|
||||||
|
encode_block(s, block[6], 6);
|
||||||
|
encode_block(s, block[10], 10);
|
||||||
|
encode_block(s, block[7], 7);
|
||||||
|
encode_block(s, block[11], 11);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
encode_block(s, block[6], 6);
|
for(i=0;i<5;i++) {
|
||||||
encode_block(s, block[5], 5);
|
encode_block(s, block[i], i);
|
||||||
encode_block(s, block[7], 7);
|
}
|
||||||
|
if (s->chroma_format == CHROMA_420) {
|
||||||
|
encode_block(s, block[5], 5);
|
||||||
|
} else {
|
||||||
|
encode_block(s, block[6], 6);
|
||||||
|
encode_block(s, block[5], 5);
|
||||||
|
encode_block(s, block[7], 7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->i_tex_bits += get_bits_diff(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -480,7 +480,8 @@ static void ff_mjpeg_build_optimal_huffman(MJpegContext *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the complete JPEG frame.
|
* Writes the complete JPEG frame when optimal huffman tables are enabled,
|
||||||
|
* otherwise writes the stuffing.
|
||||||
*
|
*
|
||||||
* Header + values + stuffing.
|
* Header + values + stuffing.
|
||||||
*
|
*
|
||||||
@@ -508,11 +509,11 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s)
|
|||||||
s->intra_ac_vlc_last_length = m->uni_ac_vlc_len;
|
s->intra_ac_vlc_last_length = m->uni_ac_vlc_len;
|
||||||
s->intra_chroma_ac_vlc_length =
|
s->intra_chroma_ac_vlc_length =
|
||||||
s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len;
|
s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len;
|
||||||
}
|
|
||||||
|
|
||||||
ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
|
ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
|
||||||
s->pred, s->intra_matrix, s->chroma_intra_matrix);
|
s->pred, s->intra_matrix, s->chroma_intra_matrix);
|
||||||
ff_mjpeg_encode_picture_frame(s);
|
ff_mjpeg_encode_picture_frame(s);
|
||||||
|
}
|
||||||
|
|
||||||
ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100,
|
ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100,
|
||||||
put_bits_count(&s->pb) / 4 + 1000);
|
put_bits_count(&s->pb) / 4 + 1000);
|
||||||
|
@@ -3942,8 +3942,9 @@ static int encode_picture(MpegEncContext *s, int picture_number)
|
|||||||
s->last_bits= put_bits_count(&s->pb);
|
s->last_bits= put_bits_count(&s->pb);
|
||||||
switch(s->out_format) {
|
switch(s->out_format) {
|
||||||
case FMT_MJPEG:
|
case FMT_MJPEG:
|
||||||
/* The MJPEG headers are printed after the initial encoding so that the
|
if (CONFIG_MJPEG_ENCODER && s->huffman != HUFFMAN_TABLE_OPTIMAL)
|
||||||
* optimal huffman encoding can be found. */
|
ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
|
||||||
|
s->pred, s->intra_matrix, s->chroma_intra_matrix);
|
||||||
break;
|
break;
|
||||||
case FMT_H261:
|
case FMT_H261:
|
||||||
if (CONFIG_H261_ENCODER)
|
if (CONFIG_H261_ENCODER)
|
||||||
|
Reference in New Issue
Block a user