📄 mjpegdec.c
字号:
// if (s->first_picture)
// printf("mjpeg: workarounding buggy AVID\n");
}
else if(!strcmp(cbuf, "CS=ITU601")){
s->cs_itu601= 1;
}
av_free(cbuf);
}
}
return 0;
}
#if 0
static int valid_marker_list[] =
{
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* c */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* d */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* e */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
}
#endif
/* return the 8 bit start code value and update the search
state. Return -1 if no start code found */
static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
{
uint8_t *buf_ptr;
unsigned int v, v2;
int val;
#ifdef DEBUG
int skipped=0;
#endif
buf_ptr = *pbuf_ptr;
while (buf_ptr < buf_end) {
v = *buf_ptr++;
v2 = *buf_ptr;
if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) {
val = *buf_ptr++;
goto found;
}
#ifdef DEBUG
skipped++;
#endif
}
val = -1;
found:
#ifdef DEBUG
av_log(NULL, AV_LOG_VERBOSE, "find_marker skipped %d bytes\n", skipped);
#endif
*pbuf_ptr = buf_ptr;
return val;
}
int ff_mjpeg_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
MJpegDecodeContext *s = avctx->priv_data;
uint8_t *buf_end, *buf_ptr;
int start_code;
AVFrame *picture = data;
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)
{
av_free(s->buffer);
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",
s->buffer_size);
}
/* unescape buffer of SOS, use special treatment for JPEG-LS */
if (start_code == SOS && !s->ls)
{
uint8_t *src = buf_ptr;
uint8_t *dst = s->buffer;
while (src<buf_end)
{
uint8_t x = *(src++);
*(dst++) = x;
if (avctx->codec_id != CODEC_ID_THP)
{
if (x == 0xff) {
while (src < buf_end && x == 0xff)
x = *(src++);
if (x >= 0xd0 && x <= 0xd7)
*(dst++) = x;
else if (x)
break;
}
}
}
init_get_bits(&s->gb, s->buffer, (dst - s->buffer)*8);
av_log(avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n",
(buf_end - buf_ptr) - (dst - s->buffer));
}
else if(start_code == SOS && s->ls){
uint8_t *src = buf_ptr;
uint8_t *dst = s->buffer;
int bit_count = 0;
int t = 0, b = 0;
PutBitContext pb;
s->cur_scan++;
/* find marker */
while (src + t < buf_end){
uint8_t x = src[t++];
if (x == 0xff){
while((src + t < buf_end) && x == 0xff)
x = src[t++];
if (x & 0x80) {
t -= 2;
break;
}
}
}
bit_count = t * 8;
init_put_bits(&pb, dst, t);
/* unescape bitstream */
while(b < t){
uint8_t x = src[b++];
put_bits(&pb, 8, x);
if(x == 0xFF){
x = src[b++];
put_bits(&pb, 7, x);
bit_count--;
}
}
flush_put_bits(&pb);
init_get_bits(&s->gb, dst, bit_count);
}
else
init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8);
s->start_code = start_code;
if(s->avctx->debug & FF_DEBUG_STARTCODE){
av_log(avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code);
}
/* process markers */
if (start_code >= 0xd0 && start_code <= 0xd7) {
av_log(avctx, AV_LOG_DEBUG, "restart marker: %d\n", start_code&0x0f);
/* APP fields */
} else if (start_code >= APP0 && start_code <= APP15) {
mjpeg_decode_app(s);
/* Comment */
} else if (start_code == COM){
mjpeg_decode_com(s);
}
switch(start_code) {
case SOI:
s->restart_interval = 0;
s->restart_count = 0;
/* nothing to do on SOI */
break;
case DQT:
ff_mjpeg_decode_dqt(s);
break;
case DHT:
if(ff_mjpeg_decode_dht(s) < 0){
av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n");
return -1;
}
break;
case SOF0:
s->lossless=0;
s->ls=0;
s->progressive=0;
if (ff_mjpeg_decode_sof(s) < 0)
return -1;
break;
case SOF2:
s->lossless=0;
s->ls=0;
s->progressive=1;
if (ff_mjpeg_decode_sof(s) < 0)
return -1;
break;
case SOF3:
s->lossless=1;
s->ls=0;
s->progressive=0;
if (ff_mjpeg_decode_sof(s) < 0)
return -1;
break;
case SOF48:
s->lossless=1;
s->ls=1;
s->progressive=0;
if (ff_mjpeg_decode_sof(s) < 0)
return -1;
break;
case LSE:
if (!ENABLE_JPEGLS_DECODER || ff_jpegls_decode_lse(s) < 0)
return -1;
break;
case EOI:
s->cur_scan = 0;
if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
break;
eoi_parser:
{
if (s->interlaced) {
s->bottom_field ^= 1;
/* if not bottom field, do not output image yet */
if (s->bottom_field == !s->interlace_polarity)
goto not_the_end;
}
*picture = s->picture;
*data_size = sizeof(AVFrame);
if(!s->lossless){
picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
picture->qstride= 0;
picture->qscale_table= s->qscale_table;
memset(picture->qscale_table, picture->quality, (s->width+15)/16);
if(avctx->debug & FF_DEBUG_QP)
av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
picture->quality*= FF_QP2LAMBDA;
}
goto the_end;
}
break;
case SOS:
ff_mjpeg_decode_sos(s);
/* buggy avid puts EOI every 10-20th frame */
/* if restart period is over process EOI */
if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
goto eoi_parser;
break;
case DRI:
mjpeg_decode_dri(s);
break;
case SOF1:
case SOF5:
case SOF6:
case SOF7:
case SOF9:
case SOF10:
case SOF11:
case SOF13:
case SOF14:
case SOF15:
case JPG:
av_log(avctx, AV_LOG_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code);
break;
// default:
// printf("mjpeg: unsupported marker (%x)\n", start_code);
// break;
}
not_the_end:
/* eof process start code */
buf_ptr += (get_bits_count(&s->gb)+7)/8;
av_log(avctx, AV_LOG_DEBUG, "marker parser used %d bytes (%d bits)\n",
(get_bits_count(&s->gb)+7)/8, get_bits_count(&s->gb));
}
}
}
the_end:
av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %td bytes\n", buf_end - buf_ptr);
// return buf_end - buf_ptr;
return buf_ptr - buf;
}
int ff_mjpeg_decode_end(AVCodecContext *avctx)
{
MJpegDecodeContext *s = avctx->priv_data;
int i, j;
av_free(s->buffer);
av_free(s->qscale_table);
for(i=0;i<2;i++) {
for(j=0;j<4;j++)
free_vlc(&s->vlcs[i][j]);
}
return 0;
}
AVCodec mjpeg_decoder = {
"mjpeg",
CODEC_TYPE_VIDEO,
CODEC_ID_MJPEG,
sizeof(MJpegDecodeContext),
ff_mjpeg_decode_init,
NULL,
ff_mjpeg_decode_end,
ff_mjpeg_decode_frame,
CODEC_CAP_DR1,
NULL
};
AVCodec thp_decoder = {
"thp",
CODEC_TYPE_VIDEO,
CODEC_ID_THP,
sizeof(MJpegDecodeContext),
ff_mjpeg_decode_init,
NULL,
ff_mjpeg_decode_end,
ff_mjpeg_decode_frame,
CODEC_CAP_DR1,
NULL
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -