You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avcodec/prores: add parser
Introduce a basic parser for ProRes frame headers. This avoid having to decode an entire frame to extract codec information.
This commit is contained in:
		| @@ -1282,6 +1282,7 @@ OBJS-$(CONFIG_PNG_PARSER)              += png_parser.o | ||||
| OBJS-$(CONFIG_PNM_PARSER)              += pnm_parser.o pnm.o | ||||
| OBJS-$(CONFIG_PRORES_RAW_PARSER)       += prores_raw_parser.o | ||||
| OBJS-$(CONFIG_QOI_PARSER)              += qoi_parser.o | ||||
| OBJS-$(CONFIG_PRORES_PARSER)           += prores_parser.o | ||||
| OBJS-$(CONFIG_RV34_PARSER)             += rv34_parser.o | ||||
| OBJS-$(CONFIG_SBC_PARSER)              += sbc_parser.o | ||||
| OBJS-$(CONFIG_SIPR_PARSER)             += sipr_parser.o | ||||
|   | ||||
| @@ -67,6 +67,7 @@ extern const AVCodecParser ff_mpeg4video_parser; | ||||
| extern const AVCodecParser ff_mpegaudio_parser; | ||||
| extern const AVCodecParser ff_mpegvideo_parser; | ||||
| extern const AVCodecParser ff_opus_parser; | ||||
| extern const AVCodecParser ff_prores_parser; | ||||
| extern const AVCodecParser ff_png_parser; | ||||
| extern const AVCodecParser ff_pnm_parser; | ||||
| extern const AVCodecParser ff_prores_raw_parser; | ||||
|   | ||||
							
								
								
									
										128
									
								
								libavcodec/prores_parser.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								libavcodec/prores_parser.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| /* | ||||
|  * 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 | ||||
|  */ | ||||
|  | ||||
| #include "libavutil/intreadwrite.h" | ||||
| #include "bytestream.h" | ||||
|  | ||||
| #include "avcodec.h" | ||||
|  | ||||
| static int parse(AVCodecParserContext *s, | ||||
|                  AVCodecContext *avctx, | ||||
|                  const uint8_t **poutbuf, int *poutbuf_size, | ||||
|                  const uint8_t *buf, int buf_size) | ||||
| { | ||||
|     GetByteContext gb; | ||||
|     uint8_t flags, depth, chroma_format, alpha_channel_type; | ||||
|  | ||||
|     *poutbuf      = buf; | ||||
|     *poutbuf_size = buf_size; | ||||
|  | ||||
|     /* Frame fields + frame header size */ | ||||
|     if (buf_size < 28) | ||||
|         return buf_size; | ||||
|  | ||||
|     bytestream2_init(&gb, buf, buf_size); | ||||
|  | ||||
|     /* Frame size */ | ||||
|     if (bytestream2_get_be32(&gb) != buf_size) | ||||
|         return buf_size; | ||||
|  | ||||
|     /* Frame identifier */ | ||||
|     if (bytestream2_get_le32(&gb) != MKTAG('i','c','p','f')) | ||||
|         return buf_size; | ||||
|  | ||||
|     /* Frame header size */ | ||||
|     if (bytestream2_get_be16(&gb) < 20) | ||||
|         return buf_size; | ||||
|  | ||||
|     bytestream2_skip(&gb, 6); /* Bitstream version, encoder identifier */ | ||||
|  | ||||
|     s->key_frame = 1; | ||||
|     s->pict_type = AV_PICTURE_TYPE_I; | ||||
|  | ||||
|     s->width  = bytestream2_get_be16(&gb); | ||||
|     s->height = bytestream2_get_be16(&gb); | ||||
|     s->coded_width  = FFALIGN(s->width,  16); | ||||
|     s->coded_height = FFALIGN(s->height, 16); | ||||
|  | ||||
|     flags = bytestream2_get_byte(&gb); | ||||
|  | ||||
|     /* Interlace mode */ | ||||
|     switch (flags >> 2 & 3) { | ||||
|         case 0: | ||||
|             s->field_order       = AV_FIELD_PROGRESSIVE; | ||||
|             s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; | ||||
|             break; | ||||
|         case 1: | ||||
|             s->field_order       = AV_FIELD_TT; | ||||
|             s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD; | ||||
|             break; | ||||
|         case 2: | ||||
|             s->field_order       = AV_FIELD_BB; | ||||
|             s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD; | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     bytestream2_skip(&gb, 4); /* Aspect ratio information, frame rate code, color primaries, transfer characteristic, matrix coefficients */ | ||||
|  | ||||
|     /* Determine pixel format based on color depth, chroma format and alpha type */ | ||||
|     switch (avctx->codec_tag) { | ||||
|         case MKTAG('a','p','c','o'): | ||||
|         case MKTAG('a','p','c','s'): | ||||
|         case MKTAG('a','p','c','n'): | ||||
|         case MKTAG('a','p','c','h'): | ||||
|             depth = 10; | ||||
|             break; | ||||
|         case MKTAG('a','p','4','h'): | ||||
|         case MKTAG('a','p','4','x'): | ||||
|             depth = 12; | ||||
|             break; | ||||
|         default: | ||||
|             return buf_size; | ||||
|     } | ||||
|  | ||||
|     chroma_format = flags >> 6 & 3; | ||||
|     if (chroma_format < 2) | ||||
|         return buf_size; | ||||
|  | ||||
|     alpha_channel_type = bytestream2_get_byte(&gb) & 0xf; | ||||
|  | ||||
|     switch (depth | (chroma_format << 4) | (alpha_channel_type << 8)) { | ||||
|         case 10 | (2 << 4) | (0 << 8): s->format = AV_PIX_FMT_YUV422P10;  break; | ||||
|         case 10 | (2 << 4) | (1 << 8): | ||||
|         case 10 | (2 << 4) | (2 << 8): s->format = AV_PIX_FMT_YUVA422P10; break; | ||||
|         case 10 | (3 << 4) | (0 << 8): s->format = AV_PIX_FMT_YUV444P10;  break; | ||||
|         case 10 | (3 << 4) | (1 << 8): | ||||
|         case 10 | (3 << 4) | (2 << 8): s->format = AV_PIX_FMT_YUVA444P10; break; | ||||
|         case 12 | (2 << 4) | (0 << 8): s->format = AV_PIX_FMT_YUV422P12;  break; | ||||
|         case 12 | (2 << 4) | (1 << 8): | ||||
|         case 12 | (2 << 4) | (2 << 8): s->format = AV_PIX_FMT_YUVA422P12; break; | ||||
|         case 12 | (3 << 4) | (0 << 8): s->format = AV_PIX_FMT_YUV444P12;  break; | ||||
|         case 12 | (3 << 4) | (1 << 8): | ||||
|         case 12 | (3 << 4) | (2 << 8): s->format = AV_PIX_FMT_YUVA444P12; break; | ||||
|     } | ||||
|  | ||||
|     return buf_size; | ||||
| } | ||||
|  | ||||
| const AVCodecParser ff_prores_parser = { | ||||
|     .codec_ids    = { AV_CODEC_ID_PRORES }, | ||||
|     .parser_parse = parse, | ||||
| }; | ||||
| @@ -276,10 +276,10 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     ctx->frame->color_primaries = buf[14]; | ||||
|     ctx->frame->color_trc       = buf[15]; | ||||
|     ctx->frame->colorspace      = buf[16]; | ||||
|     ctx->frame->color_range     = AVCOL_RANGE_MPEG; | ||||
|     avctx->color_primaries = buf[14]; | ||||
|     avctx->color_trc       = buf[15]; | ||||
|     avctx->colorspace      = buf[16]; | ||||
|     avctx->color_range     = AVCOL_RANGE_MPEG; | ||||
|  | ||||
|     ptr   = buf + 20; | ||||
|     flags = buf[19]; | ||||
| @@ -779,6 +779,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, | ||||
|     if (frame_hdr_size < 0) | ||||
|         return frame_hdr_size; | ||||
|  | ||||
|     if (avctx->skip_frame == AVDISCARD_ALL) | ||||
|         return 0; | ||||
|  | ||||
|     buf += frame_hdr_size; | ||||
|     buf_size -= frame_hdr_size; | ||||
|  | ||||
| @@ -870,6 +873,7 @@ const FFCodec ff_prores_decoder = { | ||||
|     FF_CODEC_DECODE_CB(decode_frame), | ||||
|     UPDATE_THREAD_CONTEXT(update_thread_context), | ||||
|     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, | ||||
|     .caps_internal  = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, | ||||
|     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_prores_profiles), | ||||
| #if HWACCEL_MAX | ||||
|     .hw_configs     = (const AVCodecHWConfigInternal *const []) { | ||||
|   | ||||
| @@ -2991,6 +2991,7 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, | ||||
|         sti->need_parsing = AVSTREAM_PARSE_FULL; | ||||
|         break; | ||||
|     case AV_CODEC_ID_PRORES_RAW: | ||||
|     case AV_CODEC_ID_PRORES: | ||||
|     case AV_CODEC_ID_APV: | ||||
|     case AV_CODEC_ID_EVC: | ||||
|     case AV_CODEC_ID_AV1: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user