2010-01-30 13:35:03 +00:00
|
|
|
/*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
* This program 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.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2001-11-04 00:00:38 +00:00
|
|
|
#include <stdio.h>
|
2001-11-04 00:38:32 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2004-10-28 00:50:21 +00:00
|
|
|
#include <inttypes.h>
|
2001-11-04 00:38:32 +00:00
|
|
|
|
2004-10-28 00:50:21 +00:00
|
|
|
#include "loader/wine/mmreg.h"
|
|
|
|
#include "loader/wine/vfw.h"
|
2001-11-04 00:38:32 +00:00
|
|
|
|
2007-03-16 22:47:23 +00:00
|
|
|
#include "stream/stream.h"
|
2004-10-28 00:50:21 +00:00
|
|
|
#include "libmpdemux/muxer.h"
|
2007-03-16 22:47:23 +00:00
|
|
|
#include "libmpdemux/demuxer.h"
|
2004-10-28 00:50:21 +00:00
|
|
|
|
2008-06-06 13:28:25 +00:00
|
|
|
/* linking hacks */
|
2004-10-28 00:50:21 +00:00
|
|
|
char *info_name;
|
|
|
|
char *info_artist;
|
|
|
|
char *info_genre;
|
|
|
|
char *info_subject;
|
|
|
|
char *info_copyright;
|
|
|
|
char *info_sourceform;
|
|
|
|
char *info_comment;
|
2001-11-04 00:00:38 +00:00
|
|
|
|
2008-06-06 13:28:25 +00:00
|
|
|
char* out_filename = NULL;
|
|
|
|
char* force_fourcc=NULL;
|
|
|
|
char* passtmpfile="divx2pass.log";
|
|
|
|
|
2001-11-04 00:00:38 +00:00
|
|
|
static const short h263_format[8][2] = {
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 128, 96 },
|
|
|
|
{ 176, 144 },
|
|
|
|
{ 352, 288 },
|
|
|
|
{ 704, 576 },
|
|
|
|
{ 1408, 1152 },
|
2001-11-04 19:47:19 +00:00
|
|
|
{ 320, 240 }
|
2001-11-04 00:00:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
unsigned char* buffer;
|
|
|
|
int bufptr=0;
|
|
|
|
int bitcnt=0;
|
|
|
|
unsigned char buf=0;
|
|
|
|
|
2008-04-30 13:53:40 +00:00
|
|
|
static unsigned int x_get_bits(int n){
|
2001-11-04 00:00:38 +00:00
|
|
|
unsigned int x=0;
|
|
|
|
while(n-->0){
|
|
|
|
if(!bitcnt){
|
|
|
|
// fill buff
|
|
|
|
buf=buffer[bufptr++];
|
|
|
|
bitcnt=8;
|
|
|
|
}
|
|
|
|
//x=(x<<1)|(buf&1);buf>>=1;
|
|
|
|
x=(x<<1)|(buf>>7);buf<<=1;
|
|
|
|
--bitcnt;
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define get_bits(xxx,n) x_get_bits(n)
|
|
|
|
#define get_bits1(xxx) x_get_bits(1)
|
|
|
|
#define skip_bits(xxx,n) x_get_bits(n)
|
|
|
|
#define skip_bits1(xxx) x_get_bits(1)
|
|
|
|
|
2001-11-04 19:47:19 +00:00
|
|
|
int format;
|
|
|
|
int width=320;
|
|
|
|
int height=240;
|
2001-11-04 00:38:32 +00:00
|
|
|
|
2001-11-04 00:00:38 +00:00
|
|
|
/* most is hardcoded. should extend to handle all h263 streams */
|
2008-04-30 13:53:40 +00:00
|
|
|
static int h263_decode_picture_header(unsigned char *b_ptr)
|
2001-11-04 00:00:38 +00:00
|
|
|
{
|
2001-11-04 19:47:19 +00:00
|
|
|
int i;
|
2009-05-13 02:58:57 +00:00
|
|
|
|
2001-11-04 19:47:19 +00:00
|
|
|
for(i=0;i<16;i++) printf(" %02X",b_ptr[i]); printf("\n");
|
2009-05-13 02:58:57 +00:00
|
|
|
|
2001-11-04 00:00:38 +00:00
|
|
|
buffer=b_ptr;
|
|
|
|
bufptr=bitcnt=buf=0;
|
|
|
|
|
|
|
|
/* picture header */
|
2001-11-04 19:47:19 +00:00
|
|
|
if (get_bits(&s->gb, 22) != 0x20){
|
|
|
|
printf("bad picture header\n");
|
2001-11-04 00:00:38 +00:00
|
|
|
return -1;
|
2001-11-04 19:47:19 +00:00
|
|
|
}
|
2001-11-04 00:00:38 +00:00
|
|
|
skip_bits(&s->gb, 8); /* picture timestamp */
|
|
|
|
|
2001-11-04 19:47:19 +00:00
|
|
|
if (get_bits1(&s->gb) != 1){
|
|
|
|
printf("bad marker\n");
|
2001-11-04 00:00:38 +00:00
|
|
|
return -1; /* marker */
|
2001-11-04 19:47:19 +00:00
|
|
|
}
|
|
|
|
if (get_bits1(&s->gb) != 0){
|
|
|
|
printf("bad h263 id\n");
|
2001-11-04 00:00:38 +00:00
|
|
|
return -1; /* h263 id */
|
2001-11-04 19:47:19 +00:00
|
|
|
}
|
2001-11-04 00:00:38 +00:00
|
|
|
skip_bits1(&s->gb); /* split screen off */
|
|
|
|
skip_bits1(&s->gb); /* camera off */
|
|
|
|
skip_bits1(&s->gb); /* freeze picture release off */
|
|
|
|
|
|
|
|
format = get_bits(&s->gb, 3);
|
|
|
|
|
|
|
|
if (format != 7) {
|
|
|
|
printf("h263_plus = 0 format = %d\n",format);
|
|
|
|
/* H.263v1 */
|
|
|
|
width = h263_format[format][0];
|
|
|
|
height = h263_format[format][1];
|
|
|
|
printf("%d x %d\n",width,height);
|
2001-11-04 19:47:19 +00:00
|
|
|
// if (!width) return -1;
|
2001-11-04 00:00:38 +00:00
|
|
|
|
|
|
|
printf("pict_type=%d\n",get_bits1(&s->gb));
|
|
|
|
printf("unrestricted_mv=%d\n",get_bits1(&s->gb));
|
|
|
|
#if 1
|
|
|
|
printf("SAC: %d\n",get_bits1(&s->gb));
|
|
|
|
printf("advanced prediction mode: %d\n",get_bits1(&s->gb));
|
|
|
|
printf("PB frame: %d\n",get_bits1(&s->gb));
|
|
|
|
#else
|
|
|
|
if (get_bits1(&s->gb) != 0)
|
|
|
|
return -1; /* SAC: off */
|
|
|
|
if (get_bits1(&s->gb) != 0)
|
|
|
|
return -1; /* advanced prediction mode: off */
|
|
|
|
if (get_bits1(&s->gb) != 0)
|
|
|
|
return -1; /* not PB frame */
|
|
|
|
#endif
|
|
|
|
printf("qscale=%d\n",get_bits(&s->gb, 5));
|
|
|
|
skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */
|
|
|
|
} else {
|
|
|
|
printf("h263_plus = 1\n");
|
|
|
|
/* H.263v2 */
|
2001-11-04 19:47:19 +00:00
|
|
|
if (get_bits(&s->gb, 3) != 1){
|
|
|
|
printf("H.263v2 A error\n");
|
2001-11-04 00:00:38 +00:00
|
|
|
return -1;
|
2001-11-04 19:47:19 +00:00
|
|
|
}
|
|
|
|
if (get_bits(&s->gb, 3) != 6){ /* custom source format */
|
|
|
|
printf("custom source format\n");
|
2001-11-04 00:00:38 +00:00
|
|
|
return -1;
|
2001-11-04 19:47:19 +00:00
|
|
|
}
|
2001-11-04 00:00:38 +00:00
|
|
|
skip_bits(&s->gb, 12);
|
|
|
|
skip_bits(&s->gb, 3);
|
|
|
|
printf("pict_type=%d\n",get_bits(&s->gb, 3) + 1);
|
|
|
|
// if (s->pict_type != I_TYPE &&
|
|
|
|
// s->pict_type != P_TYPE)
|
|
|
|
// return -1;
|
|
|
|
skip_bits(&s->gb, 7);
|
|
|
|
skip_bits(&s->gb, 4); /* aspect ratio */
|
|
|
|
width = (get_bits(&s->gb, 9) + 1) * 4;
|
|
|
|
skip_bits1(&s->gb);
|
|
|
|
height = get_bits(&s->gb, 9) * 4;
|
|
|
|
printf("%d x %d\n",width,height);
|
2001-11-04 19:47:19 +00:00
|
|
|
//if (height == 0)
|
|
|
|
// return -1;
|
2001-11-04 00:00:38 +00:00
|
|
|
printf("qscale=%d\n",get_bits(&s->gb, 5));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PEI */
|
|
|
|
while (get_bits1(&s->gb) != 0) {
|
|
|
|
skip_bits(&s->gb, 8);
|
|
|
|
}
|
|
|
|
// s->f_code = 1;
|
|
|
|
// s->width = width;
|
|
|
|
// s->height = height;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-11-04 00:38:32 +00:00
|
|
|
int postable[32768];
|
2001-11-04 00:00:38 +00:00
|
|
|
|
2004-10-29 22:05:34 +00:00
|
|
|
int main(int argc,char ** argv){
|
2001-11-04 00:00:38 +00:00
|
|
|
int c;
|
2004-10-28 01:02:24 +00:00
|
|
|
FILE *f;
|
|
|
|
FILE *f2;
|
|
|
|
muxer_t* avi;
|
|
|
|
muxer_stream_t* mux;
|
2001-11-04 04:55:44 +00:00
|
|
|
//unsigned char* buffer=malloc(0x200000);
|
2001-11-04 19:47:19 +00:00
|
|
|
int i,len;
|
2001-11-04 04:55:44 +00:00
|
|
|
int v_id=0;
|
2001-11-04 19:47:19 +00:00
|
|
|
int flag2=0;
|
2001-11-30 23:13:05 +00:00
|
|
|
int prefix=0;
|
2001-11-04 00:38:32 +00:00
|
|
|
|
2004-10-29 22:05:34 +00:00
|
|
|
// check if enough args were given
|
|
|
|
if ( argc < 3 ){
|
|
|
|
printf("Too few arguments given!\n"
|
|
|
|
"Usage: %s <input_file> <output_file>\n", argv[0]);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2004-10-28 01:02:24 +00:00
|
|
|
// input
|
2004-10-29 22:05:34 +00:00
|
|
|
if(!(f=fopen(argv[1],"rb"))){
|
2004-10-28 01:02:24 +00:00
|
|
|
printf("Couldn't open input file.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
// output
|
2004-10-29 22:05:34 +00:00
|
|
|
if(!(f2=fopen(argv[2],"wb"))){
|
2004-10-28 01:02:24 +00:00
|
|
|
printf("Couldn't open output file.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
avi=muxer_new_muxer(MUXER_TYPE_AVI,f2);
|
|
|
|
mux=muxer_new_stream(avi,MUXER_TYPE_VIDEO);
|
|
|
|
|
2001-11-04 00:38:32 +00:00
|
|
|
mux->buffer_size=0x200000;
|
|
|
|
mux->buffer=malloc(mux->buffer_size);
|
|
|
|
|
2009-05-13 02:58:57 +00:00
|
|
|
mux->h.dwScale=1;
|
|
|
|
mux->h.dwRate=10;
|
2001-11-04 00:38:32 +00:00
|
|
|
|
|
|
|
mux->bih=malloc(sizeof(BITMAPINFOHEADER));
|
|
|
|
mux->bih->biSize=sizeof(BITMAPINFOHEADER);
|
|
|
|
mux->bih->biPlanes=1;
|
|
|
|
mux->bih->biBitCount=24;
|
|
|
|
mux->bih->biCompression=0x6f766976;// 7669766f;
|
2003-01-19 01:48:52 +00:00
|
|
|
muxer_write_header(avi);
|
2001-11-04 00:38:32 +00:00
|
|
|
|
2001-11-04 19:47:19 +00:00
|
|
|
/*
|
|
|
|
c=fgetc(f); if(c) printf("error! not vivo file?\n");
|
|
|
|
len=0;
|
|
|
|
while((c=fgetc(f))>=0x80) len+=0x80*(c&0x0F);
|
|
|
|
len+=c;
|
|
|
|
printf("hdr1: %d\n",len);
|
|
|
|
for(i=0;i<len;i++) fgetc(f);
|
|
|
|
*/
|
|
|
|
|
2001-11-04 04:55:44 +00:00
|
|
|
while((c=fgetc(f))>=0){
|
|
|
|
|
2007-12-10 13:16:10 +00:00
|
|
|
printf("%08lX %02X\n",ftell(f),c);
|
2001-11-30 23:13:05 +00:00
|
|
|
|
|
|
|
prefix=0;
|
|
|
|
if(c==0x82){
|
|
|
|
prefix=1;
|
|
|
|
//continue;
|
|
|
|
c=fgetc(f);
|
2007-12-10 13:16:10 +00:00
|
|
|
printf("%08lX %02X\n",ftell(f),c);
|
2001-11-30 23:13:05 +00:00
|
|
|
}
|
2001-11-04 19:47:19 +00:00
|
|
|
|
|
|
|
if(c==0x00){
|
|
|
|
// header
|
|
|
|
int len=0;
|
|
|
|
while((c=fgetc(f))>=0x80) len+=0x80*(c&0x0F);
|
|
|
|
len+=c;
|
|
|
|
printf("header: 00 (%d)\n",len);
|
|
|
|
for(i=0;i<len;i++) fgetc(f);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2001-11-04 04:55:44 +00:00
|
|
|
if((c&0xF0)==0x40){
|
|
|
|
// audio
|
2001-11-30 23:13:05 +00:00
|
|
|
len=24;
|
|
|
|
if(prefix) len=fgetc(f);
|
|
|
|
printf("audio: %02X (%d)\n",c,len);
|
|
|
|
for(i=0;i<len;i++) fgetc(f);
|
2001-11-04 04:55:44 +00:00
|
|
|
continue;
|
|
|
|
}
|
2001-11-04 19:47:19 +00:00
|
|
|
if((c&0xF0)==0x30){
|
|
|
|
// audio
|
2001-11-30 23:13:05 +00:00
|
|
|
len=40;
|
|
|
|
if(prefix) len=fgetc(f);
|
|
|
|
printf("audio: %02X (%d)\n",c,len);
|
|
|
|
for(i=0;i<len;i++) fgetc(f);
|
2001-11-04 19:47:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(flag2 || (((c&0xF0)==0x10 || (c&0xF0)==0x20) && (c&0x0F)!=(v_id&0xF))){
|
2001-11-04 04:55:44 +00:00
|
|
|
// end of frame:
|
|
|
|
printf("Frame size: %d\n",mux->buffer_len);
|
|
|
|
h263_decode_picture_header(mux->buffer);
|
2006-01-26 19:32:07 +00:00
|
|
|
muxer_write_chunk(mux,mux->buffer_len,0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
|
2001-11-04 04:55:44 +00:00
|
|
|
mux->buffer_len=0;
|
2009-05-13 02:58:57 +00:00
|
|
|
|
2001-11-04 19:47:19 +00:00
|
|
|
if((v_id&0xF0)==0x10) fprintf(stderr,"hmm. last video packet %02X\n",v_id);
|
2001-11-04 04:55:44 +00:00
|
|
|
}
|
2001-11-04 19:47:19 +00:00
|
|
|
flag2=0;
|
2001-11-04 04:55:44 +00:00
|
|
|
if((c&0xF0)==0x10){
|
|
|
|
// 128 byte
|
2001-11-30 23:13:05 +00:00
|
|
|
len=128;
|
|
|
|
if(prefix) len=fgetc(f);
|
|
|
|
printf("video: %02X (%d)\n",c,len);
|
|
|
|
fread(mux->buffer+mux->buffer_len,len,1,f);
|
|
|
|
mux->buffer_len+=len;
|
|
|
|
v_id=c;
|
2001-11-04 04:55:44 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if((c&0xF0)==0x20){
|
|
|
|
int len=fgetc(f);
|
|
|
|
printf("video: %02X (%d)\n",c,len);
|
|
|
|
fread(mux->buffer+mux->buffer_len,len,1,f);
|
|
|
|
mux->buffer_len+=len;
|
2001-11-04 19:47:19 +00:00
|
|
|
flag2=1;
|
2001-11-30 23:13:05 +00:00
|
|
|
v_id=c;
|
2001-11-04 04:55:44 +00:00
|
|
|
continue;
|
|
|
|
}
|
2001-11-04 19:47:19 +00:00
|
|
|
printf("error: %02X!\n",c);
|
2001-11-30 23:13:05 +00:00
|
|
|
exit(1);
|
2001-11-04 00:38:32 +00:00
|
|
|
}
|
2001-11-04 04:55:44 +00:00
|
|
|
|
2001-11-04 19:47:19 +00:00
|
|
|
if(!width) width=320;
|
|
|
|
if(!height) height=240;
|
|
|
|
|
2001-11-04 04:55:44 +00:00
|
|
|
mux->bih->biWidth=width;
|
|
|
|
mux->bih->biHeight=height;
|
|
|
|
mux->bih->biSizeImage=3*width*height;
|
|
|
|
|
2003-01-19 01:48:52 +00:00
|
|
|
muxer_write_index(avi);
|
2001-11-04 00:38:32 +00:00
|
|
|
fseek(f2,0,SEEK_SET);
|
2003-01-19 01:48:52 +00:00
|
|
|
muxer_write_header(avi);
|
2001-11-04 00:00:38 +00:00
|
|
|
|
2007-08-27 09:52:55 +00:00
|
|
|
return 0;
|
2001-11-04 00:00:38 +00:00
|
|
|
}
|