diff options
Diffstat (limited to 'libavcodec/mjpegenc.c')
-rw-r--r-- | libavcodec/mjpegenc.c | 140 |
1 files changed, 113 insertions, 27 deletions
diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 2a83a204a2..80a4022c7e 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -8,20 +8,20 @@ * aspecting, new decode_frame mechanism and apple mjpeg-b support * by Alex Beregszaszi * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -30,9 +30,6 @@ * MJPEG encoder. */ -//#define DEBUG -#include <assert.h> - #include "avcodec.h" #include "mpegvideo.h" #include "mjpeg.h" @@ -47,6 +44,11 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) { MJpegContext *m; + if (s->width > 65500 || s->height > 65500) { + av_log(s, AV_LOG_ERROR, "JPEG does not support resolutions above 65500x65500\n"); + return -1; + } + m = av_malloc(sizeof(MJpegContext)); if (!m) return -1; @@ -131,6 +133,12 @@ static void jpeg_table_header(MpegEncContext *s) } #endif + if(s->avctx->active_thread_type & FF_THREAD_SLICE){ + put_marker(p, DRI); + put_bits(p, 16, 4); + put_bits(p, 16, (s->width-1)/(8*s->mjpeg_hsample[0]) + 1); + } + /* huffman table */ put_marker(p, DHT); flush_put_bits(p); @@ -155,13 +163,13 @@ static void jpeg_put_comments(MpegEncContext *s) int size; uint8_t *ptr; - if (s->aspect_ratio_info /* && !lossless */) + if (s->avctx->sample_aspect_ratio.num /* && !lossless */) { /* JFIF header */ put_marker(p, APP0); put_bits(p, 16, 16); avpriv_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */ - put_bits(p, 16, 0x0201); /* v 1.02 */ + put_bits(p, 16, 0x0102); /* v 1.02 */ put_bits(p, 8, 0); /* units type: 0 - aspect ratio */ put_bits(p, 16, s->avctx->sample_aspect_ratio.num); put_bits(p, 16, s->avctx->sample_aspect_ratio.den); @@ -196,9 +204,13 @@ static void jpeg_put_comments(MpegEncContext *s) void ff_mjpeg_encode_picture_header(MpegEncContext *s) { const int lossless= s->avctx->codec_id != AV_CODEC_ID_MJPEG; + int i; put_marker(&s->pb, SOI); + // hack for AMV mjpeg format + if(s->avctx->codec_id == AV_CODEC_ID_AMV) goto end; + jpeg_put_comments(s); jpeg_table_header(s); @@ -206,11 +218,13 @@ void ff_mjpeg_encode_picture_header(MpegEncContext *s) switch(s->avctx->codec_id){ case AV_CODEC_ID_MJPEG: put_marker(&s->pb, SOF0 ); break; case AV_CODEC_ID_LJPEG: put_marker(&s->pb, SOF3 ); break; - default: assert(0); + default: av_assert0(0); } put_bits(&s->pb, 16, 17); - if(lossless && s->avctx->pix_fmt == AV_PIX_FMT_BGRA) + if(lossless && (s->avctx->pix_fmt == AV_PIX_FMT_BGR0 + || s->avctx->pix_fmt == AV_PIX_FMT_BGRA + || s->avctx->pix_fmt == AV_PIX_FMT_BGR24)) put_bits(&s->pb, 8, 9); /* 9 bits/component RCT */ else put_bits(&s->pb, 8, 8); /* 8 bits/component */ @@ -269,10 +283,15 @@ void ff_mjpeg_encode_picture_header(MpegEncContext *s) switch(s->avctx->codec_id){ case AV_CODEC_ID_MJPEG: put_bits(&s->pb, 8, 63); break; /* Se (not used) */ case AV_CODEC_ID_LJPEG: put_bits(&s->pb, 8, 0); break; /* not used */ - default: assert(0); + default: av_assert0(0); } put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */ + +end: + s->esc_pos = put_bits_count(&s->pb) >> 3; + for(i=1; i<s->slice_context_count; i++) + s->thread_context[i]->esc_pos = 0; } static void escape_FF(MpegEncContext *s, int start) @@ -282,7 +301,7 @@ static void escape_FF(MpegEncContext *s, int start) uint8_t *buf= s->pb.buf + start; int align= (-(size_t)(buf))&3; - assert((size&7) == 0); + av_assert1((size&7) == 0); size >>= 3; ff_count=0; @@ -327,21 +346,30 @@ static void escape_FF(MpegEncContext *s, int start) } } -void ff_mjpeg_encode_stuffing(PutBitContext * pbc) +void ff_mjpeg_encode_stuffing(MpegEncContext *s) { - int length; + int length, i; + PutBitContext *pbc = &s->pb; + int mb_y = s->mb_y - !s->mb_x; length= (-put_bits_count(pbc))&7; if(length) put_bits(pbc, length, (1<<length)-1); + + flush_put_bits(&s->pb); + escape_FF(s, s->esc_pos); + + if((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height) + put_marker(pbc, RST0 + (mb_y&7)); + s->esc_pos = put_bits_count(pbc) >> 3; + + for(i=0; i<3; i++) + s->last_dc[i] = 128 << s->intra_dc_precision; } void ff_mjpeg_encode_picture_trailer(MpegEncContext *s) { - ff_mjpeg_encode_stuffing(&s->pb); - flush_put_bits(&s->pb); - assert((s->header_bits&7)==0); + av_assert1((s->header_bits&7)==0); - escape_FF(s, s->header_bits>>3); put_marker(&s->pb, EOI); } @@ -429,20 +457,61 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]) { int i; - for(i=0;i<5;i++) { - encode_block(s, block[i], i); - } - if (s->chroma_format == CHROMA_420) { + if (s->chroma_format == CHROMA_444) { + encode_block(s, block[0], 0); + encode_block(s, block[2], 2); + encode_block(s, block[4], 4); + encode_block(s, block[8], 8); encode_block(s, block[5], 5); + encode_block(s, block[9], 9); + + if (16*s->mb_x+8 < s->width) { + encode_block(s, block[1], 1); + encode_block(s, block[3], 3); + encode_block(s, block[6], 6); + encode_block(s, block[10], 10); + encode_block(s, block[7], 7); + encode_block(s, block[11], 11); + } } else { - encode_block(s, block[6], 6); - encode_block(s, block[5], 5); - encode_block(s, block[7], 7); + for(i=0;i<5;i++) { + encode_block(s, block[i], i); + } + if (s->chroma_format == CHROMA_420) { + encode_block(s, block[5], 5); + } else { + encode_block(s, block[6], 6); + encode_block(s, block[5], 5); + encode_block(s, block[7], 7); + } } s->i_tex_bits += get_bits_diff(s); } +// maximum over s->mjpeg_vsample[i] +#define V_MAX 2 +static int amv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic_arg, int *got_packet) + +{ + MpegEncContext *s = avctx->priv_data; + AVFrame pic = *pic_arg; + int i; + + //CODEC_FLAG_EMU_EDGE have to be cleared + if(s->avctx->flags & CODEC_FLAG_EMU_EDGE) + return -1; + + //picture should be flipped upside-down + for(i=0; i < 3; i++) { + pic.data[i] += (pic.linesize[i] * (s->mjpeg_vsample[i] * (8 * s->mb_height -((s->height/V_MAX)&7)) - 1 )); + pic.linesize[i] *= -1; + } + return ff_MPV_encode_picture(avctx, pkt, &pic, got_packet); +} + +#if CONFIG_MJPEG_ENCODER AVCodec ff_mjpeg_encoder = { .name = "mjpeg", .type = AVMEDIA_TYPE_VIDEO, @@ -451,8 +520,25 @@ AVCodec ff_mjpeg_encoder = { .init = ff_MPV_encode_init, .encode2 = ff_MPV_encode_picture, .close = ff_MPV_encode_end, + .capabilities = CODEC_CAP_SLICE_THREADS | CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]){ - AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_NONE + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }, .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), }; +#endif +#if CONFIG_AMV_ENCODER +AVCodec ff_amv_encoder = { + .name = "amv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AMV, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = amv_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), +}; +#endif |