diff --git a/configure b/configure index e20bf8e062..4691c280a1 100755 --- a/configure +++ b/configure @@ -1801,6 +1801,7 @@ CONFIG_EXTRA=" bswapdsp cabac dsputil + dvprofile exif fdctdsp frame_thread_encoder @@ -2045,8 +2046,8 @@ dca_decoder_select="mdct" dirac_decoder_select="dsputil dwt golomb videodsp" dnxhd_decoder_select="blockdsp idctdsp" dnxhd_encoder_select="aandcttables blockdsp dsputil fdctdsp idctdsp mpegvideoenc" -dvvideo_decoder_select="idctdsp" -dvvideo_encoder_select="dsputil fdctdsp" +dvvideo_decoder_select="dvprofile idctdsp" +dvvideo_encoder_select="dsputil dvprofile fdctdsp" dxa_decoder_select="zlib" eac3_decoder_select="ac3_decoder" eac3_encoder_select="ac3_encoder" @@ -2355,6 +2356,8 @@ caf_demuxer_select="riffdec" dirac_demuxer_select="dirac_parser" dts_demuxer_select="dca_parser" dtshd_demuxer_select="dca_parser" +dv_demuxer_select="dvprofile" +dv_muxer_select="dvprofile" dxa_demuxer_select="riffdec" eac3_demuxer_select="ac3_parser" f4v_muxer_select="mov_muxer" diff --git a/doc/APIchanges b/doc/APIchanges index 55a95d18e0..97637691dc 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2014-07-xx - xxxxxxx - lavc 55.56.0 - dv_profile.h + Add a public API for DV profile handling. + 2014-06-20 - 0dceefc / 9e500ef - lavu 52.90.100 / 53.17.0 - imgutils.h Add av_image_check_sar(). diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8fbfbfd22e..50a7b17b1a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -4,6 +4,7 @@ NAME = avcodec HEADERS = avcodec.h \ avfft.h \ + dv_profile.h \ dxva2.h \ old_codec_ids.h \ vaapi.h \ @@ -19,6 +20,7 @@ OBJS = allcodecs.o \ bitstream.o \ bitstream_filter.o \ codec_desc.o \ + dv_profile.o \ fmtconvert.o \ imgconvert.o \ mathtables.o \ @@ -200,8 +202,8 @@ OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o -OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o dv_profile.o -OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o dv_profile.o +OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o +OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o OBJS-$(CONFIG_DXA_DECODER) += dxa.o OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o @@ -667,8 +669,6 @@ OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o OBJS-$(CONFIG_ADX_DEMUXER) += adx.o OBJS-$(CONFIG_CAF_DEMUXER) += mpeg4audio.o mpegaudiodata.o \ ac3tab.o -OBJS-$(CONFIG_DV_DEMUXER) += dv_profile.o -OBJS-$(CONFIG_DV_MUXER) += dv_profile.o OBJS-$(CONFIG_FLAC_DEMUXER) += flac.o flacdata.o vorbis_data.o \ vorbis_parser.o xiph.o OBJS-$(CONFIG_FLAC_MUXER) += flac.o flacdata.o vorbis_data.o diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 745ebfe7c9..25f53a7c62 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -51,7 +51,7 @@ /* XXX: also include quantization */ RL_VLC_ELEM ff_dv_rl_vlc[1184]; -static inline void dv_calc_mb_coordinates(const DVprofile *d, int chan, int seq, int slot, +static inline void dv_calc_mb_coordinates(const AVDVProfile *d, int chan, int seq, int slot, uint16_t *tbl) { static const uint8_t off[] = { 2, 6, 8, 0, 4 }; @@ -175,7 +175,7 @@ static const uint8_t dv100_qstep[16] = { static const uint8_t dv_quant_areas[4] = { 6, 21, 43, 64 }; -int ff_dv_init_dynamic_tables(DVVideoContext *ctx, const DVprofile *d) +int ff_dv_init_dynamic_tables(DVVideoContext *ctx, const AVDVProfile *d) { int j,i,c,s,p; uint32_t *factor1, *factor2; diff --git a/libavcodec/dv.h b/libavcodec/dv.h index 63530109dc..54ac06a65e 100644 --- a/libavcodec/dv.h +++ b/libavcodec/dv.h @@ -38,7 +38,7 @@ typedef struct DVwork_chunk { } DVwork_chunk; typedef struct DVVideoContext { - const DVprofile *sys; + const AVDVProfile *sys; AVFrame *frame; AVCodecContext *avctx; uint8_t *buf; @@ -95,10 +95,10 @@ enum dv_pack_type { extern RL_VLC_ELEM ff_dv_rl_vlc[1184]; -int ff_dv_init_dynamic_tables(DVVideoContext *s, const DVprofile *d); +int ff_dv_init_dynamic_tables(DVVideoContext *s, const AVDVProfile *d); int ff_dvvideo_init(AVCodecContext *avctx); -static inline int dv_work_pool_size(const DVprofile *d) +static inline int dv_work_pool_size(const AVDVProfile *d) { int size = d->n_difchan*d->difseg_size*27; if (DV_PROFILE_IS_1080i50(d)) diff --git a/libavcodec/dv_profile.c b/libavcodec/dv_profile.c index 1d8069614e..25c2f550ff 100644 --- a/libavcodec/dv_profile.c +++ b/libavcodec/dv_profile.c @@ -18,12 +18,17 @@ #include +#include "config.h" + #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" #include "avcodec.h" #include "dv_profile.h" +#include "dv_profile_internal.h" + +#if CONFIG_DVPROFILE static const uint8_t dv_audio_shuffle525[10][9] = { { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */ @@ -64,7 +69,7 @@ static const uint8_t block_sizes_dv100[8] = { 80, 80, 80, 80, 80, 80, 64, 64, }; -static const DVprofile dv_profiles[] = { +static const AVDVProfile dv_profiles[] = { { .dsf = 0, .video_stype = 0x0, .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */ @@ -247,9 +252,23 @@ static const DVprofile dv_profiles[] = { } }; -const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile *sys, - const uint8_t* frame, unsigned buf_size) +void ff_dv_print_profiles(void *logctx, int loglevel) { + int i; + for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) { + const AVDVProfile *p = &dv_profiles[i]; + av_log(logctx, loglevel, "Frame size: %dx%d; pixel format: %s, " + "framerate: %d/%d\n", p->width, p->height, av_get_pix_fmt_name(p->pix_fmt), + p->time_base.den, p->time_base.num); + } +} + +#endif /* CONFIG_DVPROFILE */ + +const AVDVProfile* avpriv_dv_frame_profile2(AVCodecContext* codec, const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size) +{ +#if CONFIG_DVPROFILE int i, dsf, stype; if(buf_size < DV_PROFILE_BYTES) @@ -278,6 +297,7 @@ const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile /* check if old sys matches and assumes corrupted input */ if (sys && buf_size == sys->frame_size) return sys; +#endif /* hack for trac issue #217, dv files created with QuickTime 3 */ if ((frame[3] & 0x7f) == 0x3f && frame[80 * 5 + 48 + 3] == 0xff) @@ -286,41 +306,40 @@ const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile return NULL; } -const DVprofile* avpriv_dv_frame_profile(const DVprofile *sys, - const uint8_t* frame, unsigned buf_size) +const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size) { return avpriv_dv_frame_profile2(NULL, sys, frame, buf_size); } -const DVprofile* avpriv_dv_codec_profile(AVCodecContext* codec) +const AVDVProfile *av_dv_codec_profile(int width, int height, + enum AVPixelFormat pix_fmt) { +#if CONFIG_DVPROFILE int i; - int w, h; - - if (codec->coded_width || codec->coded_height) { - w = codec->coded_width; - h = codec->coded_height; - } else { - w = codec->width; - h = codec->height; - } for (i=0; ipix_fmt == dv_profiles[i].pix_fmt && - w == dv_profiles[i].width) - return &dv_profiles[i]; + if (height == dv_profiles[i].height && + pix_fmt == dv_profiles[i].pix_fmt && + width == dv_profiles[i].width) + return &dv_profiles[i]; +#endif return NULL; } -void ff_dv_print_profiles(void *logctx, int loglevel) +#if LIBAVCODEC_VERSION_MAJOR < 56 +const AVDVProfile *avpriv_dv_frame_profile(const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size) { - int i; - for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) { - const DVprofile *p = &dv_profiles[i]; - av_log(logctx, loglevel, "Frame size: %dx%d; pixel format: %s, " - "framerate: %d/%d\n", p->width, p->height, av_get_pix_fmt_name(p->pix_fmt), - p->time_base.den, p->time_base.num); - } + return av_dv_frame_profile(sys, frame, buf_size); } + +const AVDVProfile *avpriv_dv_codec_profile(AVCodecContext *codec) +{ + if (codec->coded_width || codec->coded_height) { + return av_dv_codec_profile(codec->coded_width, codec->coded_height, codec->pix_fmt); + } else + return av_dv_codec_profile(codec->width, codec->height, codec->pix_fmt); +} +#endif diff --git a/libavcodec/dv_profile.h b/libavcodec/dv_profile.h index b94cd2a84c..a2ef608b57 100644 --- a/libavcodec/dv_profile.h +++ b/libavcodec/dv_profile.h @@ -30,12 +30,12 @@ #define DV_PROFILE_BYTES (6*80) /* 6 DIF blocks */ /* - * DVprofile is used to express the differences between various + * AVDVProfile is used to express the differences between various * DV flavors. For now it's primarily used for differentiating * 525/60 and 625/50, but the plans are to use it for various * DV specs as well (e.g. SMPTE314M vs. IEC 61834). */ -typedef struct DVprofile { +typedef struct AVDVProfile { int dsf; /* value of the dsf in the DV header */ int video_stype; /* stype for VAUX source pack */ int frame_size; /* total size of one frame in bytes */ @@ -55,17 +55,30 @@ typedef struct DVprofile { int audio_samples_dist[5]; /* how many samples are supposed to be */ /* in each frame in a 5 frames window */ const uint8_t (*audio_shuffle)[9]; /* PCM shuffling table */ -} DVprofile; +} AVDVProfile; -const DVprofile* avpriv_dv_frame_profile(const DVprofile *sys, - const uint8_t* frame, unsigned buf_size); -const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile *sys, - const uint8_t* frame, unsigned buf_size); -const DVprofile* avpriv_dv_codec_profile(AVCodecContext* codec); +const AVDVProfile* avpriv_dv_frame_profile2(AVCodecContext* codec, const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size); +#if LIBAVCODEC_VERSION_MAJOR < 56 +const AVDVProfile *avpriv_dv_frame_profile(const AVDVProfile *sys, + const uint8_t* frame, unsigned buf_size); +const AVDVProfile *avpriv_dv_codec_profile(AVCodecContext* codec); +#endif /** - * Print all allowed DV profiles into logctx at specified logging level. + * Get a DV profile for the provided compressed frame. + * + * @param sys the profile used for the previous frame, may be NULL + * @param frame the compressed data buffer + * @param buf_size size of the buffer in bytes + * @return the DV profile for the supplied data or NULL on failure */ -void ff_dv_print_profiles(void *logctx, int loglevel); +const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, + const uint8_t *frame, unsigned buf_size); + +/** + * Get a DV profile for the provided stream parameters. + */ +const AVDVProfile *av_dv_codec_profile(int width, int height, enum AVPixelFormat pix_fmt); #endif /* AVCODEC_DV_PROFILE_H */ diff --git a/libavcodec/dv_profile_internal.h b/libavcodec/dv_profile_internal.h new file mode 100644 index 0000000000..97720416ab --- /dev/null +++ b/libavcodec/dv_profile_internal.h @@ -0,0 +1,27 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DV_PROFILE_INTERNAL_H +#define AVCODEC_DV_PROFILE_INTERNAL_H + +/** + * Print all allowed DV profiles into logctx at specified logging level. + */ +void ff_dv_print_profiles(void *logctx, int loglevel); + +#endif /* AVCODEC_DV_PROFILE_INTERNAL_H */ diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index 96534b624b..fbd158f7d2 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -349,7 +349,7 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, DVVideoContext *s = avctx->priv_data; const uint8_t* vsc_pack; int apt, is16_9, ret; - const DVprofile *sys; + const AVDVProfile *sys; sys = avpriv_dv_frame_profile2(avctx, s->sys, buf, buf_size); if (!sys || buf_size < sys->frame_size) { diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index b01122eacc..a60b834dfe 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -34,6 +34,7 @@ #include "put_bits.h" #include "dv.h" #include "dv_tablegen.h" +#include "dv_profile_internal.h" static av_cold int dvvideo_encode_init(AVCodecContext *avctx) { diff --git a/libavcodec/version.h b/libavcodec/version.h index fedc35728e..7e57044178 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 55 -#define LIBAVCODEC_VERSION_MINOR 68 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 69 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/dv.c b/libavformat/dv.c index 8bc26ae238..4f7b062f8b 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -41,7 +41,7 @@ #include "libavutil/avassert.h" struct DVDemuxContext { - const DVprofile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ + const AVDVProfile* sys; /* Current DV profile. E.g.: 525/60, 625/50 */ AVFormatContext* fctx; AVStream* vst; AVStream* ast[4]; @@ -114,7 +114,7 @@ static const int dv_audio_frequency[3] = { * are converted into 16bit linear ones. */ static int dv_extract_audio(uint8_t *frame, uint8_t **ppcm, - const DVprofile *sys) + const AVDVProfile *sys) { int size, chan, i, j, d, of, smpls, freq, quant, half_ch; uint16_t lc, rc; @@ -369,7 +369,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, uint8_t *ppcm[5] = { 0 }; if (buf_size < DV_PROFILE_BYTES || - !(c->sys = avpriv_dv_frame_profile(c->sys, buf, buf_size)) || + !(c->sys = av_dv_frame_profile(c->sys, buf, buf_size)) || buf_size < c->sys->frame_size) { return -1; /* Broken frame, or not enough data */ } @@ -419,7 +419,8 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, int64_t timestamp, int flags) { // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk) - const DVprofile *sys = avpriv_dv_codec_profile(c->vst->codec); + const AVDVProfile *sys = av_dv_codec_profile(c->vst->codec->width, c->vst->codec->height, + c->vst->codec->pix_fmt); int64_t offset; int64_t size = avio_size(s->pb) - s->data_offset; int64_t max_offset = ((size - 1) / sys->frame_size) * sys->frame_size; @@ -519,9 +520,9 @@ static int dv_read_header(AVFormatContext *s) avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) return AVERROR(EIO); - c->dv_demux->sys = avpriv_dv_frame_profile(c->dv_demux->sys, - c->buf, - DV_PROFILE_BYTES); + c->dv_demux->sys = av_dv_frame_profile(c->dv_demux->sys, + c->buf, + DV_PROFILE_BYTES); if (!c->dv_demux->sys) { av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n"); diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index bd484d96e8..8f5277dca0 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -45,7 +45,7 @@ struct DVMuxContext { AVClass *av_class; - const DVprofile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ + const AVDVProfile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ int n_ast; /* number of stereo audio streams (up to 2) */ AVStream *ast[2]; /* stereo audio streams */ AVFifoBuffer *audio_data[2]; /* FIFO for storing excessive amounts of PCM */ @@ -72,7 +72,7 @@ static const int dv_aaux_packs_dist[12][9] = { { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff }, }; -static int dv_audio_frame_size(const DVprofile* sys, int frame) +static int dv_audio_frame_size(const AVDVProfile* sys, int frame) { return sys->audio_samples_dist[frame % (sizeof(sys->audio_samples_dist) / sizeof(sys->audio_samples_dist[0]))]; @@ -314,7 +314,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) c->ast[i]->codec->channels != 2)) goto bail_out; } - c->sys = avpriv_dv_codec_profile(vst->codec); + c->sys = av_dv_codec_profile(vst->codec->width, vst->codec->height, vst->codec->pix_fmt); if (!c->sys) goto bail_out;