Revision a69be798 libavcodec/interplayvideo.c

View differences:

libavcodec/interplayvideo.c
573 573
    return 0;
574 574
}
575 575

  
576
static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s)
577
{
578
    signed char x, y;
579

  
580
    /* copy a block from the second last frame using an expanded range */
581
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
582

  
583
    x = *s->stream_ptr++;
584
    y = *s->stream_ptr++;
585

  
586
    debug_interplay ("    motion bytes = %d, %d\n", x, y);
587
    return copy_from(s, &s->second_last_frame, x, y);
588
}
589

  
590
static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s)
591
{
592
    int x, y;
593
    uint16_t P[2];
594
    unsigned int flags;
595
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
596

  
597
    /* 2-color encoding */
598
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
599

  
600
    P[0] = bytestream_get_le16(&s->stream_ptr);
601
    P[1] = bytestream_get_le16(&s->stream_ptr);
602

  
603
    if (!(P[0] & 0x8000)) {
604

  
605
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
606

  
607
        for (y = 0; y < 8; y++) {
608
            flags = *s->stream_ptr++ | 0x100;
609
            for (; flags != 1; flags >>= 1)
610
                *pixel_ptr++ = P[flags & 1];
611
            pixel_ptr += s->line_inc;
612
        }
613

  
614
    } else {
615

  
616
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
617

  
618
        flags = bytestream_get_le16(&s->stream_ptr);
619
        for (y = 0; y < 8; y += 2) {
620
            for (x = 0; x < 8; x += 2, flags >>= 1) {
621
                pixel_ptr[x                ] =
622
                pixel_ptr[x + 1            ] =
623
                pixel_ptr[x +     s->stride] =
624
                pixel_ptr[x + 1 + s->stride] = P[flags & 1];
625
            }
626
            pixel_ptr += s->stride * 2;
627
        }
628
    }
629

  
630
    return 0;
631
}
632

  
633
static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s)
634
{
635
    int x, y;
636
    uint16_t P[2];
637
    unsigned int flags = 0;
638
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
639

  
640
    /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
641
     * either top and bottom or left and right halves */
642
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
643

  
644
    P[0] = bytestream_get_le16(&s->stream_ptr);
645
    P[1] = bytestream_get_le16(&s->stream_ptr);
646

  
647
    if (!(P[0] & 0x8000)) {
648

  
649
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
650
        s->stream_ptr -= 4;
651

  
652
        for (y = 0; y < 16; y++) {
653
            // new values for each 4x4 block
654
            if (!(y & 3)) {
655
                P[0] = bytestream_get_le16(&s->stream_ptr);
656
                P[1] = bytestream_get_le16(&s->stream_ptr);
657
                flags = bytestream_get_le16(&s->stream_ptr);
658
            }
659

  
660
            for (x = 0; x < 4; x++, flags >>= 1)
661
                *pixel_ptr++ = P[flags & 1];
662
            pixel_ptr += s->stride - 4;
663
            // switch to right half
664
            if (y == 7) pixel_ptr -= 8 * s->stride - 4;
665
        }
666

  
667
    } else {
668

  
669
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 12);
670

  
671
        if (!(AV_RL16(s->stream_ptr + 4) & 0x8000)) {
672

  
673
            flags = bytestream_get_le32(&s->stream_ptr);
674

  
675
            /* vertical split; left & right halves are 2-color encoded */
676

  
677
            for (y = 0; y < 16; y++) {
678
                for (x = 0; x < 4; x++, flags >>= 1)
679
                    *pixel_ptr++ = P[flags & 1];
680
                pixel_ptr += s->stride - 4;
681
                // switch to right half
682
                if (y == 7) {
683
                    pixel_ptr -= 8 * s->stride - 4;
684
                    P[0] = bytestream_get_le16(&s->stream_ptr);
685
                    P[1] = bytestream_get_le16(&s->stream_ptr);
686
                    flags = bytestream_get_le32(&s->stream_ptr);
687
                }
688
            }
689

  
690
        } else {
691

  
692
            /* horizontal split; top & bottom halves are 2-color encoded */
693

  
694
            for (y = 0; y < 8; y++) {
695
                if (y == 4) {
696
                    P[0] = bytestream_get_le16(&s->stream_ptr);
697
                    P[1] = bytestream_get_le16(&s->stream_ptr);
698
                }
699
                flags = *s->stream_ptr++ | 0x100;
700

  
701
                for (; flags != 1; flags >>= 1)
702
                    *pixel_ptr++ = P[flags & 1];
703
                pixel_ptr += s->line_inc;
704
            }
705
        }
706
    }
