mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
Merge remote-tracking branch 'qatar/master'
* qatar/master: rv34: add NEON rv34_idct_add rv34: 1-pass inter MB reconstruction add SMJPEG muxer avformat: split out common SMJPEG code pictordec: Use bytestream2 functions avconv: use avcodec_encode_audio2() pcmenc: use AVCodec.encode2() avcodec: bump minor version and add APIChanges for the new audio encoding API avcodec: Add avcodec_encode_audio2() as replacement for avcodec_encode_audio() avcodec: add a public function, avcodec_fill_audio_frame(). rv34: Intra 16x16 handling rv34: Inter/intra MB code split Conflicts: Changelog libavcodec/avcodec.h libavcodec/pictordec.c libavcodec/utils.c libavcodec/version.h libavcodec/x86/rv34dsp.asm libavformat/version.h Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
67f5650a78
@ -14,6 +14,7 @@ version next:
|
||||
- astreamsync audio filter
|
||||
- amerge audio filter
|
||||
- GSM audio parser
|
||||
- SMJPEG muxer
|
||||
- Automatic thread count based on detection number of (available) CPU cores
|
||||
- y41p Brooktree Uncompressed 4:1:1 12-bit encoder and decoder
|
||||
- ffprobe -show_error option
|
||||
|
205
avconv.c
205
avconv.c
@ -159,8 +159,7 @@ static float dts_delta_threshold = 10;
|
||||
static int print_stats = 1;
|
||||
|
||||
static uint8_t *audio_buf;
|
||||
static uint8_t *audio_out;
|
||||
static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
|
||||
static unsigned int allocated_audio_buf_size;
|
||||
|
||||
#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
|
||||
|
||||
@ -225,6 +224,7 @@ typedef struct OutputStream {
|
||||
AVBitStreamFilterContext *bitstream_filters;
|
||||
AVCodec *enc;
|
||||
int64_t max_frames;
|
||||
AVFrame *output_frame;
|
||||
|
||||
/* video only */
|
||||
int video_resample;
|
||||
@ -767,6 +767,13 @@ void exit_program(int ret)
|
||||
}
|
||||
output_streams[i].bitstream_filters = NULL;
|
||||
|
||||
if (output_streams[i].output_frame) {
|
||||
AVFrame *frame = output_streams[i].output_frame;
|
||||
if (frame->extended_data != frame->data)
|
||||
av_freep(&frame->extended_data);
|
||||
av_freep(&frame);
|
||||
}
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
av_freep(&output_streams[i].avfilter);
|
||||
#endif
|
||||
@ -792,8 +799,7 @@ void exit_program(int ret)
|
||||
|
||||
uninit_opts();
|
||||
av_free(audio_buf);
|
||||
av_free(audio_out);
|
||||
allocated_audio_buf_size = allocated_audio_out_size = 0;
|
||||
allocated_audio_buf_size = 0;
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
avfilter_uninit();
|
||||
@ -957,18 +963,75 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_
|
||||
memset(buf, fill_char, size);
|
||||
}
|
||||
|
||||
static int encode_audio_frame(AVFormatContext *s, OutputStream *ost,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
AVCodecContext *enc = ost->st->codec;
|
||||
AVFrame *frame = NULL;
|
||||
AVPacket pkt;
|
||||
int ret, got_packet;
|
||||
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
|
||||
if (buf) {
|
||||
if (!ost->output_frame) {
|
||||
ost->output_frame = avcodec_alloc_frame();
|
||||
if (!ost->output_frame) {
|
||||
av_log(NULL, AV_LOG_FATAL, "out-of-memory in encode_audio_frame()\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
frame = ost->output_frame;
|
||||
if (frame->extended_data != frame->data)
|
||||
av_freep(&frame->extended_data);
|
||||
avcodec_get_frame_defaults(frame);
|
||||
|
||||
frame->nb_samples = buf_size /
|
||||
(enc->channels * av_get_bytes_per_sample(enc->sample_fmt));
|
||||
if ((ret = avcodec_fill_audio_frame(frame, enc->channels, enc->sample_fmt,
|
||||
buf, buf_size, 1)) < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
|
||||
got_packet = 0;
|
||||
if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
if (got_packet) {
|
||||
pkt.stream_index = ost->index;
|
||||
if (pkt.pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
|
||||
if (pkt.duration > 0)
|
||||
pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
|
||||
|
||||
write_frame(s, &pkt, ost);
|
||||
|
||||
audio_size += pkt.size;
|
||||
}
|
||||
|
||||
if (frame)
|
||||
ost->sync_opts += frame->nb_samples;
|
||||
|
||||
return pkt.size;
|
||||
}
|
||||
|
||||
static void do_audio_out(AVFormatContext *s, OutputStream *ost,
|
||||
InputStream *ist, AVFrame *decoded_frame)
|
||||
{
|
||||
uint8_t *buftmp;
|
||||
int64_t audio_out_size, audio_buf_size;
|
||||
int64_t audio_buf_size;
|
||||
|
||||
int size_out, frame_bytes, ret, resample_changed;
|
||||
int size_out, frame_bytes, resample_changed;
|
||||
AVCodecContext *enc = ost->st->codec;
|
||||
AVCodecContext *dec = ist->st->codec;
|
||||
int osize = av_get_bytes_per_sample(enc->sample_fmt);
|
||||
int isize = av_get_bytes_per_sample(dec->sample_fmt);
|
||||
const int coded_bps = av_get_bits_per_sample(enc->codec->id);
|
||||
uint8_t *buf = decoded_frame->data[0];
|
||||
int size = decoded_frame->nb_samples * dec->channels * isize;
|
||||
int64_t allocated_for_size = size;
|
||||
@ -980,19 +1043,13 @@ need_realloc:
|
||||
audio_buf_size = FFMAX(audio_buf_size, enc->frame_size);
|
||||
audio_buf_size *= osize * enc->channels;
|
||||
|
||||
audio_out_size = FFMAX(audio_buf_size, enc->frame_size * osize * enc->channels);
|
||||
if (coded_bps > 8 * osize)
|
||||
audio_out_size = audio_out_size * coded_bps / (8*osize);
|
||||
audio_out_size += FF_MIN_BUFFER_SIZE;
|
||||
|
||||
if (audio_out_size > INT_MAX || audio_buf_size > INT_MAX) {
|
||||
if (audio_buf_size > INT_MAX) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Buffer sizes too large\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size);
|
||||
av_fast_malloc(&audio_out, &allocated_audio_out_size, audio_out_size);
|
||||
if (!audio_buf || !audio_out) {
|
||||
if (!audio_buf) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n");
|
||||
exit_program(1);
|
||||
}
|
||||
@ -1130,7 +1187,7 @@ need_realloc:
|
||||
}
|
||||
|
||||
/* now encode as many frames as possible */
|
||||
if (enc->frame_size > 1) {
|
||||
if (!(enc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
|
||||
/* output resampled raw samples */
|
||||
if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n");
|
||||
@ -1141,62 +1198,11 @@ need_realloc:
|
||||
frame_bytes = enc->frame_size * osize * enc->channels;
|
||||
|
||||
while (av_fifo_size(ost->fifo) >= frame_bytes) {
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
|
||||
|
||||
// FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
|
||||
|
||||
ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
|
||||
(short *)audio_buf);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
audio_size += ret;
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = audio_out;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
write_frame(s, &pkt, ost);
|
||||
|
||||
ost->sync_opts += enc->frame_size;
|
||||
encode_audio_frame(s, ost, audio_buf, frame_bytes);
|
||||
}
|
||||
} else {
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
ost->sync_opts += size_out / (osize * enc->channels);
|
||||
|
||||
/* output a pcm frame */
|
||||
/* determine the size of the coded buffer */
|
||||
size_out /= osize;
|
||||
if (coded_bps)
|
||||
size_out = size_out * coded_bps / 8;
|
||||
|
||||
if (size_out > audio_out_size) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Internal error, buffer size too small\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
// FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
|
||||
ret = avcodec_encode_audio(enc, audio_out, size_out,
|
||||
(short *)buftmp);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
audio_size += ret;
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = audio_out;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
write_frame(s, &pkt, ost);
|
||||
encode_audio_frame(s, ost, buftmp, size_out);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1692,6 +1698,7 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
OutputStream *ost = &ost_table[i];
|
||||
AVCodecContext *enc = ost->st->codec;
|
||||
AVFormatContext *os = output_files[ost->file_index].ctx;
|
||||
int stop_encoding = 0;
|
||||
|
||||
if (!ost->encoding_needed)
|
||||
continue;
|
||||
@ -1705,41 +1712,35 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
AVPacket pkt;
|
||||
int fifo_bytes;
|
||||
av_init_packet(&pkt);
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
|
||||
switch (ost->st->codec->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
fifo_bytes = av_fifo_size(ost->fifo);
|
||||
ret = 0;
|
||||
/* encode any samples remaining in fifo */
|
||||
if (fifo_bytes > 0) {
|
||||
int osize = av_get_bytes_per_sample(enc->sample_fmt);
|
||||
int fs_tmp = enc->frame_size;
|
||||
/* encode any samples remaining in fifo */
|
||||
int frame_bytes = fifo_bytes;
|
||||
|
||||
av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
|
||||
if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
|
||||
enc->frame_size = fifo_bytes / (osize * enc->channels);
|
||||
} else { /* pad */
|
||||
int frame_bytes = enc->frame_size*osize*enc->channels;
|
||||
|
||||
/* pad last frame with silence if needed */
|
||||
if (!(enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME)) {
|
||||
frame_bytes = enc->frame_size * enc->channels *
|
||||
av_get_bytes_per_sample(enc->sample_fmt);
|
||||
if (allocated_audio_buf_size < frame_bytes)
|
||||
exit_program(1);
|
||||
generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
|
||||
}
|
||||
|
||||
ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf);
|
||||
pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den,
|
||||
ost->st->time_base.num, enc->sample_rate);
|
||||
enc->frame_size = fs_tmp;
|
||||
encode_audio_frame(os, ost, audio_buf, frame_bytes);
|
||||
} else {
|
||||
/* flush encoder with NULL frames until it is done
|
||||
returning packets */
|
||||
if (encode_audio_frame(os, ost, NULL, 0) == 0) {
|
||||
stop_encoding = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret <= 0) {
|
||||
ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
audio_size += ret;
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
|
||||
@ -1753,18 +1754,22 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
if (ost->logfile && enc->stats_out) {
|
||||
fprintf(ost->logfile, "%s", enc->stats_out);
|
||||
}
|
||||
if (ret <= 0) {
|
||||
stop_encoding = 1;
|
||||
break;
|
||||
}
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = bit_buffer;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
write_frame(os, &pkt, ost);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
stop_encoding = 1;
|
||||
}
|
||||
|
||||
if (ret <= 0)
|
||||
if (stop_encoding)
|
||||
break;
|
||||
pkt.data = bit_buffer;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
write_frame(os, &pkt, ost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,14 @@ libavutil: 2011-04-18
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2012-xx-xx - lavc 53.34.0
|
||||
New audio encoding API:
|
||||
xxxxxxx Add CODEC_CAP_VARIABLE_FRAME_SIZE capability for use by audio
|
||||
encoders.
|
||||
xxxxxxx Add avcodec_fill_audio_frame() as a convenience function.
|
||||
xxxxxxx Add avcodec_encode_audio2() and deprecate avcodec_encode_audio().
|
||||
Add AVCodec.encode2().
|
||||
|
||||
2012-01-xx - xxxxxxx - lavfi 2.15.0
|
||||
Add a new installed header -- libavfilter/version.h -- with version macros.
|
||||
|
||||
|
@ -317,7 +317,7 @@ library:
|
||||
@tab Used in Sierra CD-ROM games.
|
||||
@item Smacker @tab @tab X
|
||||
@tab Multimedia format used by many games.
|
||||
@item SMJPEG @tab @tab X
|
||||
@item SMJPEG @tab X @tab X
|
||||
@tab Used in certain Loki game ports.
|
||||
@item Sony OpenMG (OMA) @tab X @tab X
|
||||
@tab Audio format used in Sony Sonic Stage and Sony Vegas.
|
||||
|
205
ffmpeg.c
205
ffmpeg.c
@ -176,8 +176,7 @@ static float dts_delta_threshold = 10;
|
||||
static int print_stats = 1;
|
||||
|
||||
static uint8_t *audio_buf;
|
||||
static uint8_t *audio_out;
|
||||
static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
|
||||
static unsigned int allocated_audio_buf_size;
|
||||
|
||||
static uint8_t *input_tmp= NULL;
|
||||
|
||||
@ -245,6 +244,7 @@ typedef struct OutputStream {
|
||||
AVBitStreamFilterContext *bitstream_filters;
|
||||
AVCodec *enc;
|
||||
int64_t max_frames;
|
||||
AVFrame *output_frame;
|
||||
|
||||
/* video only */
|
||||
int video_resample;
|
||||
@ -825,6 +825,13 @@ void av_noreturn exit_program(int ret)
|
||||
bsfc = next;
|
||||
}
|
||||
output_streams[i].bitstream_filters = NULL;
|
||||
|
||||
if (output_streams[i].output_frame) {
|
||||
AVFrame *frame = output_streams[i].output_frame;
|
||||
if (frame->extended_data != frame->data)
|
||||
av_freep(&frame->extended_data);
|
||||
av_freep(&frame);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nb_input_files; i++) {
|
||||
avformat_close_input(&input_files[i].ctx);
|
||||
@ -847,8 +854,7 @@ void av_noreturn exit_program(int ret)
|
||||
|
||||
uninit_opts();
|
||||
av_free(audio_buf);
|
||||
av_free(audio_out);
|
||||
allocated_audio_buf_size = allocated_audio_out_size = 0;
|
||||
allocated_audio_buf_size = 0;
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
avfilter_uninit();
|
||||
@ -1016,18 +1022,75 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_
|
||||
memset(buf, fill_char, size);
|
||||
}
|
||||
|
||||
static int encode_audio_frame(AVFormatContext *s, OutputStream *ost,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
AVCodecContext *enc = ost->st->codec;
|
||||
AVFrame *frame = NULL;
|
||||
AVPacket pkt;
|
||||
int ret, got_packet;
|
||||
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
|
||||
if (buf) {
|
||||
if (!ost->output_frame) {
|
||||
ost->output_frame = avcodec_alloc_frame();
|
||||
if (!ost->output_frame) {
|
||||
av_log(NULL, AV_LOG_FATAL, "out-of-memory in encode_audio_frame()\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
frame = ost->output_frame;
|
||||
if (frame->extended_data != frame->data)
|
||||
av_freep(&frame->extended_data);
|
||||
avcodec_get_frame_defaults(frame);
|
||||
|
||||
frame->nb_samples = buf_size /
|
||||
(enc->channels * av_get_bytes_per_sample(enc->sample_fmt));
|
||||
if ((ret = avcodec_fill_audio_frame(frame, enc->channels, enc->sample_fmt,
|
||||
buf, buf_size, 1)) < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
|
||||
got_packet = 0;
|
||||
if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
if (got_packet) {
|
||||
pkt.stream_index = ost->index;
|
||||
if (pkt.pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
|
||||
if (pkt.duration > 0)
|
||||
pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
|
||||
|
||||
write_frame(s, &pkt, ost);
|
||||
|
||||
audio_size += pkt.size;
|
||||
}
|
||||
|
||||
if (frame)
|
||||
ost->sync_opts += frame->nb_samples;
|
||||
|
||||
return pkt.size;
|
||||
}
|
||||
|
||||
static void do_audio_out(AVFormatContext *s, OutputStream *ost,
|
||||
InputStream *ist, AVFrame *decoded_frame)
|
||||
{
|
||||
uint8_t *buftmp;
|
||||
int64_t audio_out_size, audio_buf_size, size_out;
|
||||
int64_t audio_buf_size, size_out;
|
||||
|
||||
int frame_bytes, ret, resample_changed;
|
||||
int frame_bytes, resample_changed;
|
||||
AVCodecContext *enc = ost->st->codec;
|
||||
AVCodecContext *dec = ist->st->codec;
|
||||
int osize = av_get_bytes_per_sample(enc->sample_fmt);
|
||||
int isize = av_get_bytes_per_sample(dec->sample_fmt);
|
||||
const int coded_bps = av_get_bits_per_sample(enc->codec->id);
|
||||
uint8_t *buf = decoded_frame->data[0];
|
||||
int size = decoded_frame->nb_samples * dec->channels * isize;
|
||||
int64_t allocated_for_size = size;
|
||||
@ -1039,19 +1102,13 @@ need_realloc:
|
||||
audio_buf_size = FFMAX(audio_buf_size, enc->frame_size);
|
||||
audio_buf_size *= osize * enc->channels;
|
||||
|
||||
audio_out_size = FFMAX(audio_buf_size, enc->frame_size * osize * enc->channels);
|
||||
if (coded_bps > 8 * osize)
|
||||
audio_out_size = audio_out_size * coded_bps / (8*osize);
|
||||
audio_out_size += FF_MIN_BUFFER_SIZE;
|
||||
|
||||
if (audio_out_size > INT_MAX || audio_buf_size > INT_MAX) {
|
||||
if (audio_buf_size > INT_MAX) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Buffer sizes too large\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size);
|
||||
av_fast_malloc(&audio_out, &allocated_audio_out_size, audio_out_size);
|
||||
if (!audio_buf || !audio_out) {
|
||||
if (!audio_buf) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n");
|
||||
exit_program(1);
|
||||
}
|
||||
@ -1180,7 +1237,7 @@ need_realloc:
|
||||
av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
|
||||
|
||||
/* now encode as many frames as possible */
|
||||
if (enc->frame_size > 1) {
|
||||
if (!(enc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
|
||||
/* output resampled raw samples */
|
||||
if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n");
|
||||
@ -1191,62 +1248,11 @@ need_realloc:
|
||||
frame_bytes = enc->frame_size * osize * enc->channels;
|
||||
|
||||
while (av_fifo_size(ost->fifo) >= frame_bytes) {
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
|
||||
|
||||
// FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
|
||||
|
||||
ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
|
||||
(short *)audio_buf);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
audio_size += ret;
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = audio_out;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
write_frame(s, &pkt, ost);
|
||||
|
||||
ost->sync_opts += enc->frame_size;
|
||||
encode_audio_frame(s, ost, audio_buf, frame_bytes);
|
||||
}
|
||||
} else {
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
ost->sync_opts += size_out / (osize * enc->channels);
|
||||
|
||||
/* output a pcm frame */
|
||||
/* determine the size of the coded buffer */
|
||||
size_out /= osize;
|
||||
if (coded_bps)
|
||||
size_out = size_out * coded_bps / 8;
|
||||
|
||||
if (size_out > audio_out_size) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Internal error, buffer size too small\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
// FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
|
||||
ret = avcodec_encode_audio(enc, audio_out, size_out,
|
||||
(short *)buftmp);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
audio_size += ret;
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = audio_out;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
write_frame(s, &pkt, ost);
|
||||
encode_audio_frame(s, ost, buftmp, size_out);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1743,6 +1749,7 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
OutputStream *ost = &ost_table[i];
|
||||
AVCodecContext *enc = ost->st->codec;
|
||||
AVFormatContext *os = output_files[ost->file_index].ctx;
|
||||
int stop_encoding = 0;
|
||||
|
||||
if (!ost->encoding_needed)
|
||||
continue;
|
||||
@ -1756,41 +1763,35 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
AVPacket pkt;
|
||||
int fifo_bytes;
|
||||
av_init_packet(&pkt);
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
|
||||
switch (ost->st->codec->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
fifo_bytes = av_fifo_size(ost->fifo);
|
||||
ret = 0;
|
||||
/* encode any samples remaining in fifo */
|
||||
if (fifo_bytes > 0) {
|
||||
int osize = av_get_bytes_per_sample(enc->sample_fmt);
|
||||
int fs_tmp = enc->frame_size;
|
||||
/* encode any samples remaining in fifo */
|
||||
int frame_bytes = fifo_bytes;
|
||||
|
||||
av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
|
||||
if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
|
||||
enc->frame_size = fifo_bytes / (osize * enc->channels);
|
||||
} else { /* pad */
|
||||
int frame_bytes = enc->frame_size*osize*enc->channels;
|
||||
|
||||
/* pad last frame with silence if needed */
|
||||
if (!(enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME)) {
|
||||
frame_bytes = enc->frame_size * enc->channels *
|
||||
av_get_bytes_per_sample(enc->sample_fmt);
|
||||
if (allocated_audio_buf_size < frame_bytes)
|
||||
exit_program(1);
|
||||
generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
|
||||
}
|
||||
|
||||
ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf);
|
||||
pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den,
|
||||
ost->st->time_base.num, enc->sample_rate);
|
||||
enc->frame_size = fs_tmp;
|
||||
encode_audio_frame(os, ost, audio_buf, frame_bytes);
|
||||
} else {
|
||||
/* flush encoder with NULL frames until it is done
|
||||
returning packets */
|
||||
if (encode_audio_frame(os, ost, NULL, 0) == 0) {
|
||||
stop_encoding = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret <= 0) {
|
||||
ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
|
||||
}
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
|
||||
exit_program(1);
|
||||
}
|
||||
audio_size += ret;
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
|
||||
@ -1804,18 +1805,22 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
if (ost->logfile && enc->stats_out) {
|
||||
fprintf(ost->logfile, "%s", enc->stats_out);
|
||||
}
|
||||
if (ret <= 0) {
|
||||
stop_encoding = 1;
|
||||
break;
|
||||
}
|
||||
pkt.stream_index = ost->index;
|
||||
pkt.data = bit_buffer;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
write_frame(os, &pkt, ost);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
stop_encoding = 1;
|
||||
}
|
||||
|
||||
if (ret <= 0)
|
||||
if (stop_encoding)
|
||||
break;
|
||||
pkt.data = bit_buffer;
|
||||
pkt.size = ret;
|
||||
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
||||
write_frame(os, &pkt, ost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,16 +23,18 @@
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/rv34dsp.h"
|
||||
|
||||
void ff_rv34_inv_transform_neon(DCTELEM *block);
|
||||
void ff_rv34_inv_transform_noround_neon(DCTELEM *block);
|
||||
|
||||
void ff_rv34_inv_transform_dc_neon(DCTELEM *block);
|
||||
void ff_rv34_inv_transform_noround_dc_neon(DCTELEM *block);
|
||||
|
||||
void ff_rv34_idct_add_neon(uint8_t *dst, int stride, DCTELEM *block);
|
||||
void ff_rv34_idct_dc_add_neon(uint8_t *dst, int stride, int dc);
|
||||
|
||||
void ff_rv34dsp_init_neon(RV34DSPContext *c, DSPContext* dsp)
|
||||
{
|
||||
c->rv34_inv_transform_tab[0] = ff_rv34_inv_transform_neon;
|
||||
c->rv34_inv_transform_tab[1] = ff_rv34_inv_transform_noround_neon;
|
||||
c->rv34_inv_transform_dc_tab[0] = ff_rv34_inv_transform_dc_neon;
|
||||
c->rv34_inv_transform_dc_tab[1] = ff_rv34_inv_transform_noround_dc_neon;
|
||||
c->rv34_inv_transform = ff_rv34_inv_transform_noround_neon;
|
||||
c->rv34_inv_transform_dc = ff_rv34_inv_transform_noround_dc_neon;
|
||||
|
||||
c->rv34_idct_add = ff_rv34_idct_add_neon;
|
||||
c->rv34_idct_dc_add = ff_rv34_idct_dc_add_neon;
|
||||
}
|
||||
|
@ -19,13 +19,10 @@
|
||||
*/
|
||||
|
||||
#include "asm.S"
|
||||
#include "neon.S"
|
||||
|
||||
.macro rv34_inv_transform
|
||||
mov r1, #16
|
||||
vld1.16 {d28}, [r0,:64], r1 @ block[i+8*0]
|
||||
vld1.16 {d29}, [r0,:64], r1 @ block[i+8*1]
|
||||
vld1.16 {d30}, [r0,:64], r1 @ block[i+8*2]
|
||||
vld1.16 {d31}, [r0,:64], r1 @ block[i+8*3]
|
||||
.macro rv34_inv_transform r0
|
||||
vld1.16 {q14-q15}, [\r0,:128]
|
||||
vmov.s16 d0, #13
|
||||
vshll.s16 q12, d29, #3
|
||||
vshll.s16 q13, d29, #4
|
||||
@ -35,12 +32,12 @@
|
||||
vmlal.s16 q10, d30, d0
|
||||
vmull.s16 q11, d28, d0
|
||||
vmlsl.s16 q11, d30, d0
|
||||
vsubw.s16 q12, q12, d29 @ z2 = block[i+8*1]*7
|
||||
vaddw.s16 q13, q13, d29 @ z3 = block[i+8*1]*17
|
||||
vsubw.s16 q12, q12, d29 @ z2 = block[i+4*1]*7
|
||||
vaddw.s16 q13, q13, d29 @ z3 = block[i+4*1]*17
|
||||
vsubw.s16 q9, q9, d31
|
||||
vaddw.s16 q1, q1, d31
|
||||
vadd.s32 q13, q13, q9 @ z3 = 17*block[i+8*1] + 7*block[i+8*3]
|
||||
vsub.s32 q12, q12, q1 @ z2 = 7*block[i+8*1] - 17*block[i+8*3]
|
||||
vadd.s32 q13, q13, q9 @ z3 = 17*block[i+4*1] + 7*block[i+4*3]
|
||||
vsub.s32 q12, q12, q1 @ z2 = 7*block[i+4*1] - 17*block[i+4*3]
|
||||
vadd.s32 q1, q10, q13 @ z0 + z3
|
||||
vadd.s32 q2, q11, q12 @ z1 + z2
|
||||
vsub.s32 q8, q10, q13 @ z0 - z3
|
||||
@ -70,25 +67,39 @@
|
||||
vsub.s32 q15, q14, q9 @ z0 - z3
|
||||
.endm
|
||||
|
||||
/* void ff_rv34_inv_transform_neon(DCTELEM *block); */
|
||||
function ff_rv34_inv_transform_neon, export=1
|
||||
mov r2, r0
|
||||
rv34_inv_transform
|
||||
vrshrn.s32 d1, q2, #10 @ (z1 + z2) >> 10
|
||||
vrshrn.s32 d0, q1, #10 @ (z0 + z3) >> 10
|
||||
vrshrn.s32 d2, q3, #10 @ (z1 - z2) >> 10
|
||||
vrshrn.s32 d3, q15, #10 @ (z0 - z3) >> 10
|
||||
vst4.16 {d0[0], d1[0], d2[0], d3[0]}, [r2,:64], r1
|
||||
vst4.16 {d0[1], d1[1], d2[1], d3[1]}, [r2,:64], r1
|
||||
vst4.16 {d0[2], d1[2], d2[2], d3[2]}, [r2,:64], r1
|
||||
vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r2,:64], r1
|
||||
/* void rv34_idct_add_c(uint8_t *dst, int stride, DCTELEM *block) */
|
||||
function ff_rv34_idct_add_neon, export=1
|
||||
mov r3, r0
|
||||
rv34_inv_transform r2
|
||||
vmov.i16 q12, #0
|
||||
vrshrn.s32 d16, q1, #10 @ (z0 + z3) >> 10
|
||||
vrshrn.s32 d17, q2, #10 @ (z1 + z2) >> 10
|
||||
vrshrn.s32 d18, q3, #10 @ (z1 - z2) >> 10
|
||||
vrshrn.s32 d19, q15, #10 @ (z0 - z3) >> 10
|
||||
vld1.32 {d28[]}, [r0,:32], r1
|
||||
vld1.32 {d29[]}, [r0,:32], r1
|
||||
vtrn.32 q8, q9
|
||||
vld1.32 {d28[1]}, [r0,:32], r1
|
||||
vld1.32 {d29[1]}, [r0,:32], r1
|
||||
vst1.16 {q12}, [r2,:128]! @ memset(block, 0, 16)
|
||||
vst1.16 {q12}, [r2,:128] @ memset(block+16, 0, 16)
|
||||
vtrn.16 d16, d17
|
||||
vtrn.32 d28, d29
|
||||
vtrn.16 d18, d19
|
||||
vaddw.u8 q0, q8, d28
|
||||
vaddw.u8 q1, q9, d29
|
||||
vqmovun.s16 d28, q0
|
||||
vqmovun.s16 d29, q1
|
||||
vst1.32 {d28[0]}, [r3,:32], r1
|
||||
vst1.32 {d28[1]}, [r3,:32], r1
|
||||
vst1.32 {d29[0]}, [r3,:32], r1
|
||||
vst1.32 {d29[1]}, [r3,:32], r1
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
/* void rv34_inv_transform_noround_neon(DCTELEM *block); */
|
||||
function ff_rv34_inv_transform_noround_neon, export=1
|
||||
mov r2, r0
|
||||
rv34_inv_transform
|
||||
rv34_inv_transform r0
|
||||
vshl.s32 q11, q2, #1
|
||||
vshl.s32 q10, q1, #1
|
||||
vshl.s32 q12, q3, #1
|
||||
@ -101,24 +112,33 @@ function ff_rv34_inv_transform_noround_neon, export=1
|
||||
vshrn.s32 d1, q11, #11 @ (z1 + z2)*3 >> 11
|
||||
vshrn.s32 d2, q12, #11 @ (z1 - z2)*3 >> 11
|
||||
vshrn.s32 d3, q13, #11 @ (z0 - z3)*3 >> 11
|
||||
vst4.16 {d0[0], d1[0], d2[0], d3[0]}, [r2,:64], r1
|
||||
vst4.16 {d0[1], d1[1], d2[1], d3[1]}, [r2,:64], r1
|
||||
vst4.16 {d0[2], d1[2], d2[2], d3[2]}, [r2,:64], r1
|
||||
vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r2,:64], r1
|
||||
vst4.16 {d0[0], d1[0], d2[0], d3[0]}, [r0,:64]!
|
||||
vst4.16 {d0[1], d1[1], d2[1], d3[1]}, [r0,:64]!
|
||||
vst4.16 {d0[2], d1[2], d2[2], d3[2]}, [r0,:64]!
|
||||
vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r0,:64]!
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
/* void rv34_inv_transform_dc_c(DCTELEM *block) */
|
||||
function ff_rv34_inv_transform_dc_neon, export=1
|
||||
vld1.16 {d28[]}, [r0,:16] @ block[0]
|
||||
vmov.i16 d4, #169
|
||||
mov r1, #16
|
||||
vmull.s16 q3, d28, d4
|
||||
vrshrn.s32 d0, q3, #10
|
||||
vst1.16 {d0}, [r0,:64], r1
|
||||
vst1.16 {d0}, [r0,:64], r1
|
||||
vst1.16 {d0}, [r0,:64], r1
|
||||
vst1.16 {d0}, [r0,:64], r1
|
||||
/* void ff_rv34_idct_dc_add_neon(uint8_t *dst, int stride, int dc) */
|
||||
function ff_rv34_idct_dc_add_neon, export=1
|
||||
mov r3, r0
|
||||
vld1.32 {d28[]}, [r0,:32], r1
|
||||
vld1.32 {d29[]}, [r0,:32], r1
|
||||
vdup.16 d0, r2
|
||||
vmov.s16 d1, #169
|
||||
vld1.32 {d28[1]}, [r0,:32], r1
|
||||
vmull.s16 q1, d0, d1 @ dc * 13 * 13
|
||||
vld1.32 {d29[1]}, [r0,:32], r1
|
||||
vrshrn.s32 d0, q1, #10 @ (dc * 13 * 13 + 0x200) >> 10
|
||||
vmov d1, d0
|
||||
vaddw.u8 q2, q0, d28
|
||||
vaddw.u8 q3, q0, d29
|
||||
vqmovun.s16 d28, q2
|
||||
vqmovun.s16 d29, q3
|
||||
vst1.32 {d28[0]}, [r3,:32], r1
|
||||
vst1.32 {d29[0]}, [r3,:32], r1
|
||||
vst1.32 {d28[1]}, [r3,:32], r1
|
||||
vst1.32 {d29[1]}, [r3,:32], r1
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
@ -127,12 +147,10 @@ function ff_rv34_inv_transform_noround_dc_neon, export=1
|
||||
vld1.16 {d28[]}, [r0,:16] @ block[0]
|
||||
vmov.i16 d4, #251
|
||||
vorr.s16 d4, #256 @ 13^2 * 3
|
||||
mov r1, #16
|
||||
vmull.s16 q3, d28, d4
|
||||
vshrn.s32 d0, q3, #11
|
||||
vst1.64 {d0}, [r0,:64], r1
|
||||
vst1.64 {d0}, [r0,:64], r1
|
||||
vst1.64 {d0}, [r0,:64], r1
|
||||
vst1.64 {d0}, [r0,:64], r1
|
||||
vmov.i16 d1, d0
|
||||
vst1.64 {q0}, [r0,:128]!
|
||||
vst1.64 {q0}, [r0,:128]!
|
||||
bx lr
|
||||
endfunc
|
||||
|
@ -761,6 +761,11 @@ typedef struct RcOverride{
|
||||
* Encoders:
|
||||
* The encoder needs to be fed with NULL data at the end of encoding until the
|
||||
* encoder no longer returns data.
|
||||
*
|
||||
* NOTE: For encoders implementing the AVCodec.encode2() function, setting this
|
||||
* flag also means that the encoder must set the pts and duration for
|
||||
* each output packet. If this flag is not set, the pts and duration will
|
||||
* be determined by libavcodec from the input frame.
|
||||
*/
|
||||
#define CODEC_CAP_DELAY 0x0020
|
||||
/**
|
||||
@ -815,6 +820,10 @@ typedef struct RcOverride{
|
||||
* Codec supports avctx->thread_count == 0 (auto).
|
||||
*/
|
||||
#define CODEC_CAP_AUTO_THREADS 0x8000
|
||||
/**
|
||||
* Audio encoder supports receiving a different number of samples in each call.
|
||||
*/
|
||||
#define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000
|
||||
/**
|
||||
* Codec is lossless.
|
||||
*/
|
||||
@ -3314,6 +3323,19 @@ typedef struct AVCodec {
|
||||
* Initialize codec static data, called from avcodec_register().
|
||||
*/
|
||||
void (*init_static_data)(struct AVCodec *codec);
|
||||
|
||||
/**
|
||||
* Encode data to an AVPacket.
|
||||
*
|
||||
* @param avctx codec context
|
||||
* @param avpkt output AVPacket (may contain a user-provided buffer)
|
||||
* @param[in] frame AVFrame containing the raw data to be encoded
|
||||
* @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a
|
||||
* non-empty packet was returned in avpkt.
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame,
|
||||
int *got_packet_ptr);
|
||||
} AVCodec;
|
||||
|
||||
/**
|
||||
@ -4331,9 +4353,12 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
|
||||
*/
|
||||
void avsubtitle_free(AVSubtitle *sub);
|
||||
|
||||
#if FF_API_OLD_ENCODE_AUDIO
|
||||
/**
|
||||
* Encode an audio frame from samples into buf.
|
||||
*
|
||||
* @deprecated Use avcodec_encode_audio2 instead.
|
||||
*
|
||||
* @note The output buffer should be at least FF_MIN_BUFFER_SIZE bytes large.
|
||||
* However, for codecs with avctx->frame_size equal to 0 (e.g. PCM) the user
|
||||
* will know how much space is needed because it depends on the value passed
|
||||
@ -4353,8 +4378,71 @@ void avsubtitle_free(AVSubtitle *sub);
|
||||
* @return On error a negative value is returned, on success zero or the number
|
||||
* of bytes used to encode the data read from the input buffer.
|
||||
*/
|
||||
int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
|
||||
const short *samples);
|
||||
int attribute_deprecated avcodec_encode_audio(AVCodecContext *avctx,
|
||||
uint8_t *buf, int buf_size,
|
||||
const short *samples);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Encode a frame of audio.
|
||||
*
|
||||
* Takes input samples from frame and writes the next output packet, if
|
||||
* available, to avpkt. The output packet does not necessarily contain data for
|
||||
* the most recent frame, as encoders can delay, split, and combine input frames
|
||||
* internally as needed.
|
||||
*
|
||||
* @param avctx codec context
|
||||
* @param avpkt output AVPacket.
|
||||
* The user can supply an output buffer by setting
|
||||
* avpkt->data and avpkt->size prior to calling the
|
||||
* function, but if the size of the user-provided data is not
|
||||
* large enough, encoding will fail. All other AVPacket fields
|
||||
* will be reset by the encoder using av_init_packet(). If
|
||||
* avpkt->data is NULL, the encoder will allocate it.
|
||||
* The encoder will set avpkt->size to the size of the
|
||||
* output packet.
|
||||
* @param[in] frame AVFrame containing the raw audio data to be encoded.
|
||||
* May be NULL when flushing an encoder that has the
|
||||
* CODEC_CAP_DELAY capability set.
|
||||
* There are 2 codec capabilities that affect the allowed
|
||||
* values of frame->nb_samples.
|
||||
* If CODEC_CAP_SMALL_LAST_FRAME is set, then only the final
|
||||
* frame may be smaller than avctx->frame_size, and all other
|
||||
* frames must be equal to avctx->frame_size.
|
||||
* If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame
|
||||
* can have any number of samples.
|
||||
* If neither is set, frame->nb_samples must be equal to
|
||||
* avctx->frame_size for all frames.
|
||||
* @param[out] got_packet_ptr This field is set to 1 by libavcodec if the
|
||||
* output packet is non-empty, and to 0 if it is
|
||||
* empty. If the function returns an error, the
|
||||
* packet can be assumed to be invalid, and the
|
||||
* value of got_packet_ptr is undefined and should
|
||||
* not be used.
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
const AVFrame *frame, int *got_packet_ptr);
|
||||
|
||||
/**
|
||||
* Fill audio frame data and linesize.
|
||||
* AVFrame extended_data channel pointers are allocated if necessary for
|
||||
* planar audio.
|
||||
*
|
||||
* @param frame the AVFrame
|
||||
* frame->nb_samples must be set prior to calling the
|
||||
* function. This function fills in frame->data,
|
||||
* frame->extended_data, frame->linesize[0].
|
||||
* @param nb_channels channel count
|
||||
* @param sample_fmt sample format
|
||||
* @param buf buffer to use for frame data
|
||||
* @param buf_size size of buffer
|
||||
* @param align plane size sample alignment
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
|
||||
enum AVSampleFormat sample_fmt, const uint8_t *buf,
|
||||
int buf_size, int align);
|
||||
|
||||
/**
|
||||
* Encode a video frame from pict into buf.
|
||||
|
@ -61,6 +61,14 @@ typedef struct AVCodecInternal {
|
||||
* should be freed from the original context only.
|
||||
*/
|
||||
int is_copy;
|
||||
|
||||
#if FF_API_OLD_DECODE_AUDIO
|
||||
/**
|
||||
* Internal sample count used by avcodec_encode_audio() to fabricate pts.
|
||||
* Can be removed along with avcodec_encode_audio().
|
||||
*/
|
||||
int sample_count;
|
||||
#endif
|
||||
} AVCodecInternal;
|
||||
|
||||
struct AVCodecDefault {
|
||||
@ -111,4 +119,21 @@ int avpriv_unlock_avformat(void);
|
||||
*/
|
||||
#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE)
|
||||
|
||||
/**
|
||||
* Check AVPacket size and/or allocate data.
|
||||
*
|
||||
* Encoders supporting AVCodec.encode2() can use this as a convenience to
|
||||
* ensure the output packet data is large enough, whether provided by the user
|
||||
* or allocated in this function.
|
||||
*
|
||||
* @param avpkt the AVPacket
|
||||
* If avpkt->data is already set, avpkt->size is checked
|
||||
* to ensure it is large enough.
|
||||
* If avpkt->data is NULL, a new buffer is allocated.
|
||||
* All other AVPacket fields will be reset with av_init_packet().
|
||||
* @param size the minimum required packet size
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int ff_alloc_packet(AVPacket *avpkt, int size);
|
||||
|
||||
#endif /* AVCODEC_INTERNAL_H */
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "avcodec.h"
|
||||
#include "libavutil/common.h" /* for av_reverse */
|
||||
#include "bytestream.h"
|
||||
#include "internal.h"
|
||||
#include "pcm_tablegen.h"
|
||||
|
||||
#define MAX_CHANNELS 64
|
||||
@ -77,10 +78,10 @@ static av_cold int pcm_encode_close(AVCodecContext *avctx)
|
||||
bytestream_put_##endian(&dst, v); \
|
||||
}
|
||||
|
||||
static int pcm_encode_frame(AVCodecContext *avctx,
|
||||
unsigned char *frame, int buf_size, void *data)
|
||||
static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
const AVFrame *frame, int *got_packet_ptr)
|
||||
{
|
||||
int n, sample_size, v;
|
||||
int n, sample_size, v, ret;
|
||||
const short *samples;
|
||||
unsigned char *dst;
|
||||
const uint8_t *srcu8;
|
||||
@ -91,9 +92,14 @@ static int pcm_encode_frame(AVCodecContext *avctx,
|
||||
const uint32_t *samples_uint32_t;
|
||||
|
||||
sample_size = av_get_bits_per_sample(avctx->codec->id)/8;
|
||||
n = buf_size / sample_size;
|
||||
samples = data;
|
||||
dst = frame;
|
||||
n = frame->nb_samples * avctx->channels;
|
||||
samples = (const short *)frame->data[0];
|
||||
|
||||
if ((ret = ff_alloc_packet(avpkt, n * sample_size))) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
|
||||
return ret;
|
||||
}
|
||||
dst = avpkt->data;
|
||||
|
||||
switch(avctx->codec->id) {
|
||||
case CODEC_ID_PCM_U32LE:
|
||||
@ -130,7 +136,7 @@ static int pcm_encode_frame(AVCodecContext *avctx,
|
||||
ENCODE(uint16_t, be16, samples, dst, n, 0, 0x8000)
|
||||
break;
|
||||
case CODEC_ID_PCM_S8:
|
||||
srcu8= data;
|
||||
srcu8 = frame->data[0];
|
||||
for(;n>0;n--) {
|
||||
v = *srcu8++;
|
||||
*dst++ = v - 128;
|
||||
@ -186,9 +192,10 @@ static int pcm_encode_frame(AVCodecContext *avctx,
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
//avctx->frame_size = (dst - frame) / (sample_size * avctx->channels);
|
||||
|
||||
return dst - frame;
|
||||
avpkt->size = frame->nb_samples * avctx->channels * sample_size;
|
||||
*got_packet_ptr = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct PCMDecode {
|
||||
@ -474,8 +481,9 @@ AVCodec ff_ ## name_ ## _encoder = { \
|
||||
.type = AVMEDIA_TYPE_AUDIO, \
|
||||
.id = id_, \
|
||||
.init = pcm_encode_init, \
|
||||
.encode = pcm_encode_frame, \
|
||||
.encode2 = pcm_encode_frame, \
|
||||
.close = pcm_encode_close, \
|
||||
.capabilities = CODEC_CAP_VARIABLE_FRAME_SIZE, \
|
||||
.sample_fmts = (const enum AVSampleFormat[]){sample_fmt_,AV_SAMPLE_FMT_NONE}, \
|
||||
.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ typedef struct PicContext {
|
||||
AVFrame frame;
|
||||
int width, height;
|
||||
int nb_planes;
|
||||
GetByteContext g;
|
||||
} PicContext;
|
||||
|
||||
static void picmemset_8bpp(PicContext *s, int value, int run, int *x, int *y)
|
||||
@ -55,7 +56,8 @@ static void picmemset_8bpp(PicContext *s, int value, int run, int *x, int *y)
|
||||
}
|
||||
}
|
||||
|
||||
static void picmemset(PicContext *s, int value, int run, int *x, int *y, int *plane, int bits_per_plane)
|
||||
static void picmemset(PicContext *s, int value, int run,
|
||||
int *x, int *y, int *plane, int bits_per_plane)
|
||||
{
|
||||
uint8_t *d;
|
||||
int shift = *plane * bits_per_plane;
|
||||
@ -107,34 +109,35 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
PicContext *s = avctx->priv_data;
|
||||
int buf_size = avpkt->size;
|
||||
const uint8_t *buf = avpkt->data;
|
||||
const uint8_t *buf_end = avpkt->data + buf_size;
|
||||
uint32_t *palette;
|
||||
int bits_per_plane, bpp, etype, esize, npal;
|
||||
int i, x, y, plane;
|
||||
int bits_per_plane, bpp, etype, esize, npal, pos_after_pal;
|
||||
int i, x, y, plane, tmp;
|
||||
|
||||
if (buf_size < 11)
|
||||
bytestream2_init(&s->g, avpkt->data, avpkt->size);
|
||||
|
||||
if (bytestream2_get_bytes_left(&s->g) < 11)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
if (bytestream_get_le16(&buf) != 0x1234)
|
||||
if (bytestream2_get_le16u(&s->g) != 0x1234)
|
||||
return AVERROR_INVALIDDATA;
|
||||
s->width = bytestream_get_le16(&buf);
|
||||
s->height = bytestream_get_le16(&buf);
|
||||
buf += 4;
|
||||
bits_per_plane = *buf & 0xF;
|
||||
s->nb_planes = (*buf++ >> 4) + 1;
|
||||
bpp = s->nb_planes ? bits_per_plane*s->nb_planes : bits_per_plane;
|
||||
|
||||
s->width = bytestream2_get_le16u(&s->g);
|
||||
s->height = bytestream2_get_le16u(&s->g);
|
||||
bytestream2_skip(&s->g, 4);
|
||||
tmp = bytestream2_get_byteu(&s->g);
|
||||
bits_per_plane = tmp & 0xF;
|
||||
s->nb_planes = (tmp >> 4) + 1;
|
||||
bpp = bits_per_plane * s->nb_planes;
|
||||
if (bits_per_plane > 8 || bpp < 1 || bpp > 32) {
|
||||
av_log_ask_for_sample(avctx, "unsupported bit depth\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (*buf == 0xFF || bpp == 8) {
|
||||
buf += 2;
|
||||
etype = bytestream_get_le16(&buf);
|
||||
esize = bytestream_get_le16(&buf);
|
||||
if (buf_end - buf < esize)
|
||||
if (bytestream2_peek_byte(&s->g) == 0xFF || bpp == 8) {
|
||||
bytestream2_skip(&s->g, 2);
|
||||
etype = bytestream2_get_le16(&s->g);
|
||||
esize = bytestream2_get_le16(&s->g);
|
||||
if (bytestream2_get_bytes_left(&s->g) < esize)
|
||||
return AVERROR_INVALIDDATA;
|
||||
} else {
|
||||
etype = -1;
|
||||
@ -159,25 +162,30 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
s->frame.pict_type = AV_PICTURE_TYPE_I;
|
||||
s->frame.palette_has_changed = 1;
|
||||
|
||||
pos_after_pal = bytestream2_tell(&s->g) + esize;
|
||||
palette = (uint32_t*)s->frame.data[1];
|
||||
if (etype == 1 && esize > 1 && *buf < 6) {
|
||||
int idx = *buf;
|
||||
if (etype == 1 && esize > 1 && bytestream2_peek_byte(&s->g) < 6) {
|
||||
int idx = bytestream2_get_byte(&s->g);
|
||||
npal = 4;
|
||||
for (i = 0; i < npal; i++)
|
||||
palette[i] = ff_cga_palette[ cga_mode45_index[idx][i] ];
|
||||
} else if (etype == 2) {
|
||||
npal = FFMIN(esize, 16);
|
||||
for (i = 0; i < npal; i++)
|
||||
palette[i] = ff_cga_palette[ FFMIN(buf[i], 16)];
|
||||
for (i = 0; i < npal; i++) {
|
||||
int pal_idx = bytestream2_get_byte(&s->g);
|
||||
palette[i] = ff_cga_palette[FFMIN(pal_idx, 16)];
|
||||
}
|
||||
} else if (etype == 3) {
|
||||
npal = FFMIN(esize, 16);
|
||||
for (i = 0; i < npal; i++)
|
||||
palette[i] = ff_ega_palette[ FFMIN(buf[i], 63)];
|
||||
for (i = 0; i < npal; i++) {
|
||||
int pal_idx = bytestream2_get_byte(&s->g);
|
||||
palette[i] = ff_ega_palette[FFMIN(pal_idx, 63)];
|
||||
}
|
||||
} else if (etype == 4 || etype == 5) {
|
||||
npal = FFMIN(esize / 3, 256);
|
||||
for (i = 0; i < npal; i++) {
|
||||
palette[i] = AV_RB24(buf + i*3) << 2;
|
||||
palette[i] |= 0xFF << 24 | palette[i] >> 6 & 0x30303;
|
||||
palette[i] = bytestream2_get_be24(&s->g) << 2;
|
||||
palette[i] |= 0xFFU << 24 | palette[i] >> 6 & 0x30303;
|
||||
}
|
||||
} else {
|
||||
if (bpp == 1) {
|
||||
@ -195,29 +203,34 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
}
|
||||
// fill remaining palette entries
|
||||
memset(palette + npal, 0, AVPALETTE_SIZE - npal * 4);
|
||||
buf += esize;
|
||||
|
||||
// skip remaining palette bytes
|
||||
bytestream2_seek(&s->g, pos_after_pal, SEEK_SET);
|
||||
|
||||
y = s->height - 1;
|
||||
if (bytestream_get_le16(&buf)) {
|
||||
if (bytestream2_get_le16(&s->g)) {
|
||||
x = 0;
|
||||
plane = 0;
|
||||
while (y >= 0 && buf_end - buf >= 6) {
|
||||
const uint8_t *buf_pend = buf + FFMIN(AV_RL16(buf), buf_end - buf);
|
||||
//ignore uncompressed block size reported at buf[2]
|
||||
int marker = buf[4];
|
||||
buf += 5;
|
||||
while (y >= 0 && bytestream2_get_bytes_left(&s->g) >= 6) {
|
||||
int stop_size, marker, t1, t2;
|
||||
|
||||
while (plane < s->nb_planes && y >= 0 && buf_pend - buf >= 1) {
|
||||
t1 = bytestream2_get_bytes_left(&s->g);
|
||||
t2 = bytestream2_get_le16(&s->g);
|
||||
stop_size = t1 - FFMIN(t1, t2);
|
||||
// ignore uncompressed block size
|
||||
bytestream2_skip(&s->g, 2);
|
||||
marker = bytestream2_get_byte(&s->g);
|
||||
|
||||
while (plane < s->nb_planes && y >= 0 &&
|
||||
bytestream2_get_bytes_left(&s->g) > stop_size) {
|
||||
int run = 1;
|
||||
int val = *buf++;
|
||||
int val = bytestream2_get_byte(&s->g);
|
||||
if (val == marker) {
|
||||
run = *buf++;
|
||||
run = bytestream2_get_byte(&s->g);
|
||||
if (run == 0)
|
||||
run = bytestream_get_le16(&buf);
|
||||
val = *buf++;
|
||||
run = bytestream2_get_le16(&s->g);
|
||||
val = bytestream2_get_byte(&s->g);
|
||||
}
|
||||
if (buf > buf_end)
|
||||
if (!bytestream2_get_bytes_left(&s->g))
|
||||
break;
|
||||
|
||||
if (bits_per_plane == 8) {
|
||||
@ -228,16 +241,16 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (y >= 0 && buf < buf_end) {
|
||||
memcpy(s->frame.data[0] + y * s->frame.linesize[0], buf, FFMIN(avctx->width, buf_end - buf));
|
||||
buf += avctx->width;
|
||||
while (y >= 0 && bytestream2_get_bytes_left(&s->g) > 0) {
|
||||
memcpy(s->frame.data[0] + y * s->frame.linesize[0], s->g.buffer, FFMIN(avctx->width, bytestream2_get_bytes_left(&s->g)));
|
||||
bytestream2_skip(&s->g, avctx->width);
|
||||
y--;
|
||||
}
|
||||
}
|
||||
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame*)data = s->frame;
|
||||
return buf_size;
|
||||
return avpkt->size;
|
||||
}
|
||||
|
||||
static av_cold int decode_end(AVCodecContext *avctx)
|
||||
|
@ -240,15 +240,15 @@ static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2,
|
||||
{
|
||||
int flags = modulo_three_table[code];
|
||||
|
||||
decode_coeff( dst+0, (flags >> 6) , 3, gb, vlc, q);
|
||||
decode_coeff( dst+0*4+0, (flags >> 6) , 3, gb, vlc, q);
|
||||
if(is_block2){
|
||||
decode_coeff(dst+8, (flags >> 4) & 3, 2, gb, vlc, q);
|
||||
decode_coeff(dst+1, (flags >> 2) & 3, 2, gb, vlc, q);
|
||||
decode_coeff(dst+1*4+0, (flags >> 4) & 3, 2, gb, vlc, q);
|
||||
decode_coeff(dst+0*4+1, (flags >> 2) & 3, 2, gb, vlc, q);
|
||||
}else{
|
||||
decode_coeff(dst+1, (flags >> 4) & 3, 2, gb, vlc, q);
|
||||
decode_coeff(dst+8, (flags >> 2) & 3, 2, gb, vlc, q);
|
||||
decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q);
|
||||
decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q);
|
||||
}
|
||||
decode_coeff( dst+9, (flags >> 0) & 3, 2, gb, vlc, q);
|
||||
decode_coeff( dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,15 +265,15 @@ static inline void decode_subblock3(DCTELEM *dst, int code, const int is_block2,
|
||||
{
|
||||
int flags = modulo_three_table[code];
|
||||
|
||||
decode_coeff( dst+0, (flags >> 6) , 3, gb, vlc, q_dc);
|
||||
decode_coeff( dst+0*4+0, (flags >> 6) , 3, gb, vlc, q_dc);
|
||||
if(is_block2){
|
||||
decode_coeff(dst+8, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
|
||||
decode_coeff(dst+1, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
|
||||
decode_coeff(dst+1*4+0, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
|
||||
decode_coeff(dst+0*4+1, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
|
||||
}else{
|
||||
decode_coeff(dst+1, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
|
||||
decode_coeff(dst+8, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
|
||||
decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
|
||||
decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
|
||||
}
|
||||
decode_coeff( dst+9, (flags >> 0) & 3, 2, gb, vlc, q_ac2);
|
||||
decode_coeff( dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q_ac2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -308,15 +308,15 @@ static inline int rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rv
|
||||
|
||||
if(pattern & 4){
|
||||
code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2);
|
||||
decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient, q_ac2);
|
||||
decode_subblock(dst + 4*0+2, code, 0, gb, &rvlc->coefficient, q_ac2);
|
||||
}
|
||||
if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block
|
||||
code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2);
|
||||
decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient, q_ac2);
|
||||
decode_subblock(dst + 4*2+0, code, 1, gb, &rvlc->coefficient, q_ac2);
|
||||
}
|
||||
if(pattern & 1){
|
||||
code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2);
|
||||
decode_subblock(dst + 8*2+2, code, 0, gb, &rvlc->coefficient, q_ac2);
|
||||
decode_subblock(dst + 4*2+2, code, 0, gb, &rvlc->coefficient, q_ac2);
|
||||
}
|
||||
return has_ac || pattern;
|
||||
}
|
||||
@ -351,44 +351,70 @@ static inline RV34VLC* choose_vlc_set(int quant, int mod, int type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode macroblock header and return CBP in case of success, -1 otherwise.
|
||||
* Decode intra macroblock header and return CBP in case of success, -1 otherwise.
|
||||
*/
|
||||
static int rv34_decode_mb_header(RV34DecContext *r, int8_t *intra_types)
|
||||
static int rv34_decode_intra_mb_header(RV34DecContext *r, int8_t *intra_types)
|
||||
{
|
||||
MpegEncContext *s = &r->s;
|
||||
GetBitContext *gb = &s->gb;
|
||||
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
|
||||
int t;
|
||||
|
||||
r->is16 = get_bits1(gb);
|
||||
if(r->is16){
|
||||
s->current_picture_ptr->f.mb_type[mb_pos] = MB_TYPE_INTRA16x16;
|
||||
r->block_type = RV34_MB_TYPE_INTRA16x16;
|
||||
t = get_bits(gb, 2);
|
||||
fill_rectangle(intra_types, 4, 4, r->intra_types_stride, t, sizeof(intra_types[0]));
|
||||
r->luma_vlc = 2;
|
||||
}else{
|
||||
if(!r->rv30){
|
||||
if(!get_bits1(gb))
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Need DQUANT\n");
|
||||
}
|
||||
s->current_picture_ptr->f.mb_type[mb_pos] = MB_TYPE_INTRA;
|
||||
r->block_type = RV34_MB_TYPE_INTRA;
|
||||
if(r->decode_intra_types(r, gb, intra_types) < 0)
|
||||
return -1;
|
||||
r->luma_vlc = 1;
|
||||
}
|
||||
|
||||
r->chroma_vlc = 0;
|
||||
r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0);
|
||||
|
||||
return rv34_decode_cbp(gb, r->cur_vlcs, r->is16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode inter macroblock header and return CBP in case of success, -1 otherwise.
|
||||
*/
|
||||
static int rv34_decode_inter_mb_header(RV34DecContext *r, int8_t *intra_types)
|
||||
{
|
||||
MpegEncContext *s = &r->s;
|
||||
GetBitContext *gb = &s->gb;
|
||||
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
|
||||
int i, t;
|
||||
|
||||
if(!r->si.type){
|
||||
r->is16 = get_bits1(gb);
|
||||
if(!r->is16 && !r->rv30){
|
||||
if(!get_bits1(gb))
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Need DQUANT\n");
|
||||
}
|
||||
s->current_picture_ptr->f.mb_type[mb_pos] = r->is16 ? MB_TYPE_INTRA16x16 : MB_TYPE_INTRA;
|
||||
r->block_type = r->is16 ? RV34_MB_TYPE_INTRA16x16 : RV34_MB_TYPE_INTRA;
|
||||
}else{
|
||||
r->block_type = r->decode_mb_info(r);
|
||||
if(r->block_type == -1)
|
||||
return -1;
|
||||
s->current_picture_ptr->f.mb_type[mb_pos] = rv34_mb_type_to_lavc[r->block_type];
|
||||
r->mb_type[mb_pos] = r->block_type;
|
||||
if(r->block_type == RV34_MB_SKIP){
|
||||
if(s->pict_type == AV_PICTURE_TYPE_P)
|
||||
r->mb_type[mb_pos] = RV34_MB_P_16x16;
|
||||
if(s->pict_type == AV_PICTURE_TYPE_B)
|
||||
r->mb_type[mb_pos] = RV34_MB_B_DIRECT;
|
||||
}
|
||||
r->is16 = !!IS_INTRA16x16(s->current_picture_ptr->f.mb_type[mb_pos]);
|
||||
rv34_decode_mv(r, r->block_type);
|
||||
if(r->block_type == RV34_MB_SKIP){
|
||||
fill_rectangle(intra_types, 4, 4, r->intra_types_stride, 0, sizeof(intra_types[0]));
|
||||
return 0;
|
||||
}
|
||||
r->chroma_vlc = 1;
|
||||
r->luma_vlc = 0;
|
||||
r->block_type = r->decode_mb_info(r);
|
||||
if(r->block_type == -1)
|
||||
return -1;
|
||||
s->current_picture_ptr->f.mb_type[mb_pos] = rv34_mb_type_to_lavc[r->block_type];
|
||||
r->mb_type[mb_pos] = r->block_type;
|
||||
if(r->block_type == RV34_MB_SKIP){
|
||||
if(s->pict_type == AV_PICTURE_TYPE_P)
|
||||
r->mb_type[mb_pos] = RV34_MB_P_16x16;
|
||||
if(s->pict_type == AV_PICTURE_TYPE_B)
|
||||
r->mb_type[mb_pos] = RV34_MB_B_DIRECT;
|
||||
}
|
||||
r->is16 = !!IS_INTRA16x16(s->current_picture_ptr->f.mb_type[mb_pos]);
|
||||
rv34_decode_mv(r, r->block_type);
|
||||
if(r->block_type == RV34_MB_SKIP){
|
||||
fill_rectangle(intra_types, 4, 4, r->intra_types_stride, 0, sizeof(intra_types[0]));
|
||||
return 0;
|
||||
}
|
||||
r->chroma_vlc = 1;
|
||||
r->luma_vlc = 0;
|
||||
|
||||
if(IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos])){
|
||||
if(r->is16){
|
||||
t = get_bits(gb, 2);
|
||||
@ -956,15 +982,6 @@ static void rv34_pred_4x4_block(RV34DecContext *r, uint8_t *dst, int stride, int
|
||||
r->h.pred4x4[itype](dst, prev, stride);
|
||||
}
|
||||
|
||||
/** add_pixels_clamped for 4x4 block */
|
||||
static void rv34_add_4x4_block(uint8_t *dst, int stride, DCTELEM block[64], int off)
|
||||
{
|
||||
int x, y;
|
||||
for(y = 0; y < 4; y++)
|
||||
for(x = 0; x < 4; x++)
|
||||
dst[x + y*stride] = av_clip_uint8(dst[x + y*stride] + block[off + x+y*8]);
|
||||
}
|
||||
|
||||
static inline int adjust_pred16(int itype, int up, int left)
|
||||
{
|
||||
if(!up && !left)
|
||||
@ -981,15 +998,35 @@ static inline int adjust_pred16(int itype, int up, int left)
|
||||
return itype;
|
||||
}
|
||||
|
||||
static void rv34_output_macroblock(RV34DecContext *r, int8_t *intra_types, int cbp, int is16)
|
||||
static inline void rv34_process_block(RV34DecContext *r,
|
||||
uint8_t *pdst, int stride,
|
||||
int fc, int sc, int q_dc, int q_ac)
|
||||
{
|
||||
MpegEncContext *s = &r->s;
|
||||
DSPContext *dsp = &s->dsp;
|
||||
int i, j;
|
||||
uint8_t *Y, *U, *V;
|
||||
int itype;
|
||||
int avail[6*8] = {0};
|
||||
int idx;
|
||||
DCTELEM *ptr = s->block[0];
|
||||
int has_ac = rv34_decode_block(ptr, &s->gb, r->cur_vlcs,
|
||||
fc, sc, q_dc, q_ac, q_ac);
|
||||
if(has_ac){
|
||||
r->rdsp.rv34_idct_add(pdst, stride, ptr);
|
||||
}else{
|
||||
r->rdsp.rv34_idct_dc_add(pdst, stride, ptr[0]);
|
||||
ptr[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void rv34_output_i16x16(RV34DecContext *r, int8_t *intra_types, int cbp)
|
||||
{
|
||||
LOCAL_ALIGNED_16(DCTELEM, block16, [16]);
|
||||
MpegEncContext *s = &r->s;
|
||||
GetBitContext *gb = &s->gb;
|
||||
int q_dc = rv34_qscale_tab[ r->luma_dc_quant_i[s->qscale] ],
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
uint8_t *dst = s->dest[0];
|
||||
DCTELEM *ptr = s->block[0];
|
||||
int avail[6*8] = {0};
|
||||
int i, j, itype, has_ac;
|
||||
|
||||
memset(block16, 0, 16 * sizeof(*block16));
|
||||
|
||||
// Set neighbour information.
|
||||
if(r->avail_cache[1])
|
||||
@ -1005,80 +1042,118 @@ static void rv34_output_macroblock(RV34DecContext *r, int8_t *intra_types, int c
|
||||
if(r->avail_cache[9])
|
||||
avail[24] = avail[32] = 1;
|
||||
|
||||
Y = s->dest[0];
|
||||
U = s->dest[1];
|
||||
V = s->dest[2];
|
||||
if(!is16){
|
||||
for(j = 0; j < 4; j++){
|
||||
idx = 9 + j*8;
|
||||
for(i = 0; i < 4; i++, cbp >>= 1, Y += 4, idx++){
|
||||
rv34_pred_4x4_block(r, Y, s->linesize, ittrans[intra_types[i]], avail[idx-8], avail[idx-1], avail[idx+7], avail[idx-7]);
|
||||
avail[idx] = 1;
|
||||
if(cbp & 1)
|
||||
rv34_add_4x4_block(Y, s->linesize, s->block[(i>>1)+(j&2)], (i&1)*4+(j&1)*32);
|
||||
}
|
||||
Y += s->linesize * 4 - 4*4;
|
||||
intra_types += r->intra_types_stride;
|
||||
}
|
||||
intra_types -= r->intra_types_stride * 4;
|
||||
fill_rectangle(r->avail_cache + 6, 2, 2, 4, 0, 4);
|
||||
for(j = 0; j < 2; j++){
|
||||
idx = 6 + j*4;
|
||||
for(i = 0; i < 2; i++, cbp >>= 1, idx++){
|
||||
rv34_pred_4x4_block(r, U + i*4 + j*4*s->uvlinesize, s->uvlinesize, ittrans[intra_types[i*2+j*2*r->intra_types_stride]], r->avail_cache[idx-4], r->avail_cache[idx-1], !i && !j, r->avail_cache[idx-3]);
|
||||
rv34_pred_4x4_block(r, V + i*4 + j*4*s->uvlinesize, s->uvlinesize, ittrans[intra_types[i*2+j*2*r->intra_types_stride]], r->avail_cache[idx-4], r->avail_cache[idx-1], !i && !j, r->avail_cache[idx-3]);
|
||||
r->avail_cache[idx] = 1;
|
||||
if(cbp & 0x01)
|
||||
rv34_add_4x4_block(U + i*4 + j*4*s->uvlinesize, s->uvlinesize, s->block[4], i*4+j*32);
|
||||
if(cbp & 0x10)
|
||||
rv34_add_4x4_block(V + i*4 + j*4*s->uvlinesize, s->uvlinesize, s->block[5], i*4+j*32);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
itype = ittrans16[intra_types[0]];
|
||||
itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
|
||||
r->h.pred16x16[itype](Y, s->linesize);
|
||||
dsp->add_pixels_clamped(s->block[0], Y, s->linesize);
|
||||
dsp->add_pixels_clamped(s->block[1], Y + 8, s->linesize);
|
||||
Y += s->linesize * 8;
|
||||
dsp->add_pixels_clamped(s->block[2], Y, s->linesize);
|
||||
dsp->add_pixels_clamped(s->block[3], Y + 8, s->linesize);
|
||||
has_ac = rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac);
|
||||
if(has_ac)
|
||||
r->rdsp.rv34_inv_transform(block16);
|
||||
else
|
||||
r->rdsp.rv34_inv_transform_dc(block16);
|
||||
|
||||
itype = ittrans16[intra_types[0]];
|
||||
if(itype == PLANE_PRED8x8) itype = DC_PRED8x8;
|
||||
itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
|
||||
r->h.pred8x8[itype](U, s->uvlinesize);
|
||||
dsp->add_pixels_clamped(s->block[4], U, s->uvlinesize);
|
||||
r->h.pred8x8[itype](V, s->uvlinesize);
|
||||
dsp->add_pixels_clamped(s->block[5], V, s->uvlinesize);
|
||||
itype = ittrans16[intra_types[0]];
|
||||
itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
|
||||
r->h.pred16x16[itype](dst, s->linesize);
|
||||
|
||||
for(j = 0; j < 4; j++){
|
||||
for(i = 0; i < 4; i++, cbp >>= 1){
|
||||
int dc = block16[i + j*4];
|
||||
|
||||
if(cbp & 1){
|
||||
has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
|
||||
}else
|
||||
has_ac = 0;
|
||||
|
||||
if(has_ac){
|
||||
ptr[0] = dc;
|
||||
r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr);
|
||||
}else
|
||||
r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc);
|
||||
}
|
||||
|
||||
dst += 4*s->linesize;
|
||||
}
|
||||
|
||||
itype = ittrans16[intra_types[0]];
|
||||
if(itype == PLANE_PRED8x8) itype = DC_PRED8x8;
|
||||
itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
|
||||
|
||||
q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
|
||||
q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
|
||||
|
||||
for(j = 1; j < 3; j++){
|
||||
dst = s->dest[j];
|
||||
r->h.pred8x8[itype](dst, s->uvlinesize);
|
||||
for(i = 0; i < 4; i++, cbp >>= 1){
|
||||
uint8_t *pdst;
|
||||
if(!(cbp & 1)) continue;
|
||||
pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize;
|
||||
|
||||
rv34_process_block(r, pdst, s->uvlinesize,
|
||||
r->chroma_vlc, 1, q_dc, q_ac);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mask for retrieving all bits in coded block pattern
|
||||
* corresponding to one 8x8 block
|
||||
*/
|
||||
#define LUMA_CBP_BLOCK_MASK 0x33
|
||||
|
||||
#define U_CBP_MASK 0x0F0000
|
||||
#define V_CBP_MASK 0xF00000
|
||||
|
||||
/** @} */ // recons group
|
||||
|
||||
|
||||
static void rv34_apply_differences(RV34DecContext *r, int cbp)
|
||||
static void rv34_output_intra(RV34DecContext *r, int8_t *intra_types, int cbp)
|
||||
{
|
||||
static const int shifts[4] = { 0, 2, 8, 10 };
|
||||
MpegEncContext *s = &r->s;
|
||||
int i;
|
||||
MpegEncContext *s = &r->s;
|
||||
uint8_t *dst = s->dest[0];
|
||||
int avail[6*8] = {0};
|
||||
int i, j, k;
|
||||
int idx, q_ac, q_dc;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
if((cbp & (LUMA_CBP_BLOCK_MASK << shifts[i])) || r->block_type == RV34_MB_P_MIX16x16)
|
||||
s->dsp.add_pixels_clamped(s->block[i], s->dest[0] + (i & 1)*8 + (i&2)*4*s->linesize, s->linesize);
|
||||
if(cbp & U_CBP_MASK)
|
||||
s->dsp.add_pixels_clamped(s->block[4], s->dest[1], s->uvlinesize);
|
||||
if(cbp & V_CBP_MASK)
|
||||
s->dsp.add_pixels_clamped(s->block[5], s->dest[2], s->uvlinesize);
|
||||
// Set neighbour information.
|
||||
if(r->avail_cache[1])
|
||||
avail[0] = 1;
|
||||
if(r->avail_cache[2])
|
||||
avail[1] = avail[2] = 1;
|
||||
if(r->avail_cache[3])
|
||||
avail[3] = avail[4] = 1;
|
||||
if(r->avail_cache[4])
|
||||
avail[5] = 1;
|
||||
if(r->avail_cache[5])
|
||||
avail[8] = avail[16] = 1;
|
||||
if(r->avail_cache[9])
|
||||
avail[24] = avail[32] = 1;
|
||||
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
for(j = 0; j < 4; j++){
|
||||
idx = 9 + j*8;
|
||||
for(i = 0; i < 4; i++, cbp >>= 1, dst += 4, idx++){
|
||||
rv34_pred_4x4_block(r, dst, s->linesize, ittrans[intra_types[i]], avail[idx-8], avail[idx-1], avail[idx+7], avail[idx-7]);
|
||||
avail[idx] = 1;
|
||||
if(!(cbp & 1)) continue;
|
||||
|
||||
rv34_process_block(r, dst, s->linesize,
|
||||
r->luma_vlc, 0, q_ac, q_ac);
|
||||
}
|
||||
dst += s->linesize * 4 - 4*4;
|
||||
intra_types += r->intra_types_stride;
|
||||
}
|
||||
|
||||
intra_types -= r->intra_types_stride * 4;
|
||||
|
||||
q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
|
||||
q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
|
||||
|
||||
for(k = 0; k < 2; k++){
|
||||
dst = s->dest[1+k];
|
||||
fill_rectangle(r->avail_cache + 6, 2, 2, 4, 0, 4);
|
||||
|
||||
for(j = 0; j < 2; j++){
|
||||
int* acache = r->avail_cache + 6 + j*4;
|
||||
for(i = 0; i < 2; i++, cbp >>= 1, acache++){
|
||||
int itype = ittrans[intra_types[i*2+j*2*r->intra_types_stride]];
|
||||
rv34_pred_4x4_block(r, dst+4*i, s->uvlinesize, itype, acache[-4], acache[-1], !i && !j, acache[-3]);
|
||||
acache[0] = 1;
|
||||
|
||||
if(!(cbp&1)) continue;
|
||||
|
||||
rv34_process_block(r, dst + 4*i, s->uvlinesize,
|
||||
r->chroma_vlc, 1, q_dc, q_ac);
|
||||
}
|
||||
|
||||
dst += 4*s->uvlinesize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int is_mv_diff_gt_3(int16_t (*motion_val)[2], int step)
|
||||
@ -1123,16 +1198,118 @@ static int rv34_set_deblock_coef(RV34DecContext *r)
|
||||
return hmvmask | vmvmask;
|
||||
}
|
||||
|
||||
static int rv34_decode_macroblock(RV34DecContext *r, int8_t *intra_types)
|
||||
static int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types)
|
||||
{
|
||||
MpegEncContext *s = &r->s;
|
||||
GetBitContext *gb = &s->gb;
|
||||
MpegEncContext *s = &r->s;
|
||||
GetBitContext *gb = &s->gb;
|
||||
uint8_t *dst = s->dest[0];
|
||||
DCTELEM *ptr = s->block[0];
|
||||
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
|
||||
int cbp, cbp2;
|
||||
int q_dc, q_ac, has_ac;
|
||||
int i, blknum, blkoff;
|
||||
LOCAL_ALIGNED_16(DCTELEM, block16, [64]);
|
||||
int luma_dc_quant;
|
||||
int i, j;
|
||||
int dist;
|
||||
|
||||
// Calculate which neighbours are available. Maybe it's worth optimizing too.
|
||||
memset(r->avail_cache, 0, sizeof(r->avail_cache));
|
||||
fill_rectangle(r->avail_cache + 6, 2, 2, 4, 1, 4);
|
||||
dist = (s->mb_x - s->resync_mb_x) + (s->mb_y - s->resync_mb_y) * s->mb_width;
|
||||
if(s->mb_x && dist)
|
||||
r->avail_cache[5] =
|
||||
r->avail_cache[9] = s->current_picture_ptr->f.mb_type[mb_pos - 1];
|
||||
if(dist >= s->mb_width)
|
||||
r->avail_cache[2] =
|
||||
r->avail_cache[3] = s->current_picture_ptr->f.mb_type[mb_pos - s->mb_stride];
|
||||
if(((s->mb_x+1) < s->mb_width) && dist >= s->mb_width - 1)
|
||||
r->avail_cache[4] = s->current_picture_ptr->f.mb_type[mb_pos - s->mb_stride + 1];
|
||||
if(s->mb_x && dist > s->mb_width)
|
||||
r->avail_cache[1] = s->current_picture_ptr->f.mb_type[mb_pos - s->mb_stride - 1];
|
||||
|
||||
s->qscale = r->si.quant;
|
||||
cbp = cbp2 = rv34_decode_inter_mb_header(r, intra_types);
|
||||
r->cbp_luma [mb_pos] = cbp;
|
||||
r->cbp_chroma[mb_pos] = cbp >> 16;
|
||||
r->deblock_coefs[mb_pos] = rv34_set_deblock_coef(r) | r->cbp_luma[mb_pos];
|
||||
s->current_picture_ptr->f.qscale_table[mb_pos] = s->qscale;
|
||||
|
||||
if(cbp == -1)
|
||||
return -1;
|
||||
|
||||
if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos])){
|
||||
if(r->is16) rv34_output_i16x16(r, intra_types, cbp);
|
||||
else rv34_output_intra(r, intra_types, cbp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(r->is16){
|
||||
// Only for RV34_MB_P_MIX16x16
|
||||
LOCAL_ALIGNED_16(DCTELEM, block16, [16]);
|
||||
memset(block16, 0, 16 * sizeof(*block16));
|
||||
q_dc = rv34_qscale_tab[ r->luma_dc_quant_p[s->qscale] ];
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
if (rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac))
|
||||
r->rdsp.rv34_inv_transform(block16);
|
||||
else
|
||||
r->rdsp.rv34_inv_transform_dc(block16);
|
||||
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
|
||||
for(j = 0; j < 4; j++){
|
||||
for(i = 0; i < 4; i++, cbp >>= 1){
|
||||
int dc = block16[i + j*4];
|
||||
|
||||
if(cbp & 1){
|
||||
has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
|
||||
}else
|
||||
has_ac = 0;
|
||||
|
||||
if(has_ac){
|
||||
ptr[0] = dc;
|
||||
r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr);
|
||||
}else
|
||||
r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc);
|
||||
}
|
||||
|
||||
dst += 4*s->linesize;
|
||||
}
|
||||
|
||||
r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1);
|
||||
}else{
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
|
||||
for(j = 0; j < 4; j++){
|
||||
for(i = 0; i < 4; i++, cbp >>= 1){
|
||||
if(!(cbp & 1)) continue;
|
||||
|
||||
rv34_process_block(r, dst + 4*i, s->linesize,
|
||||
r->luma_vlc, 0, q_ac, q_ac);
|
||||
}
|
||||
dst += 4*s->linesize;
|
||||
}
|
||||
}
|
||||
|
||||
q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
|
||||
q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
|
||||
|
||||
for(j = 1; j < 3; j++){
|
||||
dst = s->dest[j];
|
||||
for(i = 0; i < 4; i++, cbp >>= 1){
|
||||
uint8_t *pdst;
|
||||
if(!(cbp & 1)) continue;
|
||||
pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize;
|
||||
|
||||
rv34_process_block(r, pdst, s->uvlinesize,
|
||||
r->chroma_vlc, 1, q_dc, q_ac);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rv34_decode_intra_macroblock(RV34DecContext *r, int8_t *intra_types)
|
||||
{
|
||||
MpegEncContext *s = &r->s;
|
||||
int cbp, dist;
|
||||
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
|
||||
|
||||
// Calculate which neighbours are available. Maybe it's worth optimizing too.
|
||||
@ -1151,67 +1328,21 @@ static int rv34_decode_macroblock(RV34DecContext *r, int8_t *intra_types)
|
||||
r->avail_cache[1] = s->current_picture_ptr->f.mb_type[mb_pos - s->mb_stride - 1];
|
||||
|
||||
s->qscale = r->si.quant;
|
||||
cbp = cbp2 = rv34_decode_mb_header(r, intra_types);
|
||||
cbp = rv34_decode_intra_mb_header(r, intra_types);
|
||||
r->cbp_luma [mb_pos] = cbp;
|
||||
r->cbp_chroma[mb_pos] = cbp >> 16;
|
||||
if(s->pict_type == AV_PICTURE_TYPE_I)
|
||||
r->deblock_coefs[mb_pos] = 0xFFFF;
|
||||
else
|
||||
r->deblock_coefs[mb_pos] = rv34_set_deblock_coef(r) | r->cbp_luma[mb_pos];
|
||||
r->deblock_coefs[mb_pos] = 0xFFFF;
|
||||
s->current_picture_ptr->f.qscale_table[mb_pos] = s->qscale;
|
||||
|
||||
if(cbp == -1)
|
||||
return -1;
|
||||
|
||||
luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16 ? r->luma_dc_quant_p[s->qscale] : r->luma_dc_quant_i[s->qscale];
|
||||
if(r->is16){
|
||||
q_dc = rv34_qscale_tab[luma_dc_quant];
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
s->dsp.clear_block(block16);
|
||||
if (rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac))
|
||||
r->rdsp.rv34_inv_transform_tab[1](block16);
|
||||
else
|
||||
r->rdsp.rv34_inv_transform_dc_tab[1](block16);
|
||||
rv34_output_i16x16(r, intra_types, cbp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
q_ac = rv34_qscale_tab[s->qscale];
|
||||
for(i = 0; i < 16; i++, cbp >>= 1){
|
||||
DCTELEM *ptr;
|
||||
if(!r->is16 && !(cbp & 1)) continue;
|
||||
blknum = ((i & 2) >> 1) + ((i & 8) >> 2);
|
||||
blkoff = ((i & 1) << 2) + ((i & 4) << 3);
|
||||
ptr = s->block[blknum] + blkoff;
|
||||
if(cbp & 1)
|
||||
has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
|
||||
else
|
||||
has_ac = 0;
|
||||
if(r->is16) //FIXME: optimize
|
||||
ptr[0] = block16[(i & 3) | ((i & 0xC) << 1)];
|
||||
if(has_ac)
|
||||
r->rdsp.rv34_inv_transform_tab[0](ptr);
|
||||
else
|
||||
r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
|
||||
}
|
||||
if(r->block_type == RV34_MB_P_MIX16x16)
|
||||
r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1);
|
||||
q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
|
||||
q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
|
||||
for(; i < 24; i++, cbp >>= 1){
|
||||
DCTELEM *ptr;
|
||||
if(!(cbp & 1)) continue;
|
||||
blknum = ((i & 4) >> 2) + 4;
|
||||
blkoff = ((i & 1) << 2) + ((i & 2) << 4);
|
||||
ptr = s->block[blknum] + blkoff;
|
||||
if (rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac))
|
||||
r->rdsp.rv34_inv_transform_tab[0](ptr);
|
||||
else
|
||||
r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
|
||||
}
|
||||
if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos]))
|
||||
rv34_output_macroblock(r, intra_types, cbp2, r->is16);
|
||||
else
|
||||
rv34_apply_differences(r, cbp2);
|
||||
|
||||
rv34_output_intra(r, intra_types, cbp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1326,9 +1457,12 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int
|
||||
ff_init_block_index(s);
|
||||
while(!check_slice_end(r, s)) {
|
||||
ff_update_block_index(s);
|
||||
s->dsp.clear_blocks(s->block[0]);
|
||||
|
||||
if(rv34_decode_macroblock(r, r->intra_types + s->mb_x * 4 + 4) < 0){
|
||||
if(r->si.type)
|
||||
res = rv34_decode_inter_macroblock(r, r->intra_types + s->mb_x * 4 + 4);
|
||||
else
|
||||
res = rv34_decode_intra_macroblock(r, r->intra_types + s->mb_x * 4 + 4);
|
||||
if(res < 0){
|
||||
ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
@ -37,10 +37,10 @@ static av_always_inline void rv34_row_transform(int temp[16], DCTELEM *block)
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
const int z0 = 13*(block[i+8*0] + block[i+8*2]);
|
||||
const int z1 = 13*(block[i+8*0] - block[i+8*2]);
|
||||
const int z2 = 7* block[i+8*1] - 17*block[i+8*3];
|
||||
const int z3 = 17* block[i+8*1] + 7*block[i+8*3];
|
||||
const int z0 = 13*(block[i+4*0] + block[i+4*2]);
|
||||
const int z1 = 13*(block[i+4*0] - block[i+4*2]);
|
||||
const int z2 = 7* block[i+4*1] - 17*block[i+4*3];
|
||||
const int z3 = 17* block[i+4*1] + 7*block[i+4*3];
|
||||
|
||||
temp[4*i+0] = z0 + z3;
|
||||
temp[4*i+1] = z1 + z2;
|
||||
@ -50,14 +50,16 @@ static av_always_inline void rv34_row_transform(int temp[16], DCTELEM *block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Video 3.0/4.0 inverse transform
|
||||
* Real Video 3.0/4.0 inverse transform + sample reconstruction
|
||||
* Code is almost the same as in SVQ3, only scaling is different.
|
||||
*/
|
||||
static void rv34_inv_transform_c(DCTELEM *block){
|
||||
int temp[16];
|
||||
int i;
|
||||
static void rv34_idct_add_c(uint8_t *dst, int stride, DCTELEM *block){
|
||||
int temp[16];
|
||||
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
|
||||
int i;
|
||||
|
||||
rv34_row_transform(temp, block);
|
||||
memset(block, 0, 16*sizeof(DCTELEM));
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
const int z0 = 13*(temp[4*0+i] + temp[4*2+i]) + 0x200;
|
||||
@ -65,10 +67,12 @@ static void rv34_inv_transform_c(DCTELEM *block){
|
||||
const int z2 = 7* temp[4*1+i] - 17*temp[4*3+i];
|
||||
const int z3 = 17* temp[4*1+i] + 7*temp[4*3+i];
|
||||
|
||||
block[i*8+0] = (z0 + z3) >> 10;
|
||||
block[i*8+1] = (z1 + z2) >> 10;
|
||||
block[i*8+2] = (z1 - z2) >> 10;
|
||||
block[i*8+3] = (z0 - z3) >> 10;
|
||||
dst[0] = cm[ dst[0] + ( (z0 + z3) >> 10 ) ];
|
||||
dst[1] = cm[ dst[1] + ( (z1 + z2) >> 10 ) ];
|
||||
dst[2] = cm[ dst[2] + ( (z1 - z2) >> 10 ) ];
|
||||
dst[3] = cm[ dst[3] + ( (z0 - z3) >> 10 ) ];
|
||||
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,21 +94,27 @@ static void rv34_inv_transform_noround_c(DCTELEM *block){
|
||||
const int z2 = 7* temp[4*1+i] - 17*temp[4*3+i];
|
||||
const int z3 = 17* temp[4*1+i] + 7*temp[4*3+i];
|
||||
|
||||
block[i*8+0] = ((z0 + z3) * 3) >> 11;
|
||||
block[i*8+1] = ((z1 + z2) * 3) >> 11;
|
||||
block[i*8+2] = ((z1 - z2) * 3) >> 11;
|
||||
block[i*8+3] = ((z0 - z3) * 3) >> 11;
|
||||
block[i*4+0] = ((z0 + z3) * 3) >> 11;
|
||||
block[i*4+1] = ((z1 + z2) * 3) >> 11;
|
||||
block[i*4+2] = ((z1 - z2) * 3) >> 11;
|
||||
block[i*4+3] = ((z0 - z3) * 3) >> 11;
|
||||
}
|
||||
}
|
||||
|
||||
static void rv34_inv_transform_dc_c(DCTELEM *block)
|
||||
static void rv34_idct_dc_add_c(uint8_t *dst, int stride, int dc)
|
||||
{
|
||||
DCTELEM dc = (13 * 13 * block[0] + 0x200) >> 10;
|
||||
const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++, block += 8)
|
||||
cm += (13*13*dc + 0x200) >> 10;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
block[j] = dc;
|
||||
dst[j] = cm[ dst[j] ];
|
||||
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void rv34_inv_transform_dc_noround_c(DCTELEM *block)
|
||||
@ -112,7 +122,7 @@ static void rv34_inv_transform_dc_noround_c(DCTELEM *block)
|
||||
DCTELEM dc = (13 * 13 * 3 * block[0]) >> 11;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++, block += 8)
|
||||
for (i = 0; i < 4; i++, block += 4)
|
||||
for (j = 0; j < 4; j++)
|
||||
block[j] = dc;
|
||||
}
|
||||
@ -121,10 +131,11 @@ static void rv34_inv_transform_dc_noround_c(DCTELEM *block)
|
||||
|
||||
|
||||
av_cold void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp) {
|
||||
c->rv34_inv_transform_tab[0] = rv34_inv_transform_c;
|
||||
c->rv34_inv_transform_tab[1] = rv34_inv_transform_noround_c;
|
||||
c->rv34_inv_transform_dc_tab[0] = rv34_inv_transform_dc_c;
|
||||
c->rv34_inv_transform_dc_tab[1] = rv34_inv_transform_dc_noround_c;
|
||||
c->rv34_inv_transform = rv34_inv_transform_noround_c;
|
||||
c->rv34_inv_transform_dc = rv34_inv_transform_dc_noround_c;
|
||||
|
||||
c->rv34_idct_add = rv34_idct_add_c;
|
||||
c->rv34_idct_dc_add = rv34_idct_dc_add_c;
|
||||
|
||||
if (HAVE_NEON)
|
||||
ff_rv34dsp_init_neon(c, dsp);
|
||||
|
@ -36,6 +36,10 @@ typedef void (*rv40_weight_func)(uint8_t *dst/*align width (8 or 16)*/,
|
||||
|
||||
typedef void (*rv34_inv_transform_func)(DCTELEM *block);
|
||||
|
||||
typedef void (*rv34_idct_add_func)(uint8_t *dst, int stride, DCTELEM *block);
|
||||
typedef void (*rv34_idct_dc_add_func)(uint8_t *dst, int stride,
|
||||
int dc);
|
||||
|
||||
typedef void (*rv40_weak_loop_filter_func)(uint8_t *src, int stride,
|
||||
int filter_p1, int filter_q1,
|
||||
int alpha, int beta,
|
||||
@ -55,8 +59,10 @@ typedef struct RV34DSPContext {
|
||||
h264_chroma_mc_func put_chroma_pixels_tab[3];
|
||||
h264_chroma_mc_func avg_chroma_pixels_tab[3];
|
||||
rv40_weight_func rv40_weight_pixels_tab[2];
|
||||
rv34_inv_transform_func rv34_inv_transform_tab[2];
|
||||
void (*rv34_inv_transform_dc_tab[2])(DCTELEM *block);
|
||||
rv34_inv_transform_func rv34_inv_transform;
|
||||
rv34_inv_transform_func rv34_inv_transform_dc;
|
||||
rv34_idct_add_func rv34_idct_add;
|
||||
rv34_idct_dc_add_func rv34_idct_dc_add;
|
||||
rv40_weak_loop_filter_func rv40_weak_loop_filter[2];
|
||||
rv40_strong_loop_filter_func rv40_strong_loop_filter[2];
|
||||
rv40_loop_filter_strength_func rv40_loop_filter_strength[2];
|
||||
|
@ -25,6 +25,7 @@
|
||||
* utils.
|
||||
*/
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/crc.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
@ -102,6 +103,16 @@ void avcodec_init(void)
|
||||
dsputil_static_init();
|
||||
}
|
||||
|
||||
static av_always_inline int codec_is_encoder(AVCodec *codec)
|
||||
{
|
||||
return codec && (codec->encode || codec->encode2);
|
||||
}
|
||||
|
||||
static av_always_inline int codec_is_decoder(AVCodec *codec)
|
||||
{
|
||||
return codec && codec->decode;
|
||||
}
|
||||
|
||||
void avcodec_register(AVCodec *codec)
|
||||
{
|
||||
AVCodec **p;
|
||||
@ -260,11 +271,47 @@ void ff_init_buffer_info(AVCodecContext *s, AVFrame *pic)
|
||||
pic->format = s->pix_fmt;
|
||||
}
|
||||
|
||||
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
|
||||
enum AVSampleFormat sample_fmt, const uint8_t *buf,
|
||||
int buf_size, int align)
|
||||
{
|
||||
int ch, planar, needed_size, ret = 0;
|
||||
|
||||
needed_size = av_samples_get_buffer_size(NULL, nb_channels,
|
||||
frame->nb_samples, sample_fmt,
|
||||
align);
|
||||
if (buf_size < needed_size)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
planar = av_sample_fmt_is_planar(sample_fmt);
|
||||
if (planar && nb_channels > AV_NUM_DATA_POINTERS) {
|
||||
if (!(frame->extended_data = av_mallocz(nb_channels *
|
||||
sizeof(*frame->extended_data))))
|
||||
return AVERROR(ENOMEM);
|
||||
} else {
|
||||
frame->extended_data = frame->data;
|
||||
}
|
||||
|
||||
if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0],
|
||||
buf, nb_channels, frame->nb_samples,
|
||||
sample_fmt, align)) < 0) {
|
||||
if (frame->extended_data != frame->data)
|
||||
av_free(frame->extended_data);
|
||||
return ret;
|
||||
}
|
||||
if (frame->extended_data != frame->data) {
|
||||
for (ch = 0; ch < AV_NUM_DATA_POINTERS; ch++)
|
||||
frame->data[ch] = frame->extended_data[ch];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
AVCodecInternal *avci = avctx->internal;
|
||||
InternalBuffer *buf;
|
||||
int buf_size, ret, i, needs_extended_data;
|
||||
int buf_size, ret;
|
||||
|
||||
buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
|
||||
frame->nb_samples, avctx->sample_fmt,
|
||||
@ -272,9 +319,6 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
|
||||
if (buf_size < 0)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
needs_extended_data = av_sample_fmt_is_planar(avctx->sample_fmt) &&
|
||||
avctx->channels > AV_NUM_DATA_POINTERS;
|
||||
|
||||
/* allocate InternalBuffer if needed */
|
||||
if (!avci->buffer) {
|
||||
avci->buffer = av_mallocz(sizeof(InternalBuffer));
|
||||
@ -306,48 +350,31 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
|
||||
/* if there is no previous buffer or the previous buffer cannot be used
|
||||
as-is, allocate a new buffer and/or rearrange the channel pointers */
|
||||
if (!buf->extended_data) {
|
||||
/* if the channel pointers will fit, just set extended_data to data,
|
||||
otherwise allocate the extended_data channel pointers */
|
||||
if (needs_extended_data) {
|
||||
buf->extended_data = av_mallocz(avctx->channels *
|
||||
sizeof(*buf->extended_data));
|
||||
if (!buf->extended_data)
|
||||
if (!buf->data[0]) {
|
||||
if (!(buf->data[0] = av_mallocz(buf_size)))
|
||||
return AVERROR(ENOMEM);
|
||||
} else {
|
||||
buf->extended_data = buf->data;
|
||||
buf->audio_data_size = buf_size;
|
||||
}
|
||||
|
||||
/* if there is a previous buffer and it is large enough, reuse it and
|
||||
just fill-in new channel pointers and linesize, otherwise allocate
|
||||
a new buffer */
|
||||
if (buf->extended_data[0]) {
|
||||
ret = av_samples_fill_arrays(buf->extended_data, &buf->linesize[0],
|
||||
buf->extended_data[0], avctx->channels,
|
||||
frame->nb_samples, avctx->sample_fmt,
|
||||
32);
|
||||
} else {
|
||||
ret = av_samples_alloc(buf->extended_data, &buf->linesize[0],
|
||||
avctx->channels, frame->nb_samples,
|
||||
avctx->sample_fmt, 32);
|
||||
}
|
||||
if (ret)
|
||||
if ((ret = avcodec_fill_audio_frame(frame, avctx->channels,
|
||||
avctx->sample_fmt, buf->data[0],
|
||||
buf->audio_data_size, 32)))
|
||||
return ret;
|
||||
|
||||
/* if data was not used for extended_data, we need to copy as many of
|
||||
the extended_data channel pointers as will fit */
|
||||
if (needs_extended_data) {
|
||||
for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
|
||||
buf->data[i] = buf->extended_data[i];
|
||||
}
|
||||
buf->audio_data_size = buf_size;
|
||||
buf->nb_channels = avctx->channels;
|
||||
if (frame->extended_data == frame->data)
|
||||
buf->extended_data = buf->data;
|
||||
else
|
||||
buf->extended_data = frame->extended_data;
|
||||
memcpy(buf->data, frame->data, sizeof(frame->data));
|
||||
buf->linesize[0] = frame->linesize[0];
|
||||
buf->nb_channels = avctx->channels;
|
||||
} else {
|
||||
/* copy InternalBuffer info to the AVFrame */
|
||||
frame->extended_data = buf->extended_data;
|
||||
frame->linesize[0] = buf->linesize[0];
|
||||
memcpy(frame->data, buf->data, sizeof(frame->data));
|
||||
}
|
||||
|
||||
/* copy InternalBuffer info to the AVFrame */
|
||||
frame->type = FF_BUFFER_TYPE_INTERNAL;
|
||||
frame->extended_data = buf->extended_data;
|
||||
frame->linesize[0] = buf->linesize[0];
|
||||
memcpy(frame->data, buf->data, sizeof(frame->data));
|
||||
|
||||
if (avctx->pkt) {
|
||||
frame->pkt_pts = avctx->pkt->pts;
|
||||
@ -732,7 +759,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD
|
||||
|
||||
/* if the decoder init function was already called previously,
|
||||
free the already allocated subtitle_header before overwriting it */
|
||||
if (codec->decode)
|
||||
if (codec_is_decoder(codec))
|
||||
av_freep(&avctx->subtitle_header);
|
||||
|
||||
#define SANE_NB_CHANNELS 128U
|
||||
@ -789,7 +816,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD
|
||||
ret = AVERROR(EINVAL);
|
||||
goto free_and_end;
|
||||
}
|
||||
if (avctx->codec->encode) {
|
||||
if (codec_is_encoder(avctx->codec)) {
|
||||
int i;
|
||||
if (avctx->codec->sample_fmts) {
|
||||
for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++)
|
||||
@ -870,21 +897,225 @@ free_and_end:
|
||||
goto end;
|
||||
}
|
||||
|
||||
int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
|
||||
const short *samples)
|
||||
int ff_alloc_packet(AVPacket *avpkt, int size)
|
||||
{
|
||||
if(buf_size < FF_MIN_BUFFER_SIZE && 0){
|
||||
av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n");
|
||||
return -1;
|
||||
}
|
||||
if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){
|
||||
int ret = avctx->codec->encode(avctx, buf, buf_size, samples);
|
||||
avctx->frame_number++;
|
||||
return ret;
|
||||
}else
|
||||
if (size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (avpkt->data) {
|
||||
uint8_t *pkt_data;
|
||||
int pkt_size;
|
||||
|
||||
if (avpkt->size < size)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
pkt_data = avpkt->data;
|
||||
pkt_size = avpkt->size;
|
||||
av_init_packet(avpkt);
|
||||
avpkt->data = pkt_data;
|
||||
avpkt->size = pkt_size;
|
||||
return 0;
|
||||
} else {
|
||||
return av_new_packet(avpkt, size);
|
||||
}
|
||||
}
|
||||
|
||||
int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
|
||||
AVPacket *avpkt,
|
||||
const AVFrame *frame,
|
||||
int *got_packet_ptr)
|
||||
{
|
||||
int ret;
|
||||
int user_packet = !!avpkt->data;
|
||||
int nb_samples;
|
||||
|
||||
if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) {
|
||||
av_init_packet(avpkt);
|
||||
avpkt->size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for valid frame size */
|
||||
if (frame) {
|
||||
nb_samples = frame->nb_samples;
|
||||
if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
|
||||
if (nb_samples > avctx->frame_size)
|
||||
return AVERROR(EINVAL);
|
||||
} else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
|
||||
if (nb_samples != avctx->frame_size)
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
} else {
|
||||
nb_samples = avctx->frame_size;
|
||||
}
|
||||
|
||||
if (avctx->codec->encode2) {
|
||||
*got_packet_ptr = 0;
|
||||
ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr);
|
||||
if (!ret && *got_packet_ptr &&
|
||||
!(avctx->codec->capabilities & CODEC_CAP_DELAY)) {
|
||||
avpkt->pts = frame->pts;
|
||||
avpkt->duration = av_rescale_q(frame->nb_samples,
|
||||
(AVRational){ 1, avctx->sample_rate },
|
||||
avctx->time_base);
|
||||
}
|
||||
} else {
|
||||
/* for compatibility with encoders not supporting encode2(), we need to
|
||||
allocate a packet buffer if the user has not provided one or check
|
||||
the size otherwise */
|
||||
int fs_tmp = 0;
|
||||
int buf_size = avpkt->size;
|
||||
if (!user_packet) {
|
||||
if (avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) {
|
||||
av_assert0(av_get_bits_per_sample(avctx->codec_id) != 0);
|
||||
buf_size = nb_samples * avctx->channels *
|
||||
av_get_bits_per_sample(avctx->codec_id) / 8;
|
||||
} else {
|
||||
/* this is a guess as to the required size.
|
||||
if an encoder needs more than this, it should probably
|
||||
implement encode2() */
|
||||
buf_size = 2 * avctx->frame_size * avctx->channels *
|
||||
av_get_bytes_per_sample(avctx->sample_fmt);
|
||||
buf_size += FF_MIN_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
if ((ret = ff_alloc_packet(avpkt, buf_size)))
|
||||
return ret;
|
||||
|
||||
/* Encoders using AVCodec.encode() that support
|
||||
CODEC_CAP_SMALL_LAST_FRAME require avctx->frame_size to be set to
|
||||
the smaller size when encoding the last frame.
|
||||
This code can be removed once all encoders supporting
|
||||
CODEC_CAP_SMALL_LAST_FRAME use encode2() */
|
||||
if ((avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) &&
|
||||
nb_samples < avctx->frame_size) {
|
||||
fs_tmp = avctx->frame_size;
|
||||
avctx->frame_size = nb_samples;
|
||||
}
|
||||
|
||||
/* encode the frame */
|
||||
ret = avctx->codec->encode(avctx, avpkt->data, avpkt->size,
|
||||
frame ? frame->data[0] : NULL);
|
||||
if (ret >= 0) {
|
||||
if (!ret) {
|
||||
/* no output. if the packet data was allocated by libavcodec,
|
||||
free it */
|
||||
if (!user_packet)
|
||||
av_freep(&avpkt->data);
|
||||
} else {
|
||||
if (avctx->coded_frame)
|
||||
avpkt->pts = avctx->coded_frame->pts;
|
||||
/* Set duration for final small packet. This can be removed
|
||||
once all encoders supporting CODEC_CAP_SMALL_LAST_FRAME use
|
||||
encode2() */
|
||||
if (fs_tmp) {
|
||||
avpkt->duration = av_rescale_q(avctx->frame_size,
|
||||
(AVRational){ 1, avctx->sample_rate },
|
||||
avctx->time_base);
|
||||
}
|
||||
}
|
||||
avpkt->size = ret;
|
||||
*got_packet_ptr = (ret > 0);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (fs_tmp)
|
||||
avctx->frame_size = fs_tmp;
|
||||
}
|
||||
if (!ret)
|
||||
avctx->frame_number++;
|
||||
|
||||
/* NOTE: if we add any audio encoders which output non-keyframe packets,
|
||||
this needs to be moved to the encoders, but for now we can do it
|
||||
here to simplify things */
|
||||
avpkt->flags |= AV_PKT_FLAG_KEY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if FF_API_OLD_DECODE_AUDIO
|
||||
int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx,
|
||||
uint8_t *buf, int buf_size,
|
||||
const short *samples)
|
||||
{
|
||||
AVPacket pkt;
|
||||
AVFrame frame0;
|
||||
AVFrame *frame;
|
||||
int ret, samples_size, got_packet;
|
||||
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = buf;
|
||||
pkt.size = buf_size;
|
||||
|
||||
if (samples) {
|
||||
frame = &frame0;
|
||||
avcodec_get_frame_defaults(frame);
|
||||
|
||||
if (avctx->frame_size) {
|
||||
frame->nb_samples = avctx->frame_size;
|
||||
} else {
|
||||
/* if frame_size is not set, the number of samples must be
|
||||
calculated from the buffer size */
|
||||
int64_t nb_samples;
|
||||
if (!av_get_bits_per_sample(avctx->codec_id)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "avcodec_encode_audio() does not "
|
||||
"support this codec\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
nb_samples = (int64_t)buf_size * 8 /
|
||||
(av_get_bits_per_sample(avctx->codec_id) *
|
||||
avctx->channels);
|
||||
if (nb_samples >= INT_MAX)
|
||||
return AVERROR(EINVAL);
|
||||
frame->nb_samples = nb_samples;
|
||||
}
|
||||
|
||||
/* it is assumed that the samples buffer is large enough based on the
|
||||
relevant parameters */
|
||||
samples_size = av_samples_get_buffer_size(NULL, avctx->channels,
|
||||
frame->nb_samples,
|
||||
avctx->sample_fmt, 1);
|
||||
if ((ret = avcodec_fill_audio_frame(frame, avctx->channels,
|
||||
avctx->sample_fmt,
|
||||
samples, samples_size, 1)))
|
||||
return ret;
|
||||
|
||||
/* fabricate frame pts from sample count.
|
||||
this is needed because the avcodec_encode_audio() API does not have
|
||||
a way for the user to provide pts */
|
||||
if(avctx->sample_rate && avctx->time_base.num)
|
||||
frame->pts = av_rescale_q(avctx->internal->sample_count,
|
||||
(AVRational){ 1, avctx->sample_rate },
|
||||
avctx->time_base);
|
||||
else
|
||||
frame->pts = AV_NOPTS_VALUE;
|
||||
avctx->internal->sample_count += frame->nb_samples;
|
||||
} else {
|
||||
frame = NULL;
|
||||
}
|
||||
|
||||
got_packet = 0;
|
||||
ret = avcodec_encode_audio2(avctx, &pkt, frame, &got_packet);
|
||||
if (!ret && got_packet && avctx->coded_frame) {
|
||||
avctx->coded_frame->pts = pkt.pts;
|
||||
avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY);
|
||||
}
|
||||
/* free any side data since we cannot return it */
|
||||
if (pkt.side_data_elems > 0) {
|
||||
int i;
|
||||
for (i = 0; i < pkt.side_data_elems; i++)
|
||||
av_free(pkt.side_data[i].data);
|
||||
av_freep(&pkt.side_data);
|
||||
pkt.side_data_elems = 0;
|
||||
}
|
||||
|
||||
if (frame && frame->extended_data != frame->data)
|
||||
av_free(frame->extended_data);
|
||||
|
||||
return ret ? ret : pkt.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
int attribute_align_arg avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
|
||||
const AVFrame *pict)
|
||||
{
|
||||
@ -1187,7 +1418,7 @@ av_cold int avcodec_close(AVCodecContext *avctx)
|
||||
av_opt_free(avctx->priv_data);
|
||||
av_opt_free(avctx);
|
||||
av_freep(&avctx->priv_data);
|
||||
if(avctx->codec && avctx->codec->encode)
|
||||
if (codec_is_encoder(avctx->codec))
|
||||
av_freep(&avctx->extradata);
|
||||
avctx->codec = NULL;
|
||||
avctx->active_thread_type = 0;
|
||||
@ -1216,7 +1447,7 @@ AVCodec *avcodec_find_encoder(enum CodecID id)
|
||||
p = first_avcodec;
|
||||
id= remap_deprecated_codec_id(id);
|
||||
while (p) {
|
||||
if (p->encode != NULL && p->id == id) {
|
||||
if (codec_is_encoder(p) && p->id == id) {
|
||||
if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
|
||||
experimental = p;
|
||||
} else
|
||||
@ -1234,7 +1465,7 @@ AVCodec *avcodec_find_encoder_by_name(const char *name)
|
||||
return NULL;
|
||||
p = first_avcodec;
|
||||
while (p) {
|
||||
if (p->encode != NULL && strcmp(name,p->name) == 0)
|
||||
if (codec_is_encoder(p) && strcmp(name,p->name) == 0)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
@ -1247,7 +1478,7 @@ AVCodec *avcodec_find_decoder(enum CodecID id)
|
||||
p = first_avcodec;
|
||||
id= remap_deprecated_codec_id(id);
|
||||
while (p) {
|
||||
if (p->decode != NULL && p->id == id) {
|
||||
if (codec_is_decoder(p) && p->id == id) {
|
||||
if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
|
||||
experimental = p;
|
||||
} else
|
||||
@ -1265,7 +1496,7 @@ AVCodec *avcodec_find_decoder_by_name(const char *name)
|
||||
return NULL;
|
||||
p = first_avcodec;
|
||||
while (p) {
|
||||
if (p->decode != NULL && strcmp(name,p->name) == 0)
|
||||
if (codec_is_decoder(p) && strcmp(name,p->name) == 0)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define AVCODEC_VERSION_H
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 53
|
||||
#define LIBAVCODEC_VERSION_MINOR 55
|
||||
#define LIBAVCODEC_VERSION_MINOR 56
|
||||
#define LIBAVCODEC_VERSION_MICRO 105
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
@ -123,5 +123,8 @@
|
||||
#ifndef FF_API_AVFRAME_AGE
|
||||
#define FF_API_AVFRAME_AGE (LIBAVCODEC_VERSION_MAJOR < 54)
|
||||
#endif
|
||||
#ifndef FF_API_OLD_ENCODE_AUDIO
|
||||
#define FF_API_OLD_ENCODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 54)
|
||||
#endif
|
||||
|
||||
#endif /* AVCODEC_VERSION_H */
|
||||
|
@ -35,21 +35,84 @@ SECTION .text
|
||||
sar %1, 10
|
||||
%endmacro
|
||||
|
||||
%macro rv34_idct_dequant4x4_dc 1
|
||||
cglobal rv34_idct_dequant4x4_%1_mmx2, 1, 2, 0
|
||||
%macro rv34_idct 1
|
||||
cglobal rv34_idct_%1_mmx2, 1, 2, 0
|
||||
movsx r1, word [r0]
|
||||
IDCT_DC r1
|
||||
movd mm0, r1d
|
||||
pshufw mm0, mm0, 0
|
||||
movq [r0+ 0], mm0
|
||||
movq [r0+16], mm0
|
||||
movq [r0+32], mm0
|
||||
movq [r0+48], mm0
|
||||
movd m0, r1d
|
||||
pshufw m0, m0, 0
|
||||
movq [r0+ 0], m0
|
||||
movq [r0+ 8], m0
|
||||
movq [r0+16], m0
|
||||
movq [r0+24], m0
|
||||
REP_RET
|
||||
%endmacro
|
||||
|
||||
INIT_MMX
|
||||
%define IDCT_DC IDCT_DC_ROUND
|
||||
rv34_idct_dequant4x4_dc dc
|
||||
rv34_idct dc
|
||||
%define IDCT_DC IDCT_DC_NOROUND
|
||||
rv34_idct_dequant4x4_dc dc_noround
|
||||
rv34_idct dc_noround
|
||||
|
||||
; ff_rv34_idct_dc_add_mmx(uint8_t *dst, int stride, int dc);
|
||||
cglobal rv34_idct_dc_add_mmx, 3, 3
|
||||
; calculate DC
|
||||
IDCT_DC_ROUND r2
|
||||
pxor m1, m1
|
||||
movd m0, r2
|
||||
psubw m1, m0
|
||||
packuswb m0, m0
|
||||
packuswb m1, m1
|
||||
punpcklbw m0, m0
|
||||
punpcklbw m1, m1
|
||||
punpcklwd m0, m0
|
||||
punpcklwd m1, m1
|
||||
|
||||
; add DC
|
||||
lea r2, [r0+r1*2]
|
||||
movh m2, [r0]
|
||||
movh m3, [r0+r1]
|
||||
movh m4, [r2]
|
||||
movh m5, [r2+r1]
|
||||
paddusb m2, m0
|
||||
paddusb m3, m0
|
||||
paddusb m4, m0
|
||||
paddusb m5, m0
|
||||
psubusb m2, m1
|
||||
psubusb m3, m1
|
||||
psubusb m4, m1
|
||||
psubusb m5, m1
|
||||
movh [r0], m2
|
||||
movh [r0+r1], m3
|
||||
movh [r2], m4
|
||||
movh [r2+r1], m5
|
||||
RET
|
||||
|
||||
; ff_rv34_idct_dc_add_sse4(uint8_t *dst, int stride, int dc);
|
||||
INIT_XMM
|
||||
cglobal rv34_idct_dc_add_sse4, 3, 3, 6
|
||||
; load data
|
||||
IDCT_DC_ROUND r2
|
||||
pxor m1, m1
|
||||
|
||||
; calculate DC
|
||||
movd m0, r2
|
||||
lea r2, [r0+r1*2]
|
||||
movd m2, [r0]
|
||||
movd m3, [r0+r1]
|
||||
pshuflw m0, m0, 0
|
||||
movd m4, [r2]
|
||||
movd m5, [r2+r1]
|
||||
punpcklqdq m0, m0
|
||||
punpckldq m2, m3
|
||||
punpckldq m4, m5
|
||||
punpcklbw m2, m1
|
||||
punpcklbw m4, m1
|
||||
paddw m2, m0
|
||||
paddw m4, m0
|
||||
packuswb m2, m4
|
||||
movd [r0], m2
|
||||
pextrd [r0+r1], m2, 1
|
||||
pextrd [r2], m2, 2
|
||||
pextrd [r2+r1], m2, 3
|
||||
RET
|
||||
|
@ -24,17 +24,22 @@
|
||||
#include "libavcodec/dsputil.h"
|
||||
#include "libavcodec/rv34dsp.h"
|
||||
|
||||
void ff_rv34_idct_dequant4x4_dc_mmx2(DCTELEM *block);
|
||||
void ff_rv34_idct_dequant4x4_dc_noround_mmx2(DCTELEM *block);
|
||||
void ff_rv34_idct_dc_mmx2(DCTELEM *block);
|
||||
void ff_rv34_idct_dc_noround_mmx2(DCTELEM *block);
|
||||
void ff_rv34_idct_dc_add_mmx(uint8_t *dst, int stride, int dc);
|
||||
void ff_rv34_idct_dc_add_sse4(uint8_t *dst, int stride, int dc);
|
||||
|
||||
av_cold void ff_rv34dsp_init_x86(RV34DSPContext* c, DSPContext *dsp)
|
||||
{
|
||||
#if HAVE_YASM
|
||||
int mm_flags = av_get_cpu_flags();
|
||||
|
||||
if (mm_flags & AV_CPU_FLAG_MMX)
|
||||
c->rv34_idct_dc_add = ff_rv34_idct_dc_add_mmx;
|
||||
if (mm_flags & AV_CPU_FLAG_MMX2) {
|
||||
c->rv34_inv_transform_dc_tab[0] = ff_rv34_idct_dequant4x4_dc_mmx2;
|
||||
c->rv34_inv_transform_dc_tab[1] = ff_rv34_idct_dequant4x4_dc_noround_mmx2;
|
||||
c->rv34_inv_transform_dc = ff_rv34_idct_dc_noround_mmx2;
|
||||
}
|
||||
if (mm_flags & AV_CPU_FLAG_SSE4)
|
||||
c->rv34_idct_dc_add = ff_rv34_idct_dc_add_sse4;
|
||||
#endif
|
||||
}
|
||||
|
@ -291,7 +291,8 @@ OBJS-$(CONFIG_SEGMENT_MUXER) += segment.o
|
||||
OBJS-$(CONFIG_SHORTEN_DEMUXER) += rawdec.o
|
||||
OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o
|
||||
OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o
|
||||
OBJS-$(CONFIG_SMJPEG_DEMUXER) += smjpeg.o
|
||||
OBJS-$(CONFIG_SMJPEG_DEMUXER) += smjpegdec.o smjpeg.o
|
||||
OBJS-$(CONFIG_SMJPEG_MUXER) += smjpegenc.o smjpeg.o
|
||||
OBJS-$(CONFIG_SOL_DEMUXER) += sol.o pcm.o
|
||||
OBJS-$(CONFIG_SOX_DEMUXER) += soxdec.o pcm.o
|
||||
OBJS-$(CONFIG_SOX_MUXER) += soxenc.o
|
||||
|
@ -212,7 +212,7 @@ void av_register_all(void)
|
||||
REGISTER_DEMUXER (SHORTEN, shorten);
|
||||
REGISTER_DEMUXER (SIFF, siff);
|
||||
REGISTER_DEMUXER (SMACKER, smacker);
|
||||
REGISTER_DEMUXER (SMJPEG, smjpeg);
|
||||
REGISTER_MUXDEMUX (SMJPEG, smjpeg);
|
||||
REGISTER_DEMUXER (SOL, sol);
|
||||
REGISTER_MUXDEMUX (SOX, sox);
|
||||
REGISTER_MUXDEMUX (SPDIF, spdif);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* SMJPEG demuxer
|
||||
* Copyright (c) 2011 Paul B Mahol
|
||||
* SMJPEG common code
|
||||
* Copyright (c) 2011-2012 Paul B Mahol
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
@ -21,167 +21,20 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This is a demuxer for Loki SDL Motion JPEG files
|
||||
* SMJPEG common code
|
||||
*/
|
||||
|
||||
#include "avformat.h"
|
||||
#include "internal.h"
|
||||
#include "riff.h"
|
||||
#include "smjpeg.h"
|
||||
|
||||
static const AVCodecTag codec_smjpeg_video_tags[] = {
|
||||
const AVCodecTag ff_codec_smjpeg_video_tags[] = {
|
||||
{ CODEC_ID_MJPEG, MKTAG('J', 'F', 'I', 'F') },
|
||||
{ CODEC_ID_NONE, 0 },
|
||||
};
|
||||
|
||||
static const AVCodecTag codec_smjpeg_audio_tags[] = {
|
||||
const AVCodecTag ff_codec_smjpeg_audio_tags[] = {
|
||||
{ CODEC_ID_ADPCM_IMA_SMJPEG, MKTAG('A', 'P', 'C', 'M') },
|
||||
{ CODEC_ID_PCM_S16LE, MKTAG('N', 'O', 'N', 'E') },
|
||||
{ CODEC_ID_NONE, 0 },
|
||||
};
|
||||
|
||||
typedef struct SMJPEGContext {
|
||||
int audio_stream_index;
|
||||
int video_stream_index;
|
||||
} SMJPEGContext;
|
||||
|
||||
static int smjpeg_probe(AVProbeData *p)
|
||||
{
|
||||
if (!memcmp(p->buf, "\x0\xaSMJPEG", 8))
|
||||
return AVPROBE_SCORE_MAX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smjpeg_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
||||
{
|
||||
SMJPEGContext *sc = s->priv_data;
|
||||
AVStream *ast = NULL, *vst = NULL;
|
||||
AVIOContext *pb = s->pb;
|
||||
uint32_t version, htype, hlength, duration;
|
||||
char *comment;
|
||||
|
||||
avio_skip(pb, 8); // magic
|
||||
version = avio_rb32(pb);
|
||||
if (version)
|
||||
av_log_ask_for_sample(s, "unknown version %d\n", version);
|
||||
|
||||
duration = avio_rb32(pb); // in msec
|
||||
|
||||
while (!pb->eof_reached) {
|
||||
htype = avio_rl32(pb);
|
||||
switch (htype) {
|
||||
case MKTAG('_', 'T', 'X', 'T'):
|
||||
hlength = avio_rb32(pb);
|
||||
if (!hlength || hlength > 512)
|
||||
return AVERROR_INVALIDDATA;
|
||||
comment = av_malloc(hlength + 1);
|
||||
if (!comment)
|
||||
return AVERROR(ENOMEM);
|
||||
if (avio_read(pb, comment, hlength) != hlength) {
|
||||
av_freep(&comment);
|
||||
av_log(s, AV_LOG_ERROR, "error when reading comment\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
comment[hlength] = 0;
|
||||
av_dict_set(&s->metadata, "comment", comment,
|
||||
AV_DICT_DONT_STRDUP_VAL);
|
||||
break;
|
||||
case MKTAG('_', 'S', 'N', 'D'):
|
||||
if (ast) {
|
||||
av_log_ask_for_sample(s, "multiple audio streams not supported\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
hlength = avio_rb32(pb);
|
||||
if (hlength < 8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
ast = avformat_new_stream(s, 0);
|
||||
if (!ast)
|
||||
return AVERROR(ENOMEM);
|
||||
ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
ast->codec->sample_rate = avio_rb16(pb);
|
||||
ast->codec->bits_per_coded_sample = avio_r8(pb);
|
||||
ast->codec->channels = avio_r8(pb);
|
||||
ast->codec->codec_tag = avio_rl32(pb);
|
||||
ast->codec->codec_id = ff_codec_get_id(codec_smjpeg_audio_tags,
|
||||
ast->codec->codec_tag);
|
||||
ast->duration = duration;
|
||||
sc->audio_stream_index = ast->index;
|
||||
avpriv_set_pts_info(ast, 32, 1, 1000);
|
||||
avio_skip(pb, hlength - 8);
|
||||
break;
|
||||
case MKTAG('_', 'V', 'I', 'D'):
|
||||
if (vst) {
|
||||
av_log_ask_for_sample(s, "multiple video streams not supported\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
hlength = avio_rb32(pb);
|
||||
if (hlength < 12)
|
||||
return AVERROR_INVALIDDATA;
|
||||
avio_skip(pb, 4); // number of frames
|
||||
vst = avformat_new_stream(s, 0);
|
||||
if (!vst)
|
||||
return AVERROR(ENOMEM);
|
||||
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
vst->codec->width = avio_rb16(pb);
|
||||
vst->codec->height = avio_rb16(pb);
|
||||
vst->codec->codec_tag = avio_rl32(pb);
|
||||
vst->codec->codec_id = ff_codec_get_id(codec_smjpeg_video_tags,
|
||||
vst->codec->codec_tag);
|
||||
vst->duration = duration;
|
||||
sc->video_stream_index = vst->index;
|
||||
avpriv_set_pts_info(vst, 32, 1, 1000);
|
||||
avio_skip(pb, hlength - 12);
|
||||
break;
|
||||
case MKTAG('H', 'E', 'N', 'D'):
|
||||
return 0;
|
||||
default:
|
||||
av_log(s, AV_LOG_ERROR, "unknown header %x\n", htype);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
|
||||
return AVERROR_EOF;
|
||||
}
|
||||
|
||||
static int smjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
SMJPEGContext *sc = s->priv_data;
|
||||
uint32_t dtype, ret, size, timestamp;
|
||||
|
||||
if (s->pb->eof_reached)
|
||||
return AVERROR_EOF;
|
||||
dtype = avio_rl32(s->pb);
|
||||
switch (dtype) {
|
||||
case MKTAG('s', 'n', 'd', 'D'):
|
||||
timestamp = avio_rb32(s->pb);
|
||||
size = avio_rb32(s->pb);
|
||||
ret = av_get_packet(s->pb, pkt, size);
|
||||
pkt->stream_index = sc->audio_stream_index;
|
||||
pkt->pts = timestamp;
|
||||
break;
|
||||
case MKTAG('v', 'i', 'd', 'D'):
|
||||
timestamp = avio_rb32(s->pb);
|
||||
size = avio_rb32(s->pb);
|
||||
ret = av_get_packet(s->pb, pkt, size);
|
||||
pkt->stream_index = sc->video_stream_index;
|
||||
pkt->pts = timestamp;
|
||||
break;
|
||||
case MKTAG('D', 'O', 'N', 'E'):
|
||||
ret = AVERROR_EOF;
|
||||
break;
|
||||
default:
|
||||
av_log(s, AV_LOG_ERROR, "unknown chunk %x\n", dtype);
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AVInputFormat ff_smjpeg_demuxer = {
|
||||
.name = "smjpeg",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"),
|
||||
.priv_data_size = sizeof(SMJPEGContext),
|
||||
.read_probe = smjpeg_probe,
|
||||
.read_header = smjpeg_read_header,
|
||||
.read_packet = smjpeg_read_packet,
|
||||
.extensions = "mjpg",
|
||||
};
|
||||
|
45
libavformat/smjpeg.h
Normal file
45
libavformat/smjpeg.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SMJPEG common code
|
||||
* Copyright (c) 2011-2012 Paul B Mahol
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* SMJPEG common code
|
||||
*/
|
||||
|
||||
#ifndef AVFORMAT_SMJPEG_H
|
||||
#define AVFORMAT_SMJPEG_H
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define SMJPEG_MAGIC "\x0\xaSMJPEG"
|
||||
|
||||
#define SMJPEG_DONE MKTAG('D', 'O', 'N', 'E')
|
||||
#define SMJPEG_HEND MKTAG('H', 'E', 'N', 'D')
|
||||
#define SMJPEG_SND MKTAG('_', 'S', 'N', 'D')
|
||||
#define SMJPEG_SNDD MKTAG('s', 'n', 'd', 'D')
|
||||
#define SMJPEG_TXT MKTAG('_', 'T', 'X', 'T')
|
||||
#define SMJPEG_VID MKTAG('_', 'V', 'I', 'D')
|
||||
#define SMJPEG_VIDD MKTAG('v', 'i', 'd', 'D')
|
||||
|
||||
extern const AVCodecTag ff_codec_smjpeg_video_tags[];
|
||||
extern const AVCodecTag ff_codec_smjpeg_audio_tags[];
|
||||
|
||||
#endif /* AVFORMAT_SMJPEG_H */
|
177
libavformat/smjpegdec.c
Normal file
177
libavformat/smjpegdec.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* SMJPEG demuxer
|
||||
* Copyright (c) 2011 Paul B Mahol
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This is a demuxer for Loki SDL Motion JPEG files
|
||||
*/
|
||||
|
||||
#include "avformat.h"
|
||||
#include "internal.h"
|
||||
#include "riff.h"
|
||||
#include "smjpeg.h"
|
||||
|
||||
typedef struct SMJPEGContext {
|
||||
int audio_stream_index;
|
||||
int video_stream_index;
|
||||
} SMJPEGContext;
|
||||
|
||||
static int smjpeg_probe(AVProbeData *p)
|
||||
{
|
||||
if (!memcmp(p->buf, SMJPEG_MAGIC, 8))
|
||||
return AVPROBE_SCORE_MAX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smjpeg_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
||||
{
|
||||
SMJPEGContext *sc = s->priv_data;
|
||||
AVStream *ast = NULL, *vst = NULL;
|
||||
AVIOContext *pb = s->pb;
|
||||
uint32_t version, htype, hlength, duration;
|
||||
char *comment;
|
||||
|
||||
avio_skip(pb, 8); // magic
|
||||
version = avio_rb32(pb);
|
||||
if (version)
|
||||
av_log_ask_for_sample(s, "unknown version %d\n", version);
|
||||
|
||||
duration = avio_rb32(pb); // in msec
|
||||
|
||||
while (!pb->eof_reached) {
|
||||
htype = avio_rl32(pb);
|
||||
switch (htype) {
|
||||
case SMJPEG_TXT:
|
||||
hlength = avio_rb32(pb);
|
||||
if (!hlength || hlength > 512)
|
||||
return AVERROR_INVALIDDATA;
|
||||
comment = av_malloc(hlength + 1);
|
||||
if (!comment)
|
||||
return AVERROR(ENOMEM);
|
||||
if (avio_read(pb, comment, hlength) != hlength) {
|
||||
av_freep(&comment);
|
||||
av_log(s, AV_LOG_ERROR, "error when reading comment\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
comment[hlength] = 0;
|
||||
av_dict_set(&s->metadata, "comment", comment,
|
||||
AV_DICT_DONT_STRDUP_VAL);
|
||||
break;
|
||||
case SMJPEG_SND:
|
||||
if (ast) {
|
||||
av_log_ask_for_sample(s, "multiple audio streams not supported\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
hlength = avio_rb32(pb);
|
||||
if (hlength < 8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
ast = avformat_new_stream(s, 0);
|
||||
if (!ast)
|
||||
return AVERROR(ENOMEM);
|
||||
ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
ast->codec->sample_rate = avio_rb16(pb);
|
||||
ast->codec->bits_per_coded_sample = avio_r8(pb);
|
||||
ast->codec->channels = avio_r8(pb);
|
||||
ast->codec->codec_tag = avio_rl32(pb);
|
||||
ast->codec->codec_id = ff_codec_get_id(ff_codec_smjpeg_audio_tags,
|
||||
ast->codec->codec_tag);
|
||||
ast->duration = duration;
|
||||
sc->audio_stream_index = ast->index;
|
||||
avpriv_set_pts_info(ast, 32, 1, 1000);
|
||||
avio_skip(pb, hlength - 8);
|
||||
break;
|
||||
case SMJPEG_VID:
|
||||
if (vst) {
|
||||
av_log_ask_for_sample(s, "multiple video streams not supported\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
hlength = avio_rb32(pb);
|
||||
if (hlength < 12)
|
||||
return AVERROR_INVALIDDATA;
|
||||
avio_skip(pb, 4); // number of frames
|
||||
vst = avformat_new_stream(s, 0);
|
||||
if (!vst)
|
||||
return AVERROR(ENOMEM);
|
||||
vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
vst->codec->width = avio_rb16(pb);
|
||||
vst->codec->height = avio_rb16(pb);
|
||||
vst->codec->codec_tag = avio_rl32(pb);
|
||||
vst->codec->codec_id = ff_codec_get_id(ff_codec_smjpeg_video_tags,
|
||||
vst->codec->codec_tag);
|
||||
vst->duration = duration;
|
||||
sc->video_stream_index = vst->index;
|
||||
avpriv_set_pts_info(vst, 32, 1, 1000);
|
||||
avio_skip(pb, hlength - 12);
|
||||
break;
|
||||
case SMJPEG_HEND:
|
||||
return 0;
|
||||
default:
|
||||
av_log(s, AV_LOG_ERROR, "unknown header %x\n", htype);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
|
||||
return AVERROR_EOF;
|
||||
}
|
||||
|
||||
static int smjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
SMJPEGContext *sc = s->priv_data;
|
||||
uint32_t dtype, ret, size, timestamp;
|
||||
|
||||
if (s->pb->eof_reached)
|
||||
return AVERROR_EOF;
|
||||
dtype = avio_rl32(s->pb);
|
||||
switch (dtype) {
|
||||
case SMJPEG_SNDD:
|
||||
timestamp = avio_rb32(s->pb);
|
||||
size = avio_rb32(s->pb);
|
||||
ret = av_get_packet(s->pb, pkt, size);
|
||||
pkt->stream_index = sc->audio_stream_index;
|
||||
pkt->pts = timestamp;
|
||||
break;
|
||||
case SMJPEG_VIDD:
|
||||
timestamp = avio_rb32(s->pb);
|
||||
size = avio_rb32(s->pb);
|
||||
ret = av_get_packet(s->pb, pkt, size);
|
||||
pkt->stream_index = sc->video_stream_index;
|
||||
pkt->pts = timestamp;
|
||||
break;
|
||||
case SMJPEG_DONE:
|
||||
ret = AVERROR_EOF;
|
||||
break;
|
||||
default:
|
||||
av_log(s, AV_LOG_ERROR, "unknown chunk %x\n", dtype);
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AVInputFormat ff_smjpeg_demuxer = {
|
||||
.name = "smjpeg",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"),
|
||||
.priv_data_size = sizeof(SMJPEGContext),
|
||||
.read_probe = smjpeg_probe,
|
||||
.read_header = smjpeg_read_header,
|
||||
.read_packet = smjpeg_read_packet,
|
||||
.extensions = "mjpg",
|
||||
};
|
149
libavformat/smjpegenc.c
Normal file
149
libavformat/smjpegenc.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* SMJPEG muxer
|
||||
* Copyright (c) 2012 Paul B Mahol
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This is a muxer for Loki SDL Motion JPEG files
|
||||
*/
|
||||
|
||||
#include "avformat.h"
|
||||
#include "internal.h"
|
||||
#include "riff.h"
|
||||
#include "smjpeg.h"
|
||||
|
||||
typedef struct SMJPEGMuxContext {
|
||||
uint32_t duration;
|
||||
} SMJPEGMuxContext;
|
||||
|
||||
static int smjpeg_write_header(AVFormatContext *s)
|
||||
{
|
||||
AVDictionaryEntry *t = NULL;
|
||||
AVIOContext *pb = s->pb;
|
||||
int n, tag;
|
||||
|
||||
if (s->nb_streams > 2) {
|
||||
av_log(s, AV_LOG_ERROR, "more than >2 streams are not supported\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
avio_write(pb, SMJPEG_MAGIC, 8);
|
||||
avio_wb32(pb, 0);
|
||||
avio_wb32(pb, 0);
|
||||
|
||||
while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
|
||||
avio_wl32(pb, SMJPEG_TXT);
|
||||
avio_wb32(pb, strlen(t->key) + strlen(t->value) + 3);
|
||||
avio_write(pb, t->key, strlen(t->key));
|
||||
avio_write(pb, " = ", 3);
|
||||
avio_write(pb, t->value, strlen(t->value));
|
||||
}
|
||||
|
||||
for (n = 0; n < s->nb_streams; n++) {
|
||||
AVStream *st = s->streams[n];
|
||||
AVCodecContext *codec = st->codec;
|
||||
if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, codec->codec_id);
|
||||
if (!tag) {
|
||||
av_log(s, AV_LOG_ERROR, "unsupported audio codec\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
avio_wl32(pb, SMJPEG_SND);
|
||||
avio_wb32(pb, 8);
|
||||
avio_wb16(pb, codec->sample_rate);
|
||||
avio_w8(pb, av_get_bits_per_sample(codec->codec_id));
|
||||
avio_w8(pb, codec->channels);
|
||||
avio_wl32(pb, tag);
|
||||
avpriv_set_pts_info(st, 32, 1, 1000);
|
||||
} else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, codec->codec_id);
|
||||
if (!tag) {
|
||||
av_log(s, AV_LOG_ERROR, "unsupported video codec\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
avio_wl32(pb, SMJPEG_VID);
|
||||
avio_wb32(pb, 12);
|
||||
avio_wb32(pb, 0);
|
||||
avio_wb16(pb, codec->width);
|
||||
avio_wb16(pb, codec->height);
|
||||
avio_wl32(pb, tag);
|
||||
avpriv_set_pts_info(st, 32, 1, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
avio_wl32(pb, SMJPEG_HEND);
|
||||
avio_flush(pb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smjpeg_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
{
|
||||
SMJPEGMuxContext *smc = s->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
AVStream *st = s->streams[pkt->stream_index];
|
||||
AVCodecContext *codec = st->codec;
|
||||
|
||||
if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
avio_wl32(pb, SMJPEG_SNDD);
|
||||
else if (codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
avio_wl32(pb, SMJPEG_VIDD);
|
||||
else
|
||||
return 0;
|
||||
|
||||
avio_wb32(pb, pkt->pts);
|
||||
avio_wb32(pb, pkt->size);
|
||||
avio_write(pb, pkt->data, pkt->size);
|
||||
avio_flush(pb);
|
||||
|
||||
smc->duration = FFMAX(smc->duration, pkt->pts + pkt->duration);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smjpeg_write_trailer(AVFormatContext *s)
|
||||
{
|
||||
SMJPEGMuxContext *smc = s->priv_data;
|
||||
AVIOContext *pb = s->pb;
|
||||
int64_t currentpos;
|
||||
|
||||
if (pb->seekable) {
|
||||
currentpos = avio_tell(pb);
|
||||
avio_seek(pb, 12, SEEK_SET);
|
||||
avio_wb32(pb, smc->duration);
|
||||
avio_seek(pb, currentpos, SEEK_SET);
|
||||
}
|
||||
|
||||
avio_wl32(pb, SMJPEG_DONE);
|
||||
avio_flush(pb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVOutputFormat ff_smjpeg_muxer = {
|
||||
.name = "smjpeg",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Loki SDL MJPEG"),
|
||||
.priv_data_size = sizeof(SMJPEGMuxContext),
|
||||
.audio_codec = CODEC_ID_PCM_S16LE,
|
||||
.video_codec = CODEC_ID_MJPEG,
|
||||
.write_header = smjpeg_write_header,
|
||||
.write_packet = smjpeg_write_packet,
|
||||
.write_trailer = smjpeg_write_trailer,
|
||||
.flags = AVFMT_GLOBALHEADER,
|
||||
.codec_tag = (const AVCodecTag *const []){ ff_codec_smjpeg_video_tags, ff_codec_smjpeg_audio_tags, 0 },
|
||||
};
|
@ -30,7 +30,7 @@
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 53
|
||||
#define LIBAVFORMAT_VERSION_MINOR 29
|
||||
#define LIBAVFORMAT_VERSION_MINOR 30
|
||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
|
Loading…
x
Reference in New Issue
Block a user