## ffmpeg / libavcodec / mdec.c @ 20646267

History | View | Annotate | Download (7.93 KB)

1 | c3bf0288 | Michael Niedermayer | ```
/*
``` |
---|---|---|---|

2 | ```
* PSX MDEC codec
``` |
||

3 | ```
* Copyright (c) 2003 Michael Niedermayer
``` |
||

4 | ```
*
``` |
||

5 | ```
* This library is free software; you can redistribute it and/or
``` |
||

6 | ```
* modify it under the terms of the GNU Lesser General Public
``` |
||

7 | ```
* License as published by the Free Software Foundation; either
``` |
||

8 | ```
* version 2 of the License, or (at your option) any later version.
``` |
||

9 | ```
*
``` |
||

10 | ```
* This library is distributed in the hope that it will be useful,
``` |
||

11 | ```
* but WITHOUT ANY WARRANTY; without even the implied warranty of
``` |
||

12 | ```
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
``` |
||

13 | ```
* Lesser General Public License for more details.
``` |
||

14 | ```
*
``` |
||

15 | ```
* You should have received a copy of the GNU Lesser General Public
``` |
||

16 | ```
* License along with this library; if not, write to the Free Software
``` |
||

17 | ```
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
``` |
||

18 | ```
*
``` |
||

19 | ```
* based upon code from Sebastian Jedruszkiewicz <elf@frogger.rules.pl>
``` |
||

20 | ```
*/
``` |
||

21 | |||

22 | ```
/**
``` |
||

23 | ```
* @file mdec.c
``` |
||

24 | ```
* PSX MDEC codec.
``` |
||

25 | ```
* This is very similar to intra only MPEG1.
``` |
||

26 | ```
*/
``` |
||

27 | |||

28 | #include "avcodec.h" |
||

29 | #include "dsputil.h" |
||

30 | #include "mpegvideo.h" |
||

31 | |||

32 | ```
//#undef NDEBUG
``` |
||

33 | ```
//#include <assert.h>
``` |
||

34 | |||

35 | typedef struct MDECContext{ |
||

36 | AVCodecContext *avctx; |
||

37 | DSPContext dsp; |
||

38 | AVFrame picture; |
||

39 | PutBitContext pb; |
||

40 | GetBitContext gb; |
||

41 | ScanTable scantable; |
||

42 | ```
int version;
``` |
||

43 | ```
int qscale;
``` |
||

44 | int last_dc[3]; |
||

45 | ```
int mb_width;
``` |
||

46 | ```
int mb_height;
``` |
||

47 | ```
int mb_x, mb_y;
``` |
||

48 | DCTELEM __align8 block[6][64]; |
||

49 | ```
uint16_t __align8 intra_matrix[64];
``` |
||

50 | int __align8 q_intra_matrix[64]; |
||

51 | uint8_t *bitstream_buffer; |
||

52 | ```
int bitstream_buffer_size;
``` |
||

53 | int block_last_index[6]; |
||

54 | } MDECContext; |
||

55 | |||

56 | ```
//very similar to mpeg1
``` |
||

57 | static inline int mdec_decode_block_intra(MDECContext *a, DCTELEM *block, int n) |
||

