• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/smjpegenc.c

Go to the documentation of this file.
00001 /*
00002  * SMJPEG muxer
00003  * Copyright (c) 2012 Paul B Mahol
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 
00027 #include "avformat.h"
00028 #include "internal.h"
00029 #include "riff.h"
00030 #include "smjpeg.h"
00031 
00032 typedef struct SMJPEGMuxContext {
00033     uint32_t duration;
00034 } SMJPEGMuxContext;
00035 
00036 static int smjpeg_write_header(AVFormatContext *s)
00037 {
00038     AVDictionaryEntry *t = NULL;
00039     AVIOContext *pb = s->pb;
00040     int n, tag;
00041 
00042     if (s->nb_streams > 2) {
00043         av_log(s, AV_LOG_ERROR, "more than >2 streams are not supported\n");
00044         return AVERROR(EINVAL);
00045     }
00046     avio_write(pb, SMJPEG_MAGIC, 8);
00047     avio_wb32(pb, 0);
00048     avio_wb32(pb, 0);
00049 
00050     while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
00051         avio_wl32(pb, SMJPEG_TXT);
00052         avio_wb32(pb, strlen(t->key) + strlen(t->value) + 3);
00053         avio_write(pb, t->key, strlen(t->key));
00054         avio_write(pb, " = ", 3);
00055         avio_write(pb, t->value, strlen(t->value));
00056     }
00057 
00058     for (n = 0; n < s->nb_streams; n++) {
00059         AVStream *st = s->streams[n];
00060         AVCodecContext *codec = st->codec;
00061         if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00062             tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, codec->codec_id);
00063             if (!tag) {
00064                 av_log(s, AV_LOG_ERROR, "unsupported audio codec\n");
00065                 return AVERROR(EINVAL);
00066             }
00067             avio_wl32(pb, SMJPEG_SND);
00068             avio_wb32(pb, 8);
00069             avio_wb16(pb, codec->sample_rate);
00070             avio_w8(pb, av_get_bits_per_sample(codec->codec_id));
00071             avio_w8(pb, codec->channels);
00072             avio_wl32(pb, tag);
00073             avpriv_set_pts_info(st, 32, 1, 1000);
00074         } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00075             tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, codec->codec_id);
00076             if (!tag) {
00077                 av_log(s, AV_LOG_ERROR, "unsupported video codec\n");
00078                 return AVERROR(EINVAL);
00079             }
00080             avio_wl32(pb, SMJPEG_VID);
00081             avio_wb32(pb, 12);
00082             avio_wb32(pb, 0);
00083             avio_wb16(pb, codec->width);
00084             avio_wb16(pb, codec->height);
00085             avio_wl32(pb, tag);
00086             avpriv_set_pts_info(st, 32, 1, 1000);
00087         }
00088     }
00089 
00090     avio_wl32(pb, SMJPEG_HEND);
00091     avio_flush(pb);
00092 
00093     return 0;
00094 }
00095 
00096 static int smjpeg_write_packet(AVFormatContext *s, AVPacket *pkt)
00097 {
00098     SMJPEGMuxContext *smc = s->priv_data;
00099     AVIOContext *pb = s->pb;
00100     AVStream *st = s->streams[pkt->stream_index];
00101     AVCodecContext *codec = st->codec;
00102 
00103     if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
00104         avio_wl32(pb, SMJPEG_SNDD);
00105     else if (codec->codec_type == AVMEDIA_TYPE_VIDEO)
00106         avio_wl32(pb, SMJPEG_VIDD);
00107     else
00108         return 0;
00109 
00110     avio_wb32(pb, pkt->pts);
00111     avio_wb32(pb, pkt->size);
00112     avio_write(pb, pkt->data, pkt->size);
00113     avio_flush(pb);
00114 
00115     smc->duration = FFMAX(smc->duration, pkt->pts + pkt->duration);
00116     return 0;
00117 }
00118 
00119 static int smjpeg_write_trailer(AVFormatContext *s)
00120 {
00121     SMJPEGMuxContext *smc = s->priv_data;
00122     AVIOContext *pb = s->pb;
00123     int64_t currentpos;
00124 
00125     if (pb->seekable) {
00126         currentpos = avio_tell(pb);
00127         avio_seek(pb, 12, SEEK_SET);
00128         avio_wb32(pb, smc->duration);
00129         avio_seek(pb, currentpos, SEEK_SET);
00130     }
00131 
00132     avio_wl32(pb, SMJPEG_DONE);
00133     avio_flush(pb);
00134 
00135     return 0;
00136 }
00137 
00138 AVOutputFormat ff_smjpeg_muxer = {
00139     .name           = "smjpeg",
00140     .long_name      = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"),
00141     .priv_data_size = sizeof(SMJPEGMuxContext),
00142     .audio_codec    = CODEC_ID_PCM_S16LE,
00143     .video_codec    = CODEC_ID_MJPEG,
00144     .write_header   = smjpeg_write_header,
00145     .write_packet   = smjpeg_write_packet,
00146     .write_trailer  = smjpeg_write_trailer,
00147     .flags          = AVFMT_GLOBALHEADER,
00148     .codec_tag      = (const AVCodecTag *const []){ ff_codec_smjpeg_video_tags, ff_codec_smjpeg_audio_tags, 0 },
00149 };
Generated on Sat Mar 17 2012 12:57:55 for Libav by doxygen 1.7.1