Use av_packet_alloc instead of av_init_packet.

This commit is contained in:
John Preston 2021-05-26 22:53:54 +04:00
parent 0c5258b43a
commit 49f71f4e1e
2 changed files with 24 additions and 37 deletions

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/bytes.h"
#include "base/algorithm.h"
#include <crl/crl_time.h>
@ -61,55 +62,42 @@ private:
class Packet {
public:
Packet() {
setEmpty();
}
Packet(const AVPacket &data) {
bytes::copy(_data, bytes::object_as_span(&data));
}
Packet(Packet &&other) {
bytes::copy(_data, other._data);
if (!other.empty()) {
other.release();
}
Packet() = default;
Packet(Packet &&other) : _data(base::take(other._data)) {
}
Packet &operator=(Packet &&other) {
if (this != &other) {
av_packet_unref(&fields());
bytes::copy(_data, other._data);
if (!other.empty()) {
other.release();
}
release();
_data = base::take(other._data);
}
return *this;
}
~Packet() {
av_packet_unref(&fields());
release();
}
[[nodiscard]] AVPacket &fields() {
return *reinterpret_cast<AVPacket*>(_data);
if (!_data) {
_data = av_packet_alloc();
}
return *_data;
}
[[nodiscard]] const AVPacket &fields() const {
return *reinterpret_cast<const AVPacket*>(_data);
if (!_data) {
_data = av_packet_alloc();
}
return *_data;
}
[[nodiscard]] bool empty() const {
return !fields().data;
return !_data || !fields().data;
}
void release() {
setEmpty();
av_packet_free(&_data);
}
private:
void setEmpty() {
auto &native = fields();
av_init_packet(&native);
native.data = nullptr;
native.size = 0;
}
alignas(alignof(AVPacket)) bytes::type _data[sizeof(AVPacket)];
mutable AVPacket *_data = nullptr;
};

View file

@ -736,16 +736,15 @@ bool Instance::Inner::writeFrame(AVFrame *frame) {
}
int Instance::Inner::writePackets() {
AVPacket pkt;
memset(&pkt, 0, sizeof(pkt)); // data and size must be 0;
AVPacket *pkt = av_packet_alloc();
const auto guard = gsl::finally([&] { av_packet_free(&pkt); });
int res = 0;
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
int written = 0;
do {
av_init_packet(&pkt);
if ((res = avcodec_receive_packet(d->codecContext, &pkt)) < 0) {
if ((res = avcodec_receive_packet(d->codecContext, pkt)) < 0) {
if (res == AVERROR(EAGAIN)) {
return written;
} else if (res == AVERROR_EOF) {
@ -756,16 +755,16 @@ int Instance::Inner::writePackets() {
return res;
}
av_packet_rescale_ts(&pkt, d->codecContext->time_base, d->stream->time_base);
pkt.stream_index = d->stream->index;
if ((res = av_interleaved_write_frame(d->fmtContext, &pkt)) < 0) {
av_packet_rescale_ts(pkt, d->codecContext->time_base, d->stream->time_base);
pkt->stream_index = d->stream->index;
if ((res = av_interleaved_write_frame(d->fmtContext, pkt)) < 0) {
LOG(("Audio Error: Unable to av_interleaved_write_frame for capture, error %1, %2").arg(res).arg(av_make_error_string(err, sizeof(err), res)));
fail();
return -1;
}
++written;
av_packet_unref(&pkt);
av_packet_unref(pkt);
} while (true);
return written;
}