58 | { |
||

59 | ```
int level, diff, i, j, run;
``` |
||

60 | ```
int component;
``` |
||

61 | RLTable *rl = &rl_mpeg1; |
||

62 | ```
uint8_t * const scantable= a->scantable.permutated;
``` |
||

63 | ```
const uint16_t *quant_matrix= ff_mpeg1_default_intra_matrix;
``` |
||

64 | const int qscale= a->qscale; |
||

65 | |||

66 | ```
/* DC coef */
``` |
||

67 | if(a->version==2){ |
||

68 | 67b04c1a | Michael Niedermayer | block[0]= 2*get_sbits(&a->gb, 10) + 1024; |

69 | c3bf0288 | Michael Niedermayer | ```
}else{
``` |

70 | component = (n <= 3 ? 0 : n - 4 + 1); |
||

71 | diff = decode_dc(&a->gb, component); |
||

72 | if (diff >= 0xffff) |
||

73 | return -1; |
||

74 | a->last_dc[component]+= diff; |
||

75 | block[0] = a->last_dc[component]<<3; |
||

76 | } |
||

77 | |||

78 | ```
i = 0;
``` |
||

79 | { |
||

80 | OPEN_READER(re, &a->gb); |
||

81 | ```
/* now quantify & encode AC coefs */
``` |
||

82 | ```
for(;;) {
``` |
||

83 | UPDATE_CACHE(re, &a->gb); |
||

84 | GET_RL_VLC(level, run, re, &a->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2); |
||

85 | |||

86 | if(level == 127){ |
||

87 | ```
break;
``` |
||

88 | } else if(level != 0) { |
||

89 | i += run; |
||

90 | j = scantable[i]; |
||

91 | ```
level= (level*qscale*quant_matrix[j])>>3;
``` |
||

92 | 67b04c1a | Michael Niedermayer | ```
// level= (level-1)|1;
``` |

93 | c3bf0288 | Michael Niedermayer | level = (level ^ SHOW_SBITS(re, &a->gb, 1)) - SHOW_SBITS(re, &a->gb, 1); |

94 | ```
LAST_SKIP_BITS(re, &a->gb, 1);
``` |
||

95 | ```
} else {
``` |
||

96 | ```
/* escape */
``` |
||

97 | run = SHOW_UBITS(re, &a->gb, 6)+1; LAST_SKIP_BITS(re, &a->gb, 6); |
||

98 | UPDATE_CACHE(re, &a->gb); |
||

99 | bf5d0505 | Michael Niedermayer | level = SHOW_SBITS(re, &a->gb, 10); SKIP_BITS(re, &a->gb, 10); |

100 | c3bf0288 | Michael Niedermayer | i += run; |

101 | j = scantable[i]; |
||

102 | 67b04c1a | Michael Niedermayer | if(level<0){ |

103 | c3bf0288 | Michael Niedermayer | level= -level; |

104 | 67b04c1a | Michael Niedermayer | ```
level= (level*qscale*quant_matrix[j])>>3;
``` |

105 | c3bf0288 | Michael Niedermayer | level= (level-1)|1; |

106 | level= -level; |
||

107 | 67b04c1a | Michael Niedermayer | ```
}else{
``` |

108 | ```
level= (level*qscale*quant_matrix[j])>>3;
``` |
||

109 | level= (level-1)|1; |
||

110 | } |
||

111 | c3bf0288 | Michael Niedermayer | } |

112 | if (i > 63){ |
||

113 | 9b879566 | Michel Bardiaux | ```
av_log(a->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", a->mb_x, a->mb_y);
``` |

114 | c3bf0288 | Michael Niedermayer | return -1; |

115 | } |
||

116 | |||

117 | block[j] = level; |
||

118 | } |
||

119 | CLOSE_READER(re, &a->gb); |
||

120 | } |
||

121 | a->block_last_index[n] = i; |
||

122 | return 0; |
||

123 | } |
||

124 | |||

125 | static inline int decode_mb(MDECContext *a, DCTELEM block[6][64]){ |
||

126 | ```
int i;
``` |
||

127 | 77ee78bc | Michael Niedermayer | const int block_index[6]= {5,4,0,1,2,3}; |

128 | c3bf0288 | Michael Niedermayer | |

129 | ```
a->dsp.clear_blocks(block[0]);
``` |
||

130 | |||

131 | 67b04c1a | Michael Niedermayer | for(i=0; i<6; i++){ |

132 | if( mdec_decode_block_intra(a, block[ block_index[i] ], block_index[i]) < 0) |
||

133 | c3bf0288 | Michael Niedermayer | return -1; |

134 | } |
||

135 | return 0; |
||

136 | } |
||

137 | |||

138 | static inline void idct_put(MDECContext *a, int mb_x, int mb_y){ |
||

139 | ```
DCTELEM (*block)[64]= a->block;
``` |
||

140 | int linesize= a->picture.linesize[0]; |
||

141 | |||

142 | uint8_t *dest_y = a->picture.data[0] + (mb_y * 16* linesize ) + mb_x * 16; |
||

143 | uint8_t *dest_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8; |
||

144 | uint8_t *dest_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8; |
||

145 | |||

146 | ```
a->dsp.idct_put(dest_y , linesize, block[0]);
``` |
||

147 | a->dsp.idct_put(dest_y + 8, linesize, block[1]); |
||

148 | a->dsp.idct_put(dest_y + 8*linesize , linesize, block[2]); |
||

149 | a->dsp.idct_put(dest_y + 8*linesize + 8, linesize, block[3]); |
||

150 | |||

151 | ```
if(!(a->avctx->flags&CODEC_FLAG_GRAY)){
``` |
||

152 | a->dsp.idct_put(dest_cb, a->picture.linesize[1], block[4]); |
||

153 | a->dsp.idct_put(dest_cr, a->picture.linesize[2], block[5]); |
||

154 | } |
||

155 | } |
||

156 | |||

