File: unit_yuv4mpeg2.pas

package info (click to toggle)
astap 2024.11.13-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,032 kB
  • sloc: pascal: 49,240; sh: 205; makefile: 5
file content (133 lines) | stat: -rw-r--r-- 4,289 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
unit unit_yuv4mpeg2;{writes YUV4MPEG2 uncompressed video file. Pixels are taken from Timage}
{$MODE Delphi}
{Copyright (C) 2017, 2023 by Han Kleijn, www.hnsky.org
 email: han.k.. at...hnsky.org

 This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at https://mozilla.org/MPL/2.0/.   }

interface

uses
  Classes, SysUtils,dialogs,graphics,
  LCLType, // for RGBtriple
  IntfGraphics, // TLazIntfImage type
  fpImage, // TFPColor type;
  lclintf;

function write_yuv4mpeg2_header(filen, framerate: string; colour : boolean; w,h: integer): boolean;{open/create file. Result is false if failure}
function write_yuv4mpeg2_frame(colour: boolean; x,y,w,h: integer): boolean; {reads pixels from Timage and writes YUV frames in 444p style, colour or mono. Call this procedure for each image. Result is false if failure}
procedure close_yuv4mpeg2; {close file}

implementation

uses astap_main;
var
  theFile : tfilestream;

function write_yuv4mpeg2_header(filen, framerate: string; colour : boolean; w, h {size}: integer): boolean;{open/create file. Result is false if failure}
var
  header: array[0..41] of ansichar;
begin
  result:=false;

  try
   TheFile:=tfilestream.Create(filen, fmcreate );
  except
   TheFile.free;
   exit;
  end;
  {'YUV4MPEG2 W0384 H0288 F01:1 Ip A0:0 C444'+#10}    {See https://wiki.multimedia.cx/index.php/YUV4MPEG2}
  if colour then header:=pansichar('YUV4MPEG2 W'+inttostr(w)+' H'+inttostr(h)+' F'+trim(framerate)+':1 Ip A0:0 C444'+#10)
            else header:=pansichar('YUV4MPEG2 W'+inttostr(w)+' H'+inttostr(h)+' F'+trim(framerate)+':1 Ip A0:0 Cmono'+#10);{width, height,frame rate, interlace progressive, unknown aspect, color space}
  { Write header }
  thefile.writebuffer ( header, strlen(Header));
  result:=true;
end;

function write_yuv4mpeg2_frame(colour: boolean;x,y,w,h: integer): boolean; {reads pixels from Timage and writes YUV frames in 444p style, colour or mono. Call this procedure for each image}
var
  k,xx,yy,steps  : integer;
  r,g,b              : byte;
  row         : array of byte;
  xLine       :  PByteArray;
const
  header: array[0..5] of ansichar=(('F'),('R'),('A'),('M'),('E'),(#10));

begin
  result:=true;
  try
    thefile.writebuffer ( header, strlen(header)); {write FRAME+#10}

    setlength(row, w {width});

    {444 frames:   Y0 (full frame), U0,V0 Y1 U1 V1 Y2 U2 V2                 422 frames:  Y0 (U0+U1)/2 Y1 (V0+V1)/2 Y2 (U2+U3)/2 Y3 (V2+V3)/2}
    // write full Y frame
    //YYYY
    //YYYY
    //YYYY
    //YYYY

    // write full U frame
    //UUUU
    //UUUU
    //UUUU
    //UUUU

    // write full V frame
    //VVVV
    //VVVV
    //VVVV
    //VVVV

    if colour then steps:=2 {colour} else steps:=0;{mono}    {for colour write Y, U, V frame else only Y}

    for k:=0 to steps {0 or 2} do {do Y,U, V frame, so scan image line 3 times}
    for yy := y to y+h-1 {height} do
    begin // scan each timage line
      xLine:=mainwindow.image1.Picture.Bitmap.ScanLine[yy];
      for xx := x to x+w-1 {width} do
      begin
       {$ifdef mswindows}
          B:=xLine^[xx*3]; {3*8=24 bit}
          G:=xLine^[xx*3+1]; {fast pixel write routine }
          R:=xLine^[xx*3+2];
       {$endif}
       {$ifdef darwin} {MacOS}
          R:=xLine^[xx*4+1]; {4*8=32 bit}
          G:=xLine^[xx*4+2]; {fast pixel write routine }
          B:=xLine^[xx*4+3];
       {$endif}
       {$ifdef linux}
          B:=xLine^[xx*4]; {4*8=32 bit}
          G:=xLine^[xx*4+1]; {fast pixel write routine }
          R:=xLine^[xx*4+2];
        {$endif}

        if k=0 then
          row[xx-x]:=trunc(R*77/256 + G*150/256 + B*29/256)        {Y frame, Full swing for BT.601}
        else
        if k=1 then
           row[xx-x]:=trunc(R*-43/256 + G*-84/256 + B*127/256 +128) {U frame}
        else
        row[xx-x]:=trunc(R*127/256 + G*-106/256 + B*-21/256 +128){V frame}
      end;
      thefile.writebuffer(row[0],length(row));
    end;
  except
    result:=false;
    row:=nil;
    exit;
  end;
  row:=nil;
end;


procedure close_yuv4mpeg2; {close file}
begin
  thefile.free;
end;

end.