FindPage
View Source:
DPG
Automated conversion scripts:<br> [makemp2.php|DPG/makemp2.php]<br> [makem1v.php|DPG/makem1v.php]<br> [makegop.php|DPG/makegop.php]<br> [makehdr.php|DPG/makehdr.php]<br> [makedpg.sh|DPG/makedpg.sh]<br> ---- DPG is a simple container format for mpeg video and audio.<br> The header is big endian, and the data is just a concatenation of raw mpeg video and either mpeg audio or GSM audio. <verbatim> The DPG format is a video and audio container used by the popular Moonshell homebrew program on the Nintendo DS. There are currently (December 2006) three versions of the DPG format, identified by the initial four bytes of in the DPG file, namely DPG0, DPG1 and DPG2. [DPG file structure] Each DPG file consists of three (DPG0,DPG1) or four (DPG2) sections: a header, the audio stream, the video stream and for the DPG2 format an additional GOP (Group Of Pictures) list used for seeking during playback. All these sections are concatenated in the above mentioned order when creating the DPG file. [Header] The first section of the DPG file is the header with the following fields: (all fields are read by Moonshell 1.5 as a 32 bit unsigned number) Offset Description 0 DPG[012] Identifier. One of the strings: DPG0 (0x30475044), DPG1 (0x31475044) or DPG2 (0x32475044). 4 DPG[012] Number of frames in video. 8 DPG[012] Frames per second (FPS). Fixed point 8.8 format, i.e. 25 fps is multiplied by 100h (FPS<<8) to 6400. 12 DPG[012] Sampling rate of audio data (e.g. 32000) 16 DPG[012] Number of audio channels. If MP2 audio, this is zero. 20 DPG[012] Offset in file to audio stream 24 DPG[012] Size of audio stream. 28 DPG[012] Offset in file to video stream 32 DPG[012] Size of video stream. 36 DPG[1] Pixel format type 36 DPG[2] Offset in file to GOP list. 40 DPG[2] Size of GOP list. 44 DPG[2] Pixel format type Note: dpgtools 1.2 reads all values except the identifier as a signed 32 bit value. Moonshell 1.5, on the other hand, reads them as unsigned 32 bit values. This should not pose any problem, at least not until we reach 2GB files. [Pixel Formats] DPG0 only supports the RGB24 pixel format. DPG1 and DPG2 know the following pixel formats, Type Description 0 RGB15 1 RGB18 2 RGB21 3 RGB24 [GOP List] The Group Of Pictures (GOP) list of a DPG2 file is the last section of a DPG file. It consists of an array of a "FrameIndex" and "Offset" pair, both are read as an unsigned 32 bit value from within Moonshell. The use of the GOP list, within Moonshell 1.5, is when requesting a jump to a certain frame. In the case when a GOP list exists, it is searched in order to find the frame within the GOP list lower than or equal to the requested frame. (The search in Moonshell requires the GOP list to be ordered. Also a trivial optimization was omitted, namely to break out of the search loop once the GOP frame number is larger than the requested one.) So, to get clean seeks, I would put I-frames from the MPEG stream in the GOP list. [Audio Format] The audio format can be one of two types: GSM or MP2. The type used in a DPG file is distinguished by the number of audio channels. If audio channels is zero, an MP2 stream is assumed, otherwise the audio is GSM. </verbatim> Some useful commands: Audio conversion doesn't seem to work correctly in mencoder, so I used sox and twolame. <verbatim> mplayer -ao pcm:fast -vo null file.avi # extract the audio sox audiodump.wav -r 32000 out.wav # Transform it into 32kHz, to save some space twolame -b 128 out.wav out.mp2 # Create an Mpeg-1 Layer-II file </verbatim> dpgconv calculates the video stuff and transcodes it sufficiently well. Patch the header file, and concatenate the results together. mplayer -aid 0 source.mkv -endpos 1:35 -vo null -ao pcm:fast sox audiodump.wav -r 32000 audio.wav twolame -b 128 audio.wav audio.mp2 mencoder source.mkv -endpos 1:35 -v -ofps 16 -sws 9 -vf format=rgb24,scale=256:146:::3 -nosound -ovc lavc -lavcopts vcodec=mpeg1video:vstrict=-2:mbd=2:trell:cbp:mv0:cmp=6:subcmp=6:precmp=6:dia=3:predia=3:last_pred=3:vbitrate=256 -o video.mpg -of rawvideo ---- mencoder source.avi -o output.mp2 -of rawaudio -srate 32000 -ovc copy -oac lavc -lavcopts acodec=mp2:abitrate=128 mencoder source.avi -o output.m1v -of rawvideo -ofps 15 -vf scale=256:192:0:0:1.00:0.00 -ovc lavc -oac copy -lavcopts vcodec=mpeg1video:vstrict=-1:vbitrate=384:vrc_buf_size=327:vrc_maxrate=512:keyint=15 mpeg_stat -offsets output.off output.m1v mpeg_stat will give you the frame count. cat output.hdr output.mp2 output.m1v output.gop > output.dpg A PHP script to turn output.off into a gop list suitable for DPG2 <verbatim> #!/usr/bin/env php <?php $stat = fopen("output.off","r"); $gop = fopen("output.gop", "w"); $frame = 0; while ($line = fgets($stat, 4096)) { $stuff = explode(" ", $line); switch ($stuff[0]) { case "picture": $frame++; break; case "gop": if ($frame) { $point = (((int) $stuff[1]) / 8 - 140); printf("%u: %u\n", $frame, $point); fwrite($gop, pack('VV', $frame, $point), 8); } break; default: break; } } ?> </verbatim> A PHP script to create a DPG2-compatible binary header <verbatim> #!/usr/bin/env php <?php # Make header $asize = filesize("output.mp2"); $vsize = filesize("output.m1v"); $gsize = filesize("output.gop"); $astart = 36 + 12; $vstart = $astart + $asize; $gstart = $vstart + $vsize; $frames = 2737; $fps = 15; $hz = 32000; $hdr = sprintf("DPG2%s", pack('lnnlllllllll', $frames, $fps, 0, $hz, 0, $astart, $asize, $vstart, $vsize, $gstart, $gsize, 3)); file_put_contents("output.hdr", $hdr); ?> </verbatim> Some command line options, stolen shamelessly from BatchDPG v1.55's mencoder invocation. The trick here is that avisynth resamples to the target framerate, then lies and says it's 60fps (mpeg spec). Moonshell ignores that, and uses the framerate in the DPG header so this works. For linux, it's usually easier to add vstrict=-1 to the lavcopts to turn off bitching about out-of-spec target framerates. <verbatim> Ultra pass 1: C:\DOCUME~1\ADMINI~1\Desktop\BATCHD~1.55\Bin\mencoder.exe "C:\dpg\tmp\Rozen Maiden 01.avi.avs" -o "C:\dpg\tmp\Rozen Maiden 01.avi.m1v" -nosound -passlogfile "C:\dpg\tmp\Rozen Maiden 01.avi.log" -ovc lavc -lavcopts vcodec=mpeg1video:keyint=60:vrc_buf_size=327:vrc_maxrate=3072:vbitrate=1536:vpass=1:mbd=2:trell:cbp:mv0:vmax_b_frames=2:cmp=6:subcmp=6:precmp=6:dia=4:predia=4:vb_strategy=2:bidir_refine=4:mv0_threshold=0:last_pred=3:preme=2:intra_matrix=8,9,12,22,26,27,29,34,9,10,14,26,27,29,34,37,12,14,18,27,29,34,37,38,22,26,27,31,36,37,38,40,26,27,29,36,39,38,40,48,27,29,34,37,38,40,48,58,29,34,37,38,40,48,58,69,34,37,38,40,48,58,69,79:inter_matrix=16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44 -of rawvideo Ultra pass 2: C:\DOCUME~1\ADMINI~1\Desktop\BATCHD~1.55\Bin\mencoder.exe "C:\dpg\tmp\Rozen Maiden 01.avi.avs" -o "C:\dpg\tmp\Rozen Maiden 01.avi.m1v" -nosound -passlogfile "C:\dpg\tmp\Rozen Maiden 01.avi.log" -ovc lavc -lavcopts vcodec=mpeg1video:keyint=60:vrc_buf_size=327:vrc_maxrate=3072:vbitrate=1536:vpass=2:mbd=2:trell:cbp:mv0:vmax_b_frames=2:cmp=6:subcmp=6:precmp=6:dia=4:predia=4:vb_strategy=2:bidir_refine=4:mv0_threshold=0:last_pred=3:preme=2:intra_matrix=8,9,12,22,26,27,29,34,9,10,14,26,27,29,34,37,12,14,18,27,29,34,37,38,22,26,27,31,36,37,38,40,26,27,29,36,39,38,40,48,27,29,34,37,38,40,48,58,29,34,37,38,40,48,58,69,34,37,38,40,48,58,69,79:inter_matrix=16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44 -of rawvideo </verbatim>