mirror of
https://github.com/Danile71/go-rtsp.git
synced 2025-09-27 12:32:05 +08:00

* Removed use of av_init_packet as it is deprecated in new FFMPEG version Changed LogLevel to AV_LOG_QUIET Added socket TCP I/O timeout value 10s * Fix type layout in swr_alloc_set_opts
173 lines
4.6 KiB
C
173 lines
4.6 KiB
C
#include "ffmpeg.h"
|
|
|
|
void ffmpeginit() {
|
|
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
|
|
av_register_all();
|
|
avformat_network_init();
|
|
#endif
|
|
}
|
|
|
|
struct AVStream * stream_at(struct AVFormatContext *c, int idx) {
|
|
if (idx >= 0 && idx < c->nb_streams)
|
|
return c->streams[idx];
|
|
return NULL;
|
|
}
|
|
|
|
int rtsp_encode(AVCodecContext *avctx, AVPacket *pkt, int *got_packet, AVFrame *frame)
|
|
{
|
|
int ret;
|
|
|
|
*got_packet = 0;
|
|
|
|
if (!frame) {
|
|
return -1;
|
|
}
|
|
|
|
ret = avcodec_send_frame(avctx, frame);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
ret = avcodec_receive_packet(avctx, pkt);
|
|
if (!ret)
|
|
*got_packet = 1;
|
|
if (ret == AVERROR(EAGAIN))
|
|
return 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int rtsp_avcodec_encode_wav(AVCodecContext *pCodecCtx, AVFrame *pFrame,AVPacket *packet) {
|
|
const AVCodec *wavCodec = avcodec_find_encoder(AV_CODEC_ID_PCM_S16LE );
|
|
int ret = -1;
|
|
|
|
if (!wavCodec) {
|
|
return ret;
|
|
}
|
|
|
|
AVCodecContext *wavContext = avcodec_alloc_context3(wavCodec);
|
|
if (!wavContext) {
|
|
wavCodec = NULL;
|
|
return ret;
|
|
}
|
|
|
|
wavContext->bit_rate = pCodecCtx->bit_rate;
|
|
wavContext->sample_fmt = AV_SAMPLE_FMT_S16;
|
|
wavContext->sample_rate = pFrame->sample_rate;
|
|
wavContext->channel_layout = pFrame->channel_layout;
|
|
wavContext->channels = pFrame->channels;
|
|
|
|
ret = avcodec_open2(wavContext, wavCodec, NULL);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
int gotFrame;
|
|
|
|
ret = rtsp_encode(wavContext, packet, &gotFrame, pFrame);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
avcodec_close(wavContext);
|
|
avcodec_free_context(&wavContext);
|
|
wavCodec = NULL;
|
|
return ret;
|
|
}
|
|
|
|
int rtsp_avcodec_encode_jpeg(AVCodecContext *pCodecCtx, AVFrame *pFrame,AVPacket *packet) {
|
|
const AVCodec *jpegCodec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
|
|
int ret = -1;
|
|
|
|
if (!jpegCodec) {
|
|
return ret;
|
|
}
|
|
|
|
AVCodecContext *jpegContext = avcodec_alloc_context3(jpegCodec);
|
|
if (!jpegContext) {
|
|
jpegCodec = NULL;
|
|
return ret;
|
|
}
|
|
|
|
jpegContext->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
|
jpegContext->height = pFrame->height;
|
|
jpegContext->width = pFrame->width;
|
|
jpegContext->time_base= (AVRational){1,25};
|
|
|
|
ret = avcodec_open2(jpegContext, jpegCodec, NULL);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
int gotFrame;
|
|
|
|
ret = rtsp_encode(jpegContext, packet, &gotFrame, pFrame);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
avcodec_close(jpegContext);
|
|
avcodec_free_context(&jpegContext);
|
|
jpegCodec = NULL;
|
|
return ret;
|
|
}
|
|
|
|
uint8_t *rtsp_convert(AVCodecContext *pCodecCtx,AVFrame *pFrame,AVFrame *nFrame,int *size, int format) {
|
|
struct SwsContext *img_convert_ctx = sws_getCachedContext( NULL, pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pFrame->width, pFrame->height, format, SWS_BICUBIC, NULL, NULL, NULL );
|
|
nFrame->format = format;
|
|
nFrame->width = pFrame->width;
|
|
nFrame->height = pFrame->height;
|
|
|
|
*size = av_image_get_buffer_size( format, pFrame->width, pFrame->height, 1);
|
|
|
|
uint8_t *tmp_picture_buf = (uint8_t *)malloc(*size);
|
|
|
|
av_image_fill_arrays(nFrame->data, nFrame->linesize, tmp_picture_buf, format, pFrame->width, pFrame->height, 1);
|
|
|
|
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, nFrame->height, nFrame->data, nFrame->linesize);
|
|
sws_freeContext(img_convert_ctx);
|
|
return tmp_picture_buf;
|
|
}
|
|
|
|
int rtsp_avcodec_encode_jpeg_nv12(AVCodecContext *pCodecCtx, AVFrame *pFrame,AVPacket *packet) {
|
|
int size = 0;
|
|
AVFrame *nFrame = av_frame_alloc();
|
|
uint8_t * data = rtsp_convert(pCodecCtx, pFrame, nFrame, &size, AV_PIX_FMT_YUV420P);
|
|
int ret = rtsp_avcodec_encode_jpeg(pCodecCtx,nFrame,packet);
|
|
free(data);
|
|
av_frame_free(&nFrame);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int rtsp_avcodec_encode_resample_wav(AVCodecContext *pCodecCtx,SwrContext *swr_ctx, AVFrame *pFrame,AVPacket *packet) {
|
|
int ret = 0;
|
|
|
|
AVFrame *nFrame = av_frame_alloc();
|
|
|
|
nFrame->channel_layout = pFrame->channel_layout;
|
|
nFrame->sample_rate = pFrame->sample_rate;
|
|
nFrame->format = AV_SAMPLE_FMT_S16;
|
|
|
|
// Without this, there is no sound at all at the output (PTS stuff I guess)
|
|
ret = av_frame_copy_props(nFrame, pFrame);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
ret = swr_convert_frame(swr_ctx, nFrame, pFrame);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
ret = rtsp_avcodec_encode_wav(pCodecCtx,nFrame,packet);
|
|
if (ret < 0) {
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
av_frame_free(&nFrame);
|
|
|
|
return ret;
|
|
} |