707

  
708
    /* report success */
709
    return 0;
710
}
711

  
712
static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s)
713
{
714
    int x, y;
715
    uint16_t P[4];
716
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
717

  
718
    /* 4-color encoding */
719
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
720

  
721
    for (x = 0; x < 4; x++)
722
        P[x] = bytestream_get_le16(&s->stream_ptr);
723

  
724
    if (!(P[0] & 0x8000)) {
725
        if (!(P[2] & 0x8000)) {
726

  
727
            /* 1 of 4 colors for each pixel */
728
            CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
729

  
730
            for (y = 0; y < 8; y++) {
731
                /* get the next set of 8 2-bit flags */
732
                int flags = bytestream_get_le16(&s->stream_ptr);
733
                for (x = 0; x < 8; x++, flags >>= 2)
734
                    *pixel_ptr++ = P[flags & 0x03];
735
                pixel_ptr += s->line_inc;
736
            }
737

  
738
        } else {
739
            uint32_t flags;
740

  
741
            /* 1 of 4 colors for each 2x2 block */
742
            CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
743

  
744
            flags = bytestream_get_le32(&s->stream_ptr);
745

  
746
            for (y = 0; y < 8; y += 2) {
747
                for (x = 0; x < 8; x += 2, flags >>= 2) {
748
                    pixel_ptr[x                ] =
749
                    pixel_ptr[x + 1            ] =
750
                    pixel_ptr[x +     s->stride] =
751
                    pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
752
                }
753
                pixel_ptr += s->stride * 2;
754
            }
755

  
756
        }
757
    } else {
758
        uint64_t flags;
759

  
760
        /* 1 of 4 colors for each 2x1 or 1x2 block */
761
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
762

  
763
        flags = bytestream_get_le64(&s->stream_ptr);
764
        if (!(P[2] & 0x8000)) {
765
            for (y = 0; y < 8; y++) {
766
                for (x = 0; x < 8; x += 2, flags >>= 2) {
767
                    pixel_ptr[x    ] =
768
                    pixel_ptr[x + 1] = P[flags & 0x03];
769
                }
770
                pixel_ptr += s->stride;
771
            }
772
        } else {
773
            for (y = 0; y < 8; y += 2) {
774
                for (x = 0; x < 8; x++, flags >>= 2) {
775
                    pixel_ptr[x            ] =
776
                    pixel_ptr[x + s->stride] = P[flags & 0x03];
777
                }
778
                pixel_ptr += s->stride * 2;
779
            }
780
        }
781
    }
782

  
783
    /* report success */
784
    return 0;
785
}
786

  
787
static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s)
788
{
789
    int x, y;
790
    uint16_t P[4];
791
    int flags = 0;
792
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
793

  
794
    /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
795
     * either top and bottom or left and right halves */
796
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
797

  
798
    if (!(AV_RL16(s->stream_ptr) & 0x8000)) {
799

  
800
        /* 4-color encoding for each quadrant */
801
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 48);
802

  
803
        for (y = 0; y < 16; y++) {
804
            // new values for each 4x4 block
805
            if (!(y & 3)) {
806
                for (x = 0; x < 4; x++)
807
                    P[x] = bytestream_get_le16(&s->stream_ptr);
808
                flags = bytestream_get_le32(&s->stream_ptr);
809
            }
810

  
811
            for (x = 0; x < 4; x++, flags >>= 2)
812
                *pixel_ptr++ = P[flags & 0x03];
813

  
814
            pixel_ptr += s->stride - 4;
815
            // switch to right half
816
            if (y == 7) pixel_ptr -= 8 * s->stride - 4;
817
        }
818

  
819
    } else {
820
        // vertical split?
821
        int vert = !(AV_RL16(s->stream_ptr + 16) & 0x8000);
822
        uint64_t flags = 0;
823

  
824
        /* 4-color encoding for either left and right or top and bottom
825
         * halves */
826

  
827
        for (y = 0; y < 16; y++) {
828
            // load values for each half
829
            if (!(y & 7)) {
830
                for (x = 0; x < 4; x++)
831
                    P[x] = bytestream_get_le16(&s->stream_ptr);
832
                flags = bytestream_get_le64(&s->stream_ptr);
833
            }
834

  
835
            for (x = 0; x < 4; x++, flags >>= 2)
836
                *pixel_ptr++ = P[flags & 0x03];
837

  
838
            if (vert) {
839
                pixel_ptr += s->stride - 4;
840
                // switch to right half
841
                if (y == 7) pixel_ptr -= 8 * s->stride - 4;
842
            } else if (y & 1) pixel_ptr += s->line_inc;
843
        }
844
    }
