comparison interplayvideo.c @ 10719:cc2f80bbf304 libavcodec

Add missing opcodes for 16-bit Interplay Video decoding and finally enable it
author kostya
date Sun, 27 Dec 2009 09:12:50 +0000
parents 1b91df81bda4
children bcc62edd9b41
comparison
equal deleted inserted replaced
10718:1b91df81bda4 10719:cc2f80bbf304
571 571
572 /* report success */ 572 /* report success */
573 return 0; 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 static int (* const ipvideo_decode_block[])(IpvideoContext *s) = { 933 static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
577 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1, 934 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
578 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3, 935 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
579 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5, 936 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
580 ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7, 937 ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
582 ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB, 939 ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
583 ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD, 940 ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
584 ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF, 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 static void ipvideo_decode_opcodes(IpvideoContext *s) 955 static void ipvideo_decode_opcodes(IpvideoContext *s)
588 { 956 {
589 int x, y; 957 int x, y;
590 unsigned char opcode; 958 unsigned char opcode;
591 int ret; 959 int ret;
626 + y*s->current_frame.linesize[0]; 994 + y*s->current_frame.linesize[0];
627 ret = ipvideo_decode_block[opcode](s); 995 ret = ipvideo_decode_block[opcode](s);
628 } else { 996 } else {
629 s->pixel_ptr = s->current_frame.data[0] + x*2 997 s->pixel_ptr = s->current_frame.data[0] + x*2
630 + y*s->current_frame.linesize[0]; 998 + y*s->current_frame.linesize[0];
999 ret = ipvideo_decode_block16[opcode](s);
631 } 1000 }
632 if (ret != 0) { 1001 if (ret != 0) {
633 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n", 1002 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
634 frame, x, y); 1003 frame, x, y);
635 return; 1004 return;
653 return -1; 1022 return -1;
654 } 1023 }
655 1024
656 s->is_16bpp = avctx->bits_per_coded_sample == 16; 1025 s->is_16bpp = avctx->bits_per_coded_sample == 16;
657 avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8; 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 dsputil_init(&s->dsp, avctx); 1027 dsputil_init(&s->dsp, avctx);
663 1028
664 /* decoding map contains 4 bits of information per 8x8 block */ 1029 /* decoding map contains 4 bits of information per 8x8 block */
665 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2); 1030 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
666 1031