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

libavformat/avisynth.c

Go to the documentation of this file.
00001 /*
00002  * AVISynth support for ffmpeg system
00003  * Copyright (c) 2006 DivX, Inc.
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "avformat.h"
00023 #include "riff.h"
00024 
00025 #include <windows.h>
00026 #include <vfw.h>
00027 
00028 typedef struct {
00029   PAVISTREAM handle;
00030   AVISTREAMINFO info;
00031   DWORD read;
00032   LONG chunck_size;
00033   LONG chunck_samples;
00034 } AVISynthStream;
00035 
00036 typedef struct {
00037   PAVIFILE file;
00038   AVISynthStream *streams;
00039   int nb_streams;
00040   int next_stream;
00041 } AVISynthContext;
00042 
00043 static int avisynth_read_header(AVFormatContext *s, AVFormatParameters *ap)
00044 {
00045   AVISynthContext *avs = s->priv_data;
00046   HRESULT res;
00047   AVIFILEINFO info;
00048   DWORD id;
00049   AVStream *st;
00050   AVISynthStream *stream;
00051 
00052   AVIFileInit();
00053 
00054   res = AVIFileOpen(&avs->file, s->filename, OF_READ|OF_SHARE_DENY_WRITE, NULL);
00055   if (res != S_OK)
00056     {
00057       av_log(s, AV_LOG_ERROR, "AVIFileOpen failed with error %ld", res);
00058       AVIFileExit();
00059       return -1;
00060     }
00061 
00062   res = AVIFileInfo(avs->file, &info, sizeof(info));
00063   if (res != S_OK)
00064     {
00065       av_log(s, AV_LOG_ERROR, "AVIFileInfo failed with error %ld", res);
00066       AVIFileExit();
00067       return -1;
00068     }
00069 
00070   avs->streams = av_mallocz(info.dwStreams * sizeof(AVISynthStream));
00071 
00072   for (id=0; id<info.dwStreams; id++)
00073     {
00074       stream = &avs->streams[id];
00075       stream->read = 0;
00076       if (AVIFileGetStream(avs->file, &stream->handle, 0, id) == S_OK)
00077         {
00078           if (AVIStreamInfo(stream->handle, &stream->info, sizeof(stream->info)) == S_OK)
00079             {
00080               if (stream->info.fccType == streamtypeAUDIO)
00081                 {
00082                   WAVEFORMATEX wvfmt;
00083                   LONG struct_size = sizeof(WAVEFORMATEX);
00084                   if (AVIStreamReadFormat(stream->handle, 0, &wvfmt, &struct_size) != S_OK)
00085                     continue;
00086 
00087                   st = av_new_stream(s, id);
00088                   st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00089 
00090                   st->codec->block_align = wvfmt.nBlockAlign;
00091                   st->codec->channels = wvfmt.nChannels;
00092                   st->codec->sample_rate = wvfmt.nSamplesPerSec;
00093                   st->codec->bit_rate = wvfmt.nAvgBytesPerSec * 8;
00094                   st->codec->bits_per_coded_sample = wvfmt.wBitsPerSample;
00095 
00096                   stream->chunck_samples = wvfmt.nSamplesPerSec * (uint64_t)info.dwScale / (uint64_t)info.dwRate;
00097                   stream->chunck_size = stream->chunck_samples * wvfmt.nChannels * wvfmt.wBitsPerSample / 8;
00098 
00099                   st->codec->codec_tag = wvfmt.wFormatTag;
00100                   st->codec->codec_id = ff_wav_codec_get_id(wvfmt.wFormatTag, st->codec->bits_per_coded_sample);
00101                 }
00102               else if (stream->info.fccType == streamtypeVIDEO)
00103                 {
00104                   BITMAPINFO imgfmt;
00105                   LONG struct_size = sizeof(BITMAPINFO);
00106 
00107                   stream->chunck_size = stream->info.dwSampleSize;
00108                   stream->chunck_samples = 1;
00109 
00110                   if (AVIStreamReadFormat(stream->handle, 0, &imgfmt, &struct_size) != S_OK)
00111                     continue;
00112 
00113                   st = av_new_stream(s, id);
00114                   st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00115                   st->r_frame_rate.num = stream->info.dwRate;
00116                   st->r_frame_rate.den = stream->info.dwScale;
00117 
00118                   st->codec->width = imgfmt.bmiHeader.biWidth;
00119                   st->codec->height = imgfmt.bmiHeader.biHeight;
00120 
00121                   st->codec->bits_per_coded_sample = imgfmt.bmiHeader.biBitCount;
00122                   st->codec->bit_rate = (uint64_t)stream->info.dwSampleSize * (uint64_t)stream->info.dwRate * 8 / (uint64_t)stream->info.dwScale;
00123                   st->codec->codec_tag = imgfmt.bmiHeader.biCompression;
00124                   st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, imgfmt.bmiHeader.biCompression);
00125 
00126                   st->duration = stream->info.dwLength;
00127                 }
00128               else
00129                 {
00130                   AVIStreamRelease(stream->handle);
00131                   continue;
00132                 }
00133 
00134               avs->nb_streams++;
00135 
00136               st->codec->stream_codec_tag = stream->info.fccHandler;
00137 
00138               av_set_pts_info(st, 64, info.dwScale, info.dwRate);
00139               st->start_time = stream->info.dwStart;
00140             }
00141         }
00142     }
00143 
00144   return 0;
00145 }
00146 
00147 static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
00148 {
00149   AVISynthContext *avs = s->priv_data;
00150   HRESULT res;
00151   AVISynthStream *stream;
00152   int stream_id = avs->next_stream;
00153   LONG read_size;
00154 
00155   // handle interleaving manually...
00156   stream = &avs->streams[stream_id];
00157 
00158   if (stream->read >= stream->info.dwLength)
00159     return AVERROR(EIO);
00160 
00161   if (av_new_packet(pkt, stream->chunck_size))
00162     return AVERROR(EIO);
00163   pkt->stream_index = stream_id;
00164   pkt->pts = avs->streams[stream_id].read / avs->streams[stream_id].chunck_samples;
00165 
00166   res = AVIStreamRead(stream->handle, stream->read, stream->chunck_samples, pkt->data, stream->chunck_size, &read_size, NULL);
00167 
00168   pkt->pts = stream->read;
00169   pkt->size = read_size;
00170 
00171   stream->read += stream->chunck_samples;
00172 
00173   // prepare for the next stream to read
00174   do {
00175     avs->next_stream = (avs->next_stream+1) % avs->nb_streams;
00176   } while (avs->next_stream != stream_id && s->streams[avs->next_stream]->discard >= AVDISCARD_ALL);
00177 
00178   return (res == S_OK) ? pkt->size : -1;
00179 }
00180 
00181 static int avisynth_read_close(AVFormatContext *s)
00182 {
00183   AVISynthContext *avs = s->priv_data;
00184   int i;
00185 
00186   for (i=0;i<avs->nb_streams;i++)
00187     {
00188       AVIStreamRelease(avs->streams[i].handle);
00189     }
00190 
00191   av_free(avs->streams);
00192   AVIFileRelease(avs->file);
00193   AVIFileExit();
00194   return 0;
00195 }
00196 
00197 static int avisynth_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
00198 {
00199   AVISynthContext *avs = s->priv_data;
00200   int stream_id;
00201 
00202   for (stream_id = 0; stream_id < avs->nb_streams; stream_id++)
00203     {
00204       avs->streams[stream_id].read = pts * avs->streams[stream_id].chunck_samples;
00205     }
00206 
00207   return 0;
00208 }
00209 
00210 AVInputFormat avisynth_demuxer = {
00211   "avs",
00212   NULL_IF_CONFIG_SMALL("AVISynth"),
00213   sizeof(AVISynthContext),
00214   NULL,
00215   avisynth_read_header,
00216   avisynth_read_packet,
00217   avisynth_read_close,
00218   avisynth_read_seek,
00219   NULL,
00220   0,
00221   "avs",
00222 };

Generated on Fri Sep 16 2011 17:17:48 for FFmpeg by  doxygen 1.7.1