OpenShot Library | libopenshot  0.1.9
DecklinkWriter.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for DecklinkWriter class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2014 OpenShot Studios, LLC
9  * <http://www.openshotstudios.com/>. This file is part of
10  * OpenShot Library (libopenshot), an open-source project dedicated to
11  * delivering high quality video editing and animation solutions to the
12  * world. For more information visit <http://www.openshot.org/>.
13  *
14  * OpenShot Library (libopenshot) is free software: you can redistribute it
15  * and/or modify it under the terms of the GNU Lesser General Public License
16  * as published by the Free Software Foundation, either version 3 of the
17  * License, or (at your option) any later version.
18  *
19  * OpenShot Library (libopenshot) is distributed in the hope that it will be
20  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "../include/DecklinkWriter.h"
29 
30 using namespace openshot;
31 
32 DecklinkWriter::DecklinkWriter(int device, int video_mode, int pixel_format, int channels, int sample_depth)
33  : device(device), is_open(false), g_videoModeIndex(video_mode), g_audioChannels(channels), g_audioSampleDepth(sample_depth)
34 {
35  // Init decklink variables
36  inputFlags = 0;
37  selectedDisplayMode = bmdModeNTSC;
38  pixelFormat = bmdFormat8BitYUV;
39  displayModeCount = 0;
40  exitStatus = 1;
41  foundDisplayMode = false;
42  pthread_mutex_init(&sleepMutex, NULL);
43  pthread_cond_init(&sleepCond, NULL);
44 
45  switch(pixel_format)
46  {
47  case 0: pixelFormat = bmdFormat8BitYUV; break;
48  case 1: pixelFormat = bmdFormat10BitYUV; break;
49  case 2: pixelFormat = bmdFormat10BitRGB; break;
50  case 3: pixelFormat = bmdFormat8BitARGB; break;
51  default:
52  throw DecklinkError("Pixel format is not valid (must be 0,1,2,3).");
53  }
54 }
55 
56 // Open decklink writer
58 {
59  // Open reader if not already open
60  if (!is_open)
61  {
62  // Attempt to open blackmagic card
63  deckLinkIterator = CreateDeckLinkIteratorInstance();
64 
65  if (!deckLinkIterator)
66  throw DecklinkError("This application requires the DeckLink drivers installed.");
67 
68  /* Connect to a DeckLink instance */
69  for (int device_count = 0; device_count <= device; device_count++)
70  {
71  // Check for requested device
72  result = deckLinkIterator->Next(&deckLink);
73  if (result != S_OK)
74  throw DecklinkError("No DeckLink PCI cards found.");
75 
76  if (device_count == device)
77  break;
78  }
79 
80  if (deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&deckLinkOutput) != S_OK)
81  throw DecklinkError("DeckLink QueryInterface Failed.");
82 
83  // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output
84  result = deckLinkOutput->GetDisplayModeIterator(&displayModeIterator);
85  if (result != S_OK)
86  throw DecklinkError("Could not obtain the video output display mode iterator.");
87 
88  if (g_videoModeIndex < 0)
89  throw DecklinkError("No video mode specified.");
90 
91  // Loop through all available display modes, until a match is found (if any)
92  const char *displayModeName;
93  BMDTimeValue frameRateDuration, frameRateScale;
94 
95  while (displayModeIterator->Next(&displayMode) == S_OK)
96  {
97  if (g_videoModeIndex == displayModeCount)
98  {
99  BMDDisplayModeSupport result;
100 
101  foundDisplayMode = true;
102  displayMode->GetName(&displayModeName);
103  selectedDisplayMode = displayMode->GetDisplayMode();
104  //deckLinkOutput->DoesSupportVideoMode(selectedDisplayMode, pixelFormat, bmdVideoOutputFlagDefault, &result, NULL);
105 
106  // Get framerate
107  displayMode->GetFrameRate(&frameRateDuration, &frameRateScale);
108 
109  //if (result == bmdDisplayModeNotSupported)
110  //{
111  // cout << "The display mode does not support the selected pixel format." << endl;
112  // throw DecklinkError("The display mode does not support the selected pixel format.");
113  //}
114 
115  break;
116  }
117  displayModeCount++;
118  }
119 
120  if (!foundDisplayMode)
121  throw DecklinkError("Invalid video mode. No matching ones found.");
122 
123  // Calculate FPS
124  unsigned long m_framesPerSecond = (unsigned long)((frameRateScale + (frameRateDuration-1)) / frameRateDuration);
125 
126  // Create Delegate & Pass in pointers to the output and converters
127  delegate = new DeckLinkOutputDelegate(displayMode, deckLinkOutput);
128 
129  // Provide this class as a delegate to the audio and video output interfaces
130  deckLinkOutput->SetScheduledFrameCompletionCallback(delegate);
131  //deckLinkOutput->SetAudioCallback(delegate);
132 
133  // Check for video input
134  if (deckLinkOutput->EnableVideoOutput(displayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) != S_OK)
135  throw DecklinkError("Failed to enable video output. Is another application using the card?");
136 
137  // Check for audio input
138  //if (deckLinkOutput->EnableAudioOutput(bmdAudioSampleRate48kHz, g_audioSampleDepth, g_audioChannels, bmdAudioOutputStreamContinuous) != S_OK)
139  // throw DecklinkError("Failed to enable audio output. Is another application using the card?");
140 
141  // Begin video preroll by scheduling a second of frames in hardware
142  //std::shared_ptr<Frame> f(new Frame(1, displayMode->GetWidth(), displayMode->GetHeight(), "Blue"));
143  //f->AddColor(displayMode->GetWidth(), displayMode->GetHeight(), "Blue");
144 
145  // Preroll 1 second of video
146  //for (unsigned i = 0; i < 16; i++)
147  //{
148  // // Write 30 blank frames (for preroll)
149  // delegate->WriteFrame(f);
150  // delegate->ScheduleNextFrame(true);
151  //}
152 
153  //deckLinkOutput->StartScheduledPlayback(0, 100, 1.0);
154  //if (deckLinkOutput->BeginAudioPreroll() != S_OK)
155  // throw DecklinkError("Failed to begin audio preroll.");
156 
157 
158  // Update image properties
159  info.has_audio = true;
160  info.has_video = true;
161  info.vcodec = displayModeName;
162  info.width = displayMode->GetWidth();
163  info.height = displayMode->GetHeight();
164  info.file_size = info.width * info.height * sizeof(char) * 4;
165  info.pixel_ratio.num = 1;
166  info.pixel_ratio.den = 1;
167  info.duration = 60 * 60 * 24; // 24 hour duration... since we're capturing a live stream
168  info.fps.num = frameRateScale;
169  info.fps.den = frameRateDuration;
170  info.video_timebase.num = frameRateDuration;
171  info.video_timebase.den = frameRateScale;
173 
174  // Calculate the DAR (display aspect ratio)
176 
177  // Reduce size fraction
178  size.Reduce();
179 
180  // Set the ratio based on the reduced fraction
181  info.display_ratio.num = size.num;
182  info.display_ratio.den = size.den;
183 
184  // Mark as "open"
185  is_open = true;
186  }
187 }
188 
189 // Close device and video stream
191 {
192  // Close all objects, if reader is 'open'
193  if (is_open)
194  {
195  // Stop the audio and video output streams immediately
196  deckLinkOutput->StopScheduledPlayback(0, NULL, 0);
197  deckLinkOutput->DisableAudioOutput();
198  deckLinkOutput->DisableVideoOutput();
199 
200  // Release DisplayMode
201  displayMode->Release();
202 
203  if (displayModeIterator != NULL)
204  {
205  displayModeIterator->Release();
206  displayModeIterator = NULL;
207  }
208 
209  if (deckLinkOutput != NULL)
210  {
211  deckLinkOutput->Release();
212  deckLinkOutput = NULL;
213  }
214 
215  if (deckLink != NULL)
216  {
217  deckLink->Release();
218  deckLink = NULL;
219  }
220 
221  if (deckLinkIterator != NULL)
222  deckLinkIterator->Release();
223 
224  // Mark as "closed"
225  is_open = false;
226  }
227 }
228 
229 // This method is required for all derived classes of WriterBase. Write a Frame to the video file.
230 void DecklinkWriter::WriteFrame(std::shared_ptr<Frame> frame)
231 {
232  // Check for open reader (or throw exception)
233  if (!is_open)
234  throw WriterClosed("The DecklinkWriter is closed. Call Open() before calling this method.", "");
235 
236  delegate->WriteFrame(frame);
237 }
238 
239 // This method is required for all derived classes of WriterBase. Write a block of frames from a reader.
240 void DecklinkWriter::WriteFrame(ReaderBase* reader, int start, int length)
241 {
242  // Loop through each frame (and encoded it)
243  for (int number = start; number <= length; number++)
244  {
245  // Get the frame
246  std::shared_ptr<Frame> f = reader->GetFrame(number);
247 
248  // Encode frame
249  WriteFrame(f);
250  }
251 }
void WriteFrame(std::shared_ptr< Frame > frame)
This method is required for all derived classes of WriterBase. Write a Frame to the video file...
int num
Numerator for the fraction.
Definition: Fraction.h:44
WriterInfo info
Information about the current media file.
Definition: WriterBase.h:92
Implementation of the Blackmagic Decklink API (used by the DecklinkWriter)
Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Definition: WriterBase.h:61
int64_t video_length
The number of frames in the video stream.
Definition: WriterBase.h:64
string vcodec
The name of the video codec used to encode / decode the video stream.
Definition: WriterBase.h:63
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:95
int width
The width of the video (in pixels)
Definition: WriterBase.h:57
int64_t file_size
Size of file (in bytes)
Definition: WriterBase.h:55
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
Definition: WriterBase.h:66
float duration
Length of time (in seconds)
Definition: WriterBase.h:54
virtual std::shared_ptr< Frame > GetFrame(int64_t number)=0
Exception when accessing a blackmagic decklink card.
Definition: Exceptions.h:70
This class represents a fraction.
Definition: Fraction.h:42
Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
Definition: WriterBase.h:62
DecklinkWriter(int device, int video_mode, int pixel_format, int channels, int sample_depth)
bool has_video
Determines if this file has a video stream.
Definition: WriterBase.h:51
void WriteFrame(std::shared_ptr< openshot::Frame > frame)
Custom method to write new frames.
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: WriterBase.h:59
void Open()
Open device and video stream - which is called by the constructor automatically.
This namespace is the default namespace for all code in the openshot library.
void Close()
Close the device and video stream.
bool has_audio
Determines if this file has an audio stream.
Definition: WriterBase.h:52
Exception when a writer is closed, and a frame is requested.
Definition: Exceptions.h:264
int height
The height of the video (in pixels)
Definition: WriterBase.h:56
int den
Denominator for the fraction.
Definition: Fraction.h:45
double ToDouble()
Return this fraction as a double (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:46