Fix avcodec_align_dimensions to return values suitably aligned for FLV decoding

with SSE and add a avcodec_align_dimensions2 taht returns the stride alignment
requirements independently from doing the width/height padding.

Originally committed as revision 22095 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Reimar Döffinger 2010-02-27 21:13:22 +00:00
parent 1d53620311
commit eb285cfe8e
2 changed files with 46 additions and 15 deletions

View File

@ -1367,7 +1367,7 @@ typedef struct AVCodecContext {
/**
* Called at the beginning of each frame to get a buffer for it.
* If pic.reference is set then the frame will be read later by libavcodec.
* avcodec_align_dimensions() should be used to find the required width and
* avcodec_align_dimensions2() should be used to find the required width and
* height, as they normally need to be rounded up to the next multiple of 16.
* if CODEC_CAP_DR1 is not set then get_buffer() must call
* avcodec_default_get_buffer() instead of providing buffers allocated by
@ -3226,7 +3226,19 @@ AVFrame *avcodec_alloc_frame(void);
int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic);
void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic);
int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic);
/**
* Modifies width and height values so that they will result in a memory
* buffer that is acceptable for the codec if you do not use any horizontal
* padding.
*/
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);
/**
* Modifies width and height values so that they will result in a memory
* buffer that is acceptable for the codec if you also ensure that all
* line sizes are a multiple of the respective linesize_align[i].
*/
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
int linesize_align[4]);
/**
* Checks if the given dimension of a picture is valid, meaning that all

View File

@ -31,6 +31,7 @@
#include "libavutil/avstring.h"
#include "libavutil/integer.h"
#include "libavutil/crc.h"
#include "libavutil/pixdesc.h"
#include "avcodec.h"
#include "dsputil.h"
#include "opt.h"
@ -117,7 +118,7 @@ typedef struct InternalBuffer{
#define INTERNAL_BUFFER_SIZE 32
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int linesize_align[4]){
int w_align= 1;
int h_align= 1;
@ -180,6 +181,36 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
*height= FFALIGN(*height, h_align);
if(s->codec_id == CODEC_ID_H264)
*height+=2; // some of the optimized chroma MC reads one line too much
linesize_align[0] =
linesize_align[1] =
linesize_align[2] =
linesize_align[3] = STRIDE_ALIGN;
//STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes
//we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the
//picture size unneccessarily in some cases. The solution here is not
//pretty and better ideas are welcome!
#if HAVE_MMX
if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 ||
s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F ||
s->codec_id == CODEC_ID_VP6A) {
linesize_align[0] =
linesize_align[1] =
linesize_align[2] = 16;
}
#endif
}
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
int chroma_shift = av_pix_fmt_descriptors[s->pix_fmt].log2_chroma_w;
int linesize_align[4];
int align;
avcodec_align_dimensions2(s, width, height, linesize_align);
align = FFMAX(linesize_align[0], linesize_align[3]);
linesize_align[1] <<= chroma_shift;
linesize_align[2] <<= chroma_shift;
align = FFMAX3(align, linesize_align[1], linesize_align[2]);
*width=FFALIGN(*width, align);
}
int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){
@ -244,7 +275,7 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
avcodec_align_dimensions(s, &w, &h);
avcodec_align_dimensions2(s, &w, &h, stride_align);
if(!(s->flags&CODEC_FLAG_EMU_EDGE)){
w+= EDGE_WIDTH*2;
@ -260,18 +291,6 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
unaligned = 0;
for (i=0; i<4; i++){
//STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes
//we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the
//picture size unneccessarily in some cases. The solution here is not
//pretty and better ideas are welcome!
#if HAVE_MMX
if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 ||
s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F ||
s->codec_id == CODEC_ID_VP6A)
stride_align[i]= 16;
else
#endif
stride_align[i] = STRIDE_ALIGN;
unaligned |= picture.linesize[i] % stride_align[i];
}
} while (unaligned);