1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
4 * Authors: Steve Borho <steve@borho.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
29 #define ENABLE_THREADING 1
35 #pragma warning(disable: 4996) // POSIX setmode and fileno deprecated
42 YUVInput::YUVInput(InputFileInfo
& info
)
44 for (int i
= 0; i
< QUEUE_SIZE
; i
++)
52 colorSpace
= info
.csp
;
56 uint32_t pixelbytes
= depth
> 8 ? 2 : 1;
58 for (int i
= 0; i
< x265_cli_csps
[colorSpace
].planes
; i
++)
60 uint32_t w
= width
>> x265_cli_csps
[colorSpace
].width
[i
];
61 uint32_t h
= height
>> x265_cli_csps
[colorSpace
].height
[i
];
62 framesize
+= w
* h
* pixelbytes
;
65 if (width
== 0 || height
== 0 || info
.fpsNum
== 0 || info
.fpsDenom
== 0)
67 x265_log(NULL
, X265_LOG_ERROR
, "yuv: width, height, and FPS must be specified\n");
71 if (!strcmp(info
.filename
, "-"))
75 setmode(fileno(stdin
), O_BINARY
);
79 ifs
= new ifstream(info
.filename
, ios::binary
| ios::in
);
81 if (ifs
&& ifs
->good())
85 if (ifs
&& ifs
!= &cin
)
91 for (uint32_t i
= 0; i
< QUEUE_SIZE
; i
++)
93 buf
[i
] = X265_MALLOC(char, framesize
);
96 x265_log(NULL
, X265_LOG_ERROR
, "yuv: buffer allocation failure, aborting\n");
102 info
.frameCount
= -1;
104 /* try to estimate frame count, if this is not stdin */
107 istream::pos_type cur
= ifs
->tellg();
109 #if defined(_MSC_VER) && _MSC_VER < 1700
110 /* Older MSVC versions cannot handle 64bit file sizes properly, so go native */
111 HANDLE hFile
= CreateFileA(info
.filename
, GENERIC_READ
,
112 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
,
113 FILE_ATTRIBUTE_NORMAL
, NULL
);
114 if (hFile
!= INVALID_HANDLE_VALUE
)
117 if (GetFileSizeEx(hFile
, &size
))
118 info
.frameCount
= (int)((size
.QuadPart
- (int64_t)cur
) / framesize
);
121 #else // if defined(_MSC_VER) && _MSC_VER < 1700
124 ifs
->seekg(0, ios::end
);
125 istream::pos_type size
= ifs
->tellg();
126 ifs
->seekg(cur
, ios::beg
);
128 info
.frameCount
= (int)((size
- cur
) / framesize
);
130 #endif // if defined(_MSC_VER) && _MSC_VER < 1700
136 ifs
->seekg((uint64_t)framesize
* info
.skipFrames
, ios::cur
);
138 for (int i
= 0; i
< info
.skipFrames
; i
++)
139 ifs
->ignore(framesize
);
144 YUVInput::~YUVInput()
146 if (ifs
&& ifs
!= &cin
)
148 for (int i
= 0; i
< QUEUE_SIZE
; i
++)
152 void YUVInput::release()
154 threadActive
= false;
155 readCount
.set(readCount
.get()); // unblock read thread
160 void YUVInput::startReader()
168 void YUVInput::threadMain()
172 if (!populateFrameQueue())
176 threadActive
= false;
177 writeCount
.set(writeCount
.get()); // unblock readPicture
180 bool YUVInput::populateFrameQueue()
182 if (!ifs
|| ifs
->fail())
185 /* wait for room in the ring buffer */
186 int written
= writeCount
.get();
187 int read
= readCount
.get();
188 while (written
- read
> QUEUE_SIZE
- 2)
190 read
= readCount
.waitForChange(read
);
192 // release() has been called
196 ifs
->read(buf
[written
% QUEUE_SIZE
], framesize
);
206 bool YUVInput::readPicture(x265_picture
& pic
)
208 int read
= readCount
.get();
209 int written
= writeCount
.get();
213 /* only wait if the read thread is still active */
214 while (threadActive
&& read
== written
)
215 written
= writeCount
.waitForChange(written
);
219 populateFrameQueue();
221 #endif // if ENABLE_THREADING
225 uint32_t pixelbytes
= depth
> 8 ? 2 : 1;
226 pic
.colorSpace
= colorSpace
;
227 pic
.bitDepth
= depth
;
228 pic
.stride
[0] = width
* pixelbytes
;
229 pic
.stride
[1] = pic
.stride
[0] >> x265_cli_csps
[colorSpace
].width
[1];
230 pic
.stride
[2] = pic
.stride
[0] >> x265_cli_csps
[colorSpace
].width
[2];
231 pic
.planes
[0] = buf
[read
% QUEUE_SIZE
];
232 pic
.planes
[1] = (char*)pic
.planes
[0] + pic
.stride
[0] * height
;
233 pic
.planes
[2] = (char*)pic
.planes
[1] + pic
.stride
[1] * (height
>> x265_cli_csps
[colorSpace
].height
[1]);