157 | static int decode_frame(AVCodecContext *avctx, |
||

158 | void *data, int *data_size, |
||

159 | ```
uint8_t *buf, int buf_size)
``` |
||

160 | { |
||

161 | ```
MDECContext * const a = avctx->priv_data;
``` |
||

162 | AVFrame *picture = data; |
||

163 | ```
AVFrame * const p= (AVFrame*)&a->picture;
``` |
||

164 | ```
int i;
``` |
||

165 | |||

166 | ```
/* special case for last picture */
``` |
||

167 | if (buf_size == 0) { |
||

168 | return 0; |
||

169 | } |
||

170 | |||

171 | if(p->data[0]) |
||

172 | avctx->release_buffer(avctx, p); |
||

173 | |||

174 | ```
p->reference= 0;
``` |
||

175 | if(avctx->get_buffer(avctx, p) < 0){ |
||

176 | 9b879566 | Michel Bardiaux | ```
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
``` |

177 | c3bf0288 | Michael Niedermayer | return -1; |

178 | } |
||

179 | p->pict_type= I_TYPE; |
||

180 | ```
p->key_frame= 1;
``` |
||

181 | ```
a->last_dc[0]=
``` |
||

182 | ```
a->last_dc[1]=
``` |
||

183 | a->last_dc[2]= 0; |
||

184 | |||

185 | a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); |
||

186 | dc98fc8d | Michael Niedermayer | for(i=0; i<buf_size; i+=2){ |

187 | ```
a->bitstream_buffer[i] = buf[i+1];
``` |
||

188 | ```
a->bitstream_buffer[i+1]= buf[i ];
``` |
||

189 | c3bf0288 | Michael Niedermayer | } |

190 | ```
init_get_bits(&a->gb, a->bitstream_buffer, buf_size*8);
``` |
||

191 | |||

192 | 421e0859 | Mike Melanson | ```
/* skip over 4 preamble bytes in stream (typically 0xXX 0xXX 0x00 0x38) */
``` |

193 | ```
skip_bits(&a->gb, 32);
``` |
||

194 | |||

195 | c3bf0288 | Michael Niedermayer | ```
a->qscale= get_bits(&a->gb, 16);
``` |

196 | ```
a->version= get_bits(&a->gb, 16);
``` |
||

197 | |||

198 | e986b6e2 | Mike Melanson | ```
// printf("qscale:%d (0x%X), version:%d (0x%X)\n", a->qscale, a->qscale, a->version, a->version);
``` |

199 | c3bf0288 | Michael Niedermayer | |

200 | bf5d0505 | Michael Niedermayer | for(a->mb_x=0; a->mb_x<a->mb_width; a->mb_x++){ |

201 | for(a->mb_y=0; a->mb_y<a->mb_height; a->mb_y++){ |
||

202 | c3bf0288 | Michael Niedermayer | if( decode_mb(a, a->block) <0) |

203 | return -1; |
||

204 | |||

205 | idct_put(a, a->mb_x, a->mb_y); |
||

206 | } |
||

207 | } |
||

208 | |||

209 | ```
// p->quality= (32 + a->inv_qscale/2)/a->inv_qscale;
``` |
||

210 | ```
// memset(p->qscale_table, p->quality, p->qstride*a->mb_height);
``` |
||

211 | |||

212 | *picture= *(AVFrame*)&a->picture; |
||

213 | ```
*data_size = sizeof(AVPicture);
``` |
||

214 | |||

215 | emms_c(); |
||

216 | |||

217 | return (get_bits_count(&a->gb)+31)/32*4; |
||

218 | } |
||

219 | |||

220 | static void mdec_common_init(AVCodecContext *avctx){ |
||

221 | ```
MDECContext * const a = avctx->priv_data;
``` |
||

222 | |||

223 | dsputil_init(&a->dsp, avctx); |
||

224 | |||

225 | a->mb_width = (avctx->width + 15) / 16; |
||

226 | a->mb_height = (avctx->height + 15) / 16; |
||

227 | |||

228 | avctx->coded_frame= (AVFrame*)&a->picture; |
||

229 | a->avctx= avctx; |
||

230 | } |
||

231 | |||

232 | static int decode_init(AVCodecContext *avctx){ |
||

233 | ```
MDECContext * const a = avctx->priv_data;
``` |
||

234 | AVFrame *p= (AVFrame*)&a->picture; |
||

235 | |||

236 | mdec_common_init(avctx); |
||

237 | init_vlcs(); |
||

238 | ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_zigzag_direct); |
||

239 | ```
/*
``` |
||

240 | ```
for(i=0; i<64; i++){
``` |
||

241 | ```
int index= ff_zigzag_direct[i];
``` |
||

242 | ```
a->intra_matrix[i]= 64*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale;
``` |
||

243 | ```
}
``` |
||

244 | ```
*/
``` |
||

245 | p->qstride= a->mb_width; |
||

246 | p->qscale_table= av_mallocz( p->qstride * a->mb_height); |
||

247 | |||

248 | return 0; |
||

249 | } |
||

250 | |||

251 | static int decode_end(AVCodecContext *avctx){ |
||

252 | ```
MDECContext * const a = avctx->priv_data;
``` |
||

253 | |||

254 | av_freep(&a->bitstream_buffer); |
||

255 | av_freep(&a->picture.qscale_table); |
||

256 | ```
a->bitstream_buffer_size=0;
``` |
||

257 | |||

258 | return 0; |
||

259 | } |
||

260 | |||

261 | AVCodec mdec_decoder = { |
||

262 | ```
"mdec",
``` |
||

263 | CODEC_TYPE_VIDEO, |
||

264 | CODEC_ID_MDEC, |
||

265 | ```
sizeof(MDECContext),
``` |
||

266 | decode_init, |
||

267 | ```
NULL,
``` |
||

268 | decode_end, |
||

269 | decode_frame, |
||

270 | CODEC_CAP_DR1, |
||

271 | }; |