[FFmpeg-devel] [PATCH 2/2] Support playing SMV files.

Ash Hughes ashes-iontach at hotmail.com
Thu Oct 25 21:59:30 CEST 2012


Updated to patch against trunk.

Ash.

---
diff -uNr ffmpeg-vanilla/libavcodec/allcodecs.c ffmpeg/libavcodec/allcodecs.c
--- ffmpeg-vanilla/libavcodec/allcodecs.c    2012-10-25 20:34:52.725417510 +0100
+++ ffmpeg/libavcodec/allcodecs.c    2012-10-25 20:29:10.195718993 +0100
@@ -215,6 +215,7 @@
     REGISTER_ENCDEC  (SGI, sgi);
     REGISTER_DECODER (SMACKER, smacker);
     REGISTER_DECODER (SMC, smc);
+    REGISTER_DECODER (SMVJPEG, smvjpeg);
     REGISTER_ENCDEC  (SNOW, snow);
     REGISTER_DECODER (SP5X, sp5x);
     REGISTER_ENCDEC  (SUNRAST, sunrast);
diff -uNr ffmpeg-vanilla/libavcodec/avcodec.h ffmpeg/libavcodec/avcodec.h
--- ffmpeg-vanilla/libavcodec/avcodec.h    2012-10-25 20:34:52.725417510 +0100
+++ ffmpeg/libavcodec/avcodec.h    2012-10-25 20:29:10.219719122 +0100
@@ -284,6 +284,7 @@
     AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
     AV_CODEC_ID_CPIA       = MKBETAG('C','P','I','A'),
     AV_CODEC_ID_XFACE      = MKBETAG('X','F','A','C'),
+    AV_CODEC_ID_SMVJPEG    = MKBETAG('S','M','V','J'),
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
diff -uNr ffmpeg-vanilla/libavcodec/Makefile ffmpeg/libavcodec/Makefile
--- ffmpeg-vanilla/libavcodec/Makefile    2012-10-25 20:34:52.721417492 +0100
+++ ffmpeg/libavcodec/Makefile    2012-10-25 20:29:10.187718979 +0100
@@ -380,6 +380,7 @@
 OBJS-$(CONFIG_SMACKAUD_DECODER)        += smacker.o
 OBJS-$(CONFIG_SMACKER_DECODER)         += smacker.o
 OBJS-$(CONFIG_SMC_DECODER)             += smc.o
+OBJS-$(CONFIG_SMVJPEG_DECODER)         += smvjpegdec.o
 OBJS-$(CONFIG_SNOW_DECODER)            += snowdec.o snow.o
 OBJS-$(CONFIG_SNOW_ENCODER)            += snowenc.o snow.o              \
                                           h263.o ituh263enc.o
diff -uNr ffmpeg-vanilla/libavformat/wavdec.c ffmpeg/libavformat/wavdec.c
--- ffmpeg-vanilla/libavformat/wavdec.c    2012-10-25 20:34:52.769417736 +0100
+++ ffmpeg/libavformat/wavdec.c    2012-10-25 20:44:15.960210449 +0100
@@ -25,6 +25,7 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/dict.h"
+#include "libavutil/intreadwrite.h"
 #include "libavutil/log.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
@@ -48,6 +49,7 @@
     int smv_eof;
     int audio_eof;
     int ignore_length;
+    int smv_cur_pt;
 } WAVDemuxContext;
 
 
@@ -326,9 +328,16 @@
             avio_r8(pb);
             vst->id = 1;
             vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            vst->codec->codec_id = AV_CODEC_ID_MJPEG;
+            vst->codec->codec_id = AV_CODEC_ID_SMVJPEG;
             vst->codec->width  = avio_rl24(pb);
             vst->codec->height = avio_rl24(pb);
+            vst->codec->extradata_size = 4;
+            vst->codec->extradata = av_malloc(vst->codec->extradata_size +
+                                              FF_INPUT_BUFFER_PADDING_SIZE);
+            if (!vst->codec->extradata) {
+                av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n");
+                return AVERROR(ENOMEM);
+            }
             size = avio_rl24(pb);
             wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
             avio_rl24(pb);
@@ -338,6 +347,10 @@
             avio_rl24(pb);
             avio_rl24(pb);
             wav->smv_frames_per_jpeg = avio_rl24(pb);
+            AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg);
+            wav->smv_cur_pt = 0;
+            if (wav->smv_frames_per_jpeg > 0)
+                vst->codec->height /= wav->smv_frames_per_jpeg;
             goto break_loop;
         case MKTAG('L', 'I', 'S', 'T'):
             if (size < 4) {
@@ -436,8 +449,13 @@
             if (ret < 0)
                 goto smv_out;
             pkt->pos -= 3;
-            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
-            wav->smv_block++;
+            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt;
+            wav->smv_cur_pt++;
+            if (wav->smv_frames_per_jpeg > 0)
+                wav->smv_cur_pt %= wav->smv_frames_per_jpeg;
+            if (!wav->smv_cur_pt)
+                wav->smv_block++;
+
             pkt->stream_index = 1;
 smv_out:
             avio_seek(s->pb, old_pos, SEEK_SET);
@@ -496,7 +514,10 @@
             smv_timestamp = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[1]->time_base);
         else
             timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base);
-        wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
+        if (wav->smv_frames_per_jpeg > 0) {
+            wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
+            wav->smv_cur_pt = smv_timestamp % wav->smv_frames_per_jpeg;
+        }
     }
 
     st = s->streams[0];
diff -uNr ffmpeg-vanilla/libavcodec/smvjpegdec.c ffmpeg/libavcodec/smvjpegdec.c
--- ffmpeg-vanilla/libavcodec/smvjpegdec.c    1970-01-01 01:00:00.000000000 +0100
+++ ffmpeg/libavcodec/smvjpegdec.c    2012-10-19 01:48:26.496972741 +0100
@@ -0,0 +1,182 @@
+/*
+ * SMV JPEG decoder
+ * Copyright (c) 2012 Ash Hughes
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * SMV JPEG decoder.
+ */
+
+// #define DEBUG
+#include "avcodec.h"
+#include "libavutil/opt.h"
+#include "libavutil/imgutils.h"
+#include "mjpegdec.h"
+#include "internal.h"
+
+typedef struct SMVJpegDecodeContext {
+    MJpegDecodeContext jpg;
+    AVFrame picture[2]; /* pictures array */
+    AVCodecContext* avctx;
+    int frames_per_jpeg;
+} SMVJpegDecodeContext;
+
+static inline void smv_img_pnt_plane(uint8_t      **dst, uint8_t *src,
+                                     int src_linesize, int height, int nlines)
+{
+    if (!dst || !src)
+        return;
+    src += (nlines) * src_linesize * height;
+    *dst = src;
+}
+
+static inline void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4],
+                               const int src_linesizes[4],
+                               enum PixelFormat pix_fmt, int width, int height,
+                               int nlines)
+{
+    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
+    int i, planes_nb = 0;
+
+    if (desc->flags & PIX_FMT_HWACCEL)
+        return;
+
+    for (i = 0; i < desc->nb_components; i++)
+        planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
+
+    for (i = 0; i < planes_nb; i++) {
+        int h = height;
+        if (i == 1 || i == 2) {
+            h= -((-height)>>desc->log2_chroma_h);
+        }
+        smv_img_pnt_plane(&dst_data[i], src_data[i],
+            src_linesizes[i], h, nlines);
+    }
+}
+
+static av_cold int smvjpeg_decode_init(AVCodecContext *avctx)
+{
+    SMVJpegDecodeContext *s = avctx->priv_data;
+    AVCodec *codec;
+    AVDictionary *thread_opt = NULL;
+    int ret = 0;
+
+    s->frames_per_jpeg = 0;
+    s->jpg.picture_ptr      = &s->picture[0];
+
+    if (avctx->extradata_size >= 4)
+        s->frames_per_jpeg = AV_RL32(avctx->extradata);
+
+    if (s->frames_per_jpeg <= 0) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n");
+        ret = -1;
+    }
+
+    avcodec_get_frame_defaults(&s->picture[1]);
+    avctx->coded_frame = &s->picture[1];
+    codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
+    if (!codec) {
+        av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n");
+        ret = -1;
+    }
+
+    s->avctx = avcodec_alloc_context3(codec);
+
+    av_dict_set(&thread_opt, "threads", "1", 0);
+    if (ff_codec_open2_recursive(s->avctx, codec, &thread_opt) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n");
+        ret = -1;
+    }
+    av_dict_free(&thread_opt);
+
+    return ret;
+}
+
+static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+                            AVPacket *avpkt)
+{
+    SMVJpegDecodeContext *s = avctx->priv_data;
+    AVFrame* mjpeg_data = &s->picture[0];
+    AVFrame* output = data;
+    int i, cur_frame = 0, ret = 0;
+
+    cur_frame = avpkt->pts % s->frames_per_jpeg;
+
+    /* Are we at the start of a block? */
+    if (!cur_frame)
+        ret = avcodec_decode_video2(s->avctx, mjpeg_data, data_size, avpkt);
+    else /*use the last lot... */
+        *data_size = sizeof(AVPicture);
+
+    avctx->pix_fmt = s->avctx->pix_fmt;
+
+    /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected
+       in init */
+    avcodec_set_dimensions(avctx, mjpeg_data->width,
+        mjpeg_data->height / s->frames_per_jpeg);
+
+    s->picture[1].extended_data = NULL;
+    s->picture[1].width         = avctx->width;
+    s->picture[1].height        = avctx->height;
+    s->picture[1].format        = avctx->pix_fmt;
+    /* ff_init_buffer_info(avctx, &s->picture[1]); */
+    smv_img_pnt(s->picture[1].data, mjpeg_data->data, mjpeg_data->linesize,
+                avctx->pix_fmt, avctx->width, avctx->height, cur_frame);
+    for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
+        s->picture[1].base[i]     =  s->picture[1].data[i];
+        s->picture[1].linesize[i] = mjpeg_data->linesize[i];
+    }
+
+    *output = s->picture[1];
+
+    return ret;
+}
+
+static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
+{
+    SMVJpegDecodeContext *s = avctx->priv_data;
+    MJpegDecodeContext *jpg = &s->jpg;
+
+    jpg->picture_ptr = NULL;
+    if (s->picture[1].data[0])
+        avctx->release_buffer(avctx, &s->picture[1]);
+    ff_codec_close_recursive(s->avctx);
+    av_freep(&s->avctx);
+    return 0;
+}
+
+static const AVClass smvjpegdec_class = {
+    .class_name = "SMVJPEG decoder",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_smvjpeg_decoder = {
+    .name           = "smvjpeg",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_SMVJPEG,
+    .priv_data_size = sizeof(SMVJpegDecodeContext),
+    .init           = smvjpeg_decode_init,
+    .close          = smvjpeg_decode_end,
+    .decode         = smvjpeg_decode_frame,
+    .max_lowres     = 3,
+    .long_name      = NULL_IF_CONFIG_SMALL("SMV JPEG"),
+    .priv_class     = &smvjpegdec_class,
+};

> From: ashes-iontach at hotmail.com
> To: ffmpeg-devel at ffmpeg.org
> Date: Fri, 19 Oct 2012 01:14:33 +0000
> Subject: Re: [FFmpeg-devel] [PATCH 2/2] Support playing SMV files.
> 
> Updated to use renamed functions.
> 
> Ash
> 
> ---
> diff -uNr ffmpeg-vanilla/libavcodec/allcodecs.c ffmpeg/libavcodec/allcodecs.c
> --- ffmpeg-vanilla/libavcodec/allcodecs.c    2012-10-16 18:09:41.215862776 +0100
> +++ ffmpeg/libavcodec/allcodecs.c    2012-10-16 17:58:22.748498431 +0100
> @@ -215,6 +215,7 @@
>      REGISTER_ENCDEC  (SGI, sgi);
>      REGISTER_DECODER (SMACKER, smacker);
>      REGISTER_DECODER (SMC, smc);
> +    REGISTER_DECODER (SMVJPEG, smvjpeg);
>      REGISTER_ENCDEC  (SNOW, snow);
>      REGISTER_DECODER (SP5X, sp5x);
>      REGISTER_ENCDEC  (SUNRAST, sunrast);
> diff -uNr ffmpeg-vanilla/libavcodec/avcodec.h ffmpeg/libavcodec/avcodec.h
> --- ffmpeg-vanilla/libavcodec/avcodec.h    2012-10-16 18:09:41.223862804 +0100
> +++ ffmpeg/libavcodec/avcodec.h    2012-10-16 18:20:23.747048918 +0100
> @@ -284,6 +284,7 @@
>      AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
>      AV_CODEC_ID_CPIA       = MKBETAG('C','P','I','A'),
>      AV_CODEC_ID_XFACE      = MKBETAG('X','F','A','C'),
> +    AV_CODEC_ID_SMVJPEG    = MKBETAG('S','M','V','J'),
>  
>      /* various PCM "codecs" */
>      AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
> diff -uNr ffmpeg-vanilla/libavcodec/Makefile ffmpeg/libavcodec/Makefile
> --- ffmpeg-vanilla/libavcodec/Makefile    2012-10-16 18:09:41.211862745 +0100
> +++ ffmpeg/libavcodec/Makefile    2012-10-16 17:58:22.748498432 +0100
> @@ -380,6 +380,7 @@
>  OBJS-$(CONFIG_SMACKAUD_DECODER)        += smacker.o
>  OBJS-$(CONFIG_SMACKER_DECODER)         += smacker.o
>  OBJS-$(CONFIG_SMC_DECODER)             += smc.o
> +OBJS-$(CONFIG_SMVJPEG_DECODER)         += smvjpegdec.o
>  OBJS-$(CONFIG_SNOW_DECODER)            += snowdec.o snow.o
>  OBJS-$(CONFIG_SNOW_ENCODER)            += snowenc.o snow.o              \
>                                            h263.o ituh263enc.o
> diff -uNr ffmpeg-vanilla/libavformat/wav.c ffmpeg/libavformat/wav.c
> --- ffmpeg-vanilla/libavformat/wav.c    2012-10-01 19:34:06.872974243 +0100
> +++ ffmpeg/libavformat/wav.c    2012-10-16 18:40:09.632929405 +0100
> @@ -25,6 +25,7 @@
>  
>  #include "libavutil/avassert.h"
>  #include "libavutil/dict.h"
> +#include "libavutil/intreadwrite.h"
>  #include "libavutil/log.h"
>  #include "libavutil/mathematics.h"
>  #include "libavutil/opt.h"
> @@ -53,6 +54,7 @@
>      int smv_eof;
>      int audio_eof;
>      int ignore_length;
> +    int smv_cur_pt;
>  } WAVContext;
>  
>  #if CONFIG_WAV_MUXER
> @@ -506,9 +508,16 @@
>              avio_r8(pb);
>              vst->id = 1;
>              vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> -            vst->codec->codec_id = AV_CODEC_ID_MJPEG;
> +            vst->codec->codec_id = AV_CODEC_ID_SMVJPEG;
>              vst->codec->width  = avio_rl24(pb);
>              vst->codec->height = avio_rl24(pb);
> +            vst->codec->extradata_size = 4;
> +            vst->codec->extradata = av_malloc(vst->codec->extradata_size +
> +                                              FF_INPUT_BUFFER_PADDING_SIZE);
> +            if (!vst->codec->extradata) {
> +                av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n");
> +                return AVERROR(ENOMEM);
> +            }
>              size = avio_rl24(pb);
>              wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
>              avio_rl24(pb);
> @@ -518,6 +527,10 @@
>              avio_rl24(pb);
>              avio_rl24(pb);
>              wav->smv_frames_per_jpeg = avio_rl24(pb);
> +            AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg);
> +            wav->smv_cur_pt = 0;
> +            if (wav->smv_frames_per_jpeg > 0)
> +                vst->codec->height /= wav->smv_frames_per_jpeg;
>              goto break_loop;
>          case MKTAG('L', 'I', 'S', 'T'):
>              list_type = avio_rl32(pb);
> @@ -617,8 +630,13 @@
>              if (ret < 0)
>                  goto smv_out;
>              pkt->pos -= 3;
> -            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
> -            wav->smv_block++;
> +            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt;
> +            wav->smv_cur_pt++;
> +            if (wav->smv_frames_per_jpeg > 0)
> +                wav->smv_cur_pt %= wav->smv_frames_per_jpeg;
> +            if (!wav->smv_cur_pt)
> +                wav->smv_block++;
> +
>              pkt->stream_index = 1;
>  smv_out:
>              avio_seek(s->pb, old_pos, SEEK_SET);
> @@ -677,7 +695,10 @@
>              smv_timestamp = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[1]->time_base);
>          else
>              timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base);
> -        wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
> +        if (wav->smv_frames_per_jpeg > 0) {
> +            wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
> +            wav->smv_cur_pt = smv_timestamp % wav->smv_frames_per_jpeg;
> +        }
>      }
>  
>      st = s->streams[0];
> diff -uNr ffmpeg-vanilla/libavcodec/smvjpegdec.c ffmpeg/libavcodec/smvjpegdec.c
> --- ffmpeg-vanilla/libavcodec/smvjpegdec.c    1970-01-01 01:00:00.000000000 +0100
> +++ ffmpeg/libavcodec/smvjpegdec.c    2012-10-19 01:48:26.496972741 +0100
> @@ -0,0 +1,182 @@
> +/*
> + * SMV JPEG decoder
> + * Copyright (c) 2012 Ash Hughes
> + *
> + * 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
> + */
> +
> +/**
> + * @file
> + * SMV JPEG decoder.
> + */
> +
> +// #define DEBUG
> +#include "avcodec.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/imgutils.h"
> +#include "mjpegdec.h"
> +#include "internal.h"
> +
> +typedef struct SMVJpegDecodeContext {
> +    MJpegDecodeContext jpg;
> +    AVFrame picture[2]; /* pictures array */
> +    AVCodecContext* avctx;
> +    int frames_per_jpeg;
> +} SMVJpegDecodeContext;
> +
> +static inline void smv_img_pnt_plane(uint8_t      **dst, uint8_t *src,
> +                                     int src_linesize, int height, int nlines)
> +{
> +    if (!dst || !src)
> +        return;
> +    src += (nlines) * src_linesize * height;
> +    *dst = src;
> +}
> +
> +static inline void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4],
> +                               const int src_linesizes[4],
> +                               enum PixelFormat pix_fmt, int width, int height,
> +                               int nlines)
> +{
> +    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
> +    int i, planes_nb = 0;
> +
> +    if (desc->flags & PIX_FMT_HWACCEL)
> +        return;
> +
> +    for (i = 0; i < desc->nb_components; i++)
> +        planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
> +
> +    for (i = 0; i < planes_nb; i++) {
> +        int h = height;
> +        if (i == 1 || i == 2) {
> +            h= -((-height)>>desc->log2_chroma_h);
> +        }
> +        smv_img_pnt_plane(&dst_data[i], src_data[i],
> +            src_linesizes[i], h, nlines);
> +    }
> +}
> +
> +static av_cold int smvjpeg_decode_init(AVCodecContext *avctx)
> +{
> +    SMVJpegDecodeContext *s = avctx->priv_data;
> +    AVCodec *codec;
> +    AVDictionary *thread_opt = NULL;
> +    int ret = 0;
> +
> +    s->frames_per_jpeg = 0;
> +    s->jpg.picture_ptr      = &s->picture[0];
> +
> +    if (avctx->extradata_size >= 4)
> +        s->frames_per_jpeg = AV_RL32(avctx->extradata);
> +
> +    if (s->frames_per_jpeg <= 0) {
> +        av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n");
> +        ret = -1;
> +    }
> +
> +    avcodec_get_frame_defaults(&s->picture[1]);
> +    avctx->coded_frame = &s->picture[1];
> +    codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
> +    if (!codec) {
> +        av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n");
> +        ret = -1;
> +    }
> +
> +    s->avctx = avcodec_alloc_context3(codec);
> +
> +    av_dict_set(&thread_opt, "threads", "1", 0);
> +    if (ff_codec_open2_recursive(s->avctx, codec, &thread_opt) < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n");
> +        ret = -1;
> +    }
> +    av_dict_free(&thread_opt);
> +
> +    return ret;
> +}
> +
> +static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
> +                            AVPacket *avpkt)
> +{
> +    SMVJpegDecodeContext *s = avctx->priv_data;
> +    AVFrame* mjpeg_data = &s->picture[0];
> +    AVFrame* output = data;
> +    int i, cur_frame = 0, ret = 0;
> +
> +    cur_frame = avpkt->pts % s->frames_per_jpeg;
> +
> +    /* Are we at the start of a block? */
> +    if (!cur_frame)
> +        ret = avcodec_decode_video2(s->avctx, mjpeg_data, data_size, avpkt);
> +    else /*use the last lot... */
> +        *data_size = sizeof(AVPicture);
> +
> +    avctx->pix_fmt = s->avctx->pix_fmt;
> +
> +    /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected
> +       in init */
> +    avcodec_set_dimensions(avctx, mjpeg_data->width,
> +        mjpeg_data->height / s->frames_per_jpeg);
> +
> +    s->picture[1].extended_data = NULL;
> +    s->picture[1].width         = avctx->width;
> +    s->picture[1].height        = avctx->height;
> +    s->picture[1].format        = avctx->pix_fmt;
> +    /* ff_init_buffer_info(avctx, &s->picture[1]); */
> +    smv_img_pnt(s->picture[1].data, mjpeg_data->data, mjpeg_data->linesize,
> +                avctx->pix_fmt, avctx->width, avctx->height, cur_frame);
> +    for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
> +        s->picture[1].base[i]     =  s->picture[1].data[i];
> +        s->picture[1].linesize[i] = mjpeg_data->linesize[i];
> +    }
> +
> +    *output = s->picture[1];
> +
> +    return ret;
> +}
> +
> +static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
> +{
> +    SMVJpegDecodeContext *s = avctx->priv_data;
> +    MJpegDecodeContext *jpg = &s->jpg;
> +
> +    jpg->picture_ptr = NULL;
> +    if (s->picture[1].data[0])
> +        avctx->release_buffer(avctx, &s->picture[1]);
> +    ff_codec_close_recursive(s->avctx);
> +    av_freep(&s->avctx);
> +    return 0;
> +}
> +
> +static const AVClass smvjpegdec_class = {
> +    .class_name = "SMVJPEG decoder",
> +    .item_name  = av_default_item_name,
> +    .version    = LIBAVUTIL_VERSION_INT,
> +};
> +
> +AVCodec ff_smvjpeg_decoder = {
> +    .name           = "smvjpeg",
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_SMVJPEG,
> +    .priv_data_size = sizeof(SMVJpegDecodeContext),
> +    .init           = smvjpeg_decode_init,
> +    .close          = smvjpeg_decode_end,
> +    .decode         = smvjpeg_decode_frame,
> +    .max_lowres     = 3,
> +    .long_name      = NULL_IF_CONFIG_SMALL("SMV JPEG"),
> +    .priv_class     = &smvjpegdec_class,
> +};
> 
> > From: ashes-iontach at hotmail.com
> > To: ffmpeg-devel at ffmpeg.org
> > Date: Tue, 16 Oct 2012 18:53:14 +0000
> > Subject: Re: [FFmpeg-devel] [PATCH 2/2] Support playing SMV files.
> > 
> > Updated patch from previous comments to play SMV files.
> > 
> > ---
> > diff -uNr ffmpeg-vanilla/libavcodec/allcodecs.c ffmpeg/libavcodec/allcodecs.c
> > --- ffmpeg-vanilla/libavcodec/allcodecs.c    2012-10-16 18:09:41.215862776 +0100
> > +++ ffmpeg/libavcodec/allcodecs.c    2012-10-16 17:58:22.748498431 +0100
> > @@ -215,6 +215,7 @@
> >      REGISTER_ENCDEC  (SGI, sgi);
> >      REGISTER_DECODER (SMACKER, smacker);
> >      REGISTER_DECODER (SMC, smc);
> > +    REGISTER_DECODER (SMVJPEG, smvjpeg);
> >      REGISTER_ENCDEC  (SNOW, snow);
> >      REGISTER_DECODER (SP5X, sp5x);
> >      REGISTER_ENCDEC  (SUNRAST, sunrast);
> > diff -uNr ffmpeg-vanilla/libavcodec/avcodec.h ffmpeg/libavcodec/avcodec.h
> > --- ffmpeg-vanilla/libavcodec/avcodec.h    2012-10-16 18:09:41.223862804 +0100
> > +++ ffmpeg/libavcodec/avcodec.h    2012-10-16 18:20:23.747048918 +0100
> > @@ -284,6 +284,7 @@
> >      AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
> >      AV_CODEC_ID_CPIA       = MKBETAG('C','P','I','A'),
> >      AV_CODEC_ID_XFACE      = MKBETAG('X','F','A','C'),
> > +    AV_CODEC_ID_SMVJPEG    = MKBETAG('S','M','V','J'),
> >  
> >      /* various PCM "codecs" */
> >      AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
> > diff -uNr ffmpeg-vanilla/libavcodec/Makefile ffmpeg/libavcodec/Makefile
> > --- ffmpeg-vanilla/libavcodec/Makefile    2012-10-16 18:09:41.211862745 +0100
> > +++ ffmpeg/libavcodec/Makefile    2012-10-16 17:58:22.748498432 +0100
> > @@ -380,6 +380,7 @@
> >  OBJS-$(CONFIG_SMACKAUD_DECODER)        += smacker.o
> >  OBJS-$(CONFIG_SMACKER_DECODER)         += smacker.o
> >  OBJS-$(CONFIG_SMC_DECODER)             += smc.o
> > +OBJS-$(CONFIG_SMVJPEG_DECODER)         += smvjpegdec.o
> >  OBJS-$(CONFIG_SNOW_DECODER)            += snowdec.o snow.o
> >  OBJS-$(CONFIG_SNOW_ENCODER)            += snowenc.o snow.o              \
> >                                            h263.o ituh263enc.o
> > diff -uNr ffmpeg-vanilla/libavformat/wav.c ffmpeg/libavformat/wav.c
> > --- ffmpeg-vanilla/libavformat/wav.c    2012-10-01 19:34:06.872974243 +0100
> > +++ ffmpeg/libavformat/wav.c    2012-10-16 18:40:09.632929405 +0100
> > @@ -25,6 +25,7 @@
> >  
> >  #include "libavutil/avassert.h"
> >  #include "libavutil/dict.h"
> > +#include "libavutil/intreadwrite.h"
> >  #include "libavutil/log.h"
> >  #include "libavutil/mathematics.h"
> >  #include "libavutil/opt.h"
> > @@ -53,6 +54,7 @@
> >      int smv_eof;
> >      int audio_eof;
> >      int ignore_length;
> > +    int smv_cur_pt;
> >  } WAVContext;
> >  
> >  #if CONFIG_WAV_MUXER
> > @@ -506,9 +508,16 @@
> >              avio_r8(pb);
> >              vst->id = 1;
> >              vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> > -            vst->codec->codec_id = AV_CODEC_ID_MJPEG;
> > +            vst->codec->codec_id = AV_CODEC_ID_SMVJPEG;
> >              vst->codec->width  = avio_rl24(pb);
> >              vst->codec->height = avio_rl24(pb);
> > +            vst->codec->extradata_size = 4;
> > +            vst->codec->extradata = av_malloc(vst->codec->extradata_size +
> > +                                              FF_INPUT_BUFFER_PADDING_SIZE);
> > +            if (!vst->codec->extradata) {
> > +                av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n");
> > +                return AVERROR(ENOMEM);
> > +            }
> >              size = avio_rl24(pb);
> >              wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
> >              avio_rl24(pb);
> > @@ -518,6 +527,10 @@
> >              avio_rl24(pb);
> >              avio_rl24(pb);
> >              wav->smv_frames_per_jpeg = avio_rl24(pb);
> > +            AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg);
> > +            wav->smv_cur_pt = 0;
> > +            if (wav->smv_frames_per_jpeg > 0)
> > +                vst->codec->height /= wav->smv_frames_per_jpeg;
> >              goto break_loop;
> >          case MKTAG('L', 'I', 'S', 'T'):
> >              list_type = avio_rl32(pb);
> > @@ -617,8 +630,13 @@
> >              if (ret < 0)
> >                  goto smv_out;
> >              pkt->pos -= 3;
> > -            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
> > -            wav->smv_block++;
> > +            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt;
> > +            wav->smv_cur_pt++;
> > +            if (wav->smv_frames_per_jpeg > 0)
> > +                wav->smv_cur_pt %= wav->smv_frames_per_jpeg;
> > +            if (!wav->smv_cur_pt)
> > +                wav->smv_block++;
> > +
> >              pkt->stream_index = 1;
> >  smv_out:
> >              avio_seek(s->pb, old_pos, SEEK_SET);
> > @@ -677,7 +695,10 @@
> >              smv_timestamp = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[1]->time_base);
> >          else
> >              timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base);
> > -        wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
> > +        if (wav->smv_frames_per_jpeg > 0) {
> > +            wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
> > +            wav->smv_cur_pt = smv_timestamp % wav->smv_frames_per_jpeg;
> > +        }
> >      }
> >  
> >      st = s->streams[0];
> > diff -uNr ffmpeg-vanilla/libavcodec/smvjpegdec.c ffmpeg/libavcodec/smvjpegdec.c
> > --- ffmpeg-vanilla/libavcodec/smvjpegdec.c    1970-01-01 01:00:00.000000000 +0100
> > +++ ffmpeg/libavcodec/smvjpegdec.c    2012-10-16 19:31:49.572301175 +0100
> > @@ -0,0 +1,182 @@
> > +/*
> > + * SMV JPEG decoder
> > + * Copyright (c) 2012 Ash Hughes
> > + *
> > + * 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
> > + */
> > +
> > +/**
> > + * @file
> > + * SMV JPEG decoder.
> > + */
> > +
> > +// #define DEBUG
> > +#include "avcodec.h"
> > +#include "libavutil/opt.h"
> > +#include "libavutil/imgutils.h"
> > +#include "mjpegdec.h"
> > +#include "internal.h"
> > +
> > +typedef struct SMVJpegDecodeContext {
> > +    MJpegDecodeContext jpg;
> > +    AVFrame picture[2]; /* pictures array */
> > +    AVCodecContext* avctx;
> > +    int frames_per_jpeg;
> > +} SMVJpegDecodeContext;
> > +
> > +static inline void smv_img_pnt_plane(uint8_t      **dst, uint8_t *src,
> > +                                     int src_linesize, int height, int nlines)
> > +{
> > +    if (!dst || !src)
> > +        return;
> > +    src += (nlines) * src_linesize * height;
> > +    *dst = src;
> > +}
> > +
> > +static inline void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4],
> > +                               const int src_linesizes[4],
> > +                               enum PixelFormat pix_fmt, int width, int height,
> > +                               int nlines)
> > +{
> > +    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
> > +    int i, planes_nb = 0;
> > +
> > +    if (desc->flags & PIX_FMT_HWACCEL)
> > +        return;
> > +
> > +    for (i = 0; i < desc->nb_components; i++)
> > +        planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
> > +
> > +    for (i = 0; i < planes_nb; i++) {
> > +        int h = height;
> > +        if (i == 1 || i == 2) {
> > +            h= -((-height)>>desc->log2_chroma_h);
> > +        }
> > +        smv_img_pnt_plane(&dst_data[i], src_data[i],
> > +            src_linesizes[i], h, nlines);
> > +    }
> > +}
> > +
> > +static av_cold int smvjpeg_decode_init(AVCodecContext *avctx)
> > +{
> > +    SMVJpegDecodeContext *s = avctx->priv_data;
> > +    AVCodec *codec;
> > +    AVDictionary *thread_opt = NULL;
> > +    int ret = 0;
> > +
> > +    s->frames_per_jpeg = 0;
> > +    s->jpg.picture_ptr      = &s->picture[0];
> > +
> > +    if (avctx->extradata_size >= 4)
> > +        s->frames_per_jpeg = AV_RL32(avctx->extradata);
> > +
> > +    if (s->frames_per_jpeg <= 0) {
> > +        av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n");
> > +        ret = -1;
> > +    }
> > +
> > +    avcodec_get_frame_defaults(&s->picture[1]);
> > +    avctx->coded_frame = &s->picture[1];
> > +    codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
> > +    if (!codec) {
> > +        av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n");
> > +        ret = -1;
> > +    }
> > +
> > +    s->avctx = avcodec_alloc_context3(codec);
> > +
> > +    av_dict_set(&thread_opt, "threads", "1", 0);
> > +    if (avcodec_open2_recursive(s->avctx, codec, &thread_opt) < 0) {
> > +        av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n");
> > +        ret = -1;
> > +    }
> > +    av_dict_free(&thread_opt);
> > +
> > +    return ret;
> > +}
> > +
> > +static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
> > +                            AVPacket *avpkt)
> > +{
> > +    SMVJpegDecodeContext *s = avctx->priv_data;
> > +    AVFrame* mjpeg_data = &s->picture[0];
> > +    AVFrame* output = data;
> > +    int i, cur_frame = 0, ret = 0;
> > +
> > +    cur_frame = avpkt->pts % s->frames_per_jpeg;
> > +
> > +    /* Are we at the start of a block? */
> > +    if (!cur_frame)
> > +        ret = avcodec_decode_video2(s->avctx, mjpeg_data, data_size, avpkt);
> > +    else /*use the last lot... */
> > +        *data_size = sizeof(AVPicture);
> > +
> > +    avctx->pix_fmt = s->avctx->pix_fmt;
> > +
> > +    /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected
> > +       in init */
> > +    avcodec_set_dimensions(avctx, mjpeg_data->width,
> > +        mjpeg_data->height / s->frames_per_jpeg);
> > +
> > +    s->picture[1].extended_data = NULL;
> > +    s->picture[1].width         = avctx->width;
> > +    s->picture[1].height        = avctx->height;
> > +    s->picture[1].format        = avctx->pix_fmt;
> > +    /* ff_init_buffer_info(avctx, &s->picture[1]); */
> > +    smv_img_pnt(s->picture[1].data, mjpeg_data->data, mjpeg_data->linesize,
> > +                avctx->pix_fmt, avctx->width, avctx->height, cur_frame);
> > +    for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
> > +        s->picture[1].base[i]     =  s->picture[1].data[i];
> > +        s->picture[1].linesize[i] = mjpeg_data->linesize[i];
> > +    }
> > +
> > +    *output = s->picture[1];
> > +
> > +    return ret;
> > +}
> > +
> > +static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
> > +{
> > +    SMVJpegDecodeContext *s = avctx->priv_data;
> > +    MJpegDecodeContext *jpg = &s->jpg;
> > +
> > +    jpg->picture_ptr = NULL;
> > +    if (s->picture[1].data[0])
> > +        avctx->release_buffer(avctx, &s->picture[1]);
> > +    avcodec_close_recursive(s->avctx);
> > +    av_freep(&s->avctx);
> > +    return 0;
> > +}
> > +
> > +static const AVClass smvjpegdec_class = {
> > +    .class_name = "SMVJPEG decoder",
> > +    .item_name  = av_default_item_name,
> > +    .version    = LIBAVUTIL_VERSION_INT,
> > +};
> > +
> > +AVCodec ff_smvjpeg_decoder = {
> > +    .name           = "smvjpeg",
> > +    .type           = AVMEDIA_TYPE_VIDEO,
> > +    .id             = AV_CODEC_ID_SMVJPEG,
> > +    .priv_data_size = sizeof(SMVJpegDecodeContext),
> > +    .init           = smvjpeg_decode_init,
> > +    .close          = smvjpeg_decode_end,
> > +    .decode         = smvjpeg_decode_frame,
> > +    .max_lowres     = 3,
> > +    .long_name      = NULL_IF_CONFIG_SMALL("SMV JPEG"),
> > +    .priv_class     = &smvjpegdec_class,
> > +};
> >  		 	   		  
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel at ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>  		 	   		  
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 		 	   		  


More information about the ffmpeg-devel mailing list