@@ -55,8 +55,17 @@ typedef struct IpvideoContext {
5555 HpelDSPContext hdsp ;
5656 AVFrame * second_last_frame ;
5757 AVFrame * last_frame ;
58+
59+ /* For format 0x10 */
60+ AVFrame * cur_decode_frame ;
61+ AVFrame * prev_decode_frame ;
62+
63+ uint8_t frame_format ;
64+ const unsigned char * skip_map ;
65+ int skip_map_size ;
5866 const unsigned char * decoding_map ;
5967 int decoding_map_size ;
68+ int video_data_size ;
6069
6170 int is_16bpp ;
6271 GetByteContext stream_ptr , mv_ptr ;
@@ -903,7 +912,188 @@ static int (* const ipvideo_decode_block16[])(IpvideoContext *s, AVFrame *frame)
903912 ipvideo_decode_block_opcode_0xE_16 , ipvideo_decode_block_opcode_0x1 ,
904913};
905914
906- static void ipvideo_decode_opcodes (IpvideoContext * s , AVFrame * frame )
915+
916+ static void ipvideo_decode_format_06_opcodes (IpvideoContext * s , AVFrame * frame )
917+ {
918+ int x , y , off_x , off_y ;
919+ const unsigned char * decode_map_p ;
920+ short opcode ;
921+
922+ if (!s -> is_16bpp ) {
923+ /* this is PAL8, so make the palette available */
924+ memcpy (frame -> data [1 ], s -> pal , AVPALETTE_SIZE );
925+
926+ s -> stride = frame -> linesize [0 ];
927+ }
928+
929+ s -> line_inc = s -> stride - 8 ;
930+ s -> upper_motion_limit_offset = (s -> avctx -> height - 8 ) * frame -> linesize [0 ]
931+ + (s -> avctx -> width - 8 ) * (1 + s -> is_16bpp );
932+
933+ decode_map_p = s -> decoding_map ;
934+ for (y = 0 ; y < s -> avctx -> height ; y += 8 ) {
935+ for (x = 0 ; x < s -> avctx -> width ; x += 8 ) {
936+ opcode = AV_RL16 (decode_map_p );
937+
938+ ff_tlog (s -> avctx ,
939+ " block @ (%3d, %3d): opcode 0x%X, data ptr offset %d\n" ,
940+ x , y , opcode , bytestream2_tell (& s -> stream_ptr ));
941+
942+ s -> pixel_ptr = frame -> data [0 ] + x + y * frame -> linesize [0 ];
943+ if (! opcode ) {
944+ int k ;
945+ for (k = 0 ; k < 8 ; k ++ ) {
946+ bytestream2_get_buffer (& s -> stream_ptr , s -> pixel_ptr , 8 );
947+ s -> pixel_ptr += s -> stride ;
948+ }
949+ } else {
950+ copy_from (s , s -> second_last_frame , frame , 0 , 0 );
951+ }
952+ decode_map_p += 2 ;
953+ }
954+ }
955+
956+ decode_map_p = s -> decoding_map ;
957+ for (y = 0 ; y < s -> avctx -> height ; y += 8 ) {
958+ for (x = 0 ; x < s -> avctx -> width ; x += 8 ) {
959+ opcode = AV_RL16 (decode_map_p );
960+
961+ ff_tlog (s -> avctx ,
962+ " block @ (%3d, %3d): opcode 0x%X, data ptr offset %d\n" ,
963+ x , y , opcode , bytestream2_tell (& s -> stream_ptr ));
964+
965+ s -> pixel_ptr = frame -> data [0 ] + x + y * frame -> linesize [0 ];
966+ if (opcode < 0 ) {
967+ off_x = ((unsigned short )opcode - 0xC000 ) % frame -> linesize [0 ];
968+ off_y = ((unsigned short )opcode - 0xC000 ) / frame -> linesize [0 ];
969+ copy_from (s , s -> last_frame , frame , off_x , off_y );
970+ }
971+ if (opcode > 0 ) {
972+ off_x = ((unsigned short )opcode - 0x4000 ) % frame -> linesize [0 ];
973+ off_y = ((unsigned short )opcode - 0x4000 ) / frame -> linesize [0 ];
974+ copy_from (s , frame , frame , off_x , off_y );
975+ }
976+ decode_map_p += 2 ;
977+ }
978+ }
979+
980+ if (bytestream2_get_bytes_left (& s -> stream_ptr ) > 1 ) {
981+ av_log (s -> avctx , AV_LOG_DEBUG ,
982+ "decode finished with %d bytes left over\n" ,
983+ bytestream2_get_bytes_left (& s -> stream_ptr ));
984+ }
985+ }
986+
987+ static void ipvideo_decode_format_10_opcodes (IpvideoContext * s , AVFrame * frame )
988+ {
989+ int x , y , off_x , off_y ;
990+ const unsigned char * decode_map_p ;
991+ const unsigned char * skip_map_p ;
992+ short opcode , skip ;
993+ int changed_block = 0 ;
994+
995+ if (!s -> is_16bpp ) {
996+ /* this is PAL8, so make the palette available */
997+ memcpy (frame -> data [1 ], s -> pal , AVPALETTE_SIZE );
998+
999+ s -> stride = frame -> linesize [0 ];
1000+ }
1001+
1002+ bytestream2_skip (& s -> stream_ptr , 14 ); /* data starts 14 bytes in */
1003+
1004+ s -> line_inc = s -> stride - 8 ;
1005+ s -> upper_motion_limit_offset = (s -> avctx -> height - 8 ) * frame -> linesize [0 ]
1006+ + (s -> avctx -> width - 8 ) * (1 + s -> is_16bpp );
1007+
1008+ decode_map_p = s -> decoding_map ;
1009+ skip_map_p = s -> skip_map ;
1010+ skip = AV_RL16 (skip_map_p );
1011+ for (y = 0 ; y < s -> avctx -> height ; y += 8 ) {
1012+ for (x = 0 ; x < s -> avctx -> width ; x += 8 ) {
1013+ s -> pixel_ptr = s -> cur_decode_frame -> data [0 ] + x + y * cur_decode_frame -> linesize [0 ];
1014+
1015+ while (skip <= 0 ) {
1016+ if (skip != -0x8000 && skip != 0 ) {
1017+ opcode = AV_RL16 (decode_map_p );
1018+ if (! opcode ) {
1019+ int k ;
1020+ for (k = 0 ; k < 8 ; k ++ ) {
1021+ bytestream2_get_buffer (& s -> stream_ptr , s -> pixel_ptr , 8 );
1022+ s -> pixel_ptr += s -> stride ;
1023+ }
1024+ }
1025+ decode_map_p += 2 ;
1026+ break ;
1027+ }
1028+ skip_map_p += 2 ;
1029+ skip = AV_RL16 (skip_map_p );
1030+ }
1031+ skip *= 2 ;
1032+ }
1033+ }
1034+
1035+ decode_map_p = s -> decoding_map ;
1036+ skip_map_p = s -> skip_map ;
1037+ skip = AV_RL16 (skip_map_p );
1038+ for (y = 0 ; y < s -> avctx -> height ; y += 8 ) {
1039+ for (x = 0 ; x < s -> avctx -> width ; x += 8 ) {
1040+ s -> pixel_ptr = s -> cur_decode_frame -> data [0 ] + x + y * cur_decode_frame -> linesize [0 ];
1041+
1042+ while (skip <= 0 ) {
1043+ if (skip != -0x8000 && skip != 0 ) {
1044+ opcode = AV_RL16 (decode_map_p );
1045+ if (opcode < 0 ) {
1046+ off_x = ((unsigned short )opcode - 0xC000 ) % cur_decode_frame -> linesize [0 ];
1047+ off_y = ((unsigned short )opcode - 0xC000 ) / cur_decode_frame -> linesize [0 ];
1048+ copy_from (s , s -> prev_decode_frame , s -> cur_decode_frame , off_x , off_y );
1049+ }
1050+ if (opcode > 0 ) {
1051+ off_x = ((unsigned short )opcode - 0x4000 ) % cur_decode_frame -> linesize [0 ];
1052+ off_y = ((unsigned short )opcode - 0x4000 ) / cur_decode_frame -> linesize [0 ];
1053+ copy_from (s , s -> cur_decode_frame , s -> cur_decode_frame , off_x , off_y );
1054+ }
1055+ decode_map_p += 2 ;
1056+ break ;
1057+ }
1058+ skip_map_p += 2 ;
1059+ skip = AV_RL16 (skip_map_p );
1060+ }
1061+ skip *= 2 ;
1062+ }
1063+ }
1064+
1065+ skip_map_p = s -> skip_map ;
1066+ skip = AV_RL16 (skip_map_p );
1067+ for (y = 0 ; y < s -> avctx -> height ; y += 8 ) {
1068+ for (x = 0 ; x < s -> avctx -> width ; x += 8 ) {
1069+ changed_block = 0 ;
1070+ s -> pixel_ptr = frame -> data [0 ] + x + y * frame -> linesize [0 ];
1071+ while (skip <= 0 ) {
1072+ if (skip != -0x8000 && skip != 0 ) {
1073+ changed_block = 1 ;
1074+ break ;
1075+ }
1076+ skip_map_p += 2 ;
1077+ skip = AV_RL16 (skip_map_p );
1078+ }
1079+ if (changed_block )
1080+ copy_from (s , s -> cur_decode_frame , frame , 0 , 0 );
1081+ else
1082+ copy_from (s , s -> last_frame , frame , 0 , 0 );
1083+ skip *= 2 ;
1084+ }
1085+ }
1086+
1087+ FFSWAP (AVFrame * , s -> prev_decode_frame , s -> cur_decode_frame );
1088+
1089+ if (bytestream2_get_bytes_left (& s -> stream_ptr ) > 1 ) {
1090+ av_log (s -> avctx , AV_LOG_DEBUG ,
1091+ "decode finished with %d bytes left over\n" ,
1092+ bytestream2_get_bytes_left (& s -> stream_ptr ));
1093+ }
1094+ }
1095+
1096+ static void ipvideo_decode_format_11_opcodes (IpvideoContext * s , AVFrame * frame )
9071097{
9081098 int x , y ;
9091099 unsigned char opcode ;
@@ -972,12 +1162,26 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
9721162
9731163 s -> last_frame = av_frame_alloc ();
9741164 s -> second_last_frame = av_frame_alloc ();
975- if (!s -> last_frame || !s -> second_last_frame ) {
1165+ s -> cur_decode_frame = av_frame_alloc ();
1166+ s -> prev_decode_frame = av_frame_alloc ();
1167+ if (!s -> last_frame || !s -> second_last_frame ||
1168+ !s -> cur_decode_frame || !s -> prev_decode_frame ) {
9761169 av_frame_free (& s -> last_frame );
9771170 av_frame_free (& s -> second_last_frame );
1171+ av_frame_free (& s -> cur_decode_frame );
1172+ av_frame_free (& s -> prev_decode_frame );
9781173 return AVERROR (ENOMEM );
9791174 }
9801175
1176+ s -> cur_decode_frame -> width = avctx -> width ;
1177+ s -> prev_decode_frame -> width = avctx -> width ;
1178+ s -> cur_decode_frame -> height = avctx -> height ;
1179+ s -> prev_decode_frame -> height = avctx -> height ;
1180+ s -> cur_decode_frame -> format = avctx -> pix_fmt ;
1181+ s -> prev_decode_frame -> format = avctx -> pix_fmt ;
1182+
1183+ ff_get_buffer (avctx , s -> cur_decode_frame , 0 );
1184+ ff_get_buffer (avctx , s -> prev_decode_frame , 0 );
9811185 return 0 ;
9821186}
9831187
@@ -999,18 +1203,53 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
9991203 if (buf_size < 2 )
10001204 return AVERROR_INVALIDDATA ;
10011205
1002- /* decoding map contains 4 bits of information per 8x8 block */
1003- s -> decoding_map_size = AV_RL16 (avpkt -> data );
1004-
1005- /* compressed buffer needs to be large enough to at least hold an entire
1006- * decoding map */
1007- if (buf_size < s -> decoding_map_size + 2 )
1008- return buf_size ;
1009-
1010-
1011- s -> decoding_map = buf + 2 ;
1012- bytestream2_init (& s -> stream_ptr , buf + 2 + s -> decoding_map_size ,
1013- buf_size - s -> decoding_map_size );
1206+ s -> frame_format = AV_RB8 (avpkt -> data );
1207+ switch (s -> frame_format ) {
1208+ case 0x06 :
1209+ /* Format 0x06 has decoding map appended to the top of pixel data */
1210+ /* decoding map contains 16 bits of information per 8x8 block */
1211+ s -> decoding_map_size = ((s -> avctx -> width / 8 ) * (s -> avctx -> height / 8 )) * 2 ;
1212+ s -> decoding_map = buf + 3 + 14 ; /* 14 bits of op data */
1213+
1214+ s -> video_data_size = AV_RL16 (avpkt -> data + 1 ) - s -> decoding_map_size - 14 ;
1215+ bytestream2_init (& s -> stream_ptr , buf + 3 + s -> decoding_map_size + 14 , s -> video_data_size );
1216+
1217+ if (buf_size < s -> decoding_map_size + 2 )
1218+ return buf_size ;
1219+ break ;
1220+
1221+ case 0x10 :
1222+ /* Format 0x10 has a decoding map, pixel data, and a skip map */
1223+ s -> video_data_size = AV_RL16 (avpkt -> data + 1 );
1224+ bytestream2_init (& s -> stream_ptr , buf + 3 , s -> video_data_size );
1225+
1226+ /* decoding map contains 16 bits of information per 8x8 block */
1227+ s -> decoding_map_size = AV_RL16 (avpkt -> data + 3 + s -> video_data_size );
1228+ s -> decoding_map = buf + 3 + s -> video_data_size + 2 ;
1229+
1230+ /* skip map contains 16 bits of information per 15 blocks, ish */
1231+ s -> skip_map_size = AV_RL16 (avpkt -> data + 3 + s -> video_data_size + 2 + s -> decoding_map_size );
1232+ s -> skip_map = buf + 3 + s -> video_data_size + 2 + s -> decoding_map_size + 2 ;
1233+ break ;
1234+
1235+ case 0x11 :
1236+ /* Format 0x11 has a decoding map and pixel data */
1237+ s -> video_data_size = AV_RL16 (avpkt -> data + 1 );
1238+ bytestream2_init (& s -> stream_ptr , buf + 3 , s -> video_data_size );
1239+
1240+ /* decoding map contains 4 bits of information per 8x8 block */
1241+ s -> decoding_map_size = AV_RL16 (avpkt -> data + 3 + s -> video_data_size );
1242+ s -> decoding_map = buf + 3 + s -> video_data_size + 2 ;
1243+
1244+ /* compressed buffer needs to be large enough to at least hold an entire
1245+ * decoding map */
1246+ if (buf_size < s -> decoding_map_size + 2 )
1247+ return buf_size ;
1248+ break ;
1249+
1250+ default :
1251+ av_log (avctx , AV_LOG_ERROR , "Frame type 0x%02X unsupported\n" , s -> frame_format );
1252+ }
10141253
10151254 if ((ret = ff_get_buffer (avctx , frame , AV_GET_BUFFER_FLAG_REF )) < 0 )
10161255 return ret ;
@@ -1026,7 +1265,14 @@ static int ipvideo_decode_frame(AVCodecContext *avctx,
10261265 }
10271266 }
10281267
1029- ipvideo_decode_opcodes (s , frame );
1268+ if (s -> frame_format == 0x06 )
1269+ ipvideo_decode_format_06_opcodes (s , frame );
1270+
1271+ if (s -> frame_format == 0x10 )
1272+ ipvideo_decode_format_10_opcodes (s , frame );
1273+
1274+ if (s -> frame_format == 0x11 )
1275+ ipvideo_decode_format_11_opcodes (s , frame );
10301276
10311277 * got_frame = 1 ;
10321278
@@ -1046,6 +1292,8 @@ static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
10461292
10471293 av_frame_free (& s -> last_frame );
10481294 av_frame_free (& s -> second_last_frame );
1295+ av_frame_free (& s -> cur_decode_frame );
1296+ av_frame_free (& s -> prev_decode_frame );
10491297
10501298 return 0 ;
10511299}
0 commit comments