📄 mjpegdec.c
字号:
if (i==2) s->bottom_field= 1;
else if(i==1) s->bottom_field= 0;
goto out;
}
if (id == ff_get_fourcc("JFIF"))
{
int t_w, t_h, v1, v2;
skip_bits(&s->gb, 8); /* the trailing zero-byte */
v1= get_bits(&s->gb, 8);
v2= get_bits(&s->gb, 8);
skip_bits(&s->gb, 8);
s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 16);
s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 16);
if (s->avctx->debug & FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_INFO, "mjpeg: JFIF header found (version: %x.%x) SAR=%d/%d\n",
v1, v2,
s->avctx->sample_aspect_ratio.num,
s->avctx->sample_aspect_ratio.den
);
t_w = get_bits(&s->gb, 8);
t_h = get_bits(&s->gb, 8);
if (t_w && t_h)
{
/* skip thumbnail */
if (len-10-(t_w*t_h*3) > 0)
len -= t_w*t_h*3;
}
len -= 10;
goto out;
}
if (id == ff_get_fourcc("Adob") && (get_bits(&s->gb, 8) == 'e'))
{
if (s->avctx->debug & FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n");
skip_bits(&s->gb, 16); /* version */
skip_bits(&s->gb, 16); /* flags0 */
skip_bits(&s->gb, 16); /* flags1 */
skip_bits(&s->gb, 8); /* transform */
len -= 7;
goto out;
}
if (id == ff_get_fourcc("LJIF")){
if (s->avctx->debug & FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_INFO, "Pegasus lossless jpeg header found\n");
skip_bits(&s->gb, 16); /* version ? */
skip_bits(&s->gb, 16); /* unknwon always 0? */
skip_bits(&s->gb, 16); /* unknwon always 0? */
skip_bits(&s->gb, 16); /* unknwon always 0? */
switch( get_bits(&s->gb, 8)){
case 1:
s->rgb= 1;
s->pegasus_rct=0;
break;
case 2:
s->rgb= 1;
s->pegasus_rct=1;
break;
default:
av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace\n");
}
len -= 9;
goto out;
}
/* Apple MJPEG-A */
if ((s->start_code == APP1) && (len > (0x28 - 8)))
{
id = (get_bits(&s->gb, 16) << 16) | get_bits(&s->gb, 16);
id = be2me_32(id);
len -= 4;
if (id == ff_get_fourcc("mjpg")) /* Apple MJPEG-A */
{
if (s->avctx->debug & FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n");
}
}
out:
/* slow but needed for extreme adobe jpegs */
if (len < 0)
av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error, decode_app parser read over the end\n");
while(--len > 0)
skip_bits(&s->gb, 8);
return 0;
}
static int mjpeg_decode_com(MJpegDecodeContext *s)
{
int len = get_bits(&s->gb, 16);
if (len >= 2 && 8*len - 16 + get_bits_count(&s->gb) <= s->gb.size_in_bits) {
char *cbuf = av_malloc(len - 1);
if (cbuf) {
int i;
for (i = 0; i < len - 2; i++)
cbuf[i] = get_bits(&s->gb, 8);
if (i > 0 && cbuf[i-1] == '\n')
cbuf[i-1] = 0;
else
cbuf[i] = 0;
if(s->avctx->debug & FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_INFO, "mjpeg comment: '%s'\n", cbuf);
/* buggy avid, it puts EOI only at every 10th frame */
if (!strcmp(cbuf, "AVID"))
{
s->buggy_avid = 1;
// 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;
}
/* 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 (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),
/*.init=*/ff_mjpeg_decode_init,
/*.encode=*/NULL,
/*.close=*/ff_mjpeg_decode_end,
/*.decode=*/ff_mjpeg_decode_frame,
/*.capabilities=*/CODEC_CAP_DR1,
/*.next=*/NULL,
/*.flush=*/NULL,
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -