📄 mjpegdec.c
字号:
/*
* MJPEG decoder
* Copyright (c) 2000, 2001 Fabrice Bellard.
* Copyright (c) 2003 Alex Beregszaszi
* Copyright (c) 2003-2004 Michael Niedermayer
*
* Support for external huffman table, various fixes (AVID workaround),
* aspecting, new decode_frame mechanism and apple mjpeg-b support
* by Alex Beregszaszi
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file mjpegdec.c
* MJPEG decoder.
*/
//#define DEBUG
#include <assert.h>
#include "avcodec.h"
#include "dsputil.h"
#include "mjpeg.h"
#include "mjpegdec.h"
#include "jpeglsdec.h"
static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_table,
int nb_codes, int use_static, int is_ac)
{
uint8_t huff_size[256+16];
uint16_t huff_code[256+16];
assert(nb_codes <= 256);
memset(huff_size, 0, sizeof(huff_size));
ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table);
if(is_ac){
memmove(huff_size+16, huff_size, sizeof(uint8_t)*nb_codes);
memmove(huff_code+16, huff_code, sizeof(uint16_t)*nb_codes);
memset(huff_size, 0, sizeof(uint8_t)*16);
memset(huff_code, 0, sizeof(uint16_t)*16);
nb_codes += 16;
}
return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2, use_static);
}
static void build_basic_mjpeg_vlc(MJpegDecodeContext * s) {
build_vlc(&s->vlcs[0][0], ff_mjpeg_bits_dc_luminance,
ff_mjpeg_val_dc_luminance, 12, 0, 0);
build_vlc(&s->vlcs[0][1], ff_mjpeg_bits_dc_chrominance,
ff_mjpeg_val_dc_chrominance, 12, 0, 0);
build_vlc(&s->vlcs[1][0], ff_mjpeg_bits_ac_luminance,
ff_mjpeg_val_ac_luminance, 251, 0, 1);
build_vlc(&s->vlcs[1][1], ff_mjpeg_bits_ac_chrominance,
ff_mjpeg_val_ac_chrominance, 251, 0, 1);
}
int ff_mjpeg_decode_init(AVCodecContext *avctx)
{
MJpegDecodeContext *s = avctx->priv_data;
s->avctx = avctx;
dsputil_init(&s->dsp, avctx);
ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct);
s->buffer_size = 0;
s->buffer = NULL;
s->start_code = -1;
s->first_picture = 1;
s->org_height = avctx->coded_height;
build_basic_mjpeg_vlc(s);
if (avctx->flags & CODEC_FLAG_EXTERN_HUFF)
{
av_log(avctx, AV_LOG_INFO, "mjpeg: using external huffman table\n");
init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
if (ff_mjpeg_decode_dht(s)) {
av_log(avctx, AV_LOG_ERROR, "mjpeg: error using external huffman table, switching back to internal\n");
build_basic_mjpeg_vlc(s);
}
}
if (avctx->extradata_size > 9 &&
AV_RL32(avctx->extradata + 4) == MKTAG('f','i','e','l')) {
if (avctx->extradata[9] == 6) { /* quicktime icefloe 019 */
s->interlace_polarity = 1; /* bottom field first */
av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
}
}
return 0;
}
/* quantize tables */
int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
{
int len, index, i, j;
len = get_bits(&s->gb, 16) - 2;
while (len >= 65) {
/* only 8 bit precision handled */
if (get_bits(&s->gb, 4) != 0)
{
av_log(s->avctx, AV_LOG_ERROR, "dqt: 16bit precision\n");
return -1;
}
index = get_bits(&s->gb, 4);
if (index >= 4)
return -1;
av_log(s->avctx, AV_LOG_DEBUG, "index=%d\n", index);
/* read quant table */
for(i=0;i<64;i++) {
j = s->scantable.permutated[i];
s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
}
//XXX FIXME finetune, and perhaps add dc too
s->qscale[index]= FFMAX(
s->quant_matrixes[index][s->scantable.permutated[1]],
s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1;
av_log(s->avctx, AV_LOG_DEBUG, "qscale[%d]: %d\n", index, s->qscale[index]);
len -= 65;
}
return 0;
}
/* decode huffman tables and build VLC decoders */
int ff_mjpeg_decode_dht(MJpegDecodeContext *s)
{
int len, index, i, class, n, v, code_max;
uint8_t bits_table[17];
uint8_t val_table[256];
len = get_bits(&s->gb, 16) - 2;
while (len > 0) {
if (len < 17)
return -1;
class = get_bits(&s->gb, 4);
if (class >= 2)
return -1;
index = get_bits(&s->gb, 4);
if (index >= 4)
return -1;
n = 0;
for(i=1;i<=16;i++) {
bits_table[i] = get_bits(&s->gb, 8);
n += bits_table[i];
}
len -= 17;
if (len < n || n > 256)
return -1;
code_max = 0;
for(i=0;i<n;i++) {
v = get_bits(&s->gb, 8);
if (v > code_max)
code_max = v;
val_table[i] = v;
}
len -= n;
/* build VLC and flush previous vlc if present */
free_vlc(&s->vlcs[class][index]);
av_log(s->avctx, AV_LOG_DEBUG, "class=%d index=%d nb_codes=%d\n",
class, index, code_max + 1);
if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1, 0, class > 0) < 0){
return -1;
}
}
return 0;
}
int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
{
int len, nb_components, i, width, height, pix_fmt_id;
/* XXX: verify len field validity */
len = get_bits(&s->gb, 16);
s->bits= get_bits(&s->gb, 8);
if(s->pegasus_rct) s->bits=9;
if(s->bits==9 && !s->pegasus_rct) s->rct=1; //FIXME ugly
if (s->bits != 8 && !s->lossless){
av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n");
return -1;
}
height = get_bits(&s->gb, 16);
width = get_bits(&s->gb, 16);
//HACK for odd_height.mov
if(s->interlaced && s->width == width && s->height == height + 1)
height= s->height;
av_log(s->avctx, AV_LOG_DEBUG, "sof0: picture: %dx%d\n", width, height);
if(avcodec_check_dimensions(s->avctx, width, height))
return -1;
nb_components = get_bits(&s->gb, 8);
if (nb_components <= 0 ||
nb_components > MAX_COMPONENTS)
return -1;
if (s->ls && !(s->bits <= 8 || nb_components == 1)){
av_log(s->avctx, AV_LOG_ERROR, "only <= 8 bits/component or 16-bit gray accepted for JPEG-LS\n");
return -1;
}
s->nb_components = nb_components;
s->h_max = 1;
s->v_max = 1;
for(i=0;i<nb_components;i++) {
/* component id */
s->component_id[i] = get_bits(&s->gb, 8) - 1;
s->h_count[i] = get_bits(&s->gb, 4);
s->v_count[i] = get_bits(&s->gb, 4);
/* compute hmax and vmax (only used in interleaved case) */
if (s->h_count[i] > s->h_max)
s->h_max = s->h_count[i];
if (s->v_count[i] > s->v_max)
s->v_max = s->v_count[i];
s->quant_index[i] = get_bits(&s->gb, 8);
if (s->quant_index[i] >= 4)
return -1;
av_log(s->avctx, AV_LOG_DEBUG, "component %d %d:%d id: %d quant:%d\n", i, s->h_count[i],
s->v_count[i], s->component_id[i], s->quant_index[i]);
}
if(s->ls && (s->h_max > 1 || s->v_max > 1)) {
av_log(s->avctx, AV_LOG_ERROR, "Subsampling in JPEG-LS is not supported.\n");
return -1;
}
if(s->v_max==1 && s->h_max==1 && s->lossless==1) s->rgb=1;
/* if different size, realloc/alloc picture */
/* XXX: also check h_count and v_count */
if (width != s->width || height != s->height) {
av_freep(&s->qscale_table);
s->width = width;
s->height = height;
s->interlaced = 0;
/* test interlaced mode */
if (s->first_picture &&
s->org_height != 0 &&
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;
height *= 2;
}
avcodec_set_dimensions(s->avctx, width, height);
s->qscale_table= av_mallocz((s->width+15)/16);
s->first_picture = 0;
}
if(s->interlaced && (s->bottom_field == !s->interlace_polarity))
return 0;
/* XXX: not complete test ! */
pix_fmt_id = (s->h_count[0] << 20) | (s->v_count[0] << 16) |
(s->h_count[1] << 12) | (s->v_count[1] << 8) |
(s->h_count[2] << 4) | s->v_count[2];
av_log(s->avctx, AV_LOG_DEBUG, "pix fmt id %x\n", pix_fmt_id);
switch(pix_fmt_id){
case 0x222222:
case 0x111111:
if(s->rgb){
s->avctx->pix_fmt = PIX_FMT_RGB32;
}else if(s->nb_components==3)
s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV444P : PIX_FMT_YUVJ444P;
else
s->avctx->pix_fmt = PIX_FMT_GRAY8;
break;
case 0x110000:
s->avctx->pix_fmt = PIX_FMT_GRAY8;
break;
case 0x121111:
s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV440P : PIX_FMT_YUVJ440P;
break;
case 0x211111:
case 0x221212:
s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P;
break;
case 0x221111:
s->avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420P;
break;
default:
av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id);
return -1;
}
if(s->ls){
if(s->nb_components > 1)
s->avctx->pix_fmt = PIX_FMT_RGB24;
else if(s->bits <= 8)
s->avctx->pix_fmt = PIX_FMT_GRAY8;
else
s->avctx->pix_fmt = PIX_FMT_GRAY16;
}
if(s->picture.data[0])
s->avctx->release_buffer(s->avctx, &s->picture);
s->picture.reference= 0;
if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
s->picture.pict_type= I_TYPE;
s->picture.key_frame= 1;
for(i=0; i<3; i++){
s->linesize[i]= s->picture.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);
if (len != (8+(3*nb_components)))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -