| 173 | } |
| 174 | |
| 175 | void decoderFFmpeg::copyCurImageToBuffer() |
| 176 | { |
| 177 | if (!frame) |
| 178 | return; |
| 179 | |
| 180 | //// get metadata |
| 181 | // AVDictionaryWrapper dict = this->ff.get_metadata(frame); |
| 182 | // QStringPairList values = this->ff.getDictionary_entries(dict, "", 0); |
| 183 | |
| 184 | if (this->rawFormat == video::RawFormat::YUV) |
| 185 | { |
| 186 | // At first get how many bytes we are going to write |
| 187 | const auto pixFmt = this->getPixelFormatYUV(); |
| 188 | const auto nrBytesPerSample = pixFmt.getBitsPerSample() <= 8 ? 1 : 2; |
| 189 | const auto nrBytesY = this->frameSize.width * this->frameSize.height * nrBytesPerSample; |
| 190 | const auto nrBytesC = this->frameSize.width / pixFmt.getSubsamplingHor() * |
| 191 | this->frameSize.height / pixFmt.getSubsamplingVer() * nrBytesPerSample; |
| 192 | const auto nrBytes = nrBytesY + 2 * nrBytesC; |
| 193 | |
| 194 | // Is the output big enough? |
| 195 | if (auto c = functions::clipToUnsigned(this->currentOutputBuffer.capacity()); c < nrBytes) |
| 196 | this->currentOutputBuffer.resize(nrBytes); |
| 197 | |
| 198 | // Copy line by line. The linesize of the source may be larger than the width of the frame. |
| 199 | // This may be because the frame buffer is (8) byte aligned. Also the internal decoded |
| 200 | // resolution may be larger than the output frame size. |
| 201 | for (unsigned plane = 0; plane < pixFmt.getNrPlanes(); plane++) |
| 202 | { |
| 203 | const auto component = |
| 204 | (plane == 0) ? video::yuv::Component::Luma : video::yuv::Component::Chroma; |
| 205 | auto src = frame.getData(plane); |
| 206 | const auto srcLinesize = frame.getLineSize(plane); |
| 207 | auto dst = this->currentOutputBuffer.data(); |
| 208 | if (plane > 0) |
| 209 | dst += (nrBytesY + (plane - 1) * nrBytesC); |
| 210 | const auto dstLinesize = |
| 211 | this->frameSize.width / pixFmt.getSubsamplingHor(component) * nrBytesPerSample; |
| 212 | const auto height = this->frameSize.height / pixFmt.getSubsamplingVer(component); |
| 213 | for (unsigned y = 0; y < height; y++) |
| 214 | { |
| 215 | memcpy(dst, src, dstLinesize); |
| 216 | dst += dstLinesize; |
| 217 | src += srcLinesize; |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | else if (this->rawFormat == video::RawFormat::RGB) |
| 222 | { |
| 223 | const auto pixFmt = this->getRGBPixelFormat(); |
| 224 | const auto nrBytesPerSample = pixFmt.getBitsPerSample() <= 8 ? 1 : 2; |
| 225 | const auto nrBytesPerComponent = |
| 226 | this->frameSize.width * this->frameSize.height * nrBytesPerSample; |
| 227 | const auto nrBytes = nrBytesPerComponent * pixFmt.nrChannels(); |
| 228 | |
| 229 | // Is the output big enough? |
| 230 | if (auto c = functions::clipToUnsigned(this->currentOutputBuffer.capacity()); c < nrBytes) |
| 231 | this->currentOutputBuffer.resize(nrBytes); |
| 232 |
no test coverage detected