Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
VideoSource_FFMPEGVideo.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include "VideoSource_FFMPEGVideo.hh"
26 
27 using namespace std;
28 using namespace BIAS;
29 
31  : _vidStreams(0),
32  _streamIndex(0),
33  _fmtCtx(NULL),
34  _codecCtx(NULL),
35  _swsCtx(NULL),
36  _codec(NULL),
37  _frame(NULL),
38  _frameRGB(NULL),
39  _buffer(NULL)
40 {
41  static bool firstCall = true;
42  if (firstCall)
43  {
44  av_register_all();
45  firstCall = false;
46  }
47 }
49 {
50 }
51 
53 {
54  // Open file and retreive info
55  if (av_open_input_file(&_fmtCtx, file, NULL, 0, NULL) != 0)
56  {
57  _errMsg = string("Could not open file ") + file;
58  return false;
59  }
60  if (av_find_stream_info(_fmtCtx) < 0)
61  {
62  _errMsg = "Could not find stream info";
63  return false;
64  }
65 
66  // Find video streams
67  for (unsigned int i = 0; i < _fmtCtx->nb_streams; i++)
68  {
69  if (_fmtCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
70  {
71  _vidStreams.push_back(i);
72  }
73  }
74  if (CountVideoStreams() == 0)
75  {
76  _errMsg = "No video streams found";
77  return false;
78  }
79 
80  return true;
81 }
82 
83 bool BIAS::VideoSource_FFMPEGVideo::Init(int width, int height, PixelFormat pixFmt,
84  unsigned int streamIndex)
85 {
86  // Get codec context and decoder
87  _streamIndex = streamIndex;
88  if (_streamIndex >= CountVideoStreams())
89  _streamIndex = 0;
90 
91  _codecCtx = _fmtCtx->streams[_streamIndex]->codec;
92  _codec = avcodec_find_decoder(_codecCtx->codec_id);
93  if (_codec == NULL)
94  {
95  _errMsg = "Codec not found";
96  return false;
97  }
98  if (avcodec_open(_codecCtx, _codec) < 0)
99  {
100  _errMsg = "Could not open codec";
101  return false;
102  }
103 
104  // Get Sws context
105  int w = _codecCtx->width;
106  int h = _codecCtx->height;
107 
108  if (width == 0 && height == 0)
109  {
110  width = w;
111  height = h;
112  }
113  // Resize but maintain aspect ratio
114  else if (width != 0 && height == 0)
115  {
116  height = (float)width / w * h;
117  }
118  else if (width == 0 && height != 0)
119  {
120  width = (float)height / h * w;
121  }
122 
123  _swsCtx = sws_getContext(w, h, _codecCtx->pix_fmt,
124  width, height, pixFmt,
125  SWS_BICUBIC, NULL, NULL, NULL);
126  if (_swsCtx == NULL)
127  {
128  _errMsg = "Cannot initialize the conversion context!";
129  return false;
130  }
131 
132  _frame = avcodec_alloc_frame();
133  _frameRGB = avcodec_alloc_frame();
134  int nBytes = avpicture_get_size(pixFmt, _codecCtx->width,
135  _codecCtx->height);
136  _buffer = (uint8_t*)av_malloc((nBytes + 8) * sizeof(uint8_t));
137  avpicture_fill((AVPicture*)_frameRGB, _buffer, pixFmt, w, h);
138 
139  return true;
140 }
141 
143 {
144  if (_fmtCtx != NULL)
145  av_close_input_file(_fmtCtx);
146  if (_codecCtx != NULL)
147  avcodec_close(_codecCtx);
148  if (_frame != NULL)
149  av_free(_frame);
150  if (_frameRGB != NULL)
151  av_free(_frameRGB);
152  if (_buffer != NULL)
153  av_free(_buffer);
154 
155  _fmtCtx = NULL;
156  _codecCtx = NULL;
157  _frame = NULL;
158  _frameRGB = NULL;
159  _buffer = NULL;
160 }
161 
162 
164 {
165  return _vidStreams.size();
166 }
167 
168 
170 {
171  if (_codecCtx != NULL)
172  return _codecCtx->width;
173  else
174  return _fmtCtx->streams[_streamIndex]->codec->width;
175 }
176 
178 {
179  if (_codecCtx != NULL)
180  return _codecCtx->height;
181  else
182  return _fmtCtx->streams[_streamIndex]->codec->height;
183 }
184 
185 
187 {
188  int frameFinished;
189  AVPacket packet;
190  bool ret = false;
191 
192  while (av_read_frame(_fmtCtx, &packet) >= 0 && !ret)
193  {
194  if (packet.stream_index == _vidStreams[_streamIndex])
195  {
196  avcodec_decode_video2(_codecCtx, _frame, &frameFinished,&packet);
197  if (frameFinished)
198  {
199  void *data = img.GetImageData();
200  sws_scale(_swsCtx, _frame->data, _frame->linesize, 0, _codecCtx->height,
201  (uint8_t**)&data, _frameRGB->linesize);
202  ret = true;
203  }
204  }
205  }
206 
207  av_free_packet(&packet);
208  return ret;
209 }
210 
212 {
213  av_seek_frame(_fmtCtx, _vidStreams[_streamIndex], time, 0);
214 }
215 
217 {
218  return _codecCtx->time_base;
219 }
220 
222 {
223  return _fmtCtx->streams[_vidStreams[_streamIndex]]->cur_dts;
224 }
225 
227 {
228  AVStream *s = _fmtCtx->streams[_vidStreams[_streamIndex]];
229  return s->duration;
230 }
231 
232 
234 {
235  return _errMsg;
236 }
237 
238 
240 {
241  switch (cm)
242  {
243  case ImageBase::CM_RGB:
244  return PIX_FMT_RGB24;
245  case ImageBase::CM_BGR:
246  return PIX_FMT_BGR24;
247  case ImageBase::CM_Grey:
248  return PIX_FMT_GRAY8;
249  default:
250  return PIX_FMT_NONE;
251  }
252 }
EColorModel
These are the most often used color models.
Definition: ImageBase.hh:127
gray values, 1 channel
Definition: ImageBase.hh:130
bool Open(const char *file)
Open file and retreive info.
AVRational TimeBase()
Returns the TimeBase of the video stream.
unsigned int GetCurrentDTS() const
Returns the current decoding timestamp.
bool Init(int width=0, int height=0, PixelFormat pixFmt=PIX_FMT_RGB24, unsigned int streamIndex=0)
Select video stream, initialize stuff and set destination size and pixel format.
color values, 3 channels, order: blue,green,red
Definition: ImageBase.hh:132
const void * GetImageData() const
Definition: ImageBase.hh:280
void Close()
Close file and free buffers.
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
void Seek(int64_t time)
Seeks to time which is given in TimeBase units.
unsigned int CountVideoStreams()
Return number of video streams.
int Width()
Return width of selected video stream.
static PixelFormat Colormodel2PixFmt(ImageBase::EColorModel cm)
Maps BIAS colormodels to ffmpeg pixelformats.
std::string ErrMsg()
Returns last error message.
unsigned int GetLength() const
Returns the length of the video in TimeBase units.
int Height()
Return height of selected video stream.
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
bool GetFrame(BIAS::ImageBase &img)
Retreive the next frame from the video.