On Mon, Sep 19, 2005 at 02:04:01PM -0400, Jesse Guardiani wrote:
Hui Zhou wrote:
[...]
I am running 0.3.6w, and all the mpegs it produces are "bad" as you
described. Actually the only "badness" I believe is just in the
program pack header the length of stuffing bytes is mis-marked which
resulted in extra-stuffing bytes in many packs. Apparently projectX
doesn't expect such and goes through some panic procedures which
wastes a lot of processing time.
I believe just repair the pack headers should make projectx happy. I
never tried it though.
How would I go about doing that? It would make my life soooooo much
easier/faster,
as I have a ton of pre 0.3.8 mpegs I'd like to burn...
I had a closer look at the problem. It seems that it is not simply
header error, but simply there are two extra stuffing bytes every here
and there. Since in some cases, the total stuffing bytes exceeds the
maximum of 7 bytes, so I can't just fix it by correcting the header.
The only way I see is just dump the stream to another file, skipping
the extra bytes along the way.
Attached is a c program does that. Compile it with "make packfix", and
drop it in your path. To use it, chdir to the directory of video and
run "packfix video_file_name", it will dump a fixed stream "fixed.mpg"
in the same directory. A simple test on my side seems it will make
projectx happy. Unfortunately, it does not check error messages, so
make sure you have enough disk space.
Hope that helps.
--
Hui Zhou
/* Copyright: Hui Zhou <[EMAIL PROTECTED]>, 2005 */
/* Borrows code from Tomi Ollila, too ät iki fi */
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
/******************************* zzob
******************************************/
typedef int bool;
#define true 1
#define false 0
typedef struct _ReadingBuffer ZeroZeroOneBuf;
struct _ReadingBuffer
{
unsigned char * data; /* active data pointer */
int len; /* active data length */
off_t pos; /* file offset */
off_t limit;
int * co_pos;
struct { /* c_* variables constant after initialized */
int c_fd;
unsigned char * c_buf; /* pointer to start of whole buffer area */
int c_buflen; /* bytes of whole buffer area */
} p;
};
bool zzob_init(ZeroZeroOneBuf * zzob, int fd, unsigned char * buf, int buflen);
bool zzob_fill(ZeroZeroOneBuf* zzob);
int zzob_need(ZeroZeroOneBuf* zzob, int size);
bool zzob_skip(ZeroZeroOneBuf* zzob, int size);
bool zzob_init(ZeroZeroOneBuf * zzob, int fd, unsigned char * buf, int buflen)
{
unsigned char * data;
zzob->p.c_fd = fd;
zzob->p.c_buf = buf;
zzob->p.c_buflen = buflen;
zzob->pos = 0;
zzob->data = buf;
zzob->len = 0;
zzob->limit=0;
zzob->co_pos=NULL;
return true;
}
/* read in some data into buffer */
bool zzob_fill(ZeroZeroOneBuf* zzob){
int l;
/* bufend : the absolute end of buffer */
unsigned char * bufend = zzob->p.c_buf + zzob->p.c_buflen;
/* rpos : the end of active data */
unsigned char * rpos = zzob->data + zzob->len;
/* if current end of active data reaches the end of buffer ... */
if (rpos - bufend >= 0)
{
if (zzob->len == zzob->p.c_buflen)
return false; /* raise BufferFullException */
if (zzob->len){
memmove(zzob->p.c_buf, zzob->data, zzob->len);
}
zzob->data = zzob->p.c_buf;
rpos = zzob->data + zzob->len;
}
if(zzob->limit && zzob->limit-zzob->pos<bufend-rpos)
l = read(zzob->p.c_fd, rpos, zzob->limit-zzob->pos);
else
l = read(zzob->p.c_fd, rpos, bufend - rpos);
if (l <= 0)
return false; /* raise EOFException */
zzob->len += l;
return true;
}
int zzob_need(ZeroZeroOneBuf* zzob, int size){
while (zzob->len < size){
if(! zzob_fill(zzob))
return zzob->len;
}
return size;
}
bool zzob_skip(ZeroZeroOneBuf* zzob, int size){
if(zzob->len>=size){
zzob->pos+=size;
zzob->data+=size;
zzob->len-=size;
}
else{
zzob->pos=lseek(zzob->p.c_fd, size-zzob->len, SEEK_CUR);
zzob->data=zzob->p.c_buf;
zzob->len=0;
}
return true;
}
/********************************* end of zzob ******************************/
#define PROGRAM_BUF_LEN 512
unsigned char program_buf[PROGRAM_BUF_LEN];
FILE* indexfile;
off_t total_size=0;
time_t start_time;
int index_size=2;
int len_size=2;
int pos_size=2;
unsigned int pack_index=0;
unsigned int picture_index=0;
off_t last_pack_pos=0;
float fps=29.97;
void showstatus(int signum){
int t=time(NULL)-start_time;
int sec;
int min;
int hr;
float percent=100*(float)last_pack_pos/(float)total_size;
float length;
float pfps;
if(t>2){
pfps=((float)picture_index/t);
}
else{
pfps=0;
}
hr=t/3600;
t=t%3600;
min=t/60;
sec=t%60;
length=(picture_index/fps)/60;
printf("\033[u [%02d:%02d:%02d] --- %%%.2f", hr, min, sec, percent);
//printf("[%02d:%02d:%02d] %ld frames %f", hr, min, sec, picture_index,
percent);
fflush(stdout);
if(signum){
signal(SIGALRM, showstatus);
alarm(1);
}
}
int has_badbytes=0;
int fd;
FILE* out;
off_t pos=0;
char dump_buffer[10000];
void dump(off_t to_pos){
int n;
//printf("dumping %llx -- %llx\n", pos, to_pos);
while(pos<to_pos){
last_pack_pos=pos;
n=to_pos-pos;
if(n>10000) n=10000;
n=read(fd, dump_buffer, n);
if(n<=0){
printf("failed reading %d bytes at %llx\n", pos);
return;
}
else{
//printf("dumping %d bytes\n", n);
}
pos+=n;
fwrite(dump_buffer, n, 1, out);
}
}
void skip(int n){
pos=lseek(fd, n, SEEK_CUR);
}
/****************************************************************************/
void parse_program(int fd){
ZeroZeroOneBuf zzob;
off_t bad_offset;
off_t bad_length=0;
int badbytes;
int n;
int hn;
int type;
zzob_init(&zzob, fd, program_buf, PROGRAM_BUF_LEN);
zzob.limit=0;
while (1){
if(4!=zzob_need(&zzob, 4)) return;
badbytes=0;
if(zzob.data[0]==0x0 && zzob.data[1]==0x0 && zzob.data[2]==0x1){
if(zzob.data[3]<0xb9){
badbytes=3;
}
else if (zzob.data[3]==0xba){
last_pack_pos=zzob.pos;
zzob_need(&zzob, 13);
n=14+(zzob.data[13]&0x7);
zzob_skip(&zzob, n);
zzob_need(&zzob,4);
n=0;
while(zzob.data[n]==0xff)n++;
if(n>0){
fwrite(&zzob.pos, 8, 1, indexfile);
fwrite(&n, 1, 1, indexfile);
has_badbytes=1;
}
}
else if (zzob.data[3]<0xf0){ // PES Stream Header
if(zzob.data[3]==0xbd || zzob.data[3]>=0xc0){
zzob_need(&zzob, 9);
n=6+(zzob.data[4]<<8)+zzob.data[5];
hn=9+zzob.data[8];
type=zzob.data[3];
zzob_skip(&zzob, n);
}
else{ //padding stream and private stream 2, as well as 0xbb
(system header) and 0xbc (program map)
zzob_need(&zzob, 6);
n=6+(zzob.data[4]<<8)+zzob.data[5];
zzob_skip(&zzob, n);
}
}
else{ // program directory and misc
badbytes=3;
}
}
else{
badbytes=1;
}
if( badbytes){
if(bad_length) bad_length+=badbytes;
else{
bad_offset=zzob.pos;
bad_length=badbytes;
}
zzob.data+=badbytes;
zzob.len-=badbytes;
zzob.pos+=badbytes;
}
else{
if(bad_length){
//program_report(BAD, bad_offset, bad_length);
bad_length=0;
}
}
}
}
int main(int argc, char** argv){
int n;
if(argc>1){
fd=open(argv[1], O_RDONLY);
if(fd<0){
printf ("Failed to open file %s\n", argv[1]);
return 1;
}
total_size=lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
}
else{
printf("No file supplied\n");
return 1;
}
indexfile=fopen("packstuff.bin", "w");
if(indexfile==NULL) {
printf("Failed to open index.bin\n");
return 1;
}
start_time=time(NULL);
printf("Indexing %s ... \n", argv[1]);
printf("\033[s"); fflush(stdout);
showstatus(SIGALRM);
parse_program(fd);
fclose(indexfile);
showstatus(0);
printf("\n");
off_t pos;
if(has_badbytes){
printf("Dumping fixed.mpg ...\n");
n=0;
lseek(fd, 0, SEEK_SET);
indexfile=fopen("packstuff.bin", "r");
out=fopen("fixed.mpg", "w");
while(fread(&pos, 8, 1, indexfile)){
fread(&n, 1, 1, indexfile);
dump(pos);
skip(n);
}
fclose(indexfile);
fclose(out);
printf("\n");
}
else{
printf("The stream seems ok to me.");
}
close(fd);
}