From 2eddfb2b13921af10d096e03f63ca98226a2a292 Mon Sep 17 00:00:00 2001 From: Brad Date: Tue, 29 Mar 2011 19:37:57 -0400 Subject: [PATCH 01/11] sndio bug fix Since the code already supports both little- and big-endian audio for recording, do not fail just because the endianness is not what we expect. Signed-off-by: Ronald S. Bultje --- libavdevice/sndio_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavdevice/sndio_common.c b/libavdevice/sndio_common.c index 60b7970051..56c37c76b7 100644 --- a/libavdevice/sndio_common.c +++ b/libavdevice/sndio_common.c @@ -64,7 +64,7 @@ av_cold int ff_sndio_open(AVFormatContext *s1, int is_output, goto fail; } - if (par.bits != 16 || par.sig != 1 || par.le != SIO_LE_NATIVE || + if (par.bits != 16 || par.sig != 1 || (is_output && (par.pchan != s->channels)) || (!is_output && (par.rchan != s->channels)) || (par.rate != s->sample_rate)) { From 8f0bd2c07d354d804b88229b621479cf0388c873 Mon Sep 17 00:00:00 2001 From: anatoly Date: Sun, 27 Mar 2011 22:16:23 +0200 Subject: [PATCH 02/11] Support reference picture defined by bitmask in MJPEG's SOS decoder Signed-off-by: Anton Khirnov --- libavcodec/mjpegbdec.c | 2 +- libavcodec/mjpegdec.c | 84 +++++++++++++++++++++++++++++++++++------- libavcodec/mjpegdec.h | 3 +- 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index 2337f77eb1..f3366ffd6f 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -113,7 +113,7 @@ read_header: init_get_bits(&s->gb, buf_ptr+sos_offs, field_size*8); s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16)); s->start_code = SOS; - ff_mjpeg_decode_sos(s); + ff_mjpeg_decode_sos(s, NULL, NULL); } if (s->interlaced) { diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 156563d723..a230fa9529 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -771,10 +771,32 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point return 0; } -static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, int Al){ +static av_always_inline void mjpeg_copy_block(uint8_t *dst, const uint8_t *src, + int linesize, int lowres) +{ + switch (lowres) { + case 0: copy_block8(dst, src, linesize, linesize, 8); + break; + case 1: copy_block4(dst, src, linesize, linesize, 4); + break; + case 2: copy_block2(dst, src, linesize, linesize, 2); + break; + case 3: *dst = *src; + break; + } +} + +static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, int Al, + const uint8_t *mb_bitmask, const AVFrame *reference){ int i, mb_x, mb_y; uint8_t* data[MAX_COMPONENTS]; + const uint8_t *reference_data[MAX_COMPONENTS]; int linesize[MAX_COMPONENTS]; + GetBitContext mb_bitmask_gb; + + if (mb_bitmask) { + init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width*s->mb_height); + } if(s->flipped && s->avctx->flags & CODEC_FLAG_EMU_EDGE) { av_log(s->avctx, AV_LOG_ERROR, "Can not flip image with CODEC_FLAG_EMU_EDGE set!\n"); @@ -783,23 +805,29 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, i for(i=0; i < nb_components; i++) { int c = s->comp_index[i]; data[c] = s->picture.data[c]; + reference_data[c] = reference ? reference->data[c] : NULL; linesize[c]=s->linesize[c]; s->coefs_finished[c] |= 1; if(s->flipped) { //picture should be flipped upside-down for this codec - data[c] += (linesize[c] * (s->v_scount[i] * (8 * s->mb_height -((s->height/s->v_max)&7)) - 1 )); + int offset = (linesize[c] * (s->v_scount[i] * (8 * s->mb_height -((s->height/s->v_max)&7)) - 1 )); + data[c] += offset; + reference_data[c] += offset; linesize[c] *= -1; } } for(mb_y = 0; mb_y < s->mb_height; mb_y++) { for(mb_x = 0; mb_x < s->mb_width; mb_x++) { + const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb); + if (s->restart_interval && !s->restart_count) s->restart_count = s->restart_interval; for(i=0;inb_blocks[i]; c = s->comp_index[i]; h = s->h_scount[i]; @@ -807,12 +835,16 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, i x = 0; y = 0; for(j=0;j> s->avctx->lowres); + block_offset = (((linesize[c] * (v * mb_y + y) * 8) + + (h * mb_x + x) * 8) >> s->avctx->lowres); + if(s->interlaced && s->bottom_field) - ptr += linesize[c] >> 1; + block_offset += linesize[c] >> 1; + ptr = data[c] + block_offset; if(!s->progressive) { + if (copy_mb) { + mjpeg_copy_block(ptr, reference_data[c] + block_offset, linesize[c], s->avctx->lowres); + } else { s->dsp.clear_block(s->block); if(decode_block(s, s->block, i, s->dc_index[i], s->ac_index[i], @@ -821,6 +853,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, i return -1; } s->dsp.idct_put(ptr, linesize[c], s->block); + } } else { int block_idx = s->block_stride[c] * (v * mb_y + y) + (h * mb_x + x); DCTELEM *block = s->blocks[c][block_idx]; @@ -851,29 +884,43 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, i return 0; } -static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, int se, int Ah, int Al){ +static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, int se, int Ah, int Al, + const uint8_t *mb_bitmask, const AVFrame *reference){ int mb_x, mb_y; int EOBRUN = 0; int c = s->comp_index[0]; uint8_t* data = s->picture.data[c]; + const uint8_t *reference_data = reference ? reference->data[c] : NULL; int linesize = s->linesize[c]; int last_scan = 0; int16_t *quant_matrix = s->quant_matrixes[ s->quant_index[c] ]; + GetBitContext mb_bitmask_gb; + + if (mb_bitmask) { + init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width*s->mb_height); + } if(!Al) { s->coefs_finished[c] |= (1LL<<(se+1))-(1LL<coefs_finished[c]; } - if(s->interlaced && s->bottom_field) - data += linesize >> 1; + if(s->interlaced && s->bottom_field) { + int offset = linesize >> 1; + data += offset; + reference_data += offset; + } for(mb_y = 0; mb_y < s->mb_height; mb_y++) { - uint8_t *ptr = data + (mb_y*linesize*8 >> s->avctx->lowres); + int block_offset = (mb_y*linesize*8 >> s->avctx->lowres); + uint8_t *ptr = data + block_offset; int block_idx = mb_y * s->block_stride[c]; DCTELEM (*block)[64] = &s->blocks[c][block_idx]; uint8_t *last_nnz = &s->last_nnz[c][block_idx]; for(mb_x = 0; mb_x < s->mb_width; mb_x++, block++, last_nnz++) { + const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb); + + if (!copy_mb) { int ret; if(Ah) ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0], @@ -885,16 +932,23 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, int s av_log(s->avctx, AV_LOG_ERROR, "error y=%d x=%d\n", mb_y, mb_x); return -1; } + } + if(last_scan) { + if (copy_mb) { + mjpeg_copy_block(ptr, reference_data + block_offset, linesize, s->avctx->lowres); + } else { s->dsp.idct_put(ptr, linesize, *block); ptr += 8 >> s->avctx->lowres; + } } } } return 0; } -int ff_mjpeg_decode_sos(MJpegDecodeContext *s) +int ff_mjpeg_decode_sos(MJpegDecodeContext *s, + const uint8_t *mb_bitmask, const AVFrame *reference) { int len, nb_components, i, h, v, predictor, point_transform; int index, id; @@ -996,10 +1050,12 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s) } }else{ if(s->progressive && predictor) { - if(mjpeg_decode_scan_progressive_ac(s, predictor, ilv, prev_shift, point_transform) < 0) + if(mjpeg_decode_scan_progressive_ac(s, predictor, ilv, prev_shift, point_transform, + mb_bitmask, reference) < 0) return -1; } else { - if(mjpeg_decode_scan(s, nb_components, prev_shift, point_transform) < 0) + if(mjpeg_decode_scan(s, nb_components, prev_shift, point_transform, + mb_bitmask, reference) < 0) return -1; } } @@ -1466,7 +1522,7 @@ eoi_parser: av_log(avctx, AV_LOG_WARNING, "Can not process SOS before SOF, skipping\n"); break; } - ff_mjpeg_decode_sos(s); + ff_mjpeg_decode_sos(s, NULL, NULL); /* buggy avid puts EOI every 10-20th frame */ /* if restart period is over process EOI */ if ((s->buggy_avid && !s->interlaced) || s->restart_interval) diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index a190fdadf8..63bcb93046 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -115,6 +115,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, int ff_mjpeg_decode_dqt(MJpegDecodeContext *s); int ff_mjpeg_decode_dht(MJpegDecodeContext *s); int ff_mjpeg_decode_sof(MJpegDecodeContext *s); -int ff_mjpeg_decode_sos(MJpegDecodeContext *s); +int ff_mjpeg_decode_sos(MJpegDecodeContext *s, + const uint8_t *mb_bitmask, const AVFrame *reference); #endif /* AVCODEC_MJPEGDEC_H */ From f16055eedf7999bb0c754dfde47d8c726b94c847 Mon Sep 17 00:00:00 2001 From: anatoly Date: Sun, 27 Mar 2011 22:16:24 +0200 Subject: [PATCH 03/11] Move MJPEG's input buffer preprocessing in separate public function Signed-off-by: Anton Khirnov --- libavcodec/mjpegdec.c | 84 ++++++++++++++++++++++++++----------------- libavcodec/mjpegdec.h | 3 ++ 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a230fa9529..da83cdfe2e 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1316,43 +1316,26 @@ found: return val; } -int ff_mjpeg_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) +int ff_mjpeg_find_marker(MJpegDecodeContext *s, + const uint8_t **buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size) { - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - MJpegDecodeContext *s = avctx->priv_data; - const uint8_t *buf_end, *buf_ptr; int start_code; - AVFrame *picture = data; + start_code = find_marker(buf_ptr, buf_end); - s->got_picture = 0; // picture from previous image can not be reused - buf_ptr = buf; - buf_end = buf + buf_size; - while (buf_ptr < buf_end) { - /* find start next marker */ - start_code = find_marker(&buf_ptr, buf_end); - { - /* EOF */ - if (start_code < 0) { - goto the_end; - } else { - av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr); - - if ((buf_end - buf_ptr) > s->buffer_size) + if ((buf_end - *buf_ptr) > s->buffer_size) { av_free(s->buffer); - s->buffer_size = buf_end-buf_ptr; + s->buffer_size = buf_end - *buf_ptr; s->buffer = av_malloc(s->buffer_size + FF_INPUT_BUFFER_PADDING_SIZE); - av_log(avctx, AV_LOG_DEBUG, "buffer too small, expanding to %d bytes\n", + av_log(s->avctx, AV_LOG_DEBUG, "buffer too small, expanding to %d bytes\n", s->buffer_size); } /* unescape buffer of SOS, use special treatment for JPEG-LS */ if (start_code == SOS && !s->ls) { - const uint8_t *src = buf_ptr; + const uint8_t *src = *buf_ptr; uint8_t *dst = s->buffer; while (srccodec_id != CODEC_ID_THP) + if (s->avctx->codec_id != CODEC_ID_THP) { if (x == 0xff) { while (src < buf_end && x == 0xff) @@ -1373,13 +1356,14 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, } } } - init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8); + *unescaped_buf_ptr = s->buffer; + *unescaped_buf_size = dst - s->buffer; - av_log(avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", - (buf_end - buf_ptr) - (dst - s->buffer)); + av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", + (buf_end - *buf_ptr) - (dst - s->buffer)); } else if(start_code == SOS && s->ls){ - const uint8_t *src = buf_ptr; + const uint8_t *src = *buf_ptr; uint8_t *dst = s->buffer; int bit_count = 0; int t = 0, b = 0; @@ -1415,10 +1399,46 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, } flush_put_bits(&pb); - init_get_bits(&s->gb, dst, bit_count); + *unescaped_buf_ptr = dst; + *unescaped_buf_size = (bit_count + 7) >> 3; } else - init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8); + { + *unescaped_buf_ptr = *buf_ptr; + *unescaped_buf_size = buf_end - *buf_ptr; + } + + return start_code; +} + +int ff_mjpeg_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MJpegDecodeContext *s = avctx->priv_data; + const uint8_t *buf_end, *buf_ptr; + const uint8_t *unescaped_buf_ptr; + int unescaped_buf_size; + int start_code; + AVFrame *picture = data; + + s->got_picture = 0; // picture from previous image can not be reused + buf_ptr = buf; + buf_end = buf + buf_size; + while (buf_ptr < buf_end) { + /* find start next marker */ + start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end, + &unescaped_buf_ptr, &unescaped_buf_size); + { + /* EOF */ + if (start_code < 0) { + goto the_end; + } else { + av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr); + + init_get_bits(&s->gb, unescaped_buf_ptr, unescaped_buf_size*8); s->start_code = start_code; if(s->avctx->debug & FF_DEBUG_STARTCODE){ diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index 63bcb93046..72fe6fa088 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -117,5 +117,8 @@ int ff_mjpeg_decode_dht(MJpegDecodeContext *s); int ff_mjpeg_decode_sof(MJpegDecodeContext *s); int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, const AVFrame *reference); +int ff_mjpeg_find_marker(MJpegDecodeContext *s, + const uint8_t **buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size); #endif /* AVCODEC_MJPEGDEC_H */ From e0e3b8b297bae5144f23fd4b46a1309857040b63 Mon Sep 17 00:00:00 2001 From: anatoly Date: Sun, 27 Mar 2011 22:16:25 +0200 Subject: [PATCH 04/11] Add support for picture_ptr field in MJpegDecodeContext Signed-off-by: Anton Khirnov --- libavcodec/jpeglsdec.c | 18 +++++++++--------- libavcodec/mjpegbdec.c | 2 +- libavcodec/mjpegdec.c | 36 +++++++++++++++++++----------------- libavcodec/mjpegdec.h | 1 + 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 2ee719b374..adaa0a3d96 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -262,9 +262,9 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transfor JLSState *state; int off = 0, stride = 1, width, shift; - zero = av_mallocz(s->picture.linesize[0]); + zero = av_mallocz(s->picture_ptr->linesize[0]); last = zero; - cur = s->picture.data[0]; + cur = s->picture_ptr->data[0]; state = av_mallocz(sizeof(JLSState)); /* initialize JPEG-LS state from JPEG parameters */ @@ -299,7 +299,7 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transfor t = *((uint16_t*)last); } last = cur; - cur += s->picture.linesize[0]; + cur += s->picture_ptr->linesize[0]; if (s->restart_interval && !--s->restart_count) { align_get_bits(&s->gb); @@ -309,7 +309,7 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transfor } else if(ilv == 1) { /* line interleaving */ int j; int Rc[3] = {0, 0, 0}; - memset(cur, 0, s->picture.linesize[0]); + memset(cur, 0, s->picture_ptr->linesize[0]); width = s->width * 3; for(i = 0; i < s->height; i++) { for(j = 0; j < 3; j++) { @@ -322,7 +322,7 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transfor } } last = cur; - cur += s->picture.linesize[0]; + cur += s->picture_ptr->linesize[0]; } } else if(ilv == 2) { /* sample interleaving */ av_log(s->avctx, AV_LOG_ERROR, "Sample interleaved images are not supported.\n"); @@ -337,22 +337,22 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transfor w = s->width * s->nb_components; if(s->bits <= 8){ - uint8_t *src = s->picture.data[0]; + uint8_t *src = s->picture_ptr->data[0]; for(i = 0; i < s->height; i++){ for(x = off; x < w; x+= stride){ src[x] <<= shift; } - src += s->picture.linesize[0]; + src += s->picture_ptr->linesize[0]; } }else{ - uint16_t *src = (uint16_t*) s->picture.data[0]; + uint16_t *src = (uint16_t*) s->picture_ptr->data[0]; for(i = 0; i < s->height; i++){ for(x = 0; x < w; x++){ src[x] <<= shift; } - src += s->picture.linesize[0]/2; + src += s->picture_ptr->linesize[0]/2; } } } diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index f3366ffd6f..837304ea74 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -129,7 +129,7 @@ read_header: //XXX FIXME factorize, this looks very similar to the EOI code - *picture= s->picture; + *picture= *s->picture_ptr; *data_size = sizeof(AVFrame); if(!s->lossless){ diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index da83cdfe2e..6f29e466eb 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -81,6 +81,9 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; + if (!s->picture_ptr) + s->picture_ptr = &s->picture; + s->avctx = avctx; dsputil_init(&s->dsp, avctx); ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); @@ -282,8 +285,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) s->height < ((s->org_height * 3) / 4)) { s->interlaced = 1; s->bottom_field = s->interlace_polarity; - s->picture.interlaced_frame = 1; - s->picture.top_field_first = !s->interlace_polarity; + s->picture_ptr->interlaced_frame = 1; + s->picture_ptr->top_field_first = !s->interlace_polarity; height *= 2; } @@ -342,20 +345,19 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) s->avctx->pix_fmt = PIX_FMT_GRAY16; } - if(s->picture.data[0]) - s->avctx->release_buffer(s->avctx, &s->picture); + if(s->picture_ptr->data[0]) + s->avctx->release_buffer(s->avctx, s->picture_ptr); - s->picture.reference= 0; - if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){ + if(s->avctx->get_buffer(s->avctx, s->picture_ptr) < 0){ av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } - s->picture.pict_type= FF_I_TYPE; - s->picture.key_frame= 1; + s->picture_ptr->pict_type= FF_I_TYPE; + s->picture_ptr->key_frame= 1; s->got_picture = 1; for(i=0; i<3; i++){ - s->linesize[i]= s->picture.linesize[i] << s->interlaced; + s->linesize[i]= s->picture_ptr->linesize[i] << s->interlaced; } // printf("%d %d %d %d %d %d\n", s->width, s->height, s->linesize[0], s->linesize[1], s->interlaced, s->avctx->height); @@ -635,7 +637,7 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point } for(mb_y = 0; mb_y < s->mb_height; mb_y++) { const int modified_predictor= mb_y ? predictor : 1; - uint8_t *ptr = s->picture.data[0] + (linesize * mb_y); + uint8_t *ptr = s->picture_ptr->data[0] + (linesize * mb_y); if (s->interlaced && s->bottom_field) ptr += linesize >> 1; @@ -712,7 +714,7 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point for(j=0; jpicture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap if(y==0 && mb_y==0){ if(x==0 && mb_x==0){ pred= 128 << point_transform; @@ -752,7 +754,7 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point for(j=0; jpicture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); if (++x == h) { @@ -804,7 +806,7 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, i } for(i=0; i < nb_components; i++) { int c = s->comp_index[i]; - data[c] = s->picture.data[c]; + data[c] = s->picture_ptr->data[c]; reference_data[c] = reference ? reference->data[c] : NULL; linesize[c]=s->linesize[c]; s->coefs_finished[c] |= 1; @@ -889,7 +891,7 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, int s int mb_x, mb_y; int EOBRUN = 0; int c = s->comp_index[0]; - uint8_t* data = s->picture.data[c]; + uint8_t* data = s->picture_ptr->data[c]; const uint8_t *reference_data = reference ? reference->data[c] : NULL; int linesize = s->linesize[c]; int last_scan = 0; @@ -1521,7 +1523,7 @@ eoi_parser: if (s->bottom_field == !s->interlace_polarity) goto not_the_end; } - *picture = s->picture; + *picture = *s->picture_ptr; *data_size = sizeof(AVFrame); if(!s->lossless){ @@ -1593,8 +1595,8 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) MJpegDecodeContext *s = avctx->priv_data; int i, j; - if (s->picture.data[0]) - avctx->release_buffer(avctx, &s->picture); + if (s->picture_ptr && s->picture_ptr->data[0]) + avctx->release_buffer(avctx, s->picture_ptr); av_free(s->buffer); av_free(s->qscale_table); diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h index 72fe6fa088..52c256ee2f 100644 --- a/libavcodec/mjpegdec.h +++ b/libavcodec/mjpegdec.h @@ -81,6 +81,7 @@ typedef struct MJpegDecodeContext { int quant_index[4]; /* quant table index for each component */ int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */ AVFrame picture; /* picture structure */ + AVFrame *picture_ptr; /* pointer to picture structure */ int got_picture; ///< we found a SOF and picture is valid, too. int linesize[MAX_COMPONENTS]; ///< linesize << interlaced int8_t *qscale_table; From ce02f9becfc2e89bf552a86303b00d0b36323cdf Mon Sep 17 00:00:00 2001 From: anatoly Date: Mon, 28 Mar 2011 20:02:19 +0400 Subject: [PATCH 05/11] Add MxPEG decoder Signed-off-by: Anton Khirnov --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/mxpegdec.c | 340 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- 6 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 libavcodec/mxpegdec.c diff --git a/Changelog b/Changelog index 9fd22fe361..ec09c280a4 100644 --- a/Changelog +++ b/Changelog @@ -82,6 +82,7 @@ version : - sndio support for playback and record - Linux framebuffer input device added - Chronomaster DFA decoder +- Mobotix MxPEG decoder version 0.6: diff --git a/doc/general.texi b/doc/general.texi index 7d5f082477..5d66e42b6b 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -443,6 +443,7 @@ following image formats are supported: @item Miro VideoXL @tab @tab X @tab fourcc: VIXL @item MJPEG (Motion JPEG) @tab X @tab X +@item Mobotix MxPEG video @tab @tab X @item Motion Pixels video @tab @tab X @item MPEG-1 video @tab X @tab X @item MPEG-1/2 video XvMC (X-Video Motion Compensation) @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 4cb61ca21e..2dea2036ad 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -271,6 +271,7 @@ OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4.o msmpeg4data.o h263dec.o \ OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o +OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o OBJS-$(CONFIG_NELLYMOSER_DECODER) += nellymoserdec.o nellymoser.o OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 9aa29b7e3c..7636392d48 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -153,6 +153,7 @@ void avcodec_register_all(void) REGISTER_DECODER (MSRLE, msrle); REGISTER_DECODER (MSVIDEO1, msvideo1); REGISTER_DECODER (MSZH, mszh); + REGISTER_DECODER (MXPEG, mxpeg); REGISTER_DECODER (NUV, nuv); REGISTER_ENCDEC (PAM, pam); REGISTER_ENCDEC (PBM, pbm); diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c new file mode 100644 index 0000000000..7d6f759333 --- /dev/null +++ b/libavcodec/mxpegdec.c @@ -0,0 +1,340 @@ +/* + * MxPEG decoder + * Copyright (c) 2011 Anatoly Nenashev + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +/** + * @file + * MxPEG decoder + */ + +#include "mjpeg.h" +#include "mjpegdec.h" + +typedef struct MXpegDecodeContext { + MJpegDecodeContext jpg; + AVFrame picture[2]; /* pictures array */ + int picture_index; /* index of current picture */ + int got_sof_data; /* true if SOF data successfully parsed */ + int got_mxm_bitmask; /* true if MXM bitmask available */ + uint8_t *mxm_bitmask; /* bitmask buffer */ + unsigned bitmask_size; /* size of bitmask */ + int has_complete_frame; /* true if has complete frame */ + uint8_t *completion_bitmask; /* completion bitmask of macroblocks */ + unsigned mb_width, mb_height; /* size of picture in MB's from MXM header */ +} MXpegDecodeContext; + +static av_cold int mxpeg_decode_init(AVCodecContext *avctx) +{ + MXpegDecodeContext *s = avctx->priv_data; + + s->picture[0].reference = s->picture[1].reference = 3; + s->jpg.picture_ptr = &s->picture[0]; + ff_mjpeg_decode_init(avctx); + + return 0; +} + +static int mxpeg_decode_app(MXpegDecodeContext *s, + const uint8_t *buf_ptr, int buf_size) +{ + int len; + if (buf_size < 2) + return 0; + len = AV_RB16(buf_ptr); + skip_bits(&s->jpg.gb, 8*FFMIN(len,buf_size)); + + return 0; +} + +static int mxpeg_decode_mxm(MXpegDecodeContext *s, + const uint8_t *buf_ptr, int buf_size) +{ + unsigned bitmask_size, mb_count; + int i; + + s->mb_width = AV_RL16(buf_ptr+4); + s->mb_height = AV_RL16(buf_ptr+6); + mb_count = s->mb_width * s->mb_height; + + bitmask_size = (mb_count + 7) >> 3; + if (bitmask_size > buf_size - 12) { + av_log(s->jpg.avctx, AV_LOG_ERROR, + "MXM bitmask is not complete\n"); + return AVERROR(EINVAL); + } + + if (s->bitmask_size != bitmask_size) { + av_freep(&s->mxm_bitmask); + s->mxm_bitmask = av_malloc(bitmask_size); + if (!s->mxm_bitmask) { + av_log(s->jpg.avctx, AV_LOG_ERROR, + "MXM bitmask memory allocation error\n"); + return AVERROR(ENOMEM); + } + + av_freep(&s->completion_bitmask); + s->completion_bitmask = av_mallocz(bitmask_size); + if (!s->completion_bitmask) { + av_log(s->jpg.avctx, AV_LOG_ERROR, + "Completion bitmask memory allocation error\n"); + return AVERROR(ENOMEM); + } + + s->bitmask_size = bitmask_size; + } + + memcpy(s->mxm_bitmask, buf_ptr + 12, bitmask_size); + s->got_mxm_bitmask = 1; + + if (!s->has_complete_frame) { + uint8_t completion_check = 0xFF; + for (i = 0; i < bitmask_size; ++i) { + s->completion_bitmask[i] |= s->mxm_bitmask[i]; + completion_check &= s->completion_bitmask[i]; + } + s->has_complete_frame = !(completion_check ^ 0xFF); + } + + return 0; +} + +static int mxpeg_decode_com(MXpegDecodeContext *s, + const uint8_t *buf_ptr, int buf_size) +{ + int len, ret = 0; + if (buf_size < 2) + return 0; + len = AV_RB16(buf_ptr); + if (len > 14 && len <= buf_size && !strncmp(buf_ptr + 2, "MXM", 3)) { + ret = mxpeg_decode_mxm(s, buf_ptr + 2, len - 2); + } + skip_bits(&s->jpg.gb, 8*FFMIN(len,buf_size)); + + return ret; +} + +static int mxpeg_check_dimensions(MXpegDecodeContext *s, MJpegDecodeContext *jpg, + AVFrame *reference_ptr) +{ + if ((jpg->width + 0x0F)>>4 != s->mb_width || + (jpg->height + 0x0F)>>4 != s->mb_height) { + av_log(jpg->avctx, AV_LOG_ERROR, + "Picture dimensions stored in SOF and MXM mismatch\n"); + return AVERROR(EINVAL); + } + + if (reference_ptr->data[0]) { + int i; + for (i = 0; i < MAX_COMPONENTS; ++i) { + if ( (!reference_ptr->data[i] ^ !jpg->picture_ptr->data[i]) || + reference_ptr->linesize[i] != jpg->picture_ptr->linesize[i]) { + av_log(jpg->avctx, AV_LOG_ERROR, + "Dimensions of current and reference picture mismatch\n"); + return AVERROR(EINVAL); + } + } + } + + return 0; +} + +static int mxpeg_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MXpegDecodeContext *s = avctx->priv_data; + MJpegDecodeContext *jpg = &s->jpg; + const uint8_t *buf_end, *buf_ptr; + const uint8_t *unescaped_buf_ptr; + int unescaped_buf_size; + int start_code; + AVFrame *picture = data; + int ret; + + buf_ptr = buf; + buf_end = buf + buf_size; + jpg->got_picture = 0; + s->got_mxm_bitmask = 0; + while (buf_ptr < buf_end) { + start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, buf_end, + &unescaped_buf_ptr, &unescaped_buf_size); + if (start_code < 0) + goto the_end; + { + init_get_bits(&jpg->gb, unescaped_buf_ptr, unescaped_buf_size*8); + + if (start_code >= APP0 && start_code <= APP15) { + mxpeg_decode_app(s, unescaped_buf_ptr, unescaped_buf_size); + } + + switch (start_code) { + case SOI: + if (jpg->got_picture) //emulating EOI + goto the_end; + break; + case EOI: + goto the_end; + case DQT: + ret = ff_mjpeg_decode_dqt(jpg); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "quantization table decode error\n"); + return ret; + } + break; + case DHT: + ret = ff_mjpeg_decode_dht(jpg); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "huffman table decode error\n"); + return ret; + } + break; + case COM: + ret = mxpeg_decode_com(s, unescaped_buf_ptr, + unescaped_buf_size); + if (ret < 0) + return ret; + break; + case SOF0: + s->got_sof_data = 0; + ret = ff_mjpeg_decode_sof(jpg); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "SOF data decode error\n"); + return ret; + } + if (jpg->interlaced) { + av_log(avctx, AV_LOG_ERROR, + "Interlaced mode not supported in MxPEG\n"); + return AVERROR(EINVAL); + } + s->got_sof_data = 1; + break; + case SOS: + if (!s->got_sof_data) { + av_log(avctx, AV_LOG_WARNING, + "Can not process SOS without SOF data, skipping\n"); + break; + } + if (!jpg->got_picture) { + if (jpg->first_picture) { + av_log(avctx, AV_LOG_WARNING, + "First picture has no SOF, skipping\n"); + break; + } + if (!s->got_mxm_bitmask){ + av_log(avctx, AV_LOG_WARNING, + "Non-key frame has no MXM, skipping\n"); + break; + } + /* use stored SOF data to allocate current picture */ + if (jpg->picture_ptr->data[0]) + avctx->release_buffer(avctx, jpg->picture_ptr); + if (avctx->get_buffer(avctx, jpg->picture_ptr) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return AVERROR(ENOMEM); + } + jpg->picture_ptr->pict_type = FF_P_TYPE; + jpg->picture_ptr->key_frame = 0; + jpg->got_picture = 1; + } else { + jpg->picture_ptr->pict_type = FF_I_TYPE; + jpg->picture_ptr->key_frame = 1; + } + + if (s->got_mxm_bitmask) { + AVFrame *reference_ptr = &s->picture[s->picture_index ^ 1]; + if (mxpeg_check_dimensions(s, jpg, reference_ptr) < 0) + break; + + /* allocate dummy reference picture if needed */ + if (!reference_ptr->data[0] && + avctx->get_buffer(avctx, reference_ptr) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return AVERROR(ENOMEM); + } + + ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, reference_ptr); + } else { + ff_mjpeg_decode_sos(jpg, NULL, NULL); + } + + break; + } + + buf_ptr += (get_bits_count(&jpg->gb)+7) >> 3; + } + + } + +the_end: + if (jpg->got_picture) { + *data_size = sizeof(AVFrame); + *picture = *jpg->picture_ptr; + s->picture_index ^= 1; + jpg->picture_ptr = &s->picture[s->picture_index]; + + if (!s->has_complete_frame) { + if (!s->got_mxm_bitmask) + s->has_complete_frame = 1; + else + *data_size = 0; + } + } + + return buf_ptr - buf; +} + +static av_cold int mxpeg_decode_end(AVCodecContext *avctx) +{ + MXpegDecodeContext *s = avctx->priv_data; + MJpegDecodeContext *jpg = &s->jpg; + int i; + + jpg->picture_ptr = NULL; + ff_mjpeg_decode_end(avctx); + + for (i = 0; i < 2; ++i) { + if (s->picture[i].data[0]) + avctx->release_buffer(avctx, &s->picture[i]); + } + + av_freep(&s->mxm_bitmask); + av_freep(&s->completion_bitmask); + + return 0; +} + +AVCodec ff_mxpeg_decoder = { + .name = "mxpeg", + .long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_MXPEG, + .priv_data_size = sizeof(MXpegDecodeContext), + .init = mxpeg_decode_init, + .close = mxpeg_decode_end, + .decode = mxpeg_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3 +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a1c8365e5c..5aa0b82c45 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 52 -#define LIBAVCODEC_VERSION_MINOR 116 +#define LIBAVCODEC_VERSION_MINOR 117 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 4c4427a75da1cbb81f3097e0a0fbd6755516bc0d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 17 Mar 2011 12:56:25 +0100 Subject: [PATCH 06/11] avio: make init_checksum() internal. --- libavformat/avio.h | 7 ++++--- libavformat/avio_internal.h | 3 +++ libavformat/aviobuf.c | 8 +++++++- libavformat/nutdec.c | 4 ++-- libavformat/nutenc.c | 7 ++++--- libavformat/oggenc.c | 2 +- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index 07a893e312..bce2fc9682 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -451,6 +451,10 @@ attribute_deprecated int url_ferror(AVIOContext *s); attribute_deprecated int udp_set_remote_url(URLContext *h, const char *uri); attribute_deprecated int udp_get_local_port(URLContext *h); + +attribute_deprecated void init_checksum(AVIOContext *s, + unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), + unsigned long checksum); #endif AVIOContext *avio_alloc_context( @@ -674,9 +678,6 @@ int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len); unsigned long get_checksum(AVIOContext *s); -void init_checksum(AVIOContext *s, - unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), - unsigned long checksum); #if FF_API_UDP_GET_FILE int udp_get_file_handle(URLContext *h); diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 6eee947383..c50514d833 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -74,5 +74,8 @@ int64_t ffio_read_seek (AVIOContext *h, int stream_index, int ff_udp_set_remote_url(URLContext *h, const char *uri); int ff_udp_get_local_port(URLContext *h); +void ffio_init_checksum(AVIOContext *s, + unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), + unsigned long checksum); #endif // AVFORMAT_AVIO_INTERNAL_H diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index bb417e0506..7399905e89 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -406,6 +406,12 @@ int64_t av_url_read_fseek(AVIOContext *s, int stream_index, { return ffio_read_seek(s, stream_index, timestamp, flags); } +void init_checksum(AVIOContext *s, + unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), + unsigned long checksum) +{ + ffio_init_checksum(s, update_checksum, checksum); +} #endif int avio_put_str(AVIOContext *s, const char *str) @@ -555,7 +561,7 @@ unsigned long get_checksum(AVIOContext *s) return s->checksum; } -void init_checksum(AVIOContext *s, +void ffio_init_checksum(AVIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum) { diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c index 0968faf39c..1191962b50 100644 --- a/libavformat/nutdec.c +++ b/libavformat/nutdec.c @@ -104,14 +104,14 @@ static int get_packetheader(NUTContext *nut, AVIOContext *bc, int calculate_chec startcode= av_be2ne64(startcode); startcode= ff_crc04C11DB7_update(0, (uint8_t*)&startcode, 8); - init_checksum(bc, ff_crc04C11DB7_update, startcode); + ffio_init_checksum(bc, ff_crc04C11DB7_update, startcode); size= ffio_read_varlen(bc); if(size > 4096) avio_rb32(bc); if(get_checksum(bc) && size > 4096) return -1; - init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0); + ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0); return size; } diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 89cfb97381..8a2a6faba1 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -24,6 +24,7 @@ #include "libavcodec/mpegaudiodata.h" #include "nut.h" #include "internal.h" +#include "avio_internal.h" static int find_expected_header(AVCodecContext *c, int size, int key_frame, uint8_t out[64]){ int sample_rate= c->sample_rate; @@ -284,14 +285,14 @@ static void put_packet(NUTContext *nut, AVIOContext *bc, AVIOContext *dyn_bc, in int forw_ptr= dyn_size + 4*calculate_checksum; if(forw_ptr > 4096) - init_checksum(bc, ff_crc04C11DB7_update, 0); + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_wb64(bc, startcode); ff_put_v(bc, forw_ptr); if(forw_ptr > 4096) avio_wl32(bc, get_checksum(bc)); if(calculate_checksum) - init_checksum(bc, ff_crc04C11DB7_update, 0); + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_write(bc, dyn_buf, dyn_size); if(calculate_checksum) avio_wl32(bc, get_checksum(bc)); @@ -806,7 +807,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt){ needed_flags= get_needed_flags(nut, nus, fc, pkt); header_idx= fc->header_idx; - init_checksum(bc, ff_crc04C11DB7_update, 0); + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_w8(bc, frame_code); if(flags & FLAG_CODED){ ff_put_v(bc, (flags^needed_flags) & ~(FLAG_CODED)); diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 03e2f6caa2..036d21c6a4 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -85,7 +85,7 @@ static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags) ret = url_open_dyn_buf(&pb); if (ret < 0) return ret; - init_checksum(pb, ff_crc04C11DB7_update, 0); + ffio_init_checksum(pb, ff_crc04C11DB7_update, 0); ffio_wfourcc(pb, "OggS"); avio_w8(pb, 0); avio_w8(pb, page->flags | extra_flags); From d09cc22d9c2dd2843179e7d11a1b564387f62dd2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 17 Mar 2011 13:02:54 +0100 Subject: [PATCH 07/11] avio: move ff_crc04C11DB7_update() from avio.h -> avio_internal.h --- libavformat/avio.h | 2 -- libavformat/avio_internal.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index bce2fc9682..22f7a2c9c3 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -675,8 +675,6 @@ int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size); */ int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); -unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, - unsigned int len); unsigned long get_checksum(AVIOContext *s); #if FF_API_UDP_GET_FILE diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index c50514d833..243b16dc52 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -77,5 +77,7 @@ int ff_udp_get_local_port(URLContext *h); void ffio_init_checksum(AVIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum); +unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, + unsigned int len); #endif // AVFORMAT_AVIO_INTERNAL_H From b64030f26d2ace99b9c782f5d5e264802d2d80a0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 17 Mar 2011 13:04:38 +0100 Subject: [PATCH 08/11] avio: make get_checksum() internal. --- libavformat/avio.h | 3 +-- libavformat/avio_internal.h | 1 + libavformat/aviobuf.c | 6 +++++- libavformat/nutdec.c | 12 ++++++------ libavformat/nutenc.c | 8 ++++---- libavformat/oggenc.c | 2 +- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/libavformat/avio.h b/libavformat/avio.h index 22f7a2c9c3..12fa2d586b 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -455,6 +455,7 @@ attribute_deprecated int udp_get_local_port(URLContext *h); attribute_deprecated void init_checksum(AVIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum); +attribute_deprecated unsigned long get_checksum(AVIOContext *s); #endif AVIOContext *avio_alloc_context( @@ -675,8 +676,6 @@ int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size); */ int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer); -unsigned long get_checksum(AVIOContext *s); - #if FF_API_UDP_GET_FILE int udp_get_file_handle(URLContext *h); #endif diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 243b16dc52..916de8fcc7 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -77,6 +77,7 @@ int ff_udp_get_local_port(URLContext *h); void ffio_init_checksum(AVIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum); +unsigned long ffio_get_checksum(AVIOContext *s); unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len); diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 7399905e89..2e7ee15b2a 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -412,6 +412,10 @@ void init_checksum(AVIOContext *s, { ffio_init_checksum(s, update_checksum, checksum); } +unsigned long get_checksum(AVIOContext *s) +{ + return ffio_get_checksum(s); +} #endif int avio_put_str(AVIOContext *s, const char *str) @@ -554,7 +558,7 @@ unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); } -unsigned long get_checksum(AVIOContext *s) +unsigned long ffio_get_checksum(AVIOContext *s) { s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); s->update_checksum= NULL; diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c index 1191962b50..ac17e86123 100644 --- a/libavformat/nutdec.c +++ b/libavformat/nutdec.c @@ -108,7 +108,7 @@ static int get_packetheader(NUTContext *nut, AVIOContext *bc, int calculate_chec size= ffio_read_varlen(bc); if(size > 4096) avio_rb32(bc); - if(get_checksum(bc) && size > 4096) + if(ffio_get_checksum(bc) && size > 4096) return -1; ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0); @@ -285,7 +285,7 @@ static int decode_main_header(NUTContext *nut){ assert(nut->header_len[0]==0); } - if(skip_reserved(bc, end) || get_checksum(bc)){ + if(skip_reserved(bc, end) || ffio_get_checksum(bc)){ av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n"); return AVERROR_INVALIDDATA; } @@ -374,7 +374,7 @@ static int decode_stream_header(NUTContext *nut){ ffio_read_varlen(bc); // samplerate_den GET_V(st->codec->channels, tmp > 0) } - if(skip_reserved(bc, end) || get_checksum(bc)){ + if(skip_reserved(bc, end) || ffio_get_checksum(bc)){ av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id); return -1; } @@ -469,7 +469,7 @@ static int decode_info_header(NUTContext *nut){ } } - if(skip_reserved(bc, end) || get_checksum(bc)){ + if(skip_reserved(bc, end) || ffio_get_checksum(bc)){ av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n"); return -1; } @@ -493,7 +493,7 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){ ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count); - if(skip_reserved(bc, end) || get_checksum(bc)){ + if(skip_reserved(bc, end) || ffio_get_checksum(bc)){ av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n"); return -1; } @@ -590,7 +590,7 @@ static int find_and_decode_index(NUTContext *nut){ } } - if(skip_reserved(bc, end) || get_checksum(bc)){ + if(skip_reserved(bc, end) || ffio_get_checksum(bc)){ av_log(s, AV_LOG_ERROR, "index checksum mismatch\n"); goto fail; } diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 8a2a6faba1..a72e510d81 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -289,13 +289,13 @@ static void put_packet(NUTContext *nut, AVIOContext *bc, AVIOContext *dyn_bc, in avio_wb64(bc, startcode); ff_put_v(bc, forw_ptr); if(forw_ptr > 4096) - avio_wl32(bc, get_checksum(bc)); + avio_wl32(bc, ffio_get_checksum(bc)); if(calculate_checksum) ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_write(bc, dyn_buf, dyn_size); if(calculate_checksum) - avio_wl32(bc, get_checksum(bc)); + avio_wl32(bc, ffio_get_checksum(bc)); av_free(dyn_buf); } @@ -818,8 +818,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt){ if(flags & FLAG_SIZE_MSB) ff_put_v(bc, pkt->size / fc->size_mul); if(flags & FLAG_HEADER_IDX) ff_put_v(bc, header_idx= best_header_idx); - if(flags & FLAG_CHECKSUM) avio_wl32(bc, get_checksum(bc)); - else get_checksum(bc); + if(flags & FLAG_CHECKSUM) avio_wl32(bc, ffio_get_checksum(bc)); + else ffio_get_checksum(bc); avio_write(bc, pkt->data + nut->header_len[header_idx], pkt->size - nut->header_len[header_idx]); nus->last_flags= flags; diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 036d21c6a4..e0dc5332ae 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -68,7 +68,7 @@ typedef struct { static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset) { int64_t pos = avio_tell(pb); - uint32_t checksum = get_checksum(pb); + uint32_t checksum = ffio_get_checksum(pb); avio_seek(pb, crc_offset, SEEK_SET); avio_wb32(pb, checksum); avio_seek(pb, pos, SEEK_SET); From 95c851e2c69bb379b9458558561526bcbd02d5db Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 30 Mar 2011 16:57:08 +0200 Subject: [PATCH 09/11] APIChanges: mark the place where 0.6 was branched. --- doc/APIchanges | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 2932028139..d242791c54 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -453,16 +453,22 @@ API changes, most recent first: 2010-05-26 - r23334 - lavc 52.72.0 - CODEC_CAP_EXPERIMENTAL Add CODEC_CAP_EXPERIMENTAL flag. + NOTE: this was backported to 0.6 2010-05-23 - r23255 - lavu 50.16.0 - av_get_random_seed() Add av_get_random_seed(). 2010-05-18 - r23161 - lavf 52.63.0 - AVFMT_FLAG_RTP_HINT Add AVFMT_FLAG_RTP_HINT as possible value for AVFormatContext.flags. + NOTE: this was backported to 0.6 2010-05-09 - r23066 - lavfi 1.20.0 - AVFilterPicRef Add interlaced and top_field_first fields to AVFilterPicRef. +------------------------------8<------------------------------------- + 0.6 branch was cut here +----------------------------->8-------------------------------------- + 2010-05-01 - r23002 - lavf 52.62.0 - probe function Add av_probe_input_format2 to API, it allows ignoring probe results below given score and returns the actual probe score. From 4b6f097b21d29ac11dd587038b0d385dbbed1c24 Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Fri, 25 Mar 2011 19:34:19 -0700 Subject: [PATCH 10/11] mlp_parse.c: set AVCodecContext channel_layout The channel layout isn't getting set for mlp and truehd audio. Signed-off-by: Anton Khirnov --- libavcodec/mlp_parser.c | 59 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 97b1a32cbe..9ba3c53be1 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -42,11 +42,52 @@ static const uint8_t mlp_channels[32] = { 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +static const uint64_t mlp_layout[32] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_2_1|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + static const uint8_t thd_chancount[13] = { // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1 }; +static const uint64_t thd_layout[13] = { + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, // LR + AV_CH_FRONT_CENTER, // C + AV_CH_LOW_FREQUENCY, // LFE + AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRs + AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT, // LRvh + AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRc + AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, // LRrs + AV_CH_BACK_CENTER, // Cs + AV_CH_TOP_BACK_CENTER, // Ts + AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRsd + AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRw + AV_CH_TOP_BACK_CENTER, // Cvh + AV_CH_LOW_FREQUENCY // LFE2 +}; + static int mlp_samplerate(int in) { if (in == 0xF) @@ -65,6 +106,16 @@ static int truehd_channels(int chanmap) return channels; } +static int64_t truehd_layout(int chanmap) +{ + int layout = 0, i; + + for (i = 0; i < 13; i++) + layout |= thd_layout[i] * ((chanmap >> i) & 1); + + return layout; +} + /** Read a major sync info header - contains high level information about * the stream - sample rate, channel arrangement etc. Most of this * information is not actually necessary for decoding, only for playback. @@ -264,12 +315,16 @@ static int mlp_parse(AVCodecParserContext *s, if (mh.stream_type == 0xbb) { /* MLP stream */ avctx->channels = mlp_channels[mh.channels_mlp]; + avctx->channel_layout = mlp_layout[mh.channels_mlp]; } else { /* mh.stream_type == 0xba */ /* TrueHD stream */ - if (mh.channels_thd_stream2) + if (mh.channels_thd_stream2) { avctx->channels = truehd_channels(mh.channels_thd_stream2); - else + avctx->channel_layout = truehd_layout(mh.channels_thd_stream2); + } else { avctx->channels = truehd_channels(mh.channels_thd_stream1); + avctx->channel_layout = truehd_layout(mh.channels_thd_stream1); + } } if (!mh.is_vbr) /* Stream is CBR */ From 229e2631be528c595650a7568c1d4df8af9c4944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 30 Mar 2011 23:35:28 +0300 Subject: [PATCH 11/11] rtsp: Use GET_PARAMETER for keep-alive for generic RTSP servers According to the RFC, GET_PARAMETER should be used for this, and according to a report from Tim Ouellette, OPTIONS doesn't work for keeping the connection alive for some servers. Also, live555 uses GET_PARAMETER for this purpose. Signed-off-by: Luca Barbato --- libavformat/rtspdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 571e76dfa9..e2ba76e636 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -340,7 +340,7 @@ retry: /* send dummy request to keep TCP connection alive */ if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { - if (rt->server_type == RTSP_SERVER_WMS) { + if (rt->server_type != RTSP_SERVER_REAL) { ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); } else { ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);