00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <string.h>
00028 #include "avcodec.h"
00029 #include "mjpeg.h"
00030
00031 static const uint8_t jpeg_header[] = {
00032 0xff, 0xd8,
00033 0xff, 0xe0,
00034 0x00, 0x10,
00035
00036 0x4a, 0x46, 0x49, 0x46, 0x00,
00037 0x01, 0x01,
00038 0x00,
00039 0x00, 0x00,
00040 0x00, 0x00,
00041 0x00,
00042 0x00,
00043 };
00044
00045 static const int dht_segment_size = 420;
00046 static const uint8_t dht_segment_head[] = { 0xFF, 0xC4, 0x01, 0xA2, 0x00 };
00047 static const uint8_t dht_segment_frag[] = {
00048 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
00049 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
00050 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
00051 };
00052
00053 static uint8_t *append(uint8_t *buf, const uint8_t *src, int size)
00054 {
00055 memcpy(buf, src, size);
00056 return buf + size;
00057 }
00058
00059 static uint8_t *append_dht_segment(uint8_t *buf)
00060 {
00061 buf = append(buf, dht_segment_head, sizeof(dht_segment_head));
00062 buf = append(buf, ff_mjpeg_bits_dc_luminance + 1, 16);
00063 buf = append(buf, dht_segment_frag, sizeof(dht_segment_frag));
00064 buf = append(buf, ff_mjpeg_val_dc, 12);
00065 *(buf++) = 0x10;
00066 buf = append(buf, ff_mjpeg_bits_ac_luminance + 1, 16);
00067 buf = append(buf, ff_mjpeg_val_ac_luminance, 162);
00068 *(buf++) = 0x11;
00069 buf = append(buf, ff_mjpeg_bits_ac_chrominance + 1, 16);
00070 buf = append(buf, ff_mjpeg_val_ac_chrominance, 162);
00071 return buf;
00072 }
00073
00074 static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc,
00075 AVCodecContext *avctx, const char *args,
00076 uint8_t **poutbuf, int *poutbuf_size,
00077 const uint8_t *buf, int buf_size,
00078 int keyframe)
00079 {
00080 int input_skip, output_size;
00081 uint8_t *output, *out;
00082
00083 if (buf_size < 12) {
00084 av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
00085 return AVERROR_INVALIDDATA;
00086 }
00087 if (memcmp("AVI1", buf + 6, 4)) {
00088 av_log(avctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n");
00089 return AVERROR_INVALIDDATA;
00090 }
00091 input_skip = (buf[4] << 8) + buf[5] + 4;
00092 if (buf_size < input_skip) {
00093 av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
00094 return AVERROR_INVALIDDATA;
00095 }
00096 output_size = buf_size - input_skip +
00097 sizeof(jpeg_header) + dht_segment_size;
00098 output = out = av_malloc(output_size);
00099 if (!output)
00100 return AVERROR(ENOMEM);
00101 out = append(out, jpeg_header, sizeof(jpeg_header));
00102 out = append_dht_segment(out);
00103 out = append(out, buf + input_skip, buf_size - input_skip);
00104 *poutbuf = output;
00105 *poutbuf_size = output_size;
00106 return 1;
00107 }
00108
00109 AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
00110 .name = "mjpeg2jpeg",
00111 .priv_data_size = 0,
00112 .filter = mjpeg2jpeg_filter,
00113 };