diff options
author | Diego 'Flameeyes' Pettenò <flameeyes@gmail.com> | 2007-04-04 21:07:48 +0200 |
---|---|---|
committer | Diego 'Flameeyes' Pettenò <flameeyes@gmail.com> | 2007-04-04 21:07:48 +0200 |
commit | 3b6ef82b64306c9d03341fe60e5ad641ad50809d (patch) | |
tree | fa93a5ec92eca557517f7b6f4aa6fd8e2cb15a85 /src/libffmpeg/ff_mpeg_parser.c | |
parent | 0e0d536d4d4c3c354fdebd7ee8b1c70a2a9edc0c (diff) | |
download | xine-lib-3b6ef82b64306c9d03341fe60e5ad641ad50809d.tar.gz xine-lib-3b6ef82b64306c9d03341fe60e5ad641ad50809d.tar.bz2 |
Rename FFmpeg plugins' sources so that there are no conflicts with other source files.
This way when you get a backtrace, video_decoder.c is never the FFmpeg one.
--HG--
rename : src/libffmpeg/audio_decoder.c => src/libffmpeg/ff_audio_decoder.c
rename : src/libffmpeg/dvaudio_decoder.c => src/libffmpeg/ff_dvaudio_decoder.c
rename : src/libffmpeg/mpeg_parser.c => src/libffmpeg/ff_mpeg_parser.c
rename : src/libffmpeg/mpeg_parser.h => src/libffmpeg/ff_mpeg_parser.h
rename : src/libffmpeg/video_decoder.c => src/libffmpeg/ff_video_decoder.c
rename : src/libffmpeg/xine_decoder.c => src/libffmpeg/ffmpeg_decoder.c
rename : src/libffmpeg/xine_decoder.h => src/libffmpeg/ffmpeg_decoder.h
rename : src/libffmpeg/xine_encoder.c => src/libffmpeg/ffmpeg_encoder.c
Diffstat (limited to 'src/libffmpeg/ff_mpeg_parser.c')
-rw-r--r-- | src/libffmpeg/ff_mpeg_parser.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/libffmpeg/ff_mpeg_parser.c b/src/libffmpeg/ff_mpeg_parser.c new file mode 100644 index 000000000..fcee29a80 --- /dev/null +++ b/src/libffmpeg/ff_mpeg_parser.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2001-2004 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Simple MPEG-ES parser/framer by Thibaut Mattern (tmattern@noos.fr) + * based on libmpeg2 decoder. + * + * $Id: mpeg_parser.c,v 1.7 2007/03/29 18:52:45 dgp85 Exp $ + */ +#define LOG_MODULE "mpeg_parser" +#define LOG_VERBOSE +/* +#define LOG +*/ +#include "ff_mpeg_parser.h" + +/* mpeg frame rate table from lavc */ +static const int frame_rate_tab[][2] = { + { 0, 0}, + {24000, 1001}, + { 24, 1}, + { 25, 1}, + {30000, 1001}, + { 30, 1}, + { 50, 1}, + {60000, 1001}, + { 60, 1}, + /* Xing's 15fps: (9) */ + { 15, 1}, + /* libmpeg3's "Unofficial economy rates": (10-13) */ + { 5, 1}, + { 10, 1}, + { 12, 1}, + { 15, 1}, + { 0, 0}, +}; + +void mpeg_parser_init (mpeg_parser_t *parser) +{ + parser->chunk_buffer = xine_xmalloc(BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + mpeg_parser_reset(parser); +} + +void mpeg_parser_dispose (mpeg_parser_t *parser) +{ + if ( parser == NULL ) return; + + free(parser->chunk_buffer); +} + +void mpeg_parser_reset (mpeg_parser_t *parser) +{ + parser->shift = 0xffffff00; + parser->is_sequence_needed = 1; + parser->in_slice = 0; + parser->chunk_ptr = parser->chunk_buffer; + parser->chunk_start = parser->chunk_buffer; + parser->buffer_size = 0; + parser->code = 0xb4; + parser->picture_coding_type = 0; + parser->width = 0; + parser->height = 0; + parser->rate_code = 0; + parser->aspect_ratio_info = 0; + parser->frame_duration = 0; + parser->is_mpeg1 = 0; + parser->has_sequence = 0; + parser->frame_aspect_ratio = 0.0; +} + +static void parse_header_picture (mpeg_parser_t *parser, uint8_t * buffer) +{ + parser->picture_coding_type = (buffer [1] >> 3) & 7; +} + +static double get_aspect_ratio(mpeg_parser_t *parser) +{ + double ratio; + double mpeg1_pel_ratio[16] = {1.0 /* forbidden */, + 1.0, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, + 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 1.0 /*reserved*/ }; + + if( !parser->is_mpeg1 ) { + /* these hardcoded values are defined on mpeg2 standard for + * aspect ratio. other values are reserved or forbidden. */ + switch (parser->aspect_ratio_info) { + case 2: + ratio = 4.0 / 3.0; + break; + case 3: + ratio = 16.0 / 9.0; + break; + case 4: + ratio = 2.11 / 1.0; + break; + case 1: + default: + ratio = (double)parser->width / (double)parser->height; + break; + } + } else { + /* mpeg1 constants refer to pixel aspect ratio */ + ratio = (double)parser->width / (double)parser->height; + ratio /= mpeg1_pel_ratio[parser->aspect_ratio_info]; + } + + return ratio; +} + +static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int len) +{ + int is_frame_done; + int next_code = parser->code; + + /* wait for sequence_header_code */ + if (parser->is_sequence_needed) { + if (code != 0xb3) { + lprintf("waiting for sequence header\n"); + parser->chunk_ptr = parser->chunk_buffer; + return 0; + } + } + + is_frame_done = parser->in_slice && ((!next_code) || (next_code == 0xb7)); + + if (is_frame_done) + parser->in_slice = 0; + + switch (code) { + case 0x00: /* picture_start_code */ + + parse_header_picture (parser, buffer); + + parser->in_slice = 1; + + switch (parser->picture_coding_type) { + case B_TYPE: + lprintf ("B-Frame\n"); + break; + + case P_TYPE: + lprintf ("P-Frame\n"); + break; + + case I_TYPE: + lprintf ("I-Frame\n"); + break; + } + break; + + case 0xb2: /* user data code */ + /* process_userdata(mpeg2dec, buffer); */ + break; + + case 0xb3: /* sequence_header_code */ + { + int value; + uint16_t width, height; + + if (parser->is_sequence_needed) { + parser->is_sequence_needed = 0; + } + + if ((buffer[6] & 0x20) != 0x20) { + lprintf("Invalid sequence: missing marker_bit\n"); + parser->has_sequence = 0; + break; /* missing marker_bit */ + } + + value = (buffer[0] << 16) | + (buffer[1] << 8) | + buffer[2]; + width = ((value >> 12) + 15) & ~15; + height = ((value & 0xfff) + 15) & ~15; + + if ((width > 1920) || (height > 1152)) { + lprintf("Invalid sequence: width=%d, height=%d\n", width, height); + parser->has_sequence = 0; + break; /* size restrictions for MP@HL */ + } + + parser->width = width; + parser->height = height; + parser->rate_code = buffer[3] & 15; + parser->aspect_ratio_info = buffer[3] >> 4; + + if (parser->rate_code < (sizeof(frame_rate_tab)/sizeof(*frame_rate_tab))) { + parser->frame_duration = 90000; + parser->frame_duration *= frame_rate_tab[parser->rate_code][1]; + parser->frame_duration /= frame_rate_tab[parser->rate_code][0]; + } else { + printf ("invalid/unknown frame rate code : %d \n", + parser->rate_code); + parser->frame_duration = 0; + } + + parser->has_sequence = 1; + parser->is_mpeg1 = 1; + } + break; + + case 0xb5: /* extension_start_code */ + switch (buffer[0] & 0xf0) { + case 0x10: /* sequence extension */ + parser->is_mpeg1 = 0; + } + + default: + if (code >= 0xb9) + lprintf ("stream not demultiplexed ?\n"); + + if (code >= 0xb0) + break; + } + return is_frame_done; +} + +static inline uint8_t *copy_chunk (mpeg_parser_t *parser, + uint8_t *current, uint8_t *end) +{ + uint32_t shift; + uint8_t *chunk_ptr; + uint8_t *limit; + uint8_t byte; + + shift = parser->shift; + chunk_ptr = parser->chunk_ptr; + + limit = current + (parser->chunk_buffer + BUFFER_SIZE - chunk_ptr); + if (limit > end) + limit = end; + + while (1) { + + byte = *current++; + *chunk_ptr++ = byte; + if (shift != 0x00000100) { + shift = (shift | byte) << 8; + if (current < limit) + continue; + if (current == end) { + parser->chunk_ptr = chunk_ptr; + parser->shift = shift; + lprintf("Need more bytes\n"); + return NULL; + } else { + /* we filled the chunk buffer without finding a start code */ + lprintf("Buffer full\n"); + parser->code = 0xb4; /* sequence_error_code */ + parser->chunk_ptr = parser->chunk_buffer; + return current; + } + } + lprintf("New chunk: 0x%2X\n", byte); + parser->chunk_ptr = chunk_ptr; + parser->shift = 0xffffff00; + parser->code = byte; + return current; + } +} + + +uint8_t *mpeg_parser_decode_data (mpeg_parser_t *parser, + uint8_t *current, uint8_t *end, + int *flush) +{ + int ret; + uint8_t code; + + ret = 0; + *flush = 0; + + while (current != end) { + if (parser->chunk_ptr == parser->chunk_buffer) { + /* write the beginning of the chunk */ + parser->chunk_buffer[0] = 0x00; + parser->chunk_buffer[1] = 0x00; + parser->chunk_buffer[2] = 0x01; + parser->chunk_buffer[3] = parser->code; + parser->chunk_ptr += 4; + parser->chunk_start = parser->chunk_ptr; + parser->has_sequence = 0; + } + + code = parser->code; + + current = copy_chunk (parser, current, end); + if (current == NULL) + return NULL; + ret = parse_chunk (parser, code, parser->chunk_start, + parser->chunk_ptr - parser->chunk_start - 4); + parser->chunk_start = parser->chunk_ptr; + if (ret == 1) { + if (parser->has_sequence) { + parser->frame_aspect_ratio = get_aspect_ratio(parser); + } + parser->buffer_size = parser->chunk_ptr - parser->chunk_buffer - 4; + parser->chunk_ptr = parser->chunk_buffer; + + if (parser->code == 0xb7) /* sequence end, maybe a still menu */ + *flush = 1; + + return current; + } + } + + return NULL; +} |