mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
convert jpg to m2v with libavcodec, need --enable-demuxer=image2
This commit is contained in:
@@ -40,6 +40,12 @@
|
|||||||
|
|
||||||
#include <proc_tools.h>
|
#include <proc_tools.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
}
|
||||||
|
|
||||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
|
||||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
|
||||||
#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args)
|
#define lt_debug_c(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, NULL, args)
|
||||||
@@ -141,6 +147,126 @@ static const char *vid_modes[] = {
|
|||||||
#define VIDEO_STREAMTYPE_H265_HEVC 7
|
#define VIDEO_STREAMTYPE_H265_HEVC 7
|
||||||
#define VIDEO_STREAMTYPE_AVS 16
|
#define VIDEO_STREAMTYPE_AVS 16
|
||||||
|
|
||||||
|
void init_parameters(AVFrame* in_frame, AVCodecContext *codec_context)
|
||||||
|
{
|
||||||
|
/* put sample parameters */
|
||||||
|
codec_context->bit_rate = 400000;
|
||||||
|
/* resolution must be a multiple of two */
|
||||||
|
codec_context->width = (in_frame->width/2)*2;
|
||||||
|
codec_context->height = (in_frame->height/2)*2;
|
||||||
|
/* frames per second */
|
||||||
|
codec_context->time_base = (AVRational ) { 1, 60 };
|
||||||
|
codec_context->gop_size = 10; /* emit one intra frame every ten frames */
|
||||||
|
codec_context->max_b_frames = 1;
|
||||||
|
codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_frame(AVFrame* in_frame, FILE* fp)
|
||||||
|
{
|
||||||
|
if(in_frame == NULL || fp == NULL)
|
||||||
|
return;
|
||||||
|
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_MPEG2VIDEO);
|
||||||
|
if (codec)
|
||||||
|
{
|
||||||
|
AVCodecContext *codec_context = avcodec_alloc_context3(codec);
|
||||||
|
if (codec_context)
|
||||||
|
{
|
||||||
|
init_parameters(in_frame, codec_context);
|
||||||
|
if (avcodec_open2(codec_context, codec, 0) != -1){
|
||||||
|
AVPacket pkt;
|
||||||
|
av_init_packet(&pkt);
|
||||||
|
/* encode the image */
|
||||||
|
int got_output = 0;
|
||||||
|
int ret = avcodec_encode_video2(codec_context, &pkt, in_frame, &got_output);
|
||||||
|
if (ret != -1){
|
||||||
|
if (got_output){
|
||||||
|
fwrite(pkt.data, 1, pkt.size, fp);
|
||||||
|
av_packet_unref(&pkt);
|
||||||
|
}
|
||||||
|
int i =1;
|
||||||
|
for (got_output = 1; got_output; i++){
|
||||||
|
/* get the delayed frames */
|
||||||
|
in_frame->pts = i;
|
||||||
|
ret = avcodec_encode_video2(codec_context, &pkt, 0, &got_output);
|
||||||
|
if (ret != -1 && got_output){
|
||||||
|
fwrite(pkt.data, 1, pkt.size, fp);
|
||||||
|
av_packet_unref(&pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avcodec_close(codec_context);
|
||||||
|
av_free(codec_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int decode_frame(AVCodecContext *codecContext,AVPacket &packet, FILE* fp)
|
||||||
|
{
|
||||||
|
int decode_ok = 0;
|
||||||
|
AVFrame *frame = av_frame_alloc();
|
||||||
|
if(frame){
|
||||||
|
if ((avcodec_decode_video2(codecContext, frame, &decode_ok, &packet)) < 0 || !decode_ok){
|
||||||
|
av_frame_free(&frame);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
write_frame(frame, fp);
|
||||||
|
av_frame_free(&frame);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AVCodecContext* open_codec(AVMediaType mediaType, AVFormatContext* formatContext)
|
||||||
|
{
|
||||||
|
int stream_index = av_find_best_stream(formatContext, mediaType, -1, -1, NULL, 0);
|
||||||
|
if (stream_index < 0){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
AVCodecContext * codecContext = formatContext->streams[stream_index]->codec;
|
||||||
|
AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);
|
||||||
|
if (!codec){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((avcodec_open2(codecContext, codec, NULL)) != 0){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codecContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
int image_to_mpeg2(const char *image_name, const char *encode_name)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
av_register_all();
|
||||||
|
avcodec_register_all();
|
||||||
|
|
||||||
|
AVFormatContext *formatContext = avformat_alloc_context();
|
||||||
|
if ((ret = avformat_open_input(&formatContext, image_name, NULL, NULL)) == 0){
|
||||||
|
AVCodecContext *codecContext = open_codec(AVMEDIA_TYPE_VIDEO, formatContext);
|
||||||
|
if(codecContext){
|
||||||
|
AVPacket packet;
|
||||||
|
av_init_packet(&packet);
|
||||||
|
if ((ret = av_read_frame(formatContext, &packet)) !=-1){
|
||||||
|
FILE* fp = fopen(encode_name, "wb");
|
||||||
|
if(fp){
|
||||||
|
if(decode_frame(codecContext, packet, fp) != 1){
|
||||||
|
/* add sequence end code to have a real mpeg file */
|
||||||
|
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
|
||||||
|
fwrite(endcode, 1, sizeof(endcode), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avcodec_close(codecContext);
|
||||||
|
av_free_packet(&packet);
|
||||||
|
}
|
||||||
|
avformat_close_input(&formatContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av_free(formatContext);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cVideo::cVideo(int, void *, void *, unsigned int unit)
|
cVideo::cVideo(int, void *, void *, unsigned int unit)
|
||||||
{
|
{
|
||||||
lt_debug("%s unit %u\n", __func__, unit);
|
lt_debug("%s unit %u\n", __func__, unit);
|
||||||
@@ -431,7 +557,6 @@ void cVideo::ShowPicture(const char * fname, const char *_destname)
|
|||||||
static const unsigned char pes_header[] = {0x0, 0x0, 0x1, 0xe0, 0x00, 0x00, 0x80, 0x80, 0x5, 0x21, 0x0, 0x1, 0x0, 0x1};
|
static const unsigned char pes_header[] = {0x0, 0x0, 0x1, 0xe0, 0x00, 0x00, 0x80, 0x80, 0x5, 0x21, 0x0, 0x1, 0x0, 0x1};
|
||||||
static const unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 };
|
static const unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 };
|
||||||
char destname[512];
|
char destname[512];
|
||||||
char cmd[512];
|
|
||||||
char *p;
|
char *p;
|
||||||
int mfd;
|
int mfd;
|
||||||
struct stat st, st2;
|
struct stat st, st2;
|
||||||
@@ -472,9 +597,7 @@ void cVideo::ShowPicture(const char * fname, const char *_destname)
|
|||||||
u.actime = time(NULL);
|
u.actime = time(NULL);
|
||||||
u.modtime = st2.st_mtime;
|
u.modtime = st2.st_mtime;
|
||||||
/* it does not exist or has a different date, so call ffmpeg... */
|
/* it does not exist or has a different date, so call ffmpeg... */
|
||||||
sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 1280x720 -aspect 16:9 '%s' >/dev/null",
|
image_to_mpeg2(fname, destname);
|
||||||
fname, destname);
|
|
||||||
system(cmd); /* TODO: use libavcodec to directly convert it */
|
|
||||||
utime(destname, &u);
|
utime(destname, &u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user