📄 parser.c
字号:
/* XXX: merge with libavcodec ? */#define MPEG1_FRAME_RATE_BASE 1001static const int frame_rate_tab[16] = { 0, 24000, 24024, 25025, 30000, 30030, 50050, 60000, 60060, // Xing's 15fps: (9) 15015, // libmpeg3's "Unofficial economy rates": (10-13) 5005, 10010, 12012, 15015, // random, just to avoid segfault !never encode these 25025, 25025,};//FIXME move into mpeg12.cstatic void mpegvideo_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size){ ParseContext1 *pc = s->priv_data; const uint8_t *buf_end; int32_t start_code; int frame_rate_index, ext_type, bytes_left; int frame_rate_ext_n, frame_rate_ext_d; int picture_structure, top_field_first, repeat_first_field, progressive_frame; int horiz_size_ext, vert_size_ext, bit_rate_ext;//FIXME replace the crap with get_bits() s->repeat_pict = 0; buf_end = buf + buf_size; while (buf < buf_end) { start_code = find_start_code(&buf, buf_end); bytes_left = buf_end - buf; switch(start_code) { case PICTURE_START_CODE: if (bytes_left >= 2) { s->pict_type = (buf[1] >> 3) & 7; } break; case SEQ_START_CODE: if (bytes_left >= 7) { pc->width = (buf[0] << 4) | (buf[1] >> 4); pc->height = ((buf[1] & 0x0f) << 8) | buf[2]; avcodec_set_dimensions(avctx, pc->width, pc->height); frame_rate_index = buf[3] & 0xf; pc->frame_rate = avctx->time_base.den = frame_rate_tab[frame_rate_index]; avctx->time_base.num = MPEG1_FRAME_RATE_BASE; avctx->bit_rate = ((buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6))*400; avctx->codec_id = CODEC_ID_MPEG1VIDEO; avctx->sub_id = 1; } break; case EXT_START_CODE: if (bytes_left >= 1) { ext_type = (buf[0] >> 4); switch(ext_type) { case 0x1: /* sequence extension */ if (bytes_left >= 6) { horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7); vert_size_ext = (buf[2] >> 5) & 3; bit_rate_ext = ((buf[2] & 0x1F)<<7) | (buf[3]>>1); frame_rate_ext_n = (buf[5] >> 5) & 3; frame_rate_ext_d = (buf[5] & 0x1f); pc->progressive_sequence = buf[1] & (1 << 3); avctx->has_b_frames= !(buf[5] >> 7); pc->width |=(horiz_size_ext << 12); pc->height |=( vert_size_ext << 12); avctx->bit_rate += (bit_rate_ext << 18) * 400; avcodec_set_dimensions(avctx, pc->width, pc->height); avctx->time_base.den = pc->frame_rate * (frame_rate_ext_n + 1); avctx->time_base.num = MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d + 1); avctx->codec_id = CODEC_ID_MPEG2VIDEO; avctx->sub_id = 2; /* forces MPEG2 */ } break; case 0x8: /* picture coding extension */ if (bytes_left >= 5) { picture_structure = buf[2]&3; top_field_first = buf[3] & (1 << 7); repeat_first_field = buf[3] & (1 << 1); progressive_frame = buf[4] & (1 << 7); /* check if we must repeat the frame */ if (repeat_first_field) { if (pc->progressive_sequence) { if (top_field_first) s->repeat_pict = 4; else s->repeat_pict = 2; } else if (progressive_frame) { s->repeat_pict = 1; } } /* the packet only represents half a frame XXX,FIXME maybe find a different solution */ if(picture_structure != 3) s->repeat_pict = -1; } break; } } break; case -1: goto the_end; default: /* we stop parsing when we encounter a slice. It ensures that this function takes a negligible amount of time */ if (start_code >= SLICE_MIN_START_CODE && start_code <= SLICE_MAX_START_CODE) goto the_end; break; } } the_end: ;}static int mpegvideo_parse(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size){ ParseContext1 *pc1 = s->priv_data; ParseContext *pc= &pc1->pc; int next; if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ next= buf_size; }else{ next= ff_mpeg1_find_frame_end(pc, buf, buf_size, avctx->parserRtStart); if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } } /* we have a full frame : we just parse the first few MPEG headers to have the full timing information. The time take by this function should be negligible for uncorrupted streams */ mpegvideo_extract_headers(s, avctx, buf, buf_size);#if 0 printf("pict_type=%d frame_rate=%0.3f repeat_pict=%d\n", s->pict_type, (double)avctx->time_base.den / avctx->time_base.num, s->repeat_pict);#endif *poutbuf = (uint8_t *)buf; *poutbuf_size = buf_size; return next;}static int mpegvideo_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size){ int i; uint32_t state= -1; for(i=0; i<buf_size; i++){ state= (state<<8) | buf[i]; if(state != 0x1B3 && state != 0x1B5 && state < 0x200 && state >= 0x100) return i-3; } return 0;}void ff_parse_close(AVCodecParserContext *s){ ParseContext *pc = s->priv_data; av_free(pc->buffer);}static void parse1_close(AVCodecParserContext *s){ ParseContext1 *pc1 = s->priv_data; av_free(pc1->pc.buffer); av_free(pc1->enc);}/*************************//* used by parser *//* XXX: make it use less memory */static int av_mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx, const uint8_t *buf, int buf_size){ ParseContext1 *pc = s1->priv_data; MpegEncContext *s = pc->enc; GetBitContext gb1, *gb = &gb1; int ret; s->avctx = avctx; s->current_picture_ptr = &s->current_picture; if (avctx->extradata_size && pc->first_picture){ init_get_bits(gb, avctx->extradata, avctx->extradata_size*8); ret = ff_mpeg4_decode_picture_header(s, gb); } init_get_bits(gb, buf, 8 * buf_size); ret = ff_mpeg4_decode_picture_header(s, gb); if (s->width) { avcodec_set_dimensions(avctx, s->width, s->height); } s1->pict_type= s->pict_type; pc->first_picture = 0; return ret;}static int mpeg4video_parse_init(AVCodecParserContext *s){ ParseContext1 *pc = s->priv_data; pc->enc = av_mallocz(sizeof(MpegEncContext)); if (!pc->enc) return -1; pc->first_picture = 1; return 0;}static int mpeg4video_parse(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size){ ParseContext *pc = s->priv_data; int next; if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ next= buf_size; }else{ next= ff_mpeg4_find_frame_end(pc, buf, buf_size); if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } } av_mpeg4_decode_header(s, avctx, buf, buf_size); *poutbuf = (uint8_t *)buf; *poutbuf_size = buf_size; return next;}static int mpeg4video_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size){ int i; uint32_t state= -1; for(i=0; i<buf_size; i++){ state= (state<<8) | buf[i]; if(state == 0x1B3 || state == 0x1B6) return i-3; } return 0;}/*************************/AVCodecParser mpegvideo_parser = { { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO }, sizeof(ParseContext1), NULL, mpegvideo_parse, parse1_close, mpegvideo_split,};AVCodecParser mpeg4video_parser = { { CODEC_ID_MPEG4 }, sizeof(ParseContext1), mpeg4video_parse_init, mpeg4video_parse, parse1_close, mpeg4video_split,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -