mjpeg2jpeg_bsf.c
Go to the documentation of this file.
1 /*
2  * MJPEG/AVI1 to JPEG/JFIF bitstream format filter
3  * Copyright (c) 2010 Adrian Daerr and Nicolas George
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*
23  * Adapted from mjpeg2jpeg.c, with original copyright:
24  * Paris 2010 Adrian Daerr, public domain
25  */
26 
27 #include <string.h>
28 #include "avcodec.h"
29 #include "mjpeg.h"
30 
31 static const uint8_t jpeg_header[] = {
32  0xff, 0xd8, // SOI
33  0xff, 0xe0, // APP0
34  0x00, 0x10, // APP0 header size (including
35  // this field, but excluding preceding)
36  0x4a, 0x46, 0x49, 0x46, 0x00, // ID string 'JFIF\0'
37  0x01, 0x01, // version
38  0x00, // bits per type
39  0x00, 0x00, // X density
40  0x00, 0x00, // Y density
41  0x00, // X thumbnail size
42  0x00, // Y thumbnail size
43 };
44 
45 static const int dht_segment_size = 420;
46 static const uint8_t dht_segment_head[] = { 0xFF, 0xC4, 0x01, 0xA2, 0x00 };
47 static const uint8_t dht_segment_frag[] = {
48  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
49  0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
50  0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
51 };
52 
53 static uint8_t *append(uint8_t *buf, const uint8_t *src, int size)
54 {
55  memcpy(buf, src, size);
56  return buf + size;
57 }
58 
60 {
61  buf = append(buf, dht_segment_head, sizeof(dht_segment_head));
62  buf = append(buf, avpriv_mjpeg_bits_dc_luminance + 1, 16);
63  buf = append(buf, dht_segment_frag, sizeof(dht_segment_frag));
64  buf = append(buf, avpriv_mjpeg_val_dc, 12);
65  *(buf++) = 0x10;
66  buf = append(buf, avpriv_mjpeg_bits_ac_luminance + 1, 16);
67  buf = append(buf, avpriv_mjpeg_val_ac_luminance, 162);
68  *(buf++) = 0x11;
69  buf = append(buf, avpriv_mjpeg_bits_ac_chrominance + 1, 16);
70  buf = append(buf, avpriv_mjpeg_val_ac_chrominance, 162);
71  return buf;
72 }
73 
75  AVCodecContext *avctx, const char *args,
76  uint8_t **poutbuf, int *poutbuf_size,
77  const uint8_t *buf, int buf_size,
78  int keyframe)
79 {
80  int input_skip, output_size;
81  uint8_t *output, *out;
82 
83  if (buf_size < 12) {
84  av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
85  return AVERROR_INVALIDDATA;
86  }
87  if (memcmp("AVI1", buf + 6, 4)) {
88  av_log(avctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n");
89  return AVERROR_INVALIDDATA;
90  }
91  input_skip = (buf[4] << 8) + buf[5] + 4;
92  if (buf_size < input_skip) {
93  av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
94  return AVERROR_INVALIDDATA;
95  }
96  output_size = buf_size - input_skip +
97  sizeof(jpeg_header) + dht_segment_size;
98  output = out = av_malloc(output_size);
99  if (!output)
100  return AVERROR(ENOMEM);
101  out = append(out, jpeg_header, sizeof(jpeg_header));
102  out = append_dht_segment(out);
103  out = append(out, buf + input_skip, buf_size - input_skip);
104  *poutbuf = output;
105  *poutbuf_size = output_size;
106  return 1;
107 }
108 
110  .name = "mjpeg2jpeg",
111  .filter = mjpeg2jpeg_filter,
112 };
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
const uint8_t avpriv_mjpeg_bits_ac_luminance[17]
Definition: mjpeg.c:73
static const uint8_t dht_segment_frag[]
AVBitStreamFilter ff_mjpeg2jpeg_bsf
const uint8_t avpriv_mjpeg_bits_ac_chrominance[17]
Definition: mjpeg.c:99
MJPEG encoder and decoder.
static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int keyframe)
uint8_t
static uint8_t * append(uint8_t *buf, const uint8_t *src, int size)
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
external API header
int size
const uint8_t avpriv_mjpeg_bits_dc_luminance[17]
Definition: mjpeg.c:65
const uint8_t avpriv_mjpeg_val_dc[12]
Definition: mjpeg.c:67
AVS_Value src
Definition: avisynth_c.h:523
main external API structure.
static uint8_t * append_dht_segment(uint8_t *buf)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
const uint8_t avpriv_mjpeg_val_ac_luminance[]
Definition: mjpeg.c:75
static const uint8_t jpeg_header[]
these buffered frames must be flushed immediately if a new input produces new output(Example:frame rate-doubling filter:filter_frame must(1) flush the second copy of the previous frame, if it is still there,(2) push the first copy of the incoming frame,(3) keep the second copy for later.) If the input frame is not enough to produce output
static const int dht_segment_size
const uint8_t avpriv_mjpeg_val_ac_chrominance[]
Definition: mjpeg.c:102
static const uint8_t dht_segment_head[]
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out