Microsoft Screen Codec
From MultimediaWiki
| Revision as of 17:05, 13 June 2009 Kostya (Talk | contribs) (may it be less undiscovered codec) ← Previous diff |
Revision as of 15:00, 9 June 2012 Kostya (Talk | contribs) (→Some details about format) Next diff → |
||
| Line 13: | Line 13: | ||
| Both MSS1 and MSS2 are quite close (thus are decoded with single decoder). They employ arithmetic coding - real one, with probability coding. This coding is used with several adaptive models, which look a bit like PPM. | Both MSS1 and MSS2 are quite close (thus are decoded with single decoder). They employ arithmetic coding - real one, with probability coding. This coding is used with several adaptive models, which look a bit like PPM. | ||
| - | === Extradata format === | + | === MSS1 details === |
| + | |||
| + | MSS1 (aka Windows Media Screen codec) compresses only palletised images. | ||
| + | |||
| + | ==== Extradata format ==== | ||
| (for some reason, data in .wmv is stored in big-endian order) | (for some reason, data in .wmv is stored in big-endian order) | ||
| Line 30: | Line 34: | ||
| 52-55 nFreeColors | 52-55 nFreeColors | ||
| 56-... palette (256 RGB triplets) | 56-... palette (256 RGB triplets) | ||
| + | |||
| + | ==== Frame format ==== | ||
| + | |||
| + | Codec uses arithmetic decoders for all operations and adaptive models. All code for them is suspiciously similar to the one in [http://www.stanford.edu/class/ee398a/handouts/papers/WittenACM87ArithmCoding.pdf | 1987 paper by Witten, Neal and Cleary]. | ||
| + | |||
| + | Codec uses delta compression and can change top palette entries with every intra frame: | ||
| + | |||
| + | is_inter = coder->decode_bit(); | ||
| + | if (!is_inter) { | ||
| + | if (nFreeColors) { | ||
| + | num_entries = coder->decode_number(nFreeColors + 1); | ||
| + | for (i = 0; i < num_entries; i++) { | ||
| + | pal[(256 - nFreeColors) + i].R = coder->decode_bits(8); | ||
| + | pal[(256 - nFreeColors) + i].G = coder->decode_bits(8); | ||
| + | pal[(256 - nFreeColors) + i].B = coder->decode_bits(8); | ||
| + | } | ||
| + | } | ||
| + | recursive_decode_intra(0, 0, width, height); | ||
| + | } else { | ||
| + | recursive_decode_inter(0, 0, width, height); | ||
| + | } | ||
| + | |||
| + | Frame coding is done by recursively partitioning picture horizontally or vertically and coding partitions in some way: | ||
| + | |||
| + | recursive_decode_intra(x, y, width, height) { | ||
| + | mode = coder->decode_model(split_mode_model); | ||
| + | switch (mode) { | ||
| + | case 0: | ||
| + | pivot = decode_pivot(height); | ||
| + | recursive_decode_intra(x, y, width, pivot); | ||
| + | recursive_decode_intra(x, y + pivot, width, height - pivot); | ||
| + | break; | ||
| + | case 1: | ||
| + | pivot = decode_pivot(width); | ||
| + | recursive_decode_intra(x, y, pivot, height); | ||
| + | recursive_decode_intra(x + pivot, y, width - pivot, height | ||
| + | break; | ||
| + | case 2: | ||
| + | mode = coder->decode_model(intra_decode_model); | ||
| + | if (!mode) { | ||
| + | pix = decode_pixel(); | ||
| + | fill_rect(x, y, width, height, pixel); | ||
| + | } else { | ||
| + | decode_area(x, y, width, height); | ||
| + | } | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | recursive_decode_inter(x, y, width, height) { | ||
| + | mode = coder->decode_model(split_mode_model); | ||
| + | switch (mode) { | ||
| + | case 0: | ||
| + | pivot = decode_pivot(height); | ||
| + | recursive_decode_inter(x, y, width, pivot); | ||
| + | recursive_decode_inter(x, y + pivot, width, height - pivot); | ||
| + | break; | ||
| + | case 1: | ||
| + | pivot = decode_pivot(width); | ||
| + | recursive_decode_inter(x, y, pivot, height); | ||
| + | recursive_decode_inter(x + pivot, y, width - pivot, height | ||
| + | break; | ||
| + | case 2: | ||
| + | mode = coder->decode_model(inter_decode_model); | ||
| + | if (!mode) { | ||
| + | pix = decode_pixel(); | ||
| + | if (pix != 0xFF) { | ||
| + | copy_rect(x, y, width, height, pixel); | ||
| + | } else { | ||
| + | mode = coder->decode_model(intra_decode_model); | ||
| + | if (!mode) { | ||
| + | pix = decode_pixel(); | ||
| + | fill_rect(x, y, width, height, pixel); | ||
| + | } else { | ||
| + | decode_area(x, y, width, height); | ||
| + | } | ||
| + | } | ||
| + | } else { | ||
| + | // this decoded change mask first and then | ||
| + | // checks - if mask value is 0xFF then decode pixel | ||
| + | // otherwise copy if from the previous frame | ||
| + | mask = decode_area(x, y, width, height); | ||
| + | decode_area_masked(x, y, width, height); | ||
| + | } | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| [[Category:Video Codecs]] | [[Category:Video Codecs]] | ||
| [[Category:Screen Capture Video Codecs]] | [[Category:Screen Capture Video Codecs]] | ||
| [[Category:Undiscovered Video Codecs]] | [[Category:Undiscovered Video Codecs]] | ||
Revision as of 15:00, 9 June 2012
Also known as Windows Media Screen Codec.
- FourCCs: MSS1, MSS2, MSA1
- Samples:
MSA1 is created by Live Meeting 2007
Contents |
Some details about format
Both MSS1 and MSS2 are quite close (thus are decoded with single decoder). They employ arithmetic coding - real one, with probability coding. This coding is used with several adaptive models, which look a bit like PPM.
MSS1 details
MSS1 (aka Windows Media Screen codec) compresses only palletised images.
Extradata format
(for some reason, data in .wmv is stored in big-endian order)
4- 7 header length 8-11 major version 12-15 minor version 16-19 display width 20-23 display height 24-27 coded width 28-31 coded height 32-35 frames per second (float) 36-39 bitrate 40-43 max lead time (float) 44-47 max lag time 48-51 max seek time 52-55 nFreeColors 56-... palette (256 RGB triplets)
Frame format
Codec uses arithmetic decoders for all operations and adaptive models. All code for them is suspiciously similar to the one in | 1987 paper by Witten, Neal and Cleary.
Codec uses delta compression and can change top palette entries with every intra frame:
is_inter = coder->decode_bit();
if (!is_inter) {
if (nFreeColors) {
num_entries = coder->decode_number(nFreeColors + 1);
for (i = 0; i < num_entries; i++) {
pal[(256 - nFreeColors) + i].R = coder->decode_bits(8);
pal[(256 - nFreeColors) + i].G = coder->decode_bits(8);
pal[(256 - nFreeColors) + i].B = coder->decode_bits(8);
}
}
recursive_decode_intra(0, 0, width, height);
} else {
recursive_decode_inter(0, 0, width, height);
}
Frame coding is done by recursively partitioning picture horizontally or vertically and coding partitions in some way:
recursive_decode_intra(x, y, width, height) {
mode = coder->decode_model(split_mode_model);
switch (mode) {
case 0:
pivot = decode_pivot(height);
recursive_decode_intra(x, y, width, pivot);
recursive_decode_intra(x, y + pivot, width, height - pivot);
break;
case 1:
pivot = decode_pivot(width);
recursive_decode_intra(x, y, pivot, height);
recursive_decode_intra(x + pivot, y, width - pivot, height
break;
case 2:
mode = coder->decode_model(intra_decode_model);
if (!mode) {
pix = decode_pixel();
fill_rect(x, y, width, height, pixel);
} else {
decode_area(x, y, width, height);
}
break;
}
}
recursive_decode_inter(x, y, width, height) {
mode = coder->decode_model(split_mode_model);
switch (mode) {
case 0:
pivot = decode_pivot(height);
recursive_decode_inter(x, y, width, pivot);
recursive_decode_inter(x, y + pivot, width, height - pivot);
break;
case 1:
pivot = decode_pivot(width);
recursive_decode_inter(x, y, pivot, height);
recursive_decode_inter(x + pivot, y, width - pivot, height
break;
case 2:
mode = coder->decode_model(inter_decode_model);
if (!mode) {
pix = decode_pixel();
if (pix != 0xFF) {
copy_rect(x, y, width, height, pixel);
} else {
mode = coder->decode_model(intra_decode_model);
if (!mode) {
pix = decode_pixel();
fill_rect(x, y, width, height, pixel);
} else {
decode_area(x, y, width, height);
}
}
} else {
// this decoded change mask first and then
// checks - if mask value is 0xFF then decode pixel
// otherwise copy if from the previous frame
mask = decode_area(x, y, width, height);
decode_area_masked(x, y, width, height);
}
break;
}
}
