summaryrefslogtreecommitdiffstats
path: root/src/file_mpg.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2009-06-12 08:54:49 +0200
committerChristophe Grenier <grenier@cgsecurity.org>2009-06-12 08:54:49 +0200
commiteeb308e6bfc1c46e69f72f94965f555f75e02093 (patch)
tree7c6594d0fbdd49baa91e200740f3b9a5344733ba /src/file_mpg.c
parent4452138345a859118938f230cc5311864ed55a66 (diff)
PhotoRec: try to detect MPEG end of file
Diffstat (limited to 'src/file_mpg.c')
-rw-r--r--src/file_mpg.c105
1 files changed, 80 insertions, 25 deletions
diff --git a/src/file_mpg.c b/src/file_mpg.c
index 2c50075..9ed5585 100644
--- a/src/file_mpg.c
+++ b/src/file_mpg.c
@@ -2,7 +2,7 @@
File: file_mpg.c
- Copyright (C) 1998-2005,2007 Christophe GRENIER <grenier@cgsecurity.org>
+ Copyright (C) 1998-2005,2007-2009 Christophe GRENIER <grenier@cgsecurity.org>
This software is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@
static void register_header_check_mpg(file_stat_t *file_stat);
static int header_check_mpg(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
+static int data_check_mpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
const file_hint_t file_hint_mpg= {
.extension="mpg",
@@ -55,37 +56,91 @@ static int header_check_mpg(const unsigned char *buffer, const unsigned int buff
{
if(file_recovery!=NULL && file_recovery->file_stat!=NULL && file_recovery->file_stat->file_hint==&file_hint_mpg)
return 0;
- /* ISO/IEC 11172/13818-1 SYSTEM MULTIPLEXED PACKETIZED ELEMENTARY *
- * STREAM AND HEADERS *
- * 0x000001BA pack header start code *
- * 0x000001BB system header start code *
- * 2 bytes: header_size
- * 1 byte: stream_id
- * 0x000001BE padding block start code *
- * 0x000001BD private 1 block start code *
- * 0x000001BF private 2 block start code *
- * *
- * ISO/IEC 11172-2/13818-2 (MPEG-1/2 video) ELEMENTARY VIDEO HEADER *
- * 0x000001B3 video sequence start code *
- * 0x000001B2 video user meta data start code *
- * *
- * ISO/IEC 14496-2 (MPEG-4 video) ELEMENTARY VIDEO HEADER *
- * 0x000001B0 visual object sequence start code *
- * 0x000001B2 user meta data start code *
- * 0x000001B5 visual object start code */
+ /* MPEG-1 http://andrewduncan.ws/MPEG/MPEG-1.ps
+ * MPEG-2 Program stream http://neuron2.net/library/mpeg2/iso13818-1.pdf
+ */
+ /* MPEG-2
+ pack_start_code=0x000001BA 32
+ '01' 2
+ system_clock_reference_base [32..30] 3
+ marker_bit 1
+ system_clock_reference_base [29..15] 15
+ marker_bit 1
+ system_clock_reference_base [14..0] 15
+ marker_bit 1
+ system_clock_reference_extension 9 uimsbf
+ marker_bit 1
+ program_mux_rate 22 uimsbf
+ marker_bit 1
+ marker_bit 1
+ reserved 5
+ pack_stuffing_length 3 uimsbf
+ ...
+ */
+ /* ISO/IEC INTERNATIONAL 13818-1 STANDARD
+ system_header_start_code 32
+ header_length 16
+ marker_bit 1
+ rate_bound 22
+ marker_bit 1
+ audio_bound 6
+ fixed_flag 1
+ CSPS_flag 1
+ system_audio_lock_flag 1
+ system_video_lock_flag 1
+ marker_bit 1
+ video_bound 5
+ packet_rate_restriction_flag 1
+ reserved_bits 7
+ */
if(buffer[0]==0x00 && buffer[1]==0x00 && buffer[2]==0x01 &&
- (buffer[3]==0xB0 ||
- (buffer[3]==0xB3 && ((buffer[4]<<8)+(buffer[5]>>8)>0) && ((buffer[5]<<8)+buffer[6]>0)) ||
- buffer[3]==0xB5 ||
- buffer[3]==0xBA ||
- (buffer[3]==0xBB && (buffer[4]<<8)+(buffer[5]>>8)>0 && (buffer[6]&0x80)==0x80)))
+ (
+ /* MPEG-1 system header start code, several per file */
+ (buffer[3]==0xBA && (buffer[4]&0xF1)==0x21) ||
+ /* MPEG2 system header start code, several per file */
+ (buffer[3]==0xBA && (buffer[4]&0xc4)==0x44) ||
+ /* MPEG-1 system header start code */
+ (buffer[3]==0xBB && (buffer[6]&0x80)==0x80 && (buffer[8]&0x01)==0x01) ||
+ /* MPEG-1 sequence header code, horizontal size>0 && vertical size>0, bitrate!=0 */
+ (buffer[3]==0xB3 && (buffer[4]<<8)+(buffer[5]>>8)>0 && (buffer[5]<<8)+buffer[6]>0 && buffer[8]!=0) ||
+ /* ISO/IEC 14496-2 (MPEG-4 video) ELEMENTARY VIDEO HEADER - visual object sequence start code */
+ (buffer[3]==0xB0) ||
+ /* ISO/IEC 14496-2 (MPEG-4 video) ELEMENTARY VIDEO HEADER - visual object start code */
+ (buffer[3]==0xB5)
+ )
+ )
{
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_mpg.extension;
+ file_recovery_new->data_check=&data_check_mpg;
+ file_recovery_new->file_check=&file_check_size;
return 1;
}
return 0;
}
-
+static int data_check_mpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
+{
+ const unsigned char padding_iso_end[8]= {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xB9};
+ const unsigned char sequence_end_iso_end[8]={0x00, 0x00, 0x01, 0xB7, 0x00, 0x00, 0x01, 0xB9};
+ unsigned int i;
+ /* search padding + end code */
+ if(memcmp(&buffer[buffer_size/2-4], padding_iso_end, sizeof(padding_iso_end))==0)
+ {
+ file_recovery->calculated_file_size=file_recovery->file_size+4;
+ return 2;
+ }
+ /* search video sequence end followed by iso end code*/
+ for(i=buffer_size/2-7; i<buffer_size-7; i++)
+ {
+ if(buffer[i]==0x00 && memcmp(&buffer[i], sequence_end_iso_end, sizeof(sequence_end_iso_end))==0)
+ {
+ file_recovery->calculated_file_size=file_recovery->file_size+i+sizeof(sequence_end_iso_end)-buffer_size/2;
+ return 2;
+ }
+ }
+ /* some files don't end by iso end code, so continue... */
+ file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
+ return 1;
+}