845

  
846
    /* report success */
847
    return 0;
848
}
849

  
850
static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s)
851
{
852
    int x, y;
853
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
854

  
855
    /* 64-color encoding (each pixel in block is a different color) */
856
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 128);
857

  
858
    for (y = 0; y < 8; y++) {
859
        for (x = 0; x < 8; x++)
860
            pixel_ptr[x] = bytestream_get_le16(&s->stream_ptr);
861
        pixel_ptr  += s->stride;
862
    }
863

  
864
    /* report success */
865
    return 0;
866
}
867

  
868
static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s)
869
{
870
    int x, y;
871
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
872

  
873
    /* 16-color block encoding: each 2x2 block is a different color */
874
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
875

  
876
    for (y = 0; y < 8; y += 2) {
877
        for (x = 0; x < 8; x += 2) {
878
            pixel_ptr[x                ] =
879
            pixel_ptr[x + 1            ] =
880
            pixel_ptr[x +     s->stride] =
881
            pixel_ptr[x + 1 + s->stride] = bytestream_get_le16(&s->stream_ptr);
882
        }
883
        pixel_ptr += s->stride * 2;
884
    }
885

  
886
    /* report success */
887
    return 0;
888
}
889

  
890
static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s)
891
{
892
    int x, y;
893
    uint16_t P[2];
894
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
895

  
896
    /* 4-color block encoding: each 4x4 block is a different color */
897
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
898

  
899
    for (y = 0; y < 8; y++) {
900
        if (!(y & 3)) {
901
            P[0] = bytestream_get_le16(&s->stream_ptr);
902
            P[1] = bytestream_get_le16(&s->stream_ptr);
903
        }
904
        for (x = 0; x < 8; x++)
905
            pixel_ptr[x] = P[x >> 2];
906
        pixel_ptr += s->stride;
907
    }
908

  
909
    /* report success */
910
    return 0;
911
}
912

  
913
static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s)
914
{
915
    int x, y;
916
    uint16_t pix;
917
    uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
918

  
919
    /* 1-color encoding: the whole block is 1 solid color */
920
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
921
    pix = bytestream_get_le16(&s->stream_ptr);
922

  
923
    for (y = 0; y < 8; y++) {
924
        for (x = 0; x < 8; x++)
925
            pixel_ptr[x] = pix;
926
        pixel_ptr += s->stride;
927
    }
928

  
929
    /* report success */
930
    return 0;
931
}
932

  
576 933
static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
577 934
    ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
578 935
    ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
......
584 941
    ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
585 942
};
586 943

  
944
static int (* const ipvideo_decode_block16[])(IpvideoContext *s) = {
945
    ipvideo_decode_block_opcode_0x0,    ipvideo_decode_block_opcode_0x1,
946
    ipvideo_decode_block_opcode_0x2,    ipvideo_decode_block_opcode_0x3,
947
    ipvideo_decode_block_opcode_0x4,    ipvideo_decode_block_opcode_0x5,
948
    ipvideo_decode_block_opcode_0x6_16, ipvideo_decode_block_opcode_0x7_16,
949
    ipvideo_decode_block_opcode_0x8_16, ipvideo_decode_block_opcode_0x9_16,
950
    ipvideo_decode_block_opcode_0xA_16, ipvideo_decode_block_opcode_0xB_16,
951
    ipvideo_decode_block_opcode_0xC_16, ipvideo_decode_block_opcode_0xD_16,
952
    ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1,
953
};
954

  
587 955
static void ipvideo_decode_opcodes(IpvideoContext *s)
588 956
{
589 957
    int x, y;
......
628 996
            } else {
629 997
                s->pixel_ptr = s->current_frame.data[0] + x*2
630 998
                              + y*s->current_frame.linesize[0];
999
                ret = ipvideo_decode_block16[opcode](s);
631 1000
            }
632 1001
            if (ret != 0) {
633 1002
                av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
......
655 1024

  
656 1025
    s->is_16bpp = avctx->bits_per_coded_sample == 16;
657 1026
    avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8;
658
    if (s->is_16bpp) {
659
        av_log(avctx, AV_LOG_ERROR, "16-bit Interplay video is not supported yet.\n");
660
        return -1;
661
    }
662 1027
    dsputil_init(&s->dsp, avctx);
663 1028

  
664 1029
    /* decoding map contains 4 bits of information per 8x8 block */

Also available in: Unified diff