static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt) { int64_t dts; uint8_t header[FRAME_HEADER_SIZE+4]; int header_size = FRAME_HEADER_SIZE; dts = s->timestamp + pkt->dts; /* packet size & key_frame */ header[0] = pkt->stream_index; header[1] = 0; if (pkt->flags & PKT_FLAG_KEY) header[1] |= FLAG_KEY_FRAME; AV_WB24(header+2, pkt->size); AV_WB24(header+5, pkt->duration); AV_WB64(header+8, s->timestamp + pkt->pts); if (pkt->pts != pkt->dts) { header[1] |= FLAG_DTS; AV_WB32(header+16, pkt->pts - pkt->dts); header_size += 4; } ffm_write_data(s, header, header_size, dts, 1); ffm_write_data(s, pkt->data, pkt->size, dts, 0); return 0; }
static int cuvid_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { CUVIDContext *ctx = avctx->internal->hwaccel_priv_data; void *tmp; tmp = av_fast_realloc(ctx->bitstream, &ctx->bitstream_allocated, ctx->bitstream_len + size + 3); if (!tmp) return AVERROR(ENOMEM); ctx->bitstream = tmp; tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); if (!tmp) return AVERROR(ENOMEM); ctx->slice_offsets = tmp; AV_WB24(ctx->bitstream + ctx->bitstream_len, 1); memcpy(ctx->bitstream + ctx->bitstream_len + 3, buffer, size); ctx->slice_offsets[ctx->nb_slices] = ctx->bitstream_len ; ctx->bitstream_len += size + 3; ctx->nb_slices++; return 0; }
static int nvdec_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; CUVIDPICPARAMS *pp = &ctx->pic_params; const H264Context *h = avctx->priv_data; const H264SliceContext *sl = &h->slice_ctx[0]; void *tmp; tmp = av_fast_realloc(ctx->bitstream, &ctx->bitstream_allocated, ctx->bitstream_len + size + 3); if (!tmp) return AVERROR(ENOMEM); ctx->bitstream = tmp; tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets)); if (!tmp) return AVERROR(ENOMEM); ctx->slice_offsets = tmp; AV_WB24(ctx->bitstream + ctx->bitstream_len, 1); memcpy(ctx->bitstream + ctx->bitstream_len + 3, buffer, size); ctx->slice_offsets[ctx->nb_slices] = ctx->bitstream_len ; ctx->bitstream_len += size + 3; ctx->nb_slices++; if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI) pp->intra_pic_flag = 0; return 0; }
static int find_expected_header(AVCodecContext *c, int size, int key_frame, uint8_t out[64]){ int sample_rate= c->sample_rate; if(size>4096) return 0; AV_WB24(out, 1); if(c->codec_id == CODEC_ID_MPEG4){ if(key_frame){ return 3; }else{ out[3]= 0xB6; return 4; } }else if(c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MPEG2VIDEO){ return 3; }else if(c->codec_id == CODEC_ID_H264){ return 3; }else if(c->codec_id == CODEC_ID_MP3 || c->codec_id == CODEC_ID_MP2){ int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size; int layer= c->codec_id == CODEC_ID_MP3 ? 3 : 2; unsigned int header= 0xFFF00000; lsf = sample_rate < (24000+32000)/2; mpeg25 = sample_rate < (12000+16000)/2; sample_rate <<= lsf + mpeg25; if (sample_rate < (32000 + 44100)/2) sample_rate_index=2; else if(sample_rate < (44100 + 48000)/2) sample_rate_index=0; else sample_rate_index=1; sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); for(bitrate_index=2; bitrate_index<30; bitrate_index++){ frame_size = avpriv_mpa_bitrate_tab[lsf][layer-1][bitrate_index>>1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); if(frame_size == size) break; } header |= (!lsf)<<19; header |= (4-layer)<<17; header |= 1<<16; //no crc AV_WB32(out, header); if(size <= 0) return 2; //we guess there is no crc, if there is one the user clearly does not care about overhead if(bitrate_index == 30) return -1; //something is wrong ... header |= (bitrate_index>>1)<<12; header |= sample_rate_index<<10; header |= (bitrate_index&1)<<9; return 2; //FIXME actually put the needed ones in build_elision_headers() return 3; //we guess that the private bit is not set //FIXME the above assumptions should be checked, if these turn out false too often something should be done }
static inline void transpose_block_24_c(uint8_t *src, ptrdiff_t src_linesize, uint8_t *dst, ptrdiff_t dst_linesize, int w, int h) { int x, y; for (y = 0; y < h; y++, dst += dst_linesize) { for (x = 0; x < w; x++) { int32_t v = AV_RB24(src + x*src_linesize + y*3); AV_WB24(dst + 3*x, v); } } }
static av_always_inline void copy_elem(uint8_t *pout, const uint8_t *pin, int elem_size) { int v; switch (elem_size) { case 1: *pout = *pin; break; case 2: *((uint16_t *)pout) = *((uint16_t *)pin); break; case 3: v = AV_RB24(pin); AV_WB24(pout, v); break; case 4: *((uint32_t *)pout) = *((uint32_t *)pin); break; default: memcpy(pout, pin, elem_size); break; } }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; FlipContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; uint8_t *inrow, *outrow; int i, j, plane, step; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); /* copy palette if required */ if (av_pix_fmt_desc_get(inlink->format)->flags & AV_PIX_FMT_FLAG_PAL) memcpy(out->data[1], in->data[1], AVPALETTE_SIZE); for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { const int width = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->w, s->hsub) : inlink->w; const int height = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, s->vsub) : inlink->h; step = s->max_step[plane]; outrow = out->data[plane]; inrow = in ->data[plane] + (width - 1) * step; for (i = 0; i < height; i++) { switch (step) { case 1: for (j = 0; j < width; j++) outrow[j] = inrow[-j]; break; case 2: { uint16_t *outrow16 = (uint16_t *)outrow; uint16_t * inrow16 = (uint16_t *) inrow; for (j = 0; j < width; j++) outrow16[j] = inrow16[-j]; } break; case 3: { uint8_t *in = inrow; uint8_t *out = outrow; for (j = 0; j < width; j++, out += 3, in -= 3) { int32_t v = AV_RB24(in); AV_WB24(out, v); } } break; case 4: { uint32_t *outrow32 = (uint32_t *)outrow; uint32_t * inrow32 = (uint32_t *) inrow; for (j = 0; j < width; j++) outrow32[j] = inrow32[-j]; } break; default: for (j = 0; j < width; j++) memcpy(outrow + j*step, inrow - j*step, step); } inrow += in ->linesize[plane]; outrow += out->linesize[plane]; } } av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size) { static const int extradata_nal_types_hevc[] = { HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS, }; static const int extradata_nal_types_h264[] = { H264_NAL_SPS, H264_NAL_PPS, }; ExtractExtradataContext *s = ctx->priv_data; H2645Packet h2645_pkt = { 0 }; int extradata_size = 0; const int *extradata_nal_types; int nb_extradata_nal_types; int i, ret = 0; if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { extradata_nal_types = extradata_nal_types_hevc; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc); } else { extradata_nal_types = extradata_nal_types_h264; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264); } ret = ff_h2645_packet_split(&h2645_pkt, pkt->data, pkt->size, ctx, 0, 0, ctx->par_in->codec_id); if (ret < 0) return ret; for (i = 0; i < h2645_pkt.nb_nals; i++) { H2645NAL *nal = &h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) extradata_size += nal->raw_size + 3; } if (extradata_size) { AVBufferRef *filtered_buf; uint8_t *extradata, *filtered_data; if (s->remove) { filtered_buf = av_buffer_alloc(pkt->size + AV_INPUT_BUFFER_PADDING_SIZE); if (!filtered_buf) goto fail; filtered_data = filtered_buf->data; } extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) { av_buffer_unref(&filtered_buf); goto fail; } *data = extradata; *size = extradata_size; for (i = 0; i < h2645_pkt.nb_nals; i++) { H2645NAL *nal = &h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { AV_WB24(extradata, 1); // startcode memcpy(extradata + 3, nal->raw_data, nal->raw_size); extradata += 3 + nal->raw_size; } else if (s->remove) { AV_WB24(filtered_data, 1); // startcode memcpy(filtered_data + 3, nal->raw_data, nal->raw_size); filtered_data += 3 + nal->raw_size; } } if (s->remove) { av_buffer_unref(&pkt->buf); pkt->buf = filtered_buf; pkt->data = filtered_buf->data; pkt->size = filtered_data - filtered_buf->data; } } fail: ff_h2645_packet_uninit(&h2645_pkt); return ret; }
static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) { FlipContext *s = ctx->priv; ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; uint8_t *inrow, *outrow; int i, j, plane, step; for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { const int width = s->planewidth[plane]; const int height = s->planeheight[plane]; const int start = (height * job ) / nb_jobs; const int end = (height * (job+1)) / nb_jobs; step = s->max_step[plane]; outrow = out->data[plane] + start * out->linesize[plane]; inrow = in ->data[plane] + start * in->linesize[plane] + (width - 1) * step; for (i = start; i < end; i++) { switch (step) { case 1: for (j = 0; j < width; j++) outrow[j] = inrow[-j]; break; case 2: { uint16_t *outrow16 = (uint16_t *)outrow; uint16_t * inrow16 = (uint16_t *) inrow; for (j = 0; j < width; j++) outrow16[j] = inrow16[-j]; } break; case 3: { uint8_t *in = inrow; uint8_t *out = outrow; for (j = 0; j < width; j++, out += 3, in -= 3) { int32_t v = AV_RB24(in); AV_WB24(out, v); } } break; case 4: { uint32_t *outrow32 = (uint32_t *)outrow; uint32_t * inrow32 = (uint32_t *) inrow; for (j = 0; j < width; j++) outrow32[j] = inrow32[-j]; } break; default: for (j = 0; j < width; j++) memcpy(outrow + j*step, inrow - j*step, step); } inrow += in ->linesize[plane]; outrow += out->linesize[plane]; } } return 0; }
static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size) { static const int extradata_nal_types_hevc[] = { HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS, }; static const int extradata_nal_types_h264[] = { H264_NAL_SPS, H264_NAL_PPS, }; ExtractExtradataContext *s = ctx->priv_data; int extradata_size = 0, filtered_size = 0; const int *extradata_nal_types; int nb_extradata_nal_types; int i, has_sps = 0, has_vps = 0, ret = 0; if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { extradata_nal_types = extradata_nal_types_hevc; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc); } else { extradata_nal_types = extradata_nal_types_h264; nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264); } ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size, ctx, 0, 0, ctx->par_in->codec_id, 1, 0); if (ret < 0) return ret; for (i = 0; i < s->h2645_pkt.nb_nals; i++) { H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { extradata_size += nal->raw_size + 3; if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { if (nal->type == HEVC_NAL_SPS) has_sps = 1; if (nal->type == HEVC_NAL_VPS) has_vps = 1; } else { if (nal->type == H264_NAL_SPS) has_sps = 1; } } else if (s->remove) { filtered_size += nal->raw_size + 3; } } if (extradata_size && ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { AVBufferRef *filtered_buf; uint8_t *extradata, *filtered_data; if (s->remove) { filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!filtered_buf) { return AVERROR(ENOMEM); } memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); filtered_data = filtered_buf->data; } extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) { av_buffer_unref(&filtered_buf); return AVERROR(ENOMEM); } memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *data = extradata; *size = extradata_size; for (i = 0; i < s->h2645_pkt.nb_nals; i++) { H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { AV_WB24(extradata, 1); // startcode memcpy(extradata + 3, nal->raw_data, nal->raw_size); extradata += 3 + nal->raw_size; } else if (s->remove) { AV_WB24(filtered_data, 1); // startcode memcpy(filtered_data + 3, nal->raw_data, nal->raw_size); filtered_data += 3 + nal->raw_size; } } if (s->remove) { av_buffer_unref(&pkt->buf); pkt->buf = filtered_buf; pkt->data = filtered_buf->data; pkt->size = filtered_size; } } return 0; }
static void end_frame(AVFilterLink *inlink) { TransContext *trans = inlink->dst->priv; AVFilterBufferRef *inpic = inlink->cur_buf; AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; AVFilterLink *outlink = inlink->dst->outputs[0]; int plane; for (plane = 0; outpic->data[plane]; plane++) { int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; int pixstep = trans->pixsteps[plane]; int inh = inpic->video->h>>vsub; int outw = outpic->video->w>>hsub; int outh = outpic->video->h>>vsub; uint8_t *out, *in; int outlinesize, inlinesize; int x, y; out = outpic->data[plane]; outlinesize = outpic->linesize[plane]; in = inpic ->data[plane]; inlinesize = inpic ->linesize[plane]; if (trans->dir&1) { in += inpic->linesize[plane] * (inh-1); inlinesize *= -1; } if (trans->dir&2) { out += outpic->linesize[plane] * (outh-1); outlinesize *= -1; } for (y = 0; y < outh; y++) { switch (pixstep) { case 1: for (x = 0; x < outw; x++) out[x] = in[x*inlinesize + y]; break; case 2: for (x = 0; x < outw; x++) *((uint16_t *)(out + 2*x)) = *((uint16_t *)(in + x*inlinesize + y*2)); break; case 3: for (x = 0; x < outw; x++) { int32_t v = AV_RB24(in + x*inlinesize + y*3); AV_WB24(out + 3*x, v); } break; case 4: for (x = 0; x < outw; x++) *((uint32_t *)(out + 4*x)) = *((uint32_t *)(in + x*inlinesize + y*4)); break; } out += outlinesize; } } avfilter_unref_buffer(inpic); avfilter_draw_slice(outlink, 0, outpic->video->h, 1); avfilter_end_frame(outlink); avfilter_unref_buffer(outpic); }
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { AVFrame *f = data; GetByteContext gb; int width, height, ret, bits_pixel, pixel; uint8_t *out_buf; uint8_t count; int x, y; bytestream2_init(&gb, avpkt->data, avpkt->size); if (bytestream2_get_bytes_left(&gb) < ALIAS_HEADER_SIZE) { av_log(avctx, AV_LOG_ERROR, "Header too small %d.\n", avpkt->size); return AVERROR_INVALIDDATA; } width = bytestream2_get_be16u(&gb); height = bytestream2_get_be16u(&gb); bytestream2_skipu(&gb, 4); // obsolete X, Y offset bits_pixel = bytestream2_get_be16u(&gb); if (bits_pixel == 24) avctx->pix_fmt = AV_PIX_FMT_BGR24; else if (bits_pixel == 8) avctx->pix_fmt = AV_PIX_FMT_GRAY8; else { av_log(avctx, AV_LOG_ERROR, "Invalid pixel format.\n"); return AVERROR_INVALIDDATA; } ret = ff_set_dimensions(avctx, width, height); if (ret < 0) return ret; ret = ff_get_buffer(avctx, f, 0); if (ret < 0) return ret; f->pict_type = AV_PICTURE_TYPE_I; f->key_frame = 1; x = 0; y = 1; out_buf = f->data[0]; while (bytestream2_get_bytes_left(&gb) > 0) { int i; /* set buffer at the right position at every new line */ if (x == avctx->width) { x = 0; out_buf = f->data[0] + f->linesize[0] * y++; if (y > avctx->height) { av_log(avctx, AV_LOG_ERROR, "Ended frame decoding with %d bytes left.\n", bytestream2_get_bytes_left(&gb)); return AVERROR_INVALIDDATA; } } /* read packet and copy data */ count = bytestream2_get_byteu(&gb); if (!count || x + count > avctx->width) { av_log(avctx, AV_LOG_ERROR, "Invalid run length %d.\n", count); return AVERROR_INVALIDDATA; } if (avctx->pix_fmt == AV_PIX_FMT_BGR24) { pixel = bytestream2_get_be24(&gb); for (i = 0; i < count; i++) { AV_WB24(out_buf, pixel); out_buf += 3; } } else { // AV_PIX_FMT_GRAY8 pixel = bytestream2_get_byte(&gb); for (i = 0; i < count; i++) *out_buf++ = pixel; } x += i; } if (x != width || y != height) { av_log(avctx, AV_LOG_ERROR, "Picture stopped at %d,%d.\n", x, y); return AVERROR_INVALIDDATA; } *got_frame = 1; return avpkt->size; }
static int filter_slice(RotContext *rot, ThreadData *td, int job, int nb_jobs) { AVFrame *in = td->in; AVFrame *out = td->out; const int outw = td->outw, outh = td->outh; const int inw = td->inw, inh = td->inh; const int plane = td->plane; const int xi = td->xi, yi = td->yi; const int c = td->c, s = td->s; const int start = (outh * job ) / nb_jobs; const int end = (outh * (job+1)) / nb_jobs; int xprime = td->xprime + start * s; int yprime = td->yprime + start * c; int i, j, x, y; for (j = start; j < end; j++) { x = xprime + xi + FIXP*(inw-1)/2; y = yprime + yi + FIXP*(inh-1)/2; if (fabs(rot->angle - 0) < FLT_EPSILON && outw == inw && outh == inh) { simple_rotate(out->data[plane] + j * out->linesize[plane], in->data[plane] + j * in->linesize[plane], in->linesize[plane], 0, rot->draw.pixelstep[plane], outw); } else if (fabs(rot->angle - M_PI/2) < FLT_EPSILON && outw == inh && outh == inw) { simple_rotate(out->data[plane] + j * out->linesize[plane], in->data[plane] + j * rot->draw.pixelstep[plane], in->linesize[plane], 1, rot->draw.pixelstep[plane], outw); } else if (fabs(rot->angle - M_PI) < FLT_EPSILON && outw == inw && outh == inh) { simple_rotate(out->data[plane] + j * out->linesize[plane], in->data[plane] + (outh-j-1) * in->linesize[plane], in->linesize[plane], 2, rot->draw.pixelstep[plane], outw); } else if (fabs(rot->angle - 3*M_PI/2) < FLT_EPSILON && outw == inh && outh == inw) { simple_rotate(out->data[plane] + j * out->linesize[plane], in->data[plane] + (outh-j-1) * rot->draw.pixelstep[plane], in->linesize[plane], 3, rot->draw.pixelstep[plane], outw); } else { for (i = 0; i < outw; i++) { int32_t v; int x1, y1; uint8_t *pin, *pout; x1 = x>>16; y1 = y>>16; /* the out-of-range values avoid border artifacts */ if (x1 >= -1 && x1 <= inw && y1 >= -1 && y1 <= inh) { uint8_t inp_inv[4]; /* interpolated input value */ pout = out->data[plane] + j * out->linesize[plane] + i * rot->draw.pixelstep[plane]; if (rot->use_bilinear) { pin = rot->interpolate_bilinear(inp_inv, in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane], x, y, inw-1, inh-1); } else { int x2 = av_clip(x1, 0, inw-1); int y2 = av_clip(y1, 0, inh-1); pin = in->data[plane] + y2 * in->linesize[plane] + x2 * rot->draw.pixelstep[plane]; } switch (rot->draw.pixelstep[plane]) { case 1: *pout = *pin; break; case 2: v = AV_RL16(pin); AV_WL16(pout, v); break; case 3: v = AV_RB24(pin); AV_WB24(pout, v); break; case 4: *((uint32_t *)pout) = *((uint32_t *)pin); break; default: memcpy(pout, pin, rot->draw.pixelstep[plane]); break; } } x += c; y -= s; } } xprime += s; yprime += c; } return 0; }
static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { AVFilterLink *outlink = inlink->dst->outputs[0]; TransContext *trans = inlink->dst->priv; AVFilterBufferRef *out; int plane; out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); if (!out) { avfilter_unref_bufferp(&in); return AVERROR(ENOMEM); } out->pts = in->pts; if (in->video->pixel_aspect.num == 0) { out->video->pixel_aspect = in->video->pixel_aspect; } else { out->video->pixel_aspect.num = in->video->pixel_aspect.den; out->video->pixel_aspect.den = in->video->pixel_aspect.num; } for (plane = 0; out->data[plane]; plane++) { int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; int pixstep = trans->pixsteps[plane]; int inh = in->video->h>>vsub; int outw = out->video->w>>hsub; int outh = out->video->h>>vsub; uint8_t *dst, *src; int dstlinesize, srclinesize; int x, y; dst = out->data[plane]; dstlinesize = out->linesize[plane]; src = in->data[plane]; srclinesize = in->linesize[plane]; if (trans->dir&1) { src += in->linesize[plane] * (inh-1); srclinesize *= -1; } if (trans->dir&2) { dst += out->linesize[plane] * (outh-1); dstlinesize *= -1; } for (y = 0; y < outh; y++) { switch (pixstep) { case 1: for (x = 0; x < outw; x++) dst[x] = src[x*srclinesize + y]; break; case 2: for (x = 0; x < outw; x++) *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2)); break; case 3: for (x = 0; x < outw; x++) { int32_t v = AV_RB24(src + x*srclinesize + y*3); AV_WB24(dst + 3*x, v); } break; case 4: for (x = 0; x < outw; x++) *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4)); break; } dst += dstlinesize; } } avfilter_unref_bufferp(&in); return ff_filter_frame(outlink, out); }