
Recherche avancée
Médias (1)
-
The Great Big Beautiful Tomorrow
28 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Texte
Autres articles (53)
-
Les autorisations surchargées par les plugins
27 avril 2010, parMediaspip core
autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs -
L’utiliser, en parler, le critiquer
10 avril 2011La première attitude à adopter est d’en parler, soit directement avec les personnes impliquées dans son développement, soit autour de vous pour convaincre de nouvelles personnes à l’utiliser.
Plus la communauté sera nombreuse et plus les évolutions seront rapides ...
Une liste de discussion est disponible pour tout échange entre utilisateurs. -
Création définitive du canal
12 mars 2010, parLorsque votre demande est validée, vous pouvez alors procéder à la création proprement dite du canal. Chaque canal est un site à part entière placé sous votre responsabilité. Les administrateurs de la plateforme n’y ont aucun accès.
A la validation, vous recevez un email vous invitant donc à créer votre canal.
Pour ce faire il vous suffit de vous rendre à son adresse, dans notre exemple "http://votre_sous_domaine.mediaspip.net".
A ce moment là un mot de passe vous est demandé, il vous suffit d’y (...)
Sur d’autres sites (11402)
-
Révision 23340 : Compatibilité PHP 7.1 : minipipe() utilise call_user_func() qui ne peut pas trans...
18 janvier 2017, par marcimat@rezo.net"call_user_func() and call_user_func_array() will now always throw errors when trying to call a method whose signature has references. Previously this sometimes worked if call_user_func() was used outside a namespace."
-
Android plugin with .so lib's (UNITY)
23 mars 2017, par Vladimir IlianovSo i need ffmpeg in android. (for muxing audio and video).
I found this awesome project for android studio (link in the end of a post, in rar as ffmpeg4android_demo_studio2).
I works perfect, does muxing and overall awesome project. So i decided to make plugin for anroid from that project, so i remade project like that : (link in the end of a post, in rar as ffmpeg4android_demo_studio ((p.S. the is no GeneralUtils code because its big, please download rar and open it.))package com.netcompss.ffmpeg4android;
public class CommandValidationException extends Exception {
private static final long serialVersionUID = 1L;
}=============================================
package com.netcompss.ffmpeg4android;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
public class FFMpeg {
private Context context;
private static FFMpeg instance;
public FFMpeg (){
this.instance = this;
}
public static FFMpeg instance(){
if(instance == null){
instance = new FFMpeg();
}
return instance;
}
public void setContext(Context context){
this.context = context;
}
public void mux(String video,String audio,String out){
//GeneralUtils.checkForPermissionsMAndAbove(currentActivity, true);
LoadJNI vk = new LoadJNI();
try {
String workFolder = context.getFilesDir().getAbsolutePath()+ "/";
String cmd = "ffmpeg -i "+video+" -i "+audio+" -c copy -map 0:v:0 -map 1:a:0 -shortest "+out;
vk.run(GeneralUtils.utilConvertToComplex(cmd) , workFolder , context);
Log.i("test", "ffmpeg4android finished successfully");
} catch (Throwable e) {
Log.e("test", "vk run exception.", e);
}
}
public void showMessage(String message){
Toast.makeText(this.context,message,Toast.LENGTH_SHORT).show();
}
}==================
package com.netcompss.ffmpeg4android ;
import android.app.Activity;
import android.content.Context;
import android.widget.TextView;
import android.os.Bundle;
public class LicenseCheckJNI
{
public int licenseCheck(String path, Context ctx) {
String rcStr = "-100";
rcStr = licenseCheckComplexJNI(path);
int rc =Integer.decode(rcStr);
return rc;
}
public native String licenseCheckComplexJNI(String path);
public native String licenseCheckSimpleJNI(String path);
static {
System.loadLibrary("license-jni");
}
}
package com.netcompss.ffmpeg4android;
import java.io.File;
import android.content.Context;
import android.nfc.Tag;
import android.util.Log;
public final class LoadJNI {
static {
System.loadLibrary("loader-jni");
System.loadLibrary("license-jni");
System.loadLibrary("videokit");
}
/**
*
* @param args ffmpeg command
* @param workFolder working directory
* @param ctx Android context
* @param isValidate apply validation to the command
* @throws CommandValidationException
*/
public void run(String[] args, String workFolder, Context ctx, boolean isValidate) throws CommandValidationException {
Log.i(Prefs.TAG, "running ffmpeg4android_lib: " + Prefs.version);
// delete previous log: this is essential for correct progress calculation
String vkLogPath = workFolder + "vk.log";
GeneralUtils.deleteFileUtil(vkLogPath);
GeneralUtils.printCommand(args);
//printInternalDirStructure(ctx);
if (isValidate) {
if (GeneralUtils.isValidCommand(args)) {
Log.d(Prefs.TAG, "=LOAD================");
load(args, workFolder, getVideokitLibPath(ctx), true);
}
else
throw new CommandValidationException();
}
else {
Log.d(Prefs.TAG, "=LOAD================");
load(args, workFolder, getVideokitLibPath(ctx), true);
}
}
/**
*
* @param args ffmpeg command
* @param workFolder working directory
* @param ctx Android context
* @throws CommandValidationException
*/
public void run(String[] args, String workFolder, Context ctx) throws CommandValidationException {
run(args, workFolder, ctx, true);
}
private static void printInternalDirStructure(Context ctx) {
Log.d(Prefs.TAG, "=printInternalDirStructure=");
Log.d(Prefs.TAG, "==============================");
File file = new File(ctx.getFilesDir().getParent());
analyzeDir(file);
Log.d(Prefs.TAG, "==============================");
}
private static void analyzeDir(File path) {
if (path.isDirectory()) {
Log.d(Prefs.TAG,"Scanning dir: " + path.getAbsolutePath());
File[] files1 = path.listFiles();
for (int i = 0; i < files1.length; i++) {
analyzeDir(files1[i]);
}
Log.d(Prefs.TAG, "==========");
}
else {
Log.d(Prefs.TAG, path.getAbsolutePath());
}
}
private static String getVideokitLibPath(Context ctx) {
//File file = new File(ctx.getFilesDir().getParent() + "/lib/");
//analyzeDir(file);
String videokitLibPath = ctx.getFilesDir().getParent() + "/lib/libvideokit.so";
File file = new File(videokitLibPath);
if(file.exists()) {
Log.i(Prefs.TAG, "videokitLibPath exits");
}
else {
Log.w(Prefs.TAG, "videokitLibPath not exits: " + videokitLibPath);
videokitLibPath = ctx.getFilesDir().getParent() + "/lib/arm64/libvideokit.so";
Log.i(Prefs.TAG, "trying videokitLibPath: " + videokitLibPath);
file = new File(videokitLibPath);
if(file.exists()) {
Log.i(Prefs.TAG, "videokitLibPath exits: " + videokitLibPath);
}
else {
Log.w(Prefs.TAG, "videokitLibPath not exits: " + videokitLibPath);
videokitLibPath = "/data/app/com.examples.ffmpeg4android_demo-1/lib/arm64/libvideokit.so";
Log.i(Prefs.TAG, "trying videokitLibPath: " + videokitLibPath);
file = new File(videokitLibPath);
if(file.exists()) {
Log.i(Prefs.TAG, "videokitLibPath exits: " + videokitLibPath);
}
else {
Log.w(Prefs.TAG, "videokitLibPath not exits: " + videokitLibPath);
videokitLibPath = "/data/app/com.examples.ffmpeg4android_demo-2/lib/arm64/libvideokit.so";
Log.i(Prefs.TAG, "trying videokitLibPath: " + videokitLibPath);
if(file.exists()) {
Log.i(Prefs.TAG, "videokitLibPath exits: " + videokitLibPath);
}
else {
Log.e(Prefs.TAG, "can't find path of lib");
}
}
}
}
//String videokitLibPath = ctx.getFilesDir().getParent() + "/lib/arm64/libvideokit.so";
// only this works on Android M, and the number changes (demo-2, demo-1)
//String videokitLibPath = "/data/app/com.examples.ffmpeg4android_demo-1/lib/arm64/libvideokit.so";
//Log.i(Prefs.TAG, "videokitLibPath: " + videokitLibPath);
return videokitLibPath;
}
public void fExit( Context ctx) {
fexit(getVideokitLibPath(ctx));
}
public native String fexit(String videokitLibPath);
public native String unload();
public native String load(String[] args, String videokitSdcardPath, String videokitLibPath, boolean isComplex);
}============================
package com.netcompss.ffmpeg4android;
public class Prefs {
public static final String TAG = "ffmpeg4android";
public static final String version = "322.00.00_LM322";
}
[/code]
[code=JavaScript]
package com.netcompss.ffmpeg4android;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.util.Log;
public class ProgressCalculator {
private int _durationOfCurrentWaitIndex = 0;
private final int DURATION_OF_CURRENT_WAIT_INDEX_LIMIT = 12;
private String _durationOfCurrent;
private long _lastVklogSize = -1;
private int _vkLogNoChangeCounter = 0;
private SimpleDateFormat _simpleDateFormat;
long _timeRef = -1;
int _prevProgress = 0;
private String vkLogPath = null;
public ProgressCalculator(String vkLogPathIn) {
vkLogPath = vkLogPathIn;
_simpleDateFormat = new SimpleDateFormat("HH:mm:ss.SS");
try {
Date ref = _simpleDateFormat.parse("00:00:00.00");
ref.setYear(112);
_timeRef = ref.getTime();
} catch (ParseException e) {
Log.w(Prefs.TAG, "failed to set _timeRef");
}
}
public void initCalcParamsForNextInter() {
Log.i(Prefs.TAG, "initCalcParamsForNextInter");
_lastVklogSize = -1;
_vkLogNoChangeCounter = 0;
_durationOfCurrent = null;
}
public int calcProgress() {
return calcProgress(1);
}
public int calcProgress(int durationMultiplyer) {
//Log.i(Prefs.TAG, "========calc progress======= " + durationMultiplyer);
int progress = 0;
if (_durationOfCurrent == null) {
String dur = GeneralUtils.getDutationFromVCLogRandomAccess(vkLogPath);
Log.d(Prefs.TAG, "dur: " + dur);
if (dur == null || dur.equals("") || dur.equals("null") ) {
Log.i(Prefs.TAG, "dur is not good, not setting ");
if (_durationOfCurrentWaitIndex < DURATION_OF_CURRENT_WAIT_INDEX_LIMIT) {
Log.i(Prefs.TAG, "waiting for real duration, going out of calcProgress with 0");
_durationOfCurrentWaitIndex ++;
return 0;
}
else {
Log.i(Prefs.TAG, "_durationOfCurrentWaitIndex is equal to: " + DURATION_OF_CURRENT_WAIT_INDEX_LIMIT + " reseting.");
_durationOfCurrentWaitIndex = 0;
Log.i(Prefs.TAG, "setting fake Prefs.durationOfCurrent");
_durationOfCurrent = "00:03:00.00";
Log.w(Prefs.TAG, "setting fake Prefs.durationOfCurrent (Cant get from file): " + _durationOfCurrent);
}
}
else {
_durationOfCurrent = GeneralUtils.getDutationFromVCLogRandomAccess(vkLogPath);
Log.i(Prefs.TAG, "duration: " + _durationOfCurrent + " \nTranscoding...");
}
}
if (_durationOfCurrent != null) {
long currentVkLogSize = -1;
currentVkLogSize = GeneralUtils.getVKLogSizeRandomAccess(vkLogPath);
//Log.d(Prefs.TAG, "currentVkLogSize: " + currentVkLogSize + " _lastVklogSize: " + _lastVklogSize);
if (currentVkLogSize > _lastVklogSize) {
_lastVklogSize = currentVkLogSize;
_vkLogNoChangeCounter = 0;
}
else {
//Log.w(Prefs.TAG, "Looks like Vk log is not increasing in size");
_vkLogNoChangeCounter++;
}
String currentTimeStr = GeneralUtils.readLastTimeFromVKLogUsingRandomAccess(vkLogPath);
//Log.d(Prefs.TAG, "currentTimeStr: " + currentTimeStr);
if (currentTimeStr.equals("exit")) {
Log.d(Prefs.TAG, "============Found one of the exit tokens in the log============");
return 100;
}
else if (currentTimeStr.equals("error") && _prevProgress == 0) {
Log.d(Prefs.TAG, "============Found error in the log============");
return 100;
}
else if (_vkLogNoChangeCounter > 16) {
Log.e(Prefs.TAG, "VK log is not changing in size, and no exit token found");
return 100;
}
try {
Date durationDate = _simpleDateFormat.parse(_durationOfCurrent);
Date currentTimeDate = _simpleDateFormat.parse(currentTimeStr);
currentTimeDate.setYear(112);
durationDate.setYear(112);
//Log.d(Prefs.TAG, " durationDate: " + durationDate + " currentTimeDate: " + currentTimeDate);
long durationLong = durationDate.getTime() - _timeRef;
if (durationMultiplyer != 1) {
//Log.i(Prefs.TAG, "====durationMultiplyer is not 1, handling===");
//Log.i(Prefs.TAG, "durationLong before: " + durationLong);
durationLong = durationLong * durationMultiplyer;
//Log.i(Prefs.TAG, "durationLong after: " + durationLong);
}
long currentTimeLong = currentTimeDate.getTime() - _timeRef;
//Log.d(Prefs.TAG, " durationLong: " + durationLong + " currentTimeLong: " + currentTimeLong + " diff: " + (durationLong - currentTimeLong));
progress = Math.round(((float)currentTimeLong / durationLong) * 100);
if (progress >= 100) {
Log.w(Prefs.TAG, "progress is 100, but can't find exit in the log, probably fake progress, still running...");
progress = 99;
}
_prevProgress = progress;
} catch (ParseException e) {
Log.w(Prefs.TAG, e.getMessage());
}
}
return progress;
}
}==================================
Then clicked build and copied ffmpeg4android_lib.aar in unity project under assets/Plugins/Android/libs/
then made this wrap upusing System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
public class Test : MonoBehaviour {
private AndroidJavaObject FFMpeg = null;
private AndroidJavaObject activityContext = null;
public string Path1;
public string Path2;
public string Out3;
public string path;
public Text File1;
public Text File2;
public Text Context;
public Text End;
public void Convert(){
File1.text = File.Exists (path+Path1).ToString();
File2.text = File.Exists (path+Path2).ToString();
if (FFMpeg == null) {
using(AndroidJavaClass activityclass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")){
activityContext = activityclass.GetStatic<androidjavaobject> ("currentActivity");
}
Context.text = "Context =" + activityContext;
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass ("com.netcompss.ffmpeg4android.FFMpeg")) {
if (pluginClass != null) {
FFMpeg = pluginClass.CallStatic<androidjavaobject> ("instance");
FFMpeg.Call ("setContext", activityContext);
//activityContext.Call ("runOnUiThread", new AndroidJavaRunnable (() => {
FFMpeg.Call ("mux", path+Path1,path+Path2,path+Out3);
//}));
}
}
End.text = "Done";
}
}
</androidjavaobject></androidjavaobject>=============================================
And the problem is :
When i launch apk made from original project in AndroidStudio everything works fine.
When i launch apk made in unity its works fine until this part :
load(args, workFolder, getVideokitLibPath(ctx), true) ;IT does load all lib ok.
Its throw this error in logcat when trying to do that code03-23 10:43:17.293 28263-28277/? W/dalvikvm: No implementation found for native Lcom/netcompss/ffmpeg4android/LoadJNI;.load:([Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;
03-23 10:43:17.294 28263-28277/? E/test: vk run exception.
java.lang.UnsatisfiedLinkError: Native method not found: com.netcompss.ffmpeg4android.LoadJNI.load:([Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;
at com.netcompss.ffmpeg4android.LoadJNI.load(Native Method)
at com.netcompss.ffmpeg4android.LoadJNI.run(LoadJNI.java:37)
at com.netcompss.ffmpeg4android.LoadJNI.run(LoadJNI.java:57)
at com.netcompss.ffmpeg4android.FFMpeg.mux(FFMpeg.java:36)
at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
at com.unity3d.player.UnityPlayer.a(Unknown Source)
at com.unity3d.player.UnityPlayer$b$1.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:194)
at com.unity3d.player.UnityPlayer$b.run(Unknown Source)Projects Dropbox link :
https://www.dropbox.com/s/6vglcw7xk2n8lwu/AndroidStudioProjects.rar?dl=0 -
Can't decode h264 frame by frame
17 mai 2017, par J. DoeHere is problematic code :
int frame_count{0};
int status = -1;
while ((status = av_read_frame(ctx, pkt)) >= 0) {
int got_frame;
auto len =
avcodec_decode_video2(video_ctx, frame, &got_frame, pkt);
errcheck(len);
if (got_frame == 0)
errthrow("No frame could be decompressed");
auto w = frame->width;
auto h = frame->height;
auto gray_convert_ctx = sws_getContext(
w, h, input_pix_format, w, h, output_pix_format, SWS_POINT,
nullptr, nullptr, nullptr);
sws_scale(gray_convert_ctx, frame->data, frame->linesize, 0, h,
frame_converted->data, frame_converted->linesize);
f_(frame_converted->data[0], frame_converted->linesize[0], w,
h);
++frame_count;
sws_freeContext(gray_convert_ctx);
if (pkt->data) {
pkt->size -= len;
pkt->data += len;
}
}
if (status != AVERROR_EOF)
errcheck(status);With
vp8/vp9
all is okay, but when I’m trying to decodeh264
, I’ve got error :➤ ./cv /tmp/x
file size: 694KiB
read /tmp/x: 694KiB
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x191fc00] Format mov,mp4,m4a,3gp,3g2,mj2 probed with size=2048 and score=100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x191fc00] ISO: File Type Major Brand: mp42
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x191fc00] rfps: 31.000000 0.000599
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x191fc00] Before avformat_find_stream_info() pos: 3104 bytes read:32768 seeks:0
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x191fc00] All info found
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x191fc00] After avformat_find_stream_info() pos: 456697 bytes read:458752 seeks:0 frames:34
[h264 @ 0x1926700] no frame!
error: AV: Invalid data found when processing inputMaybe that’s because of h264 does not support AV_CODEC_CAP_TRUNCATED ? But I suppose it’s should be handled in av_read_frame.
Then ignoring (just skipping this read if error occurs) — no frame decoded anyway until EOF. :c This video working fine with ffplay/mpv/etc. and was recorded by Android.
#include <iostream>
extern "C" {
#include <libavcodec></libavcodec>avcodec.h>
#include <libavformat></libavformat>avformat.h>
}
#include <functional>
class Video
{
public:
static std::string TAG;
Video();
Video(void *data_ptr, size_t data_size);
~Video();
void set(void *data_ptr, size_t data_size);
void process(std::function f_);
private:
static constexpr AVPixelFormat output_pix_format{AV_PIX_FMT_GRAY8};
struct {
uint8_t *ptr{nullptr};
size_t size;
} bd;
bool video_ctx_opened{false};
AVCodecContext *video_ctx{nullptr};
AVStream *video_stream{nullptr};
size_t width;
size_t heigh;
AVPixelFormat input_pix_format;
size_t avio_ctx_buffer_size = 32 * 1024; // 32 KiB
uint8_t *avio_ctx_buffer{nullptr};
AVFormatContext *ctx{nullptr};
AVIOContext *avio_ctx{nullptr};
uint8_t *frame_converted_buffer{nullptr};
AVFrame *frame_converted{nullptr};
AVFrame *frame{nullptr};
AVPacket *pkt{nullptr};
void init_stream();
void init_codec();
void init_frame_converted();
};
extern "C" {
#include <libswscale></libswscale>swscale.h>
}
#include <iostream>
#include <stdexcept>
namespace
{
using str_t = decltype(Video::TAG);
static str_t averr(int code)
{
static thread_local std::array buf;
av_make_error_string(buf.data(), buf.size(), code);
return str_t(buf.data(), buf.size());
}
static str_t errstr(int err) { return Video::TAG + ": " + averr(err); }
static str_t errstr(const char *err) { return Video::TAG + ": " + err; }
static void errthrow(str_t err) { throw std::runtime_error{std::move(err)}; }
static void errcheck(int val)
{
if (val < 0)
errthrow(errstr(val));
}
template <class t="t"> static void errcheck(T *ptr, const char *errmsg)
{
if (!ptr)
errthrow(errstr(errmsg));
}
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
{
struct _bd {
uint8_t *ptr;
size_t size;
};
_bd *bd = static_cast<_bd *>(opaque);
buf_size = FFMIN(buf_size, bd->size);
memcpy(buf, bd->ptr, buf_size);
bd->ptr += buf_size;
bd->size -= buf_size;
return buf_size;
}
}
std::string Video::TAG = "AV";
Video::Video()
{
av_register_all();
avcodec_register_all();
frame = av_frame_alloc();
errcheck(frame, "Could not allocate frame");
pkt = static_cast<avpacket>(av_malloc(sizeof(AVPacket)));
errcheck(pkt, "Could not allocate packet");
av_init_packet(pkt);
}
Video::Video(void *data_ptr, size_t data_size) : Video()
{
set(data_ptr, data_size);
}
Video::~Video()
{
avformat_close_input(&ctx);
if (avio_ctx) {
av_freep(&avio_ctx->buffer);
av_freep(&avio_ctx);
}
if (video_ctx) {
avcodec_close(video_ctx);
av_free(video_ctx);
}
if (frame)
av_frame_free(&frame);
if (frame_converted_buffer)
av_freep(&frame_converted_buffer);
if (frame_converted)
av_frame_free(&frame_converted);
if (pkt) {
av_free_packet(pkt);
av_free(pkt);
}
}
void Video::set(void *data_ptr, size_t data_size)
{
bd.ptr = static_cast(data_ptr);
bd.size = data_size;
init_stream();
init_frame_converted();
init_codec();
pkt->data = nullptr;
pkt->size = 0;
}
void Video::process(
std::function f_)
{
int frame_count{0};
int status = -1;
while ((status = av_read_frame(ctx, pkt)) >= 0) {
int got_frame;
auto len =
avcodec_decode_video2(video_ctx, frame, &got_frame, pkt);
errcheck(len);
if (got_frame == 0)
errthrow("No frame could be decompressed");
auto w = frame->width;
auto h = frame->height;
auto gray_convert_ctx = sws_getContext(
w, h, input_pix_format, w, h, output_pix_format, SWS_POINT,
nullptr, nullptr, nullptr);
sws_scale(gray_convert_ctx, frame->data, frame->linesize, 0, h,
frame_converted->data, frame_converted->linesize);
f_(frame_converted->data[0], frame_converted->linesize[0], w,
h);
++frame_count;
sws_freeContext(gray_convert_ctx);
if (pkt->data) {
pkt->size -= len;
pkt->data += len;
}
}
if (status != AVERROR_EOF)
errcheck(status);
}
void Video::init_stream()
{
ctx = avformat_alloc_context();
errcheck(ctx, "Could not allocate format context");
avio_ctx_buffer =
static_cast(av_malloc(avio_ctx_buffer_size));
errcheck(avio_ctx_buffer, "Could not allocate io buffer");
avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0,
&bd, &read_packet, nullptr, nullptr);
errcheck(avio_ctx, "Could not allocate io context");
ctx->pb = avio_ctx;
auto status = avformat_open_input(&ctx, nullptr, nullptr, nullptr);
errcheck(status);
status = avformat_find_stream_info(ctx, nullptr);
errcheck(status);
for (decltype(ctx->nb_streams) i = 0; i < ctx->nb_streams; ++i) {
auto stream = ctx->streams[i];
if (!stream || !stream->codec)
continue;
if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream = stream;
break;
}
}
errcheck(video_stream, "Could not find valid video stream");
width = video_stream->codec->width;
heigh = video_stream->codec->height;
input_pix_format = video_stream->codec->pix_fmt;
}
void Video::init_codec()
{
auto codec = avcodec_find_decoder(video_stream->codec->codec_id);
errcheck(codec, "Codec not found");
video_ctx = avcodec_alloc_context3(codec);
errcheck(video_ctx, "Could not allocate video codec context");
if (codec->capabilities & AV_CODEC_CAP_TRUNCATED)
video_ctx->flags |=
AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames
auto status = avcodec_open2(video_ctx, codec, nullptr);
errcheck(status);
}
void Video::init_frame_converted()
{
frame_converted = av_frame_alloc();
errcheck(frame_converted, "Could not allocate frame");
int frame_converted_buffer_size =
avpicture_get_size(output_pix_format, width, heigh);
errcheck(frame_converted_buffer_size);
frame_converted_buffer =
static_cast(av_malloc(frame_converted_buffer_size));
errcheck(frame_converted_buffer, "Could not allocate picture buffer");
auto status = avpicture_fill(
reinterpret_cast<avpicture>(frame_converted),
frame_converted_buffer, output_pix_format, width, heigh);
errcheck(status);
}
#include <vector>
#include <fstream>
std::vector<char> read_file(const std::string &fname)
{
std::ifstream file(fname, std::ios::binary | std::ios::ate);
if (!file.is_open())
throw std::runtime_error{"can't open " + fname};
auto size = file.tellg();
file.seekg(0, std::ios::beg);
std::cout << "file size: " << std::to_string(size / 1024) << "KiB\n";
std::vector<char> buffer(size);
if (file.read(buffer.data(), size))
return buffer;
return {};
}
int main(int argc, const char **argv)
{
if (argc < 2)
return EXIT_FAILURE;
av_log_set_level(AV_LOG_DEBUG);
try {
auto data = read_file(argv[1]);
std::cout << "read " << argv[1] << ": "
<< std::to_string(data.size() / 1024) << "KiB\n";
Video v;
v.set(data.data(), data.size());
v.process([](unsigned char *data, int wrap, int xsize,
int ysize) {
std::cout << "w: " << xsize
<< " h: " << ysize << '\n';
});
} catch (const std::runtime_error &e) {
std::cout << "error: " << e.what() << '\n';
}
}
</char></char></fstream></vector></avpicture></avpacket></class></stdexcept></iostream></functional></iostream>Compile&Run :
g++ cv.cpp -std=c++14 -lavutil -lavcodec -lavformat -lswscale ; ./a.out file.name.here