I have the following code which writes a few frames to a .avi video file. This works perfectly fine on a windows machine but when I try it on my Mac it creates the .avi file and displays no errors, but the file will not play. I haven't been able to find a clear solution so far.
I am currently using Mac OSX 10.9.2.
void videoWriter()
{
CvVideoWriter *writer;
writer = cvCreateVideoWriter("test.avi",CV_FOURCC('I','Y','U','V'),1,Size(640,480),1);
for(int i = 0; i < 9; i++)
{
if(imMan.returnSelect(i)) {
cout << "Frame " << i << endl;
/****** Original Image *********/
Mat frame = imMan.returnOrg(i);
IplImage fr = frame;
cvWriteFrame(writer,&fr);
}
}
cvReleaseVideoWriter(&writer);
}
what is the size of frame?
In my experience, cvWriteFrame will not generate error even if the 4th parameter of cvCreateVideoWriter does not match with the dimension of your image frame. And it write something like an header. (with 414 byte...)
make sure they match exactly.
You have to use the right combination of codec and extension.
The codec is platform dependent. That could be the problem.
Try using this combination:
writer = cvCreateVideoWriter("test.mkv",CV_FOURCC(*'X264),1,Size(640,480),1);
Here is the reference link
Related
I'm trying to write a code in Image J that will:
Open all images in separate windows that end in " - GFP.vsi" within a folder
Use look up tables to convert images to green and RGB color
From ImageJ, the commands are: run("Green"); and run("RGB Color");
Save each image in the same, original folder with the same name and as a .tif
Would be ok if images overwrite original, but would also be ok if they had a new name.
From ImageJ, to save as .tif file: saveAs("Tiff", "Filepath");
I have no experience with Java and just a little experience with coding. I tried to piece something together using code I found on stackoverflow and on the ImageJ website, but kept getting error codes. Any help is much appreciated!
This is the way I would approach this task:
macro "Change and Resave" {
dir1 = getDirectory("Choose Source Directory ");
dir2 = getDirectory("Choose Destination Directory ");
list = getFileList(dir1);
// Make an array of files ending " - GFP.vsi"
nd2list = newArray(0);
for (i=0; i<list.length; i++) {
if (endsWith(list[i], " - GFP.vsi")) {
vsilist = append(vsilist, list[i]);
}
}
setBatchMode(true);
// loop through files
for (i=0; i<vsilist.length; i++) {
showProgress(i+1, vsilist.length);
// open file using Bio-Formats, you may need to edit these two lines
s = "open=["+dir1+vsilist[i]+"] autoscale color_mode=Composite rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT";
run("Bio-Formats Importer", s);
// your commands from your question
run("Green");
run("RGB Color");
saveAs("tiff", dir2+replace(vsilist[i],".vsi",".tif"));
close();
}
setBatchMode(false);
}
function append(arr, value) {
arr2 = newArray(arr.length+1);
for (i=0; i<arr.length; i++)
arr2[i] = arr[i];
arr2[arr.length] = value;
return arr2;
}
In a user-space application, I'm writing v210 formatted video data to a V4L2 loopback device. When I watch the video in VLC or other viewer, I just get clownbarf and claims that the stream is UYUV or other, not v210. I suspect I need to tell the loopback device something more than what I have, to make the stream appear as v210 to the viewer. Is there one more place/way to tell it that it'll be handling a certain format?
What I do now:
int frame_w, frame_h = ((some sane values))
outputfd = open("/dev/video4", O_RDWR);
// check VIDIOC_QUERYCAPS, ...
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
fmt.fmt.pix.width = frame_w;
fmt.fmt.pix.height = frame_h;
fmt.fmt.pix.bytesperline = inbpr; // no padding
fmt.fmt.pix.field = 1;
fmt.fmt.pix.sizeimage = frame_h * fmt.fmt.pix.bytesperline;
fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
v210width = (((frame_w+47)/48)*48); // round up to mult of 48 px
byte_per_row = (v210width*8)/3;
fmt.fmt.pix.pixelformat = 'v' | '2' << 8 | '1' << 16 | '0' << 24;
fmt.fmt.pix.width = v210width;
fmt.fmt.pix.bytesperline = byte_per_row ;
ioctl(outputfd, VIDIOC_S_FMT, &fmt);
// later, in some inner loop...
... write stuff to uint8_t buffer[] ...
write(outputfd, buffer, buffersize);
If I write UYVY format, or RGB or others, it can be made to work. Viewers display the video and report the correct format.
This code is based on examples, reading the V4L docs, and some working in-house code. No one here knows exactly what are all the things one must do to open and write to a video device.
While there is an easily found example online of how to read video from a V4L device, I couldn't find a similar quality example for writing. If such exists, it may show the missing piece.
Context: I have a file called libffmpeg.so, that I took from the APK of an Android application that is using FFMPEG to encode and decode files between several Codecs. Thus, I take for grant that this is compiled with encoding options enable and that this .so file is containing all the codecs somewhere. This file is compiled for ARM (what we call ARMEABI profile on Android).
I also have a very complete class with interops to call API from ffmpeg. Whatever is the origin of this static library, all call responses are good and most endpoints exist. If not I add them or fix deprecated one.
When I want to create an ffmpeg Encoder, the returned encoder is correct.
var thisIsSuccessful = avcodec_find_encoder(myAVCodec.id);
Now, I have a problem with Codecs. The problem is that - let's say that out of curiosity - I iterate through the list of all the codecs to see which one I'm able to open with the avcodec_open call ...
AVCodec codec;
var res = FFmpeg.av_codec_next(&codec);
while((res = FFmpeg.av_codec_next(res)) != null)
{
var name = res->longname;
AVCodec* encoder = FFmpeg.avcodec_find_encoder(res->id);
if (encoder != null) {
AVCodecContext c = new AVCodecContext ();
/* put sample parameters */
c.bit_rate = 64000;
c.sample_rate = 22050;
c.channels = 1;
if (FFmpeg.avcodec_open (ref c, encoder) >= 0) {
System.Diagnostics.Debug.WriteLine ("[YES] - " + name);
}
} else {
System.Diagnostics.Debug.WriteLine ("[NO ] - " + name);
}
}
... then only uncompressed codecs are working. (YUV, FFmpeg Video 1, etc)
My hypothesis are these one:
An option that was missing at the time of compiling to the .so file
The av_open_codec calls is acting depending on the properties of the AVCodecContext I've referenced in the call.
I'm really curious about why only a minimum set of uncompressed codecs are returned?
[EDIT]
#ronald-s-bultje answer led me to read AVCodecContext API description, and there are a lot of mendatory fileds with "MUST be set by user" when used on an encoder. Setting a value for these parameters on AVCodecContext made most of the nice codecs available:
c.time_base = new AVRational (); // Output framerate. Here, 30fps
c.time_base.num = 1;
c.time_base.den = 30;
c.me_method = 1; // Motion-estimation mode on compression -> 1 is none
c.width = 640; // Source width
c.height = 480; // Source height
c.gop_size = 30; // Used by h264. Just here for test purposes.
c.bit_rate = c.width * c.height * 4; // Randomly set to that...
c.pix_fmt = FFmpegSharp.Interop.Util.PixelFormat.PIX_FMT_YUV420P; // Source pixel format
The av_open_codec calls is acting depending on the properties of the
AVCodecContext I've referenced in the call.
It's basically that. I mean, for the video encoders, you didn't even set width/height, so most encoders really can't be expected to do anything useful like this, and are right to error right out.
You can set default parameters using e.g. avcodec_get_context_defaults3(), which should help you a long way to getting some useful settings in the AVCodecContext. After that, set typical ones like width/height/pix_fmt to the ones describing your input format (if you want to do audio encoding - which is actually surprisingly unclear from your question, you'll need to set some different ones like sample_fmt/sample_rate/channels, but same idea). And then you should be relatively good to go.
I was trying to extract frames from a small video using the following lines of code :
clc;
close all;
% Open an sample avi file
[FileName,PathName] = uigetfile('*.AVI','Select the Video');
file = fullfile(PathName,FileName);
%filename = '.\003.AVI';
mov = MMREADER(file);
% Output folder
outputFolder = fullfile(cd, 'frames');
if ~exist(outputFolder, 'dir')
mkdir(outputFolder);
end
%getting no of frames
numberOfFrames = mov.NumberOfFrames;
numberOfFramesWritten = 0;
for frame = 1 : numberOfFrames
thisFrame = read(mov, frame);
outputBaseFileName = sprintf('%3.3d.png', frame);
outputFullFileName = fullfile(outputFolder, outputBaseFileName);
imwrite(thisFrame, outputFullFileName, 'png');
progressIndication = sprintf('Wrote frame %4d of %d.', frame,numberOfFrames);
disp(progressIndication);
numberOfFramesWritten = numberOfFramesWritten + 1;
end
progressIndication = sprintf('Wrote %d frames to folder "%s"',numberOfFramesWritten,outputFolder);
disp(progressIndication);
However, I am getting the following error on running this code :
??? Error using ==> extract at 10
The file requires the following codec(s) to be installed on your system:
Unknown Codec
Can someone help me to sort out this error ? Thanks.
The file seems to be encoded with an unknown video codec (unknown to MatLab probably). The file extension (.avi, .mpeg, etc.) does not denote a codec but rather a container if I'm not mistaking.
The links at the bottom provide some information about supported file formats by MatLab. You should try to retrieve what container and codec your video file uses and see if MatLab supports it. A way of retrieving the codec is by opening it in VLC mediaplayer (by VideoLan) right click the movie, extra-> codec information, or if you are on windows simply open the movie in VLC and press CTRL+J.
Some usefull links:
http://www.mathworks.nl/help/matlab/ref/mmreader-class.html
http://www.mathworks.nl/help/matlab/import_export/supported-video-file-formats.html
http://www.videolan.org/vlc/
Kind regards,
Ernst Jan
Instead of MMREADER, I used the following lines of code :
movieInfo = aviinfo(movieFullFileName);
mov = aviread(movieFullFileName);
% movie(mov);
% Determine how many frames there are.
numberOfFrames = size(mov, 2);
numberOfFramesWritten = 0;
It worked.
I am running the particleWithFile() function of Coco2D-X, with a plist file created with Mac. The image data is embedded in the plist file, using the "textureImageData" key.
With Mac it works fine, but with Windows it fails, on CCAssert(isOK), see Coco2D-X code below (CCParticleSystem.cpp):
char *textureData = (char*)valueForKey("textureImageData", dictionary);
CCAssert(textureData, "");
int dataLen = strlen(textureData);
if(dataLen != 0)
{
// if it fails, try to get it from the base64-gzipped data
int decodeLen = base64Decode((unsigned char*)textureData, (unsigned int)dataLen, &buffer);
CCAssert( buffer != NULL, "CCParticleSystem: error decoding textureImageData");
CC_BREAK_IF(!buffer);
int deflatedLen = ZipUtils::ccInflateMemory(buffer, decodeLen, &deflated);
CCAssert( deflated != NULL, "CCParticleSystem: error ungzipping textureImageData");
CC_BREAK_IF(!deflated);
image = new CCImage();
bool isOK = image->initWithImageData(deflated, deflatedLen);
CCAssert(isOK, "CCParticleSystem: error init image with Data");
CC_BREAK_IF(!isOK);
m_pTexture = CCTextureCache::sharedTextureCache()->addUIImage(image, fullpath.c_str());
}
It seems the the decoding passes successfully, and the problem is inside inflate() function of zlib, failing to unzip the png file.
Any suggestions?
OK, I found the problem.
Apparently my resource wasn't a png file but a tiff file. So Inflate() returned a correct buffer (of a tiff file - looked too long for me, so I suspected it was erroneous), but initWithImageData() failed to create an image, since tiff are not supported by Cocos2d-x on windows.
I encounter the problem because I set the CC_USE_TIFF to 0.
After I recovery the CC_USE_TIFF to 1,the problem resolved.