TomiL
TomiL

Reputation: 697

Extract some YUV frames from large YUV file

I am looking for WIN32 program to copy part of the large 1920x1080px 4:2:0 .YUV file (cca. 43GB) into smaller .YUV files. All of the programs I have used, i.e. YUV players, can only copy/save 1 frame at the time. What is the easiest/appropriate method to cut YUV raw data to smaller YUV videos(images)? SOmething similar to ffmpeg command:

ffmpeg -ss [start_seconds] -t [duration_seconds] -i [input_file] [outputfile]

Upvotes: 0

Views: 2368

Answers (3)

Jeegar Patel
Jeegar Patel

Reputation: 27210

Method1:

If you are using gstreamer and you just want first X amount of yuv frames from large yuv files then you can use below method

gst-launch-1.0 filesrc num-buffers=X location="Your_large.yuv" ! videoparse width=x height=y format="xy" ! filesink location="FirstXframes.yuv"

Method2: Calculate size of 1 frames and then use split utility to divide large files in small files.

Use

split -b size_in_bytes Large_file prefix

Upvotes: 0

Fredrik Pihl
Fredrik Pihl

Reputation: 45662

If you have python available, you can use this approach to store each frame as a separate file:

src_yuv = open(self.filename, 'rb')

for i in xrange(NUMBER_OF_FRAMES):
    data = src_yuv.read(NUMBER_OF_BYTES)
    fname = "frame" + "%d" % i + ".yuv"
    dst_yuv = open(fname, 'wb')
    dst_yuv.write(data)
    sys.stdout.write('.')
    sys.stdout.flush()
    dst_yuv.close()
src_yuv.close()

just change the capitalized variable into valid numbers, e.g NUMBER_OF_BYTES for one frame 1080p should be 1920*1080*3/2=3110400

Or if you install cygwin you can use the dd tool, e.g. to get the first frame of a 1080p clip do:

dd bs=3110400 count=1 if=sample.yuv of=frame1.yuv

Upvotes: 2

TomiL
TomiL

Reputation: 697

Here is the Minimum Working Example of the code, written in C++, if anyone will search for a simple solution:

// include libraries
#include <fstream>
using namespace std;

#define P420 1.5

const int IMAGE_SIZE = 1920*1080;  // ful HD image size in pixels
const double IMAGE_CONVERTION = P420;
int n_frames = 300;  // set number of frames to copy
int skip_frames = 500;  // set number of frames to skip from the begining of the input file

char in_string[] = "F:\\BigBucksBunny\\yuv\\BigBuckBunny_1920_1080_24fps.yuv";
char out_string[] = "out.yuv";


//////////////////////
//   main
//////////////////////
int main(int argc, char** argv)
{
    double image_size = IMAGE_SIZE * IMAGE_CONVERTION;
    long file_size = 0;

    // IO files
    ofstream out_file(out_string, ios::out | ios::binary);
    ifstream in_file(in_string, ios::in | ios::binary);

    // error cheking, like check n_frames+skip_frames overflow
    // 
    // TODO

    // image buffer
    char* image = new char[(int)image_size];

    // skip frames
    in_file.seekg(skip_frames*image_size);

    // read/write image buffer one by one
    for(int i = 0; i < n_frames; i++)
    {
        in_file.read(image, image_size);
        out_file.write(image, image_size);
    }

    // close the files
    out_file.close();
    in_file.close();

    printf("Copy finished ...");
    return 0;
}

Upvotes: 2

Related Questions