Libav 0.7.1
|
00001 /* 00002 * MJPEG/AVI1 to JPEG/JFIF bitstream format filter 00003 * Copyright (c) 2010 Adrian Daerr and Nicolas George 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 /* 00023 * Adapted from mjpeg2jpeg.c, with original copyright: 00024 * Paris 2010 Adrian Daerr, public domain 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, // SOI 00033 0xff, 0xe0, // APP0 00034 0x00, 0x10, // APP0 header size (including 00035 // this field, but excluding preceding) 00036 0x4a, 0x46, 0x49, 0x46, 0x00, // ID string 'JFIF\0' 00037 0x01, 0x01, // version 00038 0x00, // bits per type 00039 0x00, 0x00, // X density 00040 0x00, 0x00, // Y density 00041 0x00, // X thumbnail size 00042 0x00, // Y thumbnail size 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 };