1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * MJPEG parser 3cabdff1aSopenharmony_ci * Copyright (c) 2000, 2001 Fabrice Bellard 4cabdff1aSopenharmony_ci * Copyright (c) 2003 Alex Beregszaszi 5cabdff1aSopenharmony_ci * Copyright (c) 2003-2004 Michael Niedermayer 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci/** 25cabdff1aSopenharmony_ci * @file 26cabdff1aSopenharmony_ci * MJPEG parser. 27cabdff1aSopenharmony_ci */ 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "parser.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_citypedef struct MJPEGParserContext{ 32cabdff1aSopenharmony_ci ParseContext pc; 33cabdff1aSopenharmony_ci int size; 34cabdff1aSopenharmony_ci}MJPEGParserContext; 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci/** 37cabdff1aSopenharmony_ci * Find the end of the current frame in the bitstream. 38cabdff1aSopenharmony_ci * @return the position of the first byte of the next frame, or -1 39cabdff1aSopenharmony_ci */ 40cabdff1aSopenharmony_cistatic int find_frame_end(MJPEGParserContext *m, const uint8_t *buf, int buf_size){ 41cabdff1aSopenharmony_ci ParseContext *pc= &m->pc; 42cabdff1aSopenharmony_ci int vop_found, i; 43cabdff1aSopenharmony_ci uint32_t state; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci vop_found= pc->frame_start_found; 46cabdff1aSopenharmony_ci state= pc->state; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci i=0; 49cabdff1aSopenharmony_ci if(!vop_found){ 50cabdff1aSopenharmony_ci for(i=0; i<buf_size;){ 51cabdff1aSopenharmony_ci state= (state<<8) | buf[i]; 52cabdff1aSopenharmony_ci if(state>=0xFFC00000 && state<=0xFFFEFFFF){ 53cabdff1aSopenharmony_ci if(state>=0xFFD8FFC0 && state<=0xFFD8FFFF){ 54cabdff1aSopenharmony_ci i++; 55cabdff1aSopenharmony_ci vop_found=1; 56cabdff1aSopenharmony_ci break; 57cabdff1aSopenharmony_ci }else if(state<0xFFD00000 || state>0xFFD9FFFF){ 58cabdff1aSopenharmony_ci m->size= (state&0xFFFF)-1; 59cabdff1aSopenharmony_ci } 60cabdff1aSopenharmony_ci } 61cabdff1aSopenharmony_ci if(m->size>0){ 62cabdff1aSopenharmony_ci int size= FFMIN(buf_size-i, m->size); 63cabdff1aSopenharmony_ci i+=size; 64cabdff1aSopenharmony_ci m->size-=size; 65cabdff1aSopenharmony_ci state=0; 66cabdff1aSopenharmony_ci continue; 67cabdff1aSopenharmony_ci }else 68cabdff1aSopenharmony_ci i++; 69cabdff1aSopenharmony_ci } 70cabdff1aSopenharmony_ci } 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci if(vop_found){ 73cabdff1aSopenharmony_ci /* EOF considered as end of frame */ 74cabdff1aSopenharmony_ci if (buf_size == 0) 75cabdff1aSopenharmony_ci return 0; 76cabdff1aSopenharmony_ci for(; i<buf_size;){ 77cabdff1aSopenharmony_ci state= (state<<8) | buf[i]; 78cabdff1aSopenharmony_ci if(state>=0xFFC00000 && state<=0xFFFEFFFF){ 79cabdff1aSopenharmony_ci if(state>=0xFFD8FFC0 && state<=0xFFD8FFFF){ 80cabdff1aSopenharmony_ci pc->frame_start_found=0; 81cabdff1aSopenharmony_ci pc->state=0; 82cabdff1aSopenharmony_ci return i-3; 83cabdff1aSopenharmony_ci } else if((state>>16)==0xFFD9 && (state&0xFFFF)!=0xFFD8){ 84cabdff1aSopenharmony_ci state= 0xFFD900|(state&0xFF); 85cabdff1aSopenharmony_ci } else if(state<0xFFD00000 || state>0xFFD9FFFF){ 86cabdff1aSopenharmony_ci m->size= (state&0xFFFF)-1; 87cabdff1aSopenharmony_ci } 88cabdff1aSopenharmony_ci } 89cabdff1aSopenharmony_ci if(m->size>0){ 90cabdff1aSopenharmony_ci int size= FFMIN(buf_size-i, m->size); 91cabdff1aSopenharmony_ci i+=size; 92cabdff1aSopenharmony_ci m->size-=size; 93cabdff1aSopenharmony_ci state=0; 94cabdff1aSopenharmony_ci continue; 95cabdff1aSopenharmony_ci }else 96cabdff1aSopenharmony_ci i++; 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci } 99cabdff1aSopenharmony_ci pc->frame_start_found= vop_found; 100cabdff1aSopenharmony_ci pc->state= state; 101cabdff1aSopenharmony_ci return END_NOT_FOUND; 102cabdff1aSopenharmony_ci} 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_cistatic int jpeg_parse(AVCodecParserContext *s, 105cabdff1aSopenharmony_ci AVCodecContext *avctx, 106cabdff1aSopenharmony_ci const uint8_t **poutbuf, int *poutbuf_size, 107cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 108cabdff1aSopenharmony_ci{ 109cabdff1aSopenharmony_ci MJPEGParserContext *m = s->priv_data; 110cabdff1aSopenharmony_ci ParseContext *pc = &m->pc; 111cabdff1aSopenharmony_ci int next; 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ 114cabdff1aSopenharmony_ci next= buf_size; 115cabdff1aSopenharmony_ci }else{ 116cabdff1aSopenharmony_ci next= find_frame_end(m, buf, buf_size); 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 119cabdff1aSopenharmony_ci *poutbuf = NULL; 120cabdff1aSopenharmony_ci *poutbuf_size = 0; 121cabdff1aSopenharmony_ci return buf_size; 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci *poutbuf = buf; 126cabdff1aSopenharmony_ci *poutbuf_size = buf_size; 127cabdff1aSopenharmony_ci return next; 128cabdff1aSopenharmony_ci} 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ciconst AVCodecParser ff_mjpeg_parser = { 132cabdff1aSopenharmony_ci .codec_ids = { AV_CODEC_ID_MJPEG, AV_CODEC_ID_JPEGLS }, 133cabdff1aSopenharmony_ci .priv_data_size = sizeof(MJPEGParserContext), 134cabdff1aSopenharmony_ci .parser_parse = jpeg_parse, 135cabdff1aSopenharmony_ci .parser_close = ff_parse_close, 136cabdff1aSopenharmony_ci}; 137