/* * MPEG mode for QEmacs. * Copyright (c) 2001 Fabrice Bellard. * * This library 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 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "qe.h" #define SEQ_END_CODE 0x000001b7 #define SEQ_START_CODE 0x000001b3 #define GOP_START_CODE 0x000001b8 #define PICTURE_START_CODE 0x00000100 #define SLICE_MIN_START_CODE 0x00000101 #define SLICE_MAX_START_CODE 0x000001af #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 #define PACK_START_CODE 0x000001ba #define SYSTEM_HEADER_START_CODE 0x000001bb #define ISO_11172_END_CODE 0x000001b9 static int mpeg_display(EditState *s, DisplayState *ds, int offset) { unsigned int startcode; int ret, badchars, offset_start; unsigned char buf[4]; /* search start code */ badchars = 0; display_bol(ds); display_printf(ds, -1, -1, "%08x:", offset); for(;;) { ret = eb_read(s->b, offset, buf, 4); if (ret == 0) { if (badchars) display_eol(ds, -1, -1); goto the_end; } if (ret == 4) { startcode = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; if ((startcode & 0xffffff00) == 0x00000100) { if (badchars) { display_eol(ds, -1, -1); display_bol(ds); display_printf(ds, -1, -1, "%08x:", offset); } break; } } /* display unknown chars */ display_printf(ds, -1, -1, " ["); display_printhex(ds, offset, offset + 1, buf[0], 2); display_printf(ds, -1, -1, "]"); offset++; if (++badchars == 8) { badchars = 0; display_eol(ds, -1, -1); goto the_end; } } offset_start = offset; offset += 4; display_printf(ds, offset_start, offset, " [%08x] ", startcode); switch(startcode) { case SEQ_END_CODE: display_printf(ds, -1, -1, "SEQ_END"); break; case SEQ_START_CODE: display_printf(ds, -1, -1, "SEQUENCE"); break; case PICTURE_START_CODE: display_printf(ds, -1, -1, "PICTURE"); break; case GOP_START_CODE: display_printf(ds, -1, -1, "GOP"); break; case EXT_START_CODE: display_printf(ds, -1, -1, "EXT"); break; case PACK_START_CODE: display_printf(ds, -1, -1, "PACK"); break; case SYSTEM_HEADER_START_CODE: display_printf(ds, -1, -1, "SYSTEM"); break; default: if (startcode >= SLICE_MIN_START_CODE && startcode <= SLICE_MAX_START_CODE) { display_printf(ds, -1, -1, "SLICE %d", startcode & 0xff); } else { display_printf(ds, -1, -1, "UNKNOWN", startcode); } break; } display_eol(ds, -1, -1); the_end: return offset; } /* go to previous synchronization point */ static int mpeg_backward_offset(EditState *s, int offset) { unsigned char buf[4]; unsigned int startcode; int ret; for(;;) { if (offset <= 0) break; ret = eb_read(s->b, offset, buf, 4); if (ret != 4) break; startcode = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; if ((startcode & 0xffffff00) == 0x00000100) { break; } offset--; } return offset; } static int mpeg_mode_init(EditState *s, ModeSavedData *saved_data) { int ret; ret = text_mode_init(s, saved_data); if (ret) return ret; s->hex_mode = 1; s->hex_nibble = 0; s->wrap = WRAP_TRUNCATE; return 0; } static int mpeg_mode_probe(ModeProbeData *p) { if (p->buf_size >= 4 && p->buf[0] == 0x00 && p->buf[1] == 0x00 && p->buf[2] == 0x01 && p->buf[3] >= 0xa0) return 100; else return 0; } static ModeDef mpeg_mode = { "mpeg", mode_probe: mpeg_mode_probe, mode_init: mpeg_mode_init, mode_close: NULL, text_display: mpeg_display, text_backward_offset: mpeg_backward_offset, write_char: hex_write_char, }; static int mpeg_init(void) { qe_register_mode(&mpeg_mode); return 0; } qe_module_init(mpeg_init);