History

lavc/vaapi_encode: wrap slice codes into row slice functions

Wrap current whole-row slice codes into following functions: - vaapi_encode_make_row_slice() - vaapi_encode_init_row_slice_structure()

Linjie Fu committed 6 years ago

Commit 65f4d561 parent 2c1cc321 file · +109 −81Browse files

Showing the changes to libavcodec/vaapi_encode.c (1 of 1 file). Show all

Unified · Split

libavcodec/vaapi_encode.c+109−81
@@ -163,6 +163,61 @@ static int vaapi_encode_wait(AVCodecContext *avctx, · 162 unmodified lines
163163 return 0;
164164 }
165165
166+static int vaapi_encode_make_row_slice(AVCodecContext *avctx,
167+ VAAPIEncodePicture *pic)
168+{
169+ VAAPIEncodeContext *ctx = avctx->priv_data;
170+ VAAPIEncodeSlice *slice;
171+ int i, rounding;
172+
173+ for (i = 0; i < pic->nb_slices; i++)
174+ pic->slices[i].row_size = ctx->slice_size;
175+
176+ rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size;
177+ if (rounding > 0) {
178+ // Place rounding error at top and bottom of frame.
179+ av_assert0(rounding < pic->nb_slices);
180+ // Some Intel drivers contain a bug where the encoder will fail
181+ // if the last slice is smaller than the one before it. Since
182+ // that's straightforward to avoid here, just do so.
183+ if (rounding <= 2) {
184+ for (i = 0; i < rounding; i++)
185+ ++pic->slices[i].row_size;
186+ } else {
187+ for (i = 0; i < (rounding + 1) / 2; i++)
188+ ++pic->slices[pic->nb_slices - i - 1].row_size;
189+ for (i = 0; i < rounding / 2; i++)
190+ ++pic->slices[i].row_size;
191+ }
192+ } else if (rounding < 0) {
193+ // Remove rounding error from last slice only.
194+ av_assert0(rounding < ctx->slice_size);
195+ pic->slices[pic->nb_slices - 1].row_size += rounding;
196+ }
197+
198+ for (i = 0; i < pic->nb_slices; i++) {
199+ slice = &pic->slices[i];
200+ slice->index = i;
201+ if (i == 0) {
202+ slice->row_start = 0;
203+ slice->block_start = 0;
204+ } else {
205+ const VAAPIEncodeSlice *prev = &pic->slices[i - 1];
206+ slice->row_start = prev->row_start + prev->row_size;
207+ slice->block_start = prev->block_start + prev->block_size;
208+ }
209+ slice->block_size = slice->row_size * ctx->slice_block_cols;
210+
211+ av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), "
212+ "%d-%d (%d blocks).\n", i, slice->row_start,
213+ slice->row_start + slice->row_size - 1, slice->row_size,
214+ slice->block_start, slice->block_start + slice->block_size - 1,
215+ slice->block_size);
216+ }
217+
218+ return 0;
219+}
220+
166221 static int vaapi_encode_issue(AVCodecContext *avctx,
167222 VAAPIEncodePicture *pic)
168223 {
@@ -346,57 +401,17 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 177 unmodified lines
346401 if (pic->nb_slices == 0)
347402 pic->nb_slices = ctx->nb_slices;
348403 if (pic->nb_slices > 0) {
349− int rounding;
350−
351404 pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices));
352405 if (!pic->slices) {
353406 err = AVERROR(ENOMEM);
354407 goto fail;
355408 }
356409
357− for (i = 0; i < pic->nb_slices; i++)
358− pic->slices[i].row_size = ctx->slice_size;
359−
360− rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size;
361− if (rounding > 0) {
362− // Place rounding error at top and bottom of frame.
363− av_assert0(rounding < pic->nb_slices);
364− // Some Intel drivers contain a bug where the encoder will fail
365− // if the last slice is smaller than the one before it. Since
366− // that's straightforward to avoid here, just do so.
367− if (rounding <= 2) {
368− for (i = 0; i < rounding; i++)
369− ++pic->slices[i].row_size;
370− } else {
371− for (i = 0; i < (rounding + 1) / 2; i++)
372− ++pic->slices[pic->nb_slices - i - 1].row_size;
373− for (i = 0; i < rounding / 2; i++)
374− ++pic->slices[i].row_size;
375− }
376− } else if (rounding < 0) {
377− // Remove rounding error from last slice only.
378− av_assert0(rounding < ctx->slice_size);
379− pic->slices[pic->nb_slices - 1].row_size += rounding;
380− }
410+ vaapi_encode_make_row_slice(avctx, pic);
381411 }
412+
382413 for (i = 0; i < pic->nb_slices; i++) {
383414 slice = &pic->slices[i];
384− slice->index = i;
385− if (i == 0) {
386− slice->row_start = 0;
387− slice->block_start = 0;
388− } else {
389− const VAAPIEncodeSlice *prev = &pic->slices[i - 1];
390− slice->row_start = prev->row_start + prev->row_size;
391− slice->block_start = prev->block_start + prev->block_size;
392− }
393− slice->block_size = slice->row_size * ctx->slice_block_cols;
394−
395− av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), "
396− "%d-%d (%d blocks).\n", i, slice->row_start,
397− slice->row_start + slice->row_size - 1, slice->row_size,
398− slice->block_start, slice->block_start + slice->block_size - 1,
399− slice->block_size);
400415
401416 if (ctx->codec->slice_params_size > 0) {
402417 slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size);
@@ -1840,6 +1855,54 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) · 1437 unmodified lines
18401855 return 0;
18411856 }
18421857
1858+static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx,
1859+ uint32_t slice_structure)
1860+{
1861+ VAAPIEncodeContext *ctx = avctx->priv_data;
1862+ int req_slices;
1863+
1864+ // For fixed-size slices currently we only support whole rows, making
1865+ // rectangular slices. This could be extended to arbitrary runs of
1866+ // blocks, but since slices tend to be a conformance requirement and
1867+ // most cases (such as broadcast or bluray) want rectangular slices
1868+ // only it would need to be gated behind another option.
1869+ if (avctx->slices > ctx->slice_block_rows) {
1870+ av_log(avctx, AV_LOG_WARNING, "Not enough rows to use "
1871+ "configured number of slices (%d < %d); using "
1872+ "maximum.\n", ctx->slice_block_rows, avctx->slices);
1873+ req_slices = ctx->slice_block_rows;
1874+ } else {
1875+ req_slices = avctx->slices;
1876+ }
1877+ if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
1878+#if VA_CHECK_VERSION(1, 8, 0)
1879+ slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_MULTI_ROWS ||
1880+#endif
1881+ slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
1882+ ctx->nb_slices = req_slices;
1883+ ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices;
1884+ } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
1885+ int k;
1886+ for (k = 1;; k *= 2) {
1887+ if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows)
1888+ break;
1889+ }
1890+ ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k;
1891+ ctx->slice_size = k;
1892+#if VA_CHECK_VERSION(1, 0, 0)
1893+ } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
1894+ ctx->nb_slices = ctx->slice_block_rows;
1895+ ctx->slice_size = 1;
1896+#endif
1897+ } else {
1898+ av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable "
1899+ "slice structure modes (%#x).\n", slice_structure);
1900+ return AVERROR(EINVAL);
1901+ }
1902+
1903+ return 0;
1904+}
1905+
18431906 static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
18441907 {
18451908 VAAPIEncodeContext *ctx = avctx->priv_data;
@@ -1847,7 +1910,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 1 unmodified line
18471910 { VAConfigAttribEncSliceStructure } };
18481911 VAStatus vas;
18491912 uint32_t max_slices, slice_structure;
1850− int req_slices;
1913+ int ret;
18511914
18521915 if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) {
18531916 if (avctx->slices > 0) {
@@ -1886,44 +1949,9 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) · 32 unmodified lines
18861949 return AVERROR(EINVAL);
18871950 }
18881951
1889− // For fixed-size slices currently we only support whole rows, making
1890− // rectangular slices. This could be extended to arbitrary runs of
1891− // blocks, but since slices tend to be a conformance requirement and
1892− // most cases (such as broadcast or bluray) want rectangular slices
1893− // only it would need to be gated behind another option.
1894− if (avctx->slices > ctx->slice_block_rows) {
1895− av_log(avctx, AV_LOG_WARNING, "Not enough rows to use "
1896− "configured number of slices (%d < %d); using "
1897− "maximum.\n", ctx->slice_block_rows, avctx->slices);
1898− req_slices = ctx->slice_block_rows;
1899− } else {
1900− req_slices = avctx->slices;
1901− }
1902− if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
1903−#if VA_CHECK_VERSION(1, 8, 0)
1904− slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_MULTI_ROWS ||
1905−#endif
1906− slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
1907− ctx->nb_slices = req_slices;
1908− ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices;
1909− } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
1910− int k;
1911− for (k = 1;; k *= 2) {
1912− if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows)
1913− break;
1914− }
1915− ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k;
1916− ctx->slice_size = k;
1917−#if VA_CHECK_VERSION(1, 0, 0)
1918− } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
1919− ctx->nb_slices = ctx->slice_block_rows;
1920− ctx->slice_size = 1;
1921−#endif
1922− } else {
1923− av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable "
1924− "slice structure modes (%#x).\n", slice_structure);
1925− return AVERROR(EINVAL);
1926− }
1952+ ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure);
1953+ if (ret < 0)
1954+ return ret;
19271955
19281956 if (ctx->nb_slices > avctx->slices) {
19291957 av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to "

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t