* @brief Write a given frame to the audio stream or, if a null frame is passed, flush the stream. * * @param frame An AVFrame to be written to the stream, or nullptr to flush the stream * @param packet A (reusable) packet, used to temporarily store frame data * @param stream The stream to write to * @param outputFormatContext The output format context */
| 174 | * @param outputFormatContext The output format context |
| 175 | */ |
| 176 | void writeFrame(AVFrame *frame, AVPacket *packet, AVStream *stream, AVCodecContext* c, AVFormatContext *outputFormatContext) |
| 177 | { |
| 178 | int ret; |
| 179 | |
| 180 | #if LIBAVFORMAT_VERSION_MAJOR < 58 |
| 181 | int gotOutput; |
| 182 | av_init_packet(packet); |
| 183 | |
| 184 | do { |
| 185 | if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) |
| 186 | ret = avcodec_encode_audio2(stream->codec, packet, frame, &gotOutput); |
| 187 | else |
| 188 | ret = avcodec_encode_video2(stream->codec, packet, frame, &gotOutput); |
| 189 | |
| 190 | if (ret < 0) |
| 191 | qWarning() << "Couldn't encode audio frame: " << avErrorToQString(ret); |
| 192 | |
| 193 | else if (gotOutput) { |
| 194 | AVRational codecTimebase = stream->codec->time_base; |
| 195 | AVRational streamVideoTimebase = stream->time_base; |
| 196 | |
| 197 | av_packet_rescale_ts(packet, codecTimebase, streamVideoTimebase); |
| 198 | packet->stream_index = stream->index; |
| 199 | |
| 200 | av_interleaved_write_frame(outputFormatContext, packet); |
| 201 | av_packet_unref(packet); |
| 202 | } |
| 203 | |
| 204 | } while (gotOutput && !frame); |
| 205 | #else |
| 206 | // send the frame to the encoder |
| 207 | ret = avcodec_send_frame(c, frame); |
| 208 | |
| 209 | while (ret >= 0) { |
| 210 | ret = avcodec_receive_packet(c, packet); |
| 211 | if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) |
| 212 | break; |
| 213 | else if (ret < 0) { |
| 214 | qWarning() << "Couldn't encode audio frame: " << avErrorToQString(ret); |
| 215 | } |
| 216 | |
| 217 | /* rescale output packet timestamp values from codec to stream timebase */ |
| 218 | av_packet_rescale_ts(packet, c->time_base, stream->time_base); |
| 219 | packet->stream_index = stream->index; |
| 220 | |
| 221 | /* Write the compressed frame to the media file. */ |
| 222 | ret = av_interleaved_write_frame(outputFormatContext, packet); |
| 223 | /* pkt is now blank (av_interleaved_write_frame() takes ownership of |
| 224 | * its contents and resets pkt), so that no unreferencing is necessary. |
| 225 | * This would be different if one used av_write_frame(). */ |
| 226 | } |
| 227 | #endif |
| 228 | } |
| 229 | |
| 230 | void flushStream(AVPacket *packet, AVStream *stream, AVCodecContext* c, AVFormatContext *outputFormatContext) |
| 231 | { |
no test coverage detected