Unified · Split
| @@ -44,6 +44,7 @@ · 43 unmodified lines | |||
| 44 | typedef struct USPPContext { | 44 | typedef struct USPPContext { |
| 45 | const AVClass *av_class; | 45 | const AVClass *av_class; |
| 46 | int log2_count; | 46 | int log2_count; |
| 47 | int count; | ||
| 47 | int hsub, vsub; | 48 | int hsub, vsub; |
| 48 | int qp; | 49 | int qp; |
| 49 | char *codec_name; | 50 | char *codec_name; |
| @@ -55,12 +56,13 @@ typedef struct USPPContext { · 5 unmodified lines | |||
| 55 | uint8_t *outbuf; | 56 | uint8_t *outbuf; |
| 56 | AVCodecContext *avctx_enc[BLOCK*BLOCK]; | 57 | AVCodecContext *avctx_enc[BLOCK*BLOCK]; |
| 57 | AVCodecContext *avctx_dec[BLOCK*BLOCK]; | 58 | AVCodecContext *avctx_dec[BLOCK*BLOCK]; |
| 58 | AVPacket *pkt; | 59 | AVPacket *pkt [BLOCK*BLOCK]; |
| 59 | AVFrame *frame; | 60 | AVFrame *frame [BLOCK*BLOCK]; |
| 60 | AVFrame *frame_dec; | 61 | AVFrame *frame_dec [BLOCK*BLOCK]; |
| 61 | int8_t *non_b_qp_table; | 62 | int8_t *non_b_qp_table; |
| 62 | int non_b_qp_stride; | 63 | int non_b_qp_stride; |
| 63 | int use_bframe_qp; | 64 | int use_bframe_qp; |
| 65 | int quality; | ||
| 64 | } USPPContext; | 66 | } USPPContext; |
| 65 | 67 | ||
| 66 | #define OFFSET(x) offsetof(USPPContext, x) | 68 | #define OFFSET(x) offsetof(USPPContext, x) |
| @@ -188,13 +190,87 @@ static void store_slice_c(uint8_t *dst, const uint16_t *src, · 121 unmodified lines | |||
| 188 | } | 190 | } |
| 189 | } | 191 | } |
| 190 | 192 | ||
| 191 | static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], | 193 | static int filter_1phase(AVFilterContext *ctx, void *arg, int i, int nb_jobs) |
| 194 | { | ||
| 195 | USPPContext *p = ctx->priv; | ||
| 196 | int ret, x, y; | ||
| 197 | int width = ctx->inputs[0]->w; | ||
| 198 | int height = ctx->inputs[0]->h; | ||
| 199 | |||
| 200 | const int x1 = offset[i+nb_jobs-1][0]; | ||
| 201 | const int y1 = offset[i+nb_jobs-1][1]; | ||
| 202 | const int x1c = x1 >> p->hsub; | ||
| 203 | const int y1c = y1 >> p->vsub; | ||
| 204 | const int BLOCKc = BLOCK >> p->hsub; | ||
| 205 | int offset; | ||
| 206 | AVPacket *pkt = p->pkt[i]; | ||
| 207 | |||
| 208 | av_packet_unref(pkt); | ||
| 209 | pkt->data = p->outbuf; | ||
| 210 | pkt->size = p->outbuf_size; | ||
| 211 | |||
| 212 | p->frame[i]->linesize[0] = p->temp_stride[0]; | ||
| 213 | p->frame[i]->linesize[1] = p->temp_stride[1]; | ||
| 214 | p->frame[i]->linesize[2] = p->temp_stride[2]; | ||
| 215 | p->frame[i]->height = height + BLOCK; | ||
| 216 | p->frame[i]->width = width + BLOCK; | ||
| 217 | p->frame[i]->data[0] = p->src[0] + x1 + y1 * p->frame[i]->linesize[0]; | ||
| 218 | p->frame[i]->data[1] = p->src[1] + x1c + y1c * p->frame[i]->linesize[1]; | ||
| 219 | p->frame[i]->data[2] = p->src[2] + x1c + y1c * p->frame[i]->linesize[2]; | ||
| 220 | p->frame[i]->format = p->avctx_enc[i]->pix_fmt; | ||
| 221 | p->frame[i]->quality = p->quality; | ||
| 222 | |||
| 223 | ret = avcodec_send_frame(p->avctx_enc[i], p->frame[i]); | ||
| 224 | if (ret < 0) { | ||
| 225 | av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error sending a frame for encoding\n"); | ||
| 226 | return ret; | ||
| 227 | } | ||
| 228 | ret = avcodec_receive_packet(p->avctx_enc[i], pkt); | ||
| 229 | if (ret < 0) { | ||
| 230 | av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error receiving a packet from encoding\n"); | ||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 234 | ret = avcodec_send_packet(p->avctx_dec[i], pkt); | ||
| 235 | av_packet_unref(pkt); | ||
| 236 | if (ret < 0) { | ||
| 237 | av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); | ||
| 238 | return ret; | ||
| 239 | } | ||
| 240 | ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec[i]); | ||
| 241 | if (ret < 0) { | ||
| 242 | av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); | ||
| 243 | return ret; | ||
| 244 | } | ||
| 245 | |||
| 246 | offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec[i]->linesize[0]; | ||
| 247 | |||
| 248 | for (y = 0; y < height; y++) | ||
| 249 | for (x = 0; x < width; x++) | ||
| 250 | p->temp[0][x + y * p->temp_stride[0]] += p->frame_dec[i]->data[0][x + y * p->frame_dec[i]->linesize[0] + offset]; | ||
| 251 | |||
| 252 | |||
| 253 | if (!p->frame_dec[i]->data[2] || !p->temp[2]) | ||
| 254 | return 0; | ||
| 255 | |||
| 256 | offset = (BLOCKc-x1c) + (BLOCKc-y1c) * p->frame_dec[i]->linesize[1]; | ||
| 257 | |||
| 258 | for (y = 0; y < AV_CEIL_RSHIFT(height, p->vsub); y++) { | ||
| 259 | for (x = 0; x < AV_CEIL_RSHIFT(width, p->hsub); x++) { | ||
| 260 | p->temp[1][x + y * p->temp_stride[1]] += p->frame_dec[i]->data[1][x + y * p->frame_dec[i]->linesize[1] + offset]; | ||
| 261 | p->temp[2][x + y * p->temp_stride[2]] += p->frame_dec[i]->data[2][x + y * p->frame_dec[i]->linesize[2] + offset]; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | static void filter(AVFilterContext *ctx, uint8_t *dst[3], uint8_t *src[3], | ||
| 192 | int dst_stride[3], int src_stride[3], int width, | 269 | int dst_stride[3], int src_stride[3], int width, |
| 193 | int height, uint8_t *qp_store, int qp_stride) | 270 | int height, uint8_t *qp_store, int qp_stride) |
| 194 | { | 271 | { |
| 272 | USPPContext *p = ctx->priv; | ||
| 195 | int x, y, i, j; | 273 | int x, y, i, j; |
| 196 | const int count = 1<<p->log2_count; | ||
| 197 | int ret; | ||
| 198 | 274 | ||
| 199 | for (i = 0; i < 3; i++) { | 275 | for (i = 0; i < 3; i++) { |
| 200 | int is_chroma = !!i; | 276 | int is_chroma = !!i; |
| @@ -219,12 +295,11 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], · 18 unmodified lines | |||
| 219 | memcpy(p->src[i] + (h+block +y) * stride, p->src[i] + (h-y+block-1) * stride, stride); | 295 | memcpy(p->src[i] + (h+block +y) * stride, p->src[i] + (h-y+block-1) * stride, stride); |
| 220 | } | 296 | } |
| 221 | 297 | ||
| 222 | p->frame->linesize[i] = stride; | ||
| 223 | memset(p->temp[i], 0, (h + 2 * block) * stride * sizeof(int16_t)); | 298 | memset(p->temp[i], 0, (h + 2 * block) * stride * sizeof(int16_t)); |
| 224 | } | 299 | } |
| 225 | 300 | ||
| 226 | if (p->qp) | 301 | if (p->qp) |
| 227 | p->frame->quality = p->qp * FF_QP2LAMBDA; | 302 | p->quality = p->qp * FF_QP2LAMBDA; |
| 228 | else { | 303 | else { |
| 229 | int qpsum=0; | 304 | int qpsum=0; |
| 230 | int qpcount = (height>>4) * (height>>4); | 305 | int qpcount = (height>>4) * (height>>4); |
| @@ -233,71 +308,11 @@ static void filter(USPPContext *p, uint8_t *dst[3], uint8_t *src[3], · 2 unmodified lines | |||
| 233 | for (x = 0; x < (width>>4); x++) | 308 | for (x = 0; x < (width>>4); x++) |
| 234 | qpsum += qp_store[x + y * qp_stride]; | 309 | qpsum += qp_store[x + y * qp_stride]; |
| 235 | } | 310 | } |
| 236 | p->frame->quality = ff_norm_qscale((qpsum + qpcount/2) / qpcount, p->qscale_type) * FF_QP2LAMBDA; | 311 | p->quality = ff_norm_qscale((qpsum + qpcount/2) / qpcount, p->qscale_type) * FF_QP2LAMBDA; |
| 237 | } | 312 | } |
| 238 | // init per MB qscale stuff FIXME | 313 | // init per MB qscale stuff FIXME |
| 239 | p->frame->height = height + BLOCK; | ||
| 240 | p->frame->width = width + BLOCK; | ||
| 241 | |||
| 242 | for (i = 0; i < count; i++) { | ||
| 243 | const int x1 = offset[i+count-1][0]; | ||
| 244 | const int y1 = offset[i+count-1][1]; | ||
| 245 | const int x1c = x1 >> p->hsub; | ||
| 246 | const int y1c = y1 >> p->vsub; | ||
| 247 | const int BLOCKc = BLOCK >> p->hsub; | ||
| 248 | int offset; | ||
| 249 | AVPacket *pkt = p->pkt; | ||
| 250 | |||
| 251 | av_packet_unref(pkt); | ||
| 252 | pkt->data = p->outbuf; | ||
| 253 | pkt->size = p->outbuf_size; | ||
| 254 | |||
| 255 | p->frame->data[0] = p->src[0] + x1 + y1 * p->frame->linesize[0]; | ||
| 256 | p->frame->data[1] = p->src[1] + x1c + y1c * p->frame->linesize[1]; | ||
| 257 | p->frame->data[2] = p->src[2] + x1c + y1c * p->frame->linesize[2]; | ||
| 258 | p->frame->format = p->avctx_enc[i]->pix_fmt; | ||
| 259 | |||
| 260 | ret = avcodec_send_frame(p->avctx_enc[i], p->frame); | ||
| 261 | if (ret < 0) { | ||
| 262 | av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error sending a frame for encoding\n"); | ||
| 263 | continue; | ||
| 264 | } | ||
| 265 | ret = avcodec_receive_packet(p->avctx_enc[i], pkt); | ||
| 266 | if (ret < 0) { | ||
| 267 | av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error receiving a packet from encoding\n"); | ||
| 268 | continue; | ||
| 269 | } | ||
| 270 | |||
| 271 | ret = avcodec_send_packet(p->avctx_dec[i], pkt); | ||
| 272 | av_packet_unref(pkt); | ||
| 273 | if (ret < 0) { | ||
| 274 | av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n"); | ||
| 275 | continue; | ||
| 276 | } | ||
| 277 | ret = avcodec_receive_frame(p->avctx_dec[i], p->frame_dec); | ||
| 278 | if (ret < 0) { | ||
| 279 | av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n"); | ||
| 280 | continue; | ||
| 281 | } | ||
| 282 | |||
| 283 | offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec->linesize[0]; | ||
| 284 | |||
| 285 | for (y = 0; y < height; y++) | ||
| 286 | for (x = 0; x < width; x++) | ||
| 287 | p->temp[0][x + y * p->temp_stride[0]] += p->frame_dec->data[0][x + y * p->frame_dec->linesize[0] + offset]; | ||
| 288 | |||
| 289 | if (!src[2] || !dst[2]) | ||
| 290 | continue; | ||
| 291 | |||
| 292 | offset = (BLOCKc-x1c) + (BLOCKc-y1c) * p->frame_dec->linesize[1]; | ||
| 293 | 314 | ||
| 294 | for (y = 0; y < AV_CEIL_RSHIFT(height, p->vsub); y++) { | 315 | ff_filter_execute(ctx, filter_1phase, NULL, NULL, p->count); |
| 295 | for (x = 0; x < AV_CEIL_RSHIFT(width, p->hsub); x++) { | ||
| 296 | p->temp[1][x + y * p->temp_stride[1]] += p->frame_dec->data[1][x + y * p->frame_dec->linesize[1] + offset]; | ||
| 297 | p->temp[2][x + y * p->temp_stride[2]] += p->frame_dec->data[2][x + y * p->frame_dec->linesize[2] + offset]; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | } | ||
| 301 | 316 | ||
| 302 | for (j = 0; j < 3; j++) { | 317 | for (j = 0; j < 3; j++) { |
| 303 | int is_chroma = !!j; | 318 | int is_chroma = !!j; |
| @@ -342,6 +357,7 @@ static int config_input(AVFilterLink *inlink) · 38 unmodified lines | |||
| 342 | 357 | ||
| 343 | uspp->hsub = desc->log2_chroma_w; | 358 | uspp->hsub = desc->log2_chroma_w; |
| 344 | uspp->vsub = desc->log2_chroma_h; | 359 | uspp->vsub = desc->log2_chroma_h; |
| 360 | uspp->count = 1<<uspp->log2_count; | ||
| 345 | 361 | ||
| 346 | for (i = 0; i < 3; i++) { | 362 | for (i = 0; i < 3; i++) { |
| 347 | int is_chroma = !!i; | 363 | int is_chroma = !!i; |
| @@ -360,7 +376,7 @@ static int config_input(AVFilterLink *inlink) · 12 unmodified lines | |||
| 360 | return AVERROR(ENOMEM); | 376 | return AVERROR(ENOMEM); |
| 361 | } | 377 | } |
| 362 | 378 | ||
| 363 | for (i = 0; i < (1<<uspp->log2_count); i++) { | 379 | for (i = 0; i < uspp->count; i++) { |
| 364 | AVCodecContext *avctx_enc, *avctx_dec; | 380 | AVCodecContext *avctx_enc, *avctx_dec; |
| 365 | AVDictionary *opts = NULL; | 381 | AVDictionary *opts = NULL; |
| 366 | int ret; | 382 | int ret; |
| @@ -383,6 +399,8 @@ static int config_input(AVFilterLink *inlink) · 16 unmodified lines | |||
| 383 | avctx_enc->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY; | 399 | avctx_enc->flags = AV_CODEC_FLAG_QSCALE | AV_CODEC_FLAG_LOW_DELAY; |
| 384 | avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; | 400 | avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; |
| 385 | avctx_enc->global_quality = 123; | 401 | avctx_enc->global_quality = 123; |
| 402 | avctx_dec->thread_count = | ||
| 403 | avctx_enc->thread_count = 1; // We do threading in the filter with muiltiple codecs | ||
| 386 | ret = avcodec_open2(avctx_enc, enc, &opts); | 404 | ret = avcodec_open2(avctx_enc, enc, &opts); |
| 387 | av_dict_free(&opts); | 405 | av_dict_free(&opts); |
| 388 | if (ret < 0) | 406 | if (ret < 0) |
| @@ -394,15 +412,15 @@ static int config_input(AVFilterLink *inlink) · 5 unmodified lines | |||
| 394 | if (ret < 0) | 412 | if (ret < 0) |
| 395 | return ret; | 413 | return ret; |
| 396 | 414 | ||
| 415 | if (!(uspp->frame[i] = av_frame_alloc())) | ||
| 416 | return AVERROR(ENOMEM); | ||
| 417 | if (!(uspp->frame_dec[i] = av_frame_alloc())) | ||
| 418 | return AVERROR(ENOMEM); | ||
| 419 | if (!(uspp->pkt[i] = av_packet_alloc())) | ||
| 420 | return AVERROR(ENOMEM); | ||
| 397 | } | 421 | } |
| 398 | 422 | ||
| 399 | uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10; | 423 | uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10; |
| 400 | if (!(uspp->frame = av_frame_alloc())) | ||
| 401 | return AVERROR(ENOMEM); | ||
| 402 | if (!(uspp->frame_dec = av_frame_alloc())) | ||
| 403 | return AVERROR(ENOMEM); | ||
| 404 | if (!(uspp->pkt = av_packet_alloc())) | ||
| 405 | return AVERROR(ENOMEM); | ||
| 406 | if (!(uspp->outbuf = av_malloc(uspp->outbuf_size))) | 424 | if (!(uspp->outbuf = av_malloc(uspp->outbuf_size))) |
| 407 | return AVERROR(ENOMEM); | 425 | return AVERROR(ENOMEM); |
| 408 | 426 | ||
| @@ -464,7 +482,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 55 unmodified lines | |||
| 464 | out->height = in->height; | 482 | out->height = in->height; |
| 465 | } | 483 | } |
| 466 | 484 | ||
| 467 | filter(uspp, out->data, in->data, out->linesize, in->linesize, | 485 | filter(ctx, out->data, in->data, out->linesize, in->linesize, |
| 468 | inlink->w, inlink->h, qp_table, qp_stride); | 486 | inlink->w, inlink->h, qp_table, qp_stride); |
| 469 | } | 487 | } |
| 470 | } | 488 | } |
| @@ -492,15 +510,16 @@ static av_cold void uninit(AVFilterContext *ctx) · 21 unmodified lines | |||
| 492 | av_freep(&uspp->src[i]); | 510 | av_freep(&uspp->src[i]); |
| 493 | } | 511 | } |
| 494 | 512 | ||
| 495 | for (i = 0; i < (1 << uspp->log2_count); i++) { | 513 | for (i = 0; i < uspp->count; i++) { |
| 496 | avcodec_free_context(&uspp->avctx_enc[i]); | 514 | avcodec_free_context(&uspp->avctx_enc[i]); |
| 497 | avcodec_free_context(&uspp->avctx_dec[i]); | 515 | avcodec_free_context(&uspp->avctx_dec[i]); |
| 516 | av_frame_free(&uspp->frame[i]); | ||
| 517 | av_frame_free(&uspp->frame_dec[i]); | ||
| 518 | av_packet_free(&uspp->pkt[i]); | ||
| 498 | } | 519 | } |
| 499 | 520 | ||
| 500 | av_freep(&uspp->non_b_qp_table); | 521 | av_freep(&uspp->non_b_qp_table); |
| 501 | av_freep(&uspp->outbuf); | 522 | av_freep(&uspp->outbuf); |
| 502 | av_packet_free(&uspp->pkt); | ||
| 503 | av_frame_free(&uspp->frame); | ||
| 504 | } | 523 | } |
| 505 | 524 | ||
| 506 | static const AVFilterPad uspp_inputs[] = { | 525 | static const AVFilterPad uspp_inputs[] = { |
| @@ -528,5 +547,5 @@ const AVFilter ff_vf_uspp = { · 21 unmodified lines | |||
| 528 | FILTER_OUTPUTS(uspp_outputs), | 547 | FILTER_OUTPUTS(uspp_outputs), |
| 529 | FILTER_PIXFMTS_ARRAY(pix_fmts), | 548 | FILTER_PIXFMTS_ARRAY(pix_fmts), |
| 530 | .priv_class = &uspp_class, | 549 | .priv_class = &uspp_class, |
| 531 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, | 550 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, |
| 532 | }; | 551 | }; |