| 3150 | } |
| 3151 | |
| 3152 | avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output) |
| 3153 | { |
| 3154 | avifDiagnosticsClearError(&encoder->diag); |
| 3155 | if (encoder->data->items.count == 0) { |
| 3156 | return AVIF_RESULT_NO_CONTENT; |
| 3157 | } |
| 3158 | |
| 3159 | const avifCodecType codecType = avifEncoderGetCodecType(encoder); |
| 3160 | if (codecType == AVIF_CODEC_TYPE_UNKNOWN) { |
| 3161 | return AVIF_RESULT_NO_CODEC_AVAILABLE; |
| 3162 | } |
| 3163 | |
| 3164 | // ----------------------------------------------------------------------- |
| 3165 | // Finish up encoding |
| 3166 | |
| 3167 | for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) { |
| 3168 | avifEncoderItem * item = &encoder->data->items.item[itemIndex]; |
| 3169 | if (item->codec) { |
| 3170 | if (!item->codec->encodeFinish(item->codec, item->encodeOutput)) { |
| 3171 | return avifGetErrorForItemCategory(item->itemCategory); |
| 3172 | } |
| 3173 | |
| 3174 | if (item->encodeOutput->samples.count != encoder->data->frames.count) { |
| 3175 | return avifGetErrorForItemCategory(item->itemCategory); |
| 3176 | } |
| 3177 | |
| 3178 | if ((item->extraLayerCount > 0) && (item->encodeOutput->samples.count != item->extraLayerCount + 1)) { |
| 3179 | // Check whether user has sent enough frames to encoder. |
| 3180 | avifDiagnosticsPrintf(&encoder->diag, |
| 3181 | "Expected %u frames given to avifEncoderAddImage() to encode this layered image according to extraLayerCount, but got %u frames.", |
| 3182 | item->extraLayerCount + 1, |
| 3183 | item->encodeOutput->samples.count); |
| 3184 | return AVIF_RESULT_INVALID_ARGUMENT; |
| 3185 | } |
| 3186 | } |
| 3187 | } |
| 3188 | |
| 3189 | // ----------------------------------------------------------------------- |
| 3190 | // Harvest configuration properties from sequence headers |
| 3191 | |
| 3192 | for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) { |
| 3193 | avifEncoderItem * item = &encoder->data->items.item[itemIndex]; |
| 3194 | if (item->encodeOutput->samples.count > 0) { |
| 3195 | const avifEncodeSample * firstSample = &item->encodeOutput->samples.sample[0]; |
| 3196 | avifSequenceHeader sequenceHeader; |
| 3197 | AVIF_CHECKERR(avifSequenceHeaderParse(&sequenceHeader, (const avifROData *)&firstSample->data, codecType), |
| 3198 | avifGetErrorForItemCategory(item->itemCategory)); |
| 3199 | item->av1C = sequenceHeader.av1C; |
| 3200 | } |
| 3201 | } |
| 3202 | |
| 3203 | // ----------------------------------------------------------------------- |
| 3204 | // Begin write stream |
| 3205 | |
| 3206 | #if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) |
| 3207 | // Decide whether to go for a reduced MinimizedImageBox or a full regular MetaBox. |
| 3208 | if ((encoder->headerFormat & AVIF_HEADER_MINI) && avifEncoderIsMiniCompatible(encoder)) { |
| 3209 | AVIF_CHECKRES(avifEncoderWriteFileTypeBoxAndMiniBox(encoder, output)); |