FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
h263.c
Go to the documentation of this file.
1 /*
2  * H.263/MPEG-4 backend for encoder and decoder
3  * Copyright (c) 2000,2001 Fabrice Bellard
4  * H.263+ support.
5  * Copyright (c) 2001 Juan J. Sierralta P
6  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 /**
26  * @file
27  * H.263/MPEG-4 codec.
28  */
29 
30 #include "config.h"
31 
32 #include "libavutil/thread.h"
33 #include "mpegvideo.h"
34 #include "h263.h"
35 #include "h263data.h"
36 #include "h263dsp.h"
37 #include "mathops.h"
38 #include "mpegpicture.h"
39 #include "mpegutils.h"
40 #include "rl.h"
41 
42 #if CONFIG_MPEGVIDEO
43 static av_cold void h263_init_rl_inter(void)
44 {
45  static uint8_t h263_rl_inter_table[2][2 * MAX_RUN + MAX_LEVEL + 3];
46  ff_rl_init(&ff_h263_rl_inter, h263_rl_inter_table);
47 }
48 
50 {
51  static AVOnce init_static_once = AV_ONCE_INIT;
52  ff_thread_once(&init_static_once, h263_init_rl_inter);
53 }
54 #endif
55 
57  const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
58  //FIXME a lot of that is only needed for !low_delay
59  const int wrap = s->b8_stride;
60  const int xy = s->block_index[0];
61 
62  if(s->mv_type != MV_TYPE_8X8){
63  int motion_x, motion_y;
64  if (s->mb_intra) {
65  motion_x = 0;
66  motion_y = 0;
67  } else if (s->mv_type == MV_TYPE_16X16) {
68  motion_x = s->mv[0][0][0];
69  motion_y = s->mv[0][0][1];
70  } else /*if (s->mv_type == MV_TYPE_FIELD)*/ {
71  int i;
72  motion_x = s->mv[0][0][0] + s->mv[0][1][0];
73  motion_y = s->mv[0][0][1] + s->mv[0][1][1];
74  motion_x = (motion_x>>1) | (motion_x&1);
75  for(i=0; i<2; i++){
76  s->p_field_mv_table[i][0][mb_xy][0]= s->mv[0][i][0];
77  s->p_field_mv_table[i][0][mb_xy][1]= s->mv[0][i][1];
78  }
79  s->cur_pic.ref_index[0][4*mb_xy ] =
80  s->cur_pic.ref_index[0][4*mb_xy + 1] = s->field_select[0][0];
81  s->cur_pic.ref_index[0][4*mb_xy + 2] =
82  s->cur_pic.ref_index[0][4*mb_xy + 3] = s->field_select[0][1];
83  }
84 
85  /* no update if 8X8 because it has been done during parsing */
86  s->cur_pic.motion_val[0][xy][0] = motion_x;
87  s->cur_pic.motion_val[0][xy][1] = motion_y;
88  s->cur_pic.motion_val[0][xy + 1][0] = motion_x;
89  s->cur_pic.motion_val[0][xy + 1][1] = motion_y;
90  s->cur_pic.motion_val[0][xy + wrap][0] = motion_x;
91  s->cur_pic.motion_val[0][xy + wrap][1] = motion_y;
92  s->cur_pic.motion_val[0][xy + 1 + wrap][0] = motion_x;
93  s->cur_pic.motion_val[0][xy + 1 + wrap][1] = motion_y;
94  }
95 }
96 
98  int qp_c;
99  const int linesize = s->linesize;
100  const int uvlinesize= s->uvlinesize;
101  const int xy = s->mb_y * s->mb_stride + s->mb_x;
102  uint8_t *dest_y = s->dest[0];
103  uint8_t *dest_cb= s->dest[1];
104  uint8_t *dest_cr= s->dest[2];
105 
106  /*
107  Diag Top
108  Left Center
109  */
110  if (!IS_SKIP(s->cur_pic.mb_type[xy])) {
111  qp_c= s->qscale;
112  s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize, linesize, qp_c);
113  s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c);
114  }else
115  qp_c= 0;
116 
117  if(s->mb_y){
118  int qp_dt, qp_tt, qp_tc;
119 
120  if (IS_SKIP(s->cur_pic.mb_type[xy - s->mb_stride]))
121  qp_tt=0;
122  else
123  qp_tt = s->cur_pic.qscale_table[xy - s->mb_stride];
124 
125  if(qp_c)
126  qp_tc= qp_c;
127  else
128  qp_tc= qp_tt;
129 
130  if(qp_tc){
131  const int chroma_qp= s->chroma_qscale_table[qp_tc];
132  s->h263dsp.h263_v_loop_filter(dest_y, linesize, qp_tc);
133  s->h263dsp.h263_v_loop_filter(dest_y + 8, linesize, qp_tc);
134 
135  s->h263dsp.h263_v_loop_filter(dest_cb, uvlinesize, chroma_qp);
136  s->h263dsp.h263_v_loop_filter(dest_cr, uvlinesize, chroma_qp);
137  }
138 
139  if(qp_tt)
140  s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize + 8, linesize, qp_tt);
141 
142  if(s->mb_x){
143  if (qp_tt || IS_SKIP(s->cur_pic.mb_type[xy - 1 - s->mb_stride]))
144  qp_dt= qp_tt;
145  else
146  qp_dt = s->cur_pic.qscale_table[xy - 1 - s->mb_stride];
147 
148  if(qp_dt){
149  const int chroma_qp= s->chroma_qscale_table[qp_dt];
150  s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize, linesize, qp_dt);
151  s->h263dsp.h263_h_loop_filter(dest_cb - 8 * uvlinesize, uvlinesize, chroma_qp);
152  s->h263dsp.h263_h_loop_filter(dest_cr - 8 * uvlinesize, uvlinesize, chroma_qp);
153  }
154  }
155  }
156 
157  if(qp_c){
158  s->h263dsp.h263_h_loop_filter(dest_y + 8, linesize, qp_c);
159  if(s->mb_y + 1 == s->mb_height)
160  s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c);
161  }
162 
163  if(s->mb_x){
164  int qp_lc;
165  if (qp_c || IS_SKIP(s->cur_pic.mb_type[xy - 1]))
166  qp_lc= qp_c;
167  else
168  qp_lc = s->cur_pic.qscale_table[xy - 1];
169 
170  if(qp_lc){
171  s->h263dsp.h263_h_loop_filter(dest_y, linesize, qp_lc);
172  if(s->mb_y + 1 == s->mb_height){
173  const int chroma_qp= s->chroma_qscale_table[qp_lc];
174  s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize, linesize, qp_lc);
175  s->h263dsp.h263_h_loop_filter(dest_cb, uvlinesize, chroma_qp);
176  s->h263dsp.h263_h_loop_filter(dest_cr, uvlinesize, chroma_qp);
177  }
178  }
179  }
180 }
181 
182 int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir,
183  int *px, int *py)
184 {
185  int wrap;
186  int16_t *A, *B, *C, (*mot_val)[2];
187  static const int off[4]= {2, 1, 1, -1};
188 
189  wrap = s->b8_stride;
190  mot_val = s->cur_pic.motion_val[dir] + s->block_index[block];
191 
192  A = mot_val[ - 1];
193  /* special case for first (slice) line */
194  if (s->first_slice_line && block<3) {
195  // we can't just change some MVs to simulate that as we need them for the B-frames (and ME)
196  // and if we ever support non rectangular objects than we need to do a few ifs here anyway :(
197  if(block==0){ //most common case
198  if(s->mb_x == s->resync_mb_x){ //rare
199  *px= *py = 0;
200  }else if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare
201  C = mot_val[off[block] - wrap];
202  if(s->mb_x==0){
203  *px = C[0];
204  *py = C[1];
205  }else{
206  *px = mid_pred(A[0], 0, C[0]);
207  *py = mid_pred(A[1], 0, C[1]);
208  }
209  }else{
210  *px = A[0];
211  *py = A[1];
212  }
213  }else if(block==1){
214  if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare
215  C = mot_val[off[block] - wrap];
216  *px = mid_pred(A[0], 0, C[0]);
217  *py = mid_pred(A[1], 0, C[1]);
218  }else{
219  *px = A[0];
220  *py = A[1];
221  }
222  }else{ /* block==2*/
223  B = mot_val[ - wrap];
224  C = mot_val[off[block] - wrap];
225  if(s->mb_x == s->resync_mb_x) //rare
226  A[0]=A[1]=0;
227 
228  *px = mid_pred(A[0], B[0], C[0]);
229  *py = mid_pred(A[1], B[1], C[1]);
230  }
231  } else {
232  B = mot_val[ - wrap];
233  C = mot_val[off[block] - wrap];
234  *px = mid_pred(A[0], B[0], C[0]);
235  *py = mid_pred(A[1], B[1], C[1]);
236  }
237  return *mot_val;
238 }
A
#define A(x)
Definition: vpx_arith.h:28
MV_TYPE_16X16
#define MV_TYPE_16X16
1 vector for the whole mb
Definition: mpegvideo.h:185
h263data.h
thread.h
MAX_RUN
#define MAX_RUN
Definition: rl.h:35
h263dsp.h
mpegvideo.h
mpegutils.h
ff_h263_pred_motion
int16_t * ff_h263_pred_motion(MpegEncContext *s, int block, int dir, int *px, int *py)
Definition: h263.c:182
wrap
#define wrap(func)
Definition: neontest.h:65
ff_h263_update_motion_val
void ff_h263_update_motion_val(MpegEncContext *s)
Definition: h263.c:56
C
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
Definition: writing_filters.txt:58
ff_thread_once
static int ff_thread_once(char *control, void(*routine)(void))
Definition: thread.h:205
av_cold
#define av_cold
Definition: attributes.h:90
s
#define s(width, name)
Definition: cbs_vp9.c:198
B
#define B
Definition: huffyuv.h:42
IS_SKIP
#define IS_SKIP(a)
Definition: mpegutils.h:75
ff_rl_init
av_cold void ff_rl_init(RLTable *rl, uint8_t static_store[2][2 *MAX_RUN+MAX_LEVEL+3])
Initialize index_run, max_level and max_run from n, last, table_vlc, table_run and table_level.
Definition: rl.c:43
AV_ONCE_INIT
#define AV_ONCE_INIT
Definition: thread.h:203
ff_h263_init_rl_inter
void ff_h263_init_rl_inter(void)
mathops.h
AVOnce
#define AVOnce
Definition: thread.h:202
MV_TYPE_8X8
#define MV_TYPE_8X8
4 vectors (H.263, MPEG-4 4MV)
Definition: mpegvideo.h:186
MAX_LEVEL
#define MAX_LEVEL
Definition: rl.h:36
ff_h263_rl_inter
RLTable ff_h263_rl_inter
Definition: h263data.c:159
mpegpicture.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
mid_pred
#define mid_pred
Definition: mathops.h:97
ff_h263_loop_filter
void ff_h263_loop_filter(MpegEncContext *s)
Definition: h263.c:97
rl.h
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
MpegEncContext
MpegEncContext.
Definition: mpegvideo.h:64
